From 245a163f9d4d75f08d24449ca7390bbd97649191 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 7 Jun 2024 07:37:23 +1000 Subject: [PATCH] Update --- src/_CCIcon_X11.h => misc/linux/CCIcon_X11.h | 0 src/_CCIcon_mac.h => misc/macOS/CCIcon_mac.h | 0 misc/sdl/CCIcon_SDL.h | 71 ++ misc/sdl/sdl_icon_gen.cs | 40 + src/Audio.c | 2 +- src/AudioBackend.c | 2 +- src/Block.c | 203 ++-- src/Block.h | 4 +- src/BlockPhysics.c | 1 + src/Builder.c | 381 ++++++- src/Camera.c | 36 +- src/Camera.h | 8 +- src/Chat.c | 2 +- src/Commands.c | 4 +- src/Core.h | 137 ++- src/Deflate.c | 54 +- src/Deflate.h | 4 + src/Entity.c | 24 +- src/Entity.h | 1 + src/EntityComponents.h | 2 +- src/EntityRenderers.c | 28 +- src/EnvRenderer.c | 6 +- src/Errors.h | 3 +- src/Event.c | 8 + src/Event.h | 9 + src/ExtMath.c | 37 +- src/ExtMath.h | 4 +- src/FancyLighting.c | 580 ++++++++++ src/Formats.c | 4 +- src/Game.c | 10 +- src/Graphics.h | 2 +- src/Graphics_3DS.c | 6 +- src/Graphics_D3D11.c | 37 +- src/Graphics_D3D9.c | 16 +- src/Graphics_Dreamcast.c | 137 ++- src/Graphics_GCWii.c | 12 +- src/Graphics_GL1.c | 325 +++--- src/Graphics_GL2.c | 93 +- src/Graphics_N64.c | 4 +- src/Graphics_NDS.c | 4 +- src/Graphics_PS1.c | 268 +++-- src/Graphics_PS2.c | 22 +- src/Graphics_PS3.c | 25 +- src/Graphics_PSP.c | 4 +- src/Graphics_PSVita.c | 38 +- src/Graphics_Saturn.c | 1011 ++++++++++-------- src/Graphics_SoftGPU.c | 254 +++-- src/Graphics_WiiU.c | 6 +- src/Graphics_Xbox.c | 35 +- src/Graphics_Xbox360.c | 6 +- src/Gui.c | 2 +- src/Gui.h | 6 + src/HeldBlockRenderer.c | 3 +- src/Http_Worker.c | 35 +- src/Input.c | 309 ++++-- src/Input.h | 100 +- src/IsometricDrawer.c | 4 +- src/LScreens.c | 21 +- src/Launcher.c | 6 +- src/Lighting.c | 86 +- src/Lighting.h | 46 +- src/Logger.c | 8 +- src/Menus.c | 163 ++- src/Model.c | 55 +- src/Model.h | 3 +- src/Options.h | 1 + src/PackedCol.c | 21 + src/PackedCol.h | 4 +- src/Particle.c | 2 +- src/Platform.h | 12 +- src/Platform_3DS.c | 7 +- src/Platform_BeOS.cpp | 110 ++ src/Platform_Dreamcast.c | 7 +- src/Platform_GCWii.c | 4 +- src/Platform_MacClassic.c | 447 ++++++++ src/Platform_N64.c | 4 +- src/Platform_NDS.c | 19 +- src/Platform_PS1.c | 4 +- src/Platform_PS2.c | 14 +- src/Platform_PS3.c | 4 +- src/Platform_PSP.c | 10 +- src/Platform_PSVita.c | 8 +- src/Platform_Posix.c | 53 +- src/Platform_Saturn.c | 12 +- src/Platform_Switch.c | 12 +- src/Platform_Web.c | 9 +- src/Platform_WiiU.c | 14 +- src/Platform_Windows.c | 75 +- src/Platform_Xbox.c | 80 +- src/Platform_Xbox360.c | 4 +- src/Protocol.c | 100 +- src/Protocol.h | 1 + src/Queue.c | 72 ++ src/Queue.h | 22 + src/SSL.c | 4 +- src/Screens.c | 39 +- src/Server.c | 13 +- src/SystemFonts.c | 136 ++- src/TouchUI.c | 18 +- src/Vectors.c | 89 +- src/VirtualKeyboard.h | 6 +- src/Vorbis.c | 20 +- src/Widgets.c | 61 +- src/Widgets.h | 2 - src/Window.h | 4 +- src/Window_3DS.c | 6 +- src/Window_Android.c | 14 +- src/Window_BeOS.cpp | 742 +++++++++++++ src/Window_Dreamcast.c | 17 +- src/Window_GCWii.c | 14 +- src/Window_MacClassic.c | 469 ++++++++ src/Window_N64.c | 40 +- src/Window_NDS.c | 21 +- src/Window_PS1.c | 1 + src/Window_PS2.c | 1 + src/Window_PS3.c | 6 +- src/Window_PSP.c | 8 +- src/Window_PSVita.c | 11 +- src/Window_SDL.c | 39 +- src/Window_SDL3.c | 44 +- src/Window_Saturn.c | 104 +- src/Window_Switch.c | 8 +- src/Window_Terminal.c | 528 +++++++++ src/Window_Web.c | 29 +- src/Window_WiiU.cpp | 14 +- src/Window_Win.c | 79 +- src/Window_X11.c | 88 +- src/Window_Xbox.c | 10 +- src/Window_Xbox360.c | 17 +- src/Window_cocoa.m | 955 +++++++++++++++++ src/World.c | 17 +- src/World.h | 22 +- src/_D3D11Shaders.h | 449 -------- src/_GL1Funcs.h | 63 ++ src/_GLShared.h | 41 +- src/_GraphicsBase.h | 30 +- src/_HttpBase.h | 4 + src/_PlatformBase.h | 7 + src/_PlatformConsole.h | 5 +- src/_WindowBase.h | 8 +- src/interop_cocoa.m | 18 +- src/interop_ios.m | 144 +-- src/interop_web.js | 6 +- src/main.c | 10 +- 144 files changed, 7916 insertions(+), 2514 deletions(-) rename src/_CCIcon_X11.h => misc/linux/CCIcon_X11.h (100%) rename src/_CCIcon_mac.h => misc/macOS/CCIcon_mac.h (100%) create mode 100644 misc/sdl/CCIcon_SDL.h create mode 100644 misc/sdl/sdl_icon_gen.cs create mode 100644 src/FancyLighting.c create mode 100644 src/Platform_BeOS.cpp create mode 100644 src/Platform_MacClassic.c create mode 100644 src/Queue.c create mode 100644 src/Queue.h create mode 100644 src/Window_BeOS.cpp create mode 100644 src/Window_MacClassic.c create mode 100644 src/Window_Terminal.c create mode 100644 src/Window_cocoa.m delete mode 100644 src/_D3D11Shaders.h create mode 100644 src/_GL1Funcs.h diff --git a/src/_CCIcon_X11.h b/misc/linux/CCIcon_X11.h similarity index 100% rename from src/_CCIcon_X11.h rename to misc/linux/CCIcon_X11.h diff --git a/src/_CCIcon_mac.h b/misc/macOS/CCIcon_mac.h similarity index 100% rename from src/_CCIcon_mac.h rename to misc/macOS/CCIcon_mac.h diff --git a/misc/sdl/CCIcon_SDL.h b/misc/sdl/CCIcon_SDL.h new file mode 100644 index 0000000..aaf79e1 --- /dev/null +++ b/misc/sdl/CCIcon_SDL.h @@ -0,0 +1,71 @@ +/* Generated using misc/linux_icon_gen.cs */ + +static const unsigned CCIcon_Data[] = { +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB8000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFB5B5B5,0xFF373737,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAFAFAF,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB5B5B5,0xFF363636,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB8000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAFAFAF,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB5B5B5,0xFF373737,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB5B5B5,0xFF363636,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB8000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAFAFAF,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB5B5B5,0xFF373737,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB6B6B6,0xFF363636,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB8000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF313131,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB5B5B5,0xFF373737,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB5B5B5,0xFF373737,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF313131,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB5B5B5,0xFF373737,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAFAFAF,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB5B5B5,0xFF373737,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB5B5B5,0xFF363636,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x96000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAFAFAF,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB5B5B5,0xFF373737,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0x9B000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFB6B6B6,0xFF363636,0xFF000000,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF080808,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFF060606,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBEBEBE,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBEBEBE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBEBEBE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBDBDBD,0xFFBDBDBD,0xFFBFBFBF,0xFFD6D6D6,0xFFEBEBEB,0xFFF6F6F6,0xFFF5F5F5,0xFFEAEAEA,0xFFCFCFCF,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFCFCFC,0xFFEDEDED,0xFFE4E4E4,0xFFE7E7E7,0xFFF2F2F2,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBEBEBE,0xFFBDBDBD,0xFFBDBDBD,0xFFD4D4D4,0xFFF7F7F7,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFCFCFC,0xFFC2C2C2,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE7E7E7,0xFFC3C3C3,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC6C6C6,0xFFE1E1E1,0xFFFCFCFC,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC0C0C0,0xFFE9E9E9,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE1E1E1,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE4E4E4,0xFFBEBEBE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC6C6C6,0xFFEFEFEF,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBEBEBE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC2C2C2,0xFFF1F1F1,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFBFBFB,0xFFC3C3C3,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF5F5F5,0xFFBFBFBF,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBFBFBF,0xFFE6E6E6,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBEBEBE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC0C0C0,0xFFF1F1F1,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE0E0E0,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFD6D6D6,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBEBEBE,0xFFE5E5E5,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF2F2F2,0xFFD2D2D2,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFEAEAEA,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF4F4F4,0xFFE8E8E8,0xFFF2F2F2,0xFFFAFAFA,0xFFC2C2C2,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFDFDFD,0xFFC1C1C1,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBEBEBE,0xFFEDEDED,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBEBEBE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFD9D9D9,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF7F7F7,0xFFD0D0D0,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC4C4C4,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFEEEEEE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC9C9C9,0xFFE0E0E0,0xFFE0E0E0,0xFFCDCDCD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC3C3C3,0xFFF8F8F8,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC6C6C6,0xFFFCFCFC,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF4F4F4,0xFFC3C3C3,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE3E3E3,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFCDCDCD,0xFFFCFCFC,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE9E9E9,0xFFC1C1C1,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFD3D3D3,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE9E9E9,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFBFBFB,0xFFC6C6C6,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFDCDCDC,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBEBEBE,0xFFF3F3F3,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF0F0F0,0xFFC0C0C0,0xFFBDBDBD,0xFFBDBDBD,0xFFC4C4C4,0xFFFAFAFA,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFCACACA,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFD9D9D9,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFD7D7D7,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC9C9C9,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE7E7E7,0xFFBDBDBD,0xFFC5C5C5,0xFFF5F5F5,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE7E7E7,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF7F7F7,0xFFBEBEBE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFD7D7D7,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFD8D8D8,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFDADADA,0xFFF6F6F6,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC2C2C2,0xFFFCFCFC,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFDCDCDC,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFD8D8D8,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFDFDFDF,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFD7D7D7,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFC6C6C6,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFDDDDDD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE1E1E1,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFEBEBEB,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF6F6F6,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE3E3E3,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE0E0E0,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBFBFBF,0xFFFAFAFA,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE9E9E9,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFECECEC,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFDDDDDD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC8C8C8,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE1E1E1,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF9F9F9,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFD5D5D5,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFD2D2D2,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFDDDDDD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFC7C7C7,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC9C9C9,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFDCDCDC,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFDDDDDD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFDADADA,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBEBEBE,0xFFF9F9F9,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE0E0E0,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFDEDEDE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC2C2C2,0xFFC2C2C2,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF0F0F0,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE6E6E6,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE3E3E3,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE4E4E4,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE4E4E4,0xFFF3F3F3,0xFFC4C4C4,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFC8C8C8,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFCCCCCC,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE3E3E3,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF0F0F0,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFD1D1D1,0xFFFEFEFE,0xFFFEFEFE,0xFFF5F5F5,0xFFC6C6C6,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE5E5E5,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFEBEBEB,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE0E0E0,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFDFDFD,0xFFC5C5C5,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFCACACA,0xFFFAFAFA,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFD1D1D1,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFDFDFD,0xFFC6C6C6,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC5C5C5,0xFFFAFAFA,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFDBDBDB,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE7E7E7,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFD0D0D0,0xFFFAFAFA,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFECECEC,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF090909,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFEBEBEB,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFCCCCCC,0xFFFAFAFA,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFD0D0D0,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFE9E9E9,0xFFD3D3D3,0xFFD6D6D6,0xFFECECEC,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFAFAFA,0xFFC5C5C5,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF070707,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF080808,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFD4D4D4,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC7C7C7,0xFFEEEEEE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF0F0F0,0xFFFCFCFC,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC3C3C3,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFD2D2D2,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF060606,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0xBF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFBFBFB,0xFFC8C8C8,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC8C8C8,0xFFD3D3D3,0xFFCCCCCC,0xFFBEBEBE,0xFFE2E2E2,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFEEEEEE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFDADADA,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF282828,0xFF000000,0xFF000000,0xBF000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x96000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAFAFAF,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF6F6F6,0xFFC4C4C4,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC3C3C3,0xFFFCFCFC,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFD2D2D2,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFDFDFD,0xFFD9D9D9,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF292929,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0x9B000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF4F4F4,0xFFC6C6C6,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE0E0E0,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE9E9E9,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF7F7F7,0xFFCECECE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF282828,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAFAFAF,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFF8F8F8,0xFFCECECE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC2C2C2,0xFFFAFAFA,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC0C0C0,0xFFE7E7E7,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFF8F8F8,0xFFDDDDDD,0xFFC0C0C0,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF292929,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF313131,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFE3E3E3,0xFFC3C3C3,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFE8E8E8,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFC9C9C9,0xFFDCDCDC,0xFFE1E1E1,0xFFDCDCDC,0xFFCFCFCF,0xFFBFBFBF,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF292929,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFBFBFB,0xFFE4E4E4,0xFFD0D0D0,0xFFC4C4C4,0xFFC3C3C3,0xFFCFCFCF,0xFFEBEBEB,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF292929,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB8000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF313131,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF292929,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF282828,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB8000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAFAFAF,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF292929,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF282828,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB8000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAFAFAF,0xFFFDFDFD,0xFFFEFEFE,0xFFFEFEFE,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF292929,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAFAFAF,0xFFFDFDFD,0xFFFEFEFE,0xFFBDBDBD,0xFFBDBDBD,0xFF878787,0xFF292929,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF303030,0xFFAEAEAE,0xFF878787,0xFF292929,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xBF000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB9000000,0xFF000000,0xFF000000,0xFF000000,0xFF000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x39000000,0xB8000000,0xC0000000,0x40000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, +}; +static const int CCIcon_Width = 64; +static const int CCIcon_Height = 64; +static const int CCIcon_Pitch = 256; diff --git a/misc/sdl/sdl_icon_gen.cs b/misc/sdl/sdl_icon_gen.cs new file mode 100644 index 0000000..62696c4 --- /dev/null +++ b/misc/sdl/sdl_icon_gen.cs @@ -0,0 +1,40 @@ +using System.Drawing.Imaging; +using System.Drawing; +using System.IO; + +namespace test +{ + public static class Program + { + const string src = "CCicon.ico"; + const string dst = "CCIcon_SDL.h"; + + static void DumpIcon(StreamWriter sw, int width, int height) { + using (Icon icon = new Icon(src, width, height)) { + using (Bitmap bmp = icon.ToBitmap()) { + for (int y = 0; y < bmp.Height; y++) { + for (int x = 0; x < bmp.Width; x++) { + Color c = bmp.GetPixel(x, y); + int p = (c.A << 24) | (c.R << 16) | (c.G << 8) | c.B; + sw.Write("0x" + ((uint)p).ToString("X8") + ","); + } + sw.WriteLine(); + } + } + } + sw.WriteLine("static const int CCIcon_Width = {0};", width); + sw.WriteLine("static const int CCIcon_Height = {0};", height); + sw.WriteLine("static const int CCIcon_Pitch = {0};", width * 4); + } + + public static void Main(string[] args) { + using (StreamWriter sw = new StreamWriter(dst)) { + sw.WriteLine("/* Generated using misc/sdl/sdl_icon_gen.cs */"); + sw.WriteLine(""); + sw.WriteLine("static const unsigned CCIcon_Data[] = {"); + DumpIcon(sw, 64, 64); + sw.WriteLine("};"); + } + } + } +} diff --git a/src/Audio.c b/src/Audio.c index 341264a..6b2e7fa 100644 --- a/src/Audio.c +++ b/src/Audio.c @@ -522,7 +522,7 @@ static void Music_Init(void) { /* music is delayed between 2 - 7 minutes by default */ music_minDelay = Options_GetInt(OPT_MIN_MUSIC_DELAY, 0, 3600, 120) * MILLIS_PER_SEC; music_maxDelay = Options_GetInt(OPT_MAX_MUSIC_DELAY, 0, 3600, 420) * MILLIS_PER_SEC; - music_waitable = Waitable_Create(); + music_waitable = Waitable_Create("Music sleep"); volume = Options_GetInt(OPT_MUSIC_VOLUME, 0, 100, DEFAULT_MUSIC_VOLUME); Audio_SetMusic(volume); diff --git a/src/AudioBackend.c b/src/AudioBackend.c index fafe33c..6d1d0c5 100644 --- a/src/AudioBackend.c +++ b/src/AudioBackend.c @@ -941,7 +941,7 @@ cc_bool AudioBackend_Init(void) { if (switchAudio) return true; switchAudio = true; - if (!audrv_mutex) audrv_mutex = Mutex_Create(); + if (!audrv_mutex) audrv_mutex = Mutex_Create("Audio sync"); Mem_Set(audioPools, 0, sizeof(audioPools)); diff --git a/src/Block.c b/src/Block.c index 9a974f0..42d0983 100644 --- a/src/Block.c +++ b/src/Block.c @@ -7,6 +7,7 @@ #include "Inventory.h" #include "Event.h" #include "Picking.h" +#include "Lighting.h" struct _BlockLists Blocks; @@ -22,11 +23,16 @@ const char* const Sound_Names[SOUND_COUNT] = { #define FOG_WATER PackedCol_Make( 5, 5, 51, 255) #define FOG_LAVA PackedCol_Make(153, 25, 0, 255) +/* Brightness */ +#define BRIT_NONE 0 +#define BRIT_FULL FANCY_LIGHTING_MAX_LEVEL +#define BRIT_MAGM 10 + struct SimpleBlockDef { const char* name; cc_uint8 topTexture, sideTexture, bottomTexture, height; PackedCol fogColor; cc_uint8 fogDensity; - cc_bool fullBright, blocksLight; cc_uint8 gravity; + cc_uint8 brightness, blocksLight; cc_uint8 gravity; cc_uint8 draw, collide, digSound, stepSound; }; static const struct SimpleBlockDef invalid_blockDef = { @@ -35,82 +41,82 @@ static const struct SimpleBlockDef invalid_blockDef = { /* Properties for all built-in blocks (Classic and CPE blocks) */ static const struct SimpleBlockDef core_blockDefs[] = { -/*NAME TOP SID BOT HEI FOG_COLOR DENS FULL BLOCKS GRAV DRAW_MODE COLLIDE_MODE DIG_SOUND STEP_SOUND */ -{ "Air", 0, 0, 0, 16, FOG_NONE , 0, false, false, 100, DRAW_GAS, COLLIDE_NONE, SOUND_NONE, SOUND_NONE }, -{ "Stone", 1, 1, 1, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Grass", 0, 3, 2, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_GRASS, SOUND_GRASS }, -{ "Dirt", 2, 2, 2, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_GRAVEL, SOUND_GRAVEL }, -{ "Cobblestone", 16, 16, 16, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Wood", 4, 4, 4, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_WOOD, SOUND_WOOD }, -{ "Sapling", 15, 15, 15, 16, FOG_NONE , 0, false, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_GRASS, SOUND_NONE }, -{ "Bedrock", 17, 17, 17, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, - -{ "Water", 14, 14, 14, 16, FOG_WATER, 10, false, true, 100, DRAW_TRANSLUCENT, COLLIDE_WATER, SOUND_NONE, SOUND_NONE }, -{ "Still water", 14, 14, 14, 16, FOG_WATER, 10, false, true, 100, DRAW_TRANSLUCENT, COLLIDE_WATER, SOUND_NONE, SOUND_NONE }, -{ "Lava", 30, 30, 30, 16, FOG_LAVA , 180, true, true, 100, DRAW_OPAQUE, COLLIDE_LAVA, SOUND_NONE, SOUND_NONE }, -{ "Still lava", 30, 30, 30, 16, FOG_LAVA , 180, true, true, 100, DRAW_OPAQUE, COLLIDE_LAVA, SOUND_NONE, SOUND_NONE }, -{ "Sand", 18, 18, 18, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_SAND, SOUND_SAND }, -{ "Gravel", 19, 19, 19, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_GRAVEL, SOUND_GRAVEL }, -{ "Gold ore", 32, 32, 32, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Iron ore", 33, 33, 33, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, - -{ "Coal ore", 34, 34, 34, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Log", 21, 20, 21, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_WOOD, SOUND_WOOD }, -{ "Leaves", 22, 22, 22, 16, FOG_NONE , 0, false, false, 40, DRAW_TRANSPARENT_THICK, COLLIDE_SOLID, SOUND_GRASS, SOUND_GRASS }, -{ "Sponge", 48, 48, 48, 16, FOG_NONE , 0, false, true, 90, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_GRASS, SOUND_GRASS }, -{ "Glass", 49, 49, 49, 16, FOG_NONE , 0, false, false, 100, DRAW_TRANSPARENT, COLLIDE_SOLID, SOUND_GLASS,SOUND_STONE}, -{ "Red", 64, 64, 64, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Orange", 65, 65, 65, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Yellow", 66, 66, 66, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +/*NAME TOP SID BOT HEI FOG_COLOR DENS BRIT BLOCKS GRAV DRAW_MODE COLLIDE_MODE DIG_SOUND STEP_SOUND */ +{ "Air", 0, 0, 0, 16, FOG_NONE , 0, BRIT_NONE, false, 100, DRAW_GAS, COLLIDE_NONE, SOUND_NONE, SOUND_NONE }, +{ "Stone", 1, 1, 1, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Grass", 0, 3, 2, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_GRASS, SOUND_GRASS }, +{ "Dirt", 2, 2, 2, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_GRAVEL, SOUND_GRAVEL }, +{ "Cobblestone", 16, 16, 16, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Wood", 4, 4, 4, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_WOOD, SOUND_WOOD }, +{ "Sapling", 15, 15, 15, 16, FOG_NONE , 0, BRIT_NONE, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_GRASS, SOUND_NONE }, +{ "Bedrock", 17, 17, 17, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, + +{ "Water", 14, 14, 14, 16, FOG_WATER, 10, BRIT_NONE, true, 100, DRAW_TRANSLUCENT, COLLIDE_WATER, SOUND_NONE, SOUND_NONE }, +{ "Still water", 14, 14, 14, 16, FOG_WATER, 10, BRIT_NONE, true, 100, DRAW_TRANSLUCENT, COLLIDE_WATER, SOUND_NONE, SOUND_NONE }, +{ "Lava", 30, 30, 30, 16, FOG_LAVA , 180, BRIT_FULL, true, 100, DRAW_OPAQUE, COLLIDE_LAVA, SOUND_NONE, SOUND_NONE }, +{ "Still lava", 30, 30, 30, 16, FOG_LAVA , 180, BRIT_FULL, true, 100, DRAW_OPAQUE, COLLIDE_LAVA, SOUND_NONE, SOUND_NONE }, +{ "Sand", 18, 18, 18, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_SAND, SOUND_SAND }, +{ "Gravel", 19, 19, 19, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_GRAVEL, SOUND_GRAVEL }, +{ "Gold ore", 32, 32, 32, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Iron ore", 33, 33, 33, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, + +{ "Coal ore", 34, 34, 34, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Log", 21, 20, 21, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_WOOD, SOUND_WOOD }, +{ "Leaves", 22, 22, 22, 16, FOG_NONE , 0, BRIT_NONE, false, 40, DRAW_TRANSPARENT_THICK, COLLIDE_SOLID, SOUND_GRASS, SOUND_GRASS }, +{ "Sponge", 48, 48, 48, 16, FOG_NONE , 0, BRIT_NONE, true, 90, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_GRASS, SOUND_GRASS }, +{ "Glass", 49, 49, 49, 16, FOG_NONE , 0, BRIT_NONE, false, 100, DRAW_TRANSPARENT, COLLIDE_SOLID, SOUND_GLASS,SOUND_STONE}, +{ "Red", 64, 64, 64, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Orange", 65, 65, 65, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Yellow", 66, 66, 66, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Lime", 67, 67, 67, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Green", 68, 68, 68, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Teal", 69, 69, 69, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Aqua", 70, 70, 70, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Cyan", 71, 71, 71, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Blue", 72, 72, 72, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Indigo", 73, 73, 73, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Violet", 74, 74, 74, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, - -{ "Magenta", 75, 75, 75, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Pink", 76, 76, 76, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Black", 77, 77, 77, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Gray", 78, 78, 78, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "White", 79, 79, 79, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Dandelion", 13, 13, 13, 16, FOG_NONE , 0, false, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_GRASS, SOUND_NONE }, -{ "Rose", 12, 12, 12, 16, FOG_NONE , 0, false, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_GRASS, SOUND_NONE }, -{ "Brown mushroom", 29, 29, 29, 16, FOG_NONE , 0, false, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_GRASS, SOUND_NONE }, - -{ "Red mushroom", 28, 28, 28, 16, FOG_NONE , 0, false, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_GRASS, SOUND_NONE }, -{ "Gold", 24, 40, 56, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_METAL, SOUND_METAL }, -{ "Iron", 23, 39, 55, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_METAL, SOUND_METAL }, -{ "Double slab", 6, 5, 6, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Slab", 6, 5, 6, 8, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Brick", 7, 7, 7, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "TNT", 9, 8, 10, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_GRASS, SOUND_GRASS }, -{ "Bookshelf", 4, 35, 4, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_WOOD, SOUND_WOOD }, - -{ "Mossy rocks", 36, 36, 36, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Obsidian", 37, 37, 37, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Cobblestone slab", 16, 16, 16, 8, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Rope", 11, 11, 11, 16, FOG_NONE , 0, false, false, 100, DRAW_SPRITE, COLLIDE_CLIMB, SOUND_CLOTH, SOUND_CLOTH }, -{ "Sandstone", 25, 41, 57, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Snow", 50, 50, 50, 4, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_NONE, SOUND_SNOW, SOUND_SNOW }, -{ "Fire", 38, 38, 38, 16, FOG_NONE , 0, true, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_WOOD, SOUND_NONE }, -{ "Light pink", 80, 80, 80, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, - -{ "Forest green", 81, 81, 81, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Brown", 82, 82, 82, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Deep blue", 83, 83, 83, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Turquoise", 84, 84, 84, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, -{ "Ice", 51, 51, 51, 16, FOG_NONE , 0, false, true, 100, DRAW_TRANSLUCENT, COLLIDE_ICE, SOUND_STONE, SOUND_STONE }, -{ "Ceramic tile", 54, 54, 54, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Magma", 86, 86, 86, 16, FOG_NONE , 0, true, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, -{ "Pillar", 26, 42, 58, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, - -{ "Crate", 53, 53, 53, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_WOOD, SOUND_WOOD }, -{ "Stone brick", 52, 52, 52, 16, FOG_NONE , 0, false, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE } -/*NAME TOP SID BOT HEI FOG_COLOR DENS FULL BLOCKS GRAV DRAW_MODE COLLIDE_MODE DIG_SOUND STEP_SOUND */ +{ "Lime", 67, 67, 67, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Green", 68, 68, 68, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Teal", 69, 69, 69, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Aqua", 70, 70, 70, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Cyan", 71, 71, 71, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Blue", 72, 72, 72, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Indigo", 73, 73, 73, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Violet", 74, 74, 74, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, + +{ "Magenta", 75, 75, 75, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Pink", 76, 76, 76, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Black", 77, 77, 77, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Gray", 78, 78, 78, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "White", 79, 79, 79, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Dandelion", 13, 13, 13, 16, FOG_NONE , 0, BRIT_NONE, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_GRASS, SOUND_NONE }, +{ "Rose", 12, 12, 12, 16, FOG_NONE , 0, BRIT_NONE, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_GRASS, SOUND_NONE }, +{ "Brown mushroom", 29, 29, 29, 16, FOG_NONE , 0, BRIT_NONE, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_GRASS, SOUND_NONE }, + +{ "Red mushroom", 28, 28, 28, 16, FOG_NONE , 0, BRIT_NONE, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_GRASS, SOUND_NONE }, +{ "Gold", 24, 40, 56, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_METAL, SOUND_METAL }, +{ "Iron", 23, 39, 55, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_METAL, SOUND_METAL }, +{ "Double slab", 6, 5, 6, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Slab", 6, 5, 6, 8, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Brick", 7, 7, 7, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "TNT", 9, 8, 10, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_GRASS, SOUND_GRASS }, +{ "Bookshelf", 4, 35, 4, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_WOOD, SOUND_WOOD }, + +{ "Mossy rocks", 36, 36, 36, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Obsidian", 37, 37, 37, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Cobblestone slab", 16, 16, 16, 8, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Rope", 11, 11, 11, 16, FOG_NONE , 0, BRIT_NONE, false, 100, DRAW_SPRITE, COLLIDE_CLIMB, SOUND_CLOTH, SOUND_CLOTH }, +{ "Sandstone", 25, 41, 57, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Snow", 50, 50, 50, 4, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_NONE, SOUND_SNOW, SOUND_SNOW }, +{ "Fire", 38, 38, 38, 16, FOG_NONE , 0, BRIT_FULL, false, 100, DRAW_SPRITE, COLLIDE_NONE, SOUND_WOOD, SOUND_NONE }, +{ "Light pink", 80, 80, 80, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, + +{ "Forest green", 81, 81, 81, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Brown", 82, 82, 82, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Deep blue", 83, 83, 83, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Turquoise", 84, 84, 84, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_CLOTH, SOUND_CLOTH }, +{ "Ice", 51, 51, 51, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_TRANSLUCENT, COLLIDE_ICE, SOUND_STONE, SOUND_STONE }, +{ "Ceramic tile", 54, 54, 54, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Magma", 86, 86, 86, 16, FOG_NONE , 0, BRIT_MAGM, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, +{ "Pillar", 26, 42, 58, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE }, + +{ "Crate", 53, 53, 53, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_WOOD, SOUND_WOOD }, +{ "Stone brick", 52, 52, 52, 16, FOG_NONE , 0, BRIT_NONE, true, 100, DRAW_OPAQUE, COLLIDE_SOLID, SOUND_STONE, SOUND_STONE } +/*NAME TOP SID BOT HEI FOG_COLOR DENS BRIT BLOCKS GRAV DRAW_MODE COLLIDE_MODE DIG_SOUND STEP_SOUND */ }; /* Returns a backwards compatible collide type of a block */ @@ -469,7 +475,7 @@ void Block_ResetProps(BlockID block) { const cc_string name = String_FromReadonly(def->name); Blocks.BlocksLight[block] = def->blocksLight; - Blocks.FullBright[block] = def->fullBright; + Blocks.Brightness[block] = def->brightness; Blocks.FogCol[block] = def->fogColor; Blocks.FogDensity[block] = def->fogDensity / 100.0f; Block_SetCollide(block, def->collide); @@ -526,6 +532,49 @@ int Block_Parse(const cc_string* name) { return Block_FindID(name); } +/* 0b_1000_0000 */ +#define USE_MODERN_BRIGHTNESS_FLAG 1 << 7 +/* 0b_0100_0000 */ +#define USE_LAMP_COLOR 1 << 6 +/* 0b_0000_1111 */ +#define BRIGHTNESS_MASK FANCY_LIGHTING_MAX_LEVEL + +/* Reads network format 0b_US--_LLLL where U = uses fancy brightness, S = uses lamp brightness, and L = brightness */ +/* Into CC's native format 0b_SSSS_BBBB where S = lamp brightness and B = lava brightness */ +cc_uint8 Block_ReadBrightness(cc_uint8 fullBright) { + cc_bool useSun; + /* If the fullBright byte does not use the flag, we should interpret it as either completely dark or casting max block light */ + if ((fullBright & USE_MODERN_BRIGHTNESS_FLAG) == 0) { return fullBright > 0 ? FANCY_LIGHTING_MAX_LEVEL : 0; } + + useSun = fullBright & USE_LAMP_COLOR; + + /* Preserve only the least significant four bits. This gives us our raw brightness level for sun or block light. */ + fullBright &= BRIGHTNESS_MASK; + + /* Sun light is stored in the upper four bits */ + if (useSun) { fullBright <<= FANCY_LIGHTING_LAMP_SHIFT; } + return fullBright; +} + +/* Writes CC's native format 0b_SSSS_BBBB where S = lamp brightness and B = lava brightness */ +/* into network format 0b_US--_LLLL where U = uses fancy brightness, S = uses lamp brightness, and L = brightness */ +cc_uint8 Block_WriteFullBright(cc_uint8 brightness) { + cc_uint8 lavaBrightness, lampBrightness, fullBright; + lavaBrightness = brightness & BRIGHTNESS_MASK; + lampBrightness = brightness >> FANCY_LIGHTING_LAMP_SHIFT; + fullBright = USE_MODERN_BRIGHTNESS_FLAG; + + /* Modern brightness stored in a fullbright value is mutually exclusive between using block and using sun light */ + if (lavaBrightness > 0) { + fullBright |= lavaBrightness; + } else if (lampBrightness > 0) { + fullBright |= USE_LAMP_COLOR; /* Insert flag that tells us this fullbright value should be interpreted as sun brightness */ + fullBright |= lampBrightness; + } else { + return 0; + } + return fullBright; +} /*########################################################################################################################* *-------------------------------------------------------AutoRotate--------------------------------------------------------* diff --git a/src/Block.h b/src/Block.h index 78aaf8d..370e441 100644 --- a/src/Block.h +++ b/src/Block.h @@ -46,7 +46,7 @@ CC_VAR extern struct _BlockLists { /* Whether this block prevents lights from passing through it. */ cc_bool BlocksLight[BLOCK_COUNT]; /* Whether this block is fully bright/light emitting. (Like lava) */ - cc_bool FullBright[BLOCK_COUNT]; + cc_uint8 Brightness[BLOCK_COUNT]; /* Fog colour when player is inside this block. */ /* NOTE: Only applies if fog density is not 0. */ PackedCol FogCol[BLOCK_COUNT]; @@ -112,6 +112,8 @@ if (Blocks.Tinted[block]) col = PackedCol_Tint(col, Blocks.FogCol[block]); /* The difference can be seen by placing a lower and upper slab block on a wall, */ /* and comparing whether the block directly behind them is in shadow or not */ #define LIGHT_FLAG_SHADES_FROM_BELOW 6 +cc_uint8 Block_ReadBrightness(cc_uint8 fullBright); +cc_uint8 Block_WriteFullBright(cc_uint8 brightness); /* Returns whether the given block has been changed from default */ cc_bool Block_IsCustomDefined(BlockID block); diff --git a/src/BlockPhysics.c b/src/BlockPhysics.c index bedeef7..b1f5966 100644 --- a/src/BlockPhysics.c +++ b/src/BlockPhysics.c @@ -552,6 +552,7 @@ void Physics_Init(void) { Physics.OnRandomTick[BLOCK_STILL_LAVA] = Physics_ActivateLava; Physics.OnPlace[BLOCK_SLAB] = Physics_HandleSlab; + if (Game_ClassicMode) return; Physics.OnPlace[BLOCK_COBBLE_SLAB] = Physics_HandleCobblestoneSlab; Physics.OnPlace[BLOCK_TNT] = Physics_HandleTnt; } diff --git a/src/Builder.c b/src/Builder.c index 672b47d..85940ce 100644 --- a/src/Builder.c +++ b/src/Builder.c @@ -183,7 +183,7 @@ static void PrepareChunk(int x1, int y1, int z1) { if (Blocks.Draw[b] == DRAW_SPRITE) { AddSpriteVertices(b); continue; } Builder_X = x; Builder_Y = y; Builder_Z = z; - Builder_FullBright = Blocks.FullBright[b]; + Builder_FullBright = Blocks.Brightness[b]; tileIdx = b * BLOCK_COUNT; /* All of these function calls are inlined as they can be called tens of millions to hundreds of millions of times. */ @@ -360,9 +360,16 @@ static void OutputChunkPartsMeta(int x, int y, int z, struct ChunkInfo* info) { } void Builder_MakeChunk(struct ChunkInfo* info) { +#ifdef CC_BUILD_SATURN + /* The Saturn build only has 16 kb stack, not large enough */ + static BlockID chunk[EXTCHUNK_SIZE_3]; + static cc_uint8 counts[CHUNK_SIZE_3 * FACE_COUNT]; + static int bitFlags[1]; +#else BlockID chunk[EXTCHUNK_SIZE_3]; cc_uint8 counts[CHUNK_SIZE_3 * FACE_COUNT]; int bitFlags[EXTCHUNK_SIZE_3]; +#endif cc_bool allAir, allSolid, onBorder; int xMax, yMax, zMax, totalVerts; @@ -389,7 +396,7 @@ void Builder_MakeChunk(struct ChunkInfo* info) { info->allAir = allAir; if (allAir || allSolid) return; - Lighting.LightHint(x1 - 1, z1 - 1); + Lighting.LightHint(x1 - 1, y1 - 1, z1 - 1); Mem_Set(counts, 1, CHUNK_SIZE_3 * FACE_COUNT); xMax = min(World.Width, x1 + CHUNK_SIZE); @@ -510,7 +517,7 @@ static void Builder_DrawSprite(int x, int y, int z) { if (offsetType == 7) { y1 -= valY; y2 -= valY; } } - bright = Blocks.FullBright[Builder_Block]; + bright = Blocks.Brightness[Builder_Block]; part = &Builder_Parts[Atlas1D_Index(loc)]; color = bright ? PACKEDCOL_WHITE : Lighting.Color_Sprite_Fast(x, y, z); Block_Tint(color, Builder_Block); @@ -666,7 +673,7 @@ static void NormalBuilder_RenderBlock(int index, int x, int y, int z) { if (!count_XMin && !count_XMax && !count_ZMin && !count_ZMax && !count_YMin && !count_YMax) return; - fullBright = Blocks.FullBright[Builder_Block]; + fullBright = Blocks.Brightness[Builder_Block]; baseOffset = (Blocks.Draw[Builder_Block] == DRAW_TRANSLUCENT) * ATLAS1D_MAX_ATLASES; lightFlags = Blocks.LightOffset[Builder_Block]; @@ -761,6 +768,7 @@ static void NormalBuilder_SetActive(void) { /*########################################################################################################################* *-------------------------------------------------Advanced mesh builder---------------------------------------------------* *#########################################################################################################################*/ +#ifdef CC_BUILD_ADVLIGHTING static Vec3 adv_minBB, adv_maxBB; static int adv_initBitFlags, adv_baseOffset; static int* adv_bitFlags; @@ -820,9 +828,9 @@ static int Adv_Lit(int x, int y, int z, int cIndex) { flags |= Lighting.IsLit_Fast(x, (y + 1) - offset, z) ? LIT_P1 : 0; /* If a block is fullbright, it should also look as if that spot is lit */ - if (Blocks.FullBright[Builder_Chunk[cIndex - 324]]) flags |= LIT_M1; - if (Blocks.FullBright[block]) flags |= LIT_CC; - if (Blocks.FullBright[Builder_Chunk[cIndex + 324]]) flags |= LIT_P1; + if (Blocks.Brightness[Builder_Chunk[cIndex - 324]]) flags |= LIT_M1; + if (Blocks.Brightness[block]) flags |= LIT_CC; + if (Blocks.Brightness[Builder_Chunk[cIndex + 324]]) flags |= LIT_P1; return flags; } @@ -1219,7 +1227,7 @@ static void Adv_RenderBlock(int index, int x, int y, int z) { if (!count_XMin && !count_XMax && !count_ZMin && !count_ZMax && !count_YMin && !count_YMax) return; - Builder_FullBright = Blocks.FullBright[Builder_Block]; + Builder_FullBright = Blocks.Brightness[Builder_Block]; adv_baseOffset = (Blocks.Draw[Builder_Block] == DRAW_TRANSLUCENT) * ATLAS1D_MAX_ATLASES; adv_tinted = Blocks.Tinted[Builder_Block]; @@ -1259,7 +1267,357 @@ static void AdvBuilder_SetActive(void) { Builder_RenderBlock = Adv_RenderBlock; Builder_PrePrepareChunk = Adv_PrePrepareChunk; } +#else +static void AdvBuilder_SetActive(void) { NormalBuilder_SetActive(); } +#endif + + + +/*########################################################################################################################* +*-------------------------------------------------Modern mesh builder-----------------------------------------------------* +*#########################################################################################################################*/ +#ifdef CC_BUILD_ADVLIGHTING +/* Fast color averaging wizardy from https://stackoverflow.com/questions/8440631/how-would-you-average-two-32-bit-colors-packed-into-an-integer */ +#define AVERAGE(a, b) ( ((((a) ^ (b)) & 0xfefefefe) >> 1) + ((a) & (b)) ) + +static cc_bool Modern_IsOccluded(int x, int y, int z) { + BlockID block = World_SafeGetBlock(x, y, z); + if (Blocks.Brightness[block] > 0) { return false; } + /* If the block we're pulling colors from is solid, return a darker version of original and increment how many are like this */ + if (Blocks.FullOpaque[block] || (Blocks.Draw[block] == DRAW_TRANSPARENT && Blocks.BlocksLight[block] && Blocks.LightOffset[block] == 0xFF)) { + return true; + } + return false; +} + +static cc_bool Modern_CanStretch(BlockID initial, int chunkIndex, int x, int y, int z, Face face) { + return false; +} + +static int Modern_StretchXLiquid(int countIndex, int x, int y, int z, int chunkIndex, BlockID block) { + int count = 1; + if (Builder_OccludedLiquid(chunkIndex)) return 0; + AddVertices(block, FACE_YMAX); + return count; +} + +static int Modern_StretchX(int countIndex, int x, int y, int z, int chunkIndex, BlockID block, Face face) { + int count = 1; + AddVertices(block, face); + return count; +} + +static int Modern_StretchZ(int countIndex, int x, int y, int z, int chunkIndex, BlockID block, Face face) { + int count = 1; + AddVertices(block, face); + return count; +} + +static PackedCol Modern_GetColorX(PackedCol orig, int x, int y, int z, int oY, int oZ) { + cc_bool xOccluded = Modern_IsOccluded(x, y + oY, z ); + cc_bool zOccluded = Modern_IsOccluded(x, y , z + oZ); + cc_bool xzOccluded = Modern_IsOccluded(x, y + oY, z + oZ); + + PackedCol CoX = xOccluded ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color_XSide_Fast(x, y + oY, z ); + PackedCol CoZ = zOccluded ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color_XSide_Fast(x, y , z + oZ); + PackedCol CoXoZ = (xzOccluded || (xOccluded && zOccluded)) ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color_XSide_Fast(x, y + oY, z + oZ); + + PackedCol ab = AVERAGE(CoX, CoZ); + PackedCol cd = AVERAGE(CoXoZ, orig); + return AVERAGE(ab, cd); +} +static void Modern_DrawXMin(int count, int x, int y, int z) { + TextureLoc texLoc = Block_Tex(Builder_Block, FACE_XMIN); + float vOrigin = Atlas1D_RowId(texLoc) * Atlas1D.InvTileSize; + + float u1 = adv_minBB.z, u2 = (count - 1) + adv_maxBB.z * UV2_Scale; + float v1 = vOrigin + adv_maxBB.y * Atlas1D.InvTileSize; + float v2 = vOrigin + adv_minBB.y * Atlas1D.InvTileSize * UV2_Scale; + struct Builder1DPart* part = &Builder_Parts[adv_baseOffset + Atlas1D_Index(texLoc)]; + + PackedCol tint, white = PACKEDCOL_WHITE; + int offset = 1;// (Blocks.LightOffset[Builder_Block] >> FACE_XMIN) & 1; + PackedCol orig = Lighting.Color_XSide_Fast(x-offset, y, z); + PackedCol col0_0 = Builder_FullBright ? white : Modern_GetColorX(orig, x-offset, y, z, -1, -1); + PackedCol col1_0 = Builder_FullBright ? white : Modern_GetColorX(orig, x-offset, y, z, 1, -1); + PackedCol col1_1 = Builder_FullBright ? white : Modern_GetColorX(orig, x-offset, y, z, 1, 1); + PackedCol col0_1 = Builder_FullBright ? white : Modern_GetColorX(orig, x-offset, y, z, -1, 1); + struct VertexTextured* vertices, v; + + if (adv_tinted) { + tint = Blocks.FogCol[Builder_Block]; + col0_0 = PackedCol_Tint(col0_0, tint); col1_0 = PackedCol_Tint(col1_0, tint); + col1_1 = PackedCol_Tint(col1_1, tint); col0_1 = PackedCol_Tint(col0_1, tint); + } + + vertices = part->faces.vertices[FACE_XMIN]; + v.x = adv_x1; + v.y = adv_y2; v.z = adv_z2 + (count - 1); v.U = u2; v.V = v1; v.Col = col1_1; *vertices++ = v; + v.z = adv_z1; v.U = u1; v.Col = col1_0; *vertices++ = v; + v.y = adv_y1; v.V = v2; v.Col = col0_0; *vertices++ = v; + v.z = adv_z2 + (count - 1); v.U = u2; v.Col = col0_1; *vertices++ = v; + part->faces.vertices[FACE_XMIN] = vertices; +} + +static void Modern_DrawXMax(int count, int x, int y, int z) { + TextureLoc texLoc = Block_Tex(Builder_Block, FACE_XMAX); + float vOrigin = Atlas1D_RowId(texLoc) * Atlas1D.InvTileSize; + + float u1 = (count - adv_minBB.z), u2 = (1 - adv_maxBB.z) * UV2_Scale; + float v1 = vOrigin + adv_maxBB.y * Atlas1D.InvTileSize; + float v2 = vOrigin + adv_minBB.y * Atlas1D.InvTileSize * UV2_Scale; + struct Builder1DPart* part = &Builder_Parts[adv_baseOffset + Atlas1D_Index(texLoc)]; + + PackedCol tint, white = PACKEDCOL_WHITE; + int offset = 1;// (Blocks.LightOffset[Builder_Block] >> FACE_XMAX) & 1; + PackedCol orig = Lighting.Color_XSide_Fast(x+offset, y, z); + PackedCol col0_0 = Builder_FullBright ? white : Modern_GetColorX(orig, x+offset, y, z, -1, -1); + PackedCol col1_0 = Builder_FullBright ? white : Modern_GetColorX(orig, x+offset, y, z, 1, -1); + PackedCol col1_1 = Builder_FullBright ? white : Modern_GetColorX(orig, x+offset, y, z, 1, 1); + PackedCol col0_1 = Builder_FullBright ? white : Modern_GetColorX(orig, x+offset, y, z, -1, 1); + struct VertexTextured* vertices, v; + + if (adv_tinted) { + tint = Blocks.FogCol[Builder_Block]; + col0_0 = PackedCol_Tint(col0_0, tint); col1_0 = PackedCol_Tint(col1_0, tint); + col1_1 = PackedCol_Tint(col1_1, tint); col0_1 = PackedCol_Tint(col0_1, tint); + } + + vertices = part->faces.vertices[FACE_XMAX]; + v.x = adv_x2; + v.y = adv_y2; v.z = adv_z2 + (count - 1); v.U = u2; v.V = v1; v.Col = col1_1; *vertices++ = v; + v.y = adv_y1; v.V = v2; v.Col = col0_1; *vertices++ = v; + v.z = adv_z1; v.U = u1; v.Col = col0_0; *vertices++ = v; + v.y = adv_y2; v.V = v1; v.Col = col1_0; *vertices++ = v; + part->faces.vertices[FACE_XMAX] = vertices; +} + +static PackedCol Modern_GetColorZ(PackedCol orig, int x, int y, int z, int oX, int oY) { + cc_bool xOccluded = Modern_IsOccluded(x + oX, y , z); + cc_bool zOccluded = Modern_IsOccluded(x, y + oY, z); + cc_bool xzOccluded = Modern_IsOccluded(x + oX, y + oY, z); + + PackedCol CoX = xOccluded ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color_ZSide_Fast(x + oX, y , z); + PackedCol CoZ = zOccluded ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color_ZSide_Fast(x , y + oY, z); + PackedCol CoXoZ = (xzOccluded || (xOccluded && zOccluded)) ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color_ZSide_Fast(x + oX, y + oY, z); + + PackedCol ab = AVERAGE(CoX, CoZ); + PackedCol cd = AVERAGE(CoXoZ, orig); + return AVERAGE(ab, cd); +} +static void Modern_DrawZMin(int count, int x, int y, int z) { + TextureLoc texLoc = Block_Tex(Builder_Block, FACE_ZMIN); + float vOrigin = Atlas1D_RowId(texLoc) * Atlas1D.InvTileSize; + + float u1 = (count - adv_minBB.x), u2 = (1 - adv_maxBB.x) * UV2_Scale; + float v1 = vOrigin + adv_maxBB.y * Atlas1D.InvTileSize; + float v2 = vOrigin + adv_minBB.y * Atlas1D.InvTileSize * UV2_Scale; + struct Builder1DPart* part = &Builder_Parts[adv_baseOffset + Atlas1D_Index(texLoc)]; + + PackedCol tint, white = PACKEDCOL_WHITE; + int offset = 1;// (Blocks.LightOffset[Builder_Block] >> FACE_ZMIN) & 1; + PackedCol orig = Lighting.Color_ZSide_Fast(x, y, z-offset); + PackedCol col0_0 = Builder_FullBright ? white : Modern_GetColorZ(orig, x, y, z-offset, -1, -1); + PackedCol col1_0 = Builder_FullBright ? white : Modern_GetColorZ(orig, x, y, z-offset, 1, -1); + PackedCol col1_1 = Builder_FullBright ? white : Modern_GetColorZ(orig, x, y, z-offset, 1, 1); + PackedCol col0_1 = Builder_FullBright ? white : Modern_GetColorZ(orig, x, y, z-offset, -1, 1); + struct VertexTextured* vertices, v; + + if (adv_tinted) { + tint = Blocks.FogCol[Builder_Block]; + col0_0 = PackedCol_Tint(col0_0, tint); col1_0 = PackedCol_Tint(col1_0, tint); + col1_1 = PackedCol_Tint(col1_1, tint); col0_1 = PackedCol_Tint(col0_1, tint); + } + + vertices = part->faces.vertices[FACE_ZMIN]; + v.z = adv_z1; + v.x = adv_x1; v.y = adv_y1; v.U = u1; v.V = v2; v.Col = col0_0; *vertices++ = v; + v.y = adv_y2; v.V = v1; v.Col = col0_1; *vertices++ = v; + v.x = adv_x2 + (count - 1); v.U = u2; v.Col = col1_1; *vertices++ = v; + v.y = adv_y1; v.V = v2; v.Col = col1_0; *vertices++ = v; + part->faces.vertices[FACE_ZMIN] = vertices; +} + +static void Modern_DrawZMax(int count, int x, int y, int z) { + TextureLoc texLoc = Block_Tex(Builder_Block, FACE_ZMAX); + float vOrigin = Atlas1D_RowId(texLoc) * Atlas1D.InvTileSize; + + float u1 = adv_minBB.x, u2 = (count - 1) + adv_maxBB.x * UV2_Scale; + float v1 = vOrigin + adv_maxBB.y * Atlas1D.InvTileSize; + float v2 = vOrigin + adv_minBB.y * Atlas1D.InvTileSize * UV2_Scale; + struct Builder1DPart* part = &Builder_Parts[adv_baseOffset + Atlas1D_Index(texLoc)]; + + PackedCol tint, white = PACKEDCOL_WHITE; + int offset = 1;// (Blocks.LightOffset[Builder_Block] >> FACE_ZMAX) & 1; + PackedCol orig = Lighting.Color_ZSide_Fast(x, y, z+offset); + PackedCol col0_0 = Builder_FullBright ? white : Modern_GetColorZ(orig, x, y, z+offset, -1, -1); + PackedCol col1_0 = Builder_FullBright ? white : Modern_GetColorZ(orig, x, y, z+offset, 1, -1); + PackedCol col1_1 = Builder_FullBright ? white : Modern_GetColorZ(orig, x, y, z+offset, 1, 1); + PackedCol col0_1 = Builder_FullBright ? white : Modern_GetColorZ(orig, x, y, z+offset, -1, 1); + struct VertexTextured* vertices, v; + + if (adv_tinted) { + tint = Blocks.FogCol[Builder_Block]; + col0_0 = PackedCol_Tint(col0_0, tint); col1_0 = PackedCol_Tint(col1_0, tint); + col1_1 = PackedCol_Tint(col1_1, tint); col0_1 = PackedCol_Tint(col0_1, tint); + } + + vertices = part->faces.vertices[FACE_ZMAX]; + v.z = adv_z2; + v.x = adv_x2 + (count - 1); v.y = adv_y2; v.U = u2; v.V = v1; v.Col = col1_1; *vertices++ = v; + v.x = adv_x1; v.U = u1; v.Col = col0_1; *vertices++ = v; + v.y = adv_y1; v.V = v2; v.Col = col0_0; *vertices++ = v; + v.x = adv_x2 + (count - 1); v.U = u2; v.Col = col1_0; *vertices++ = v; + part->faces.vertices[FACE_ZMAX] = vertices; +} + +static PackedCol Modern_GetColorYMin(PackedCol orig, int x, int y, int z, int oX, int oZ) { + cc_bool xOccluded = Modern_IsOccluded(x + oX, y, z ); + cc_bool zOccluded = Modern_IsOccluded(x, y, z + oZ); + cc_bool xzOccluded = Modern_IsOccluded(x + oX, y, z + oZ); + + PackedCol CoX = xOccluded ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color_YMin_Fast(x + oX, y, z ); + PackedCol CoZ = zOccluded ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color_YMin_Fast(x , y, z + oZ); + PackedCol CoXoZ = (xzOccluded || (xOccluded && zOccluded)) ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color_YMin_Fast(x + oX, y, z + oZ); + + PackedCol ab = AVERAGE(CoX, CoZ); + PackedCol cd = AVERAGE(CoXoZ, orig); + return AVERAGE(ab, cd); +} +static void Modern_DrawYMin(int count, int x, int y, int z) { + TextureLoc texLoc = Block_Tex(Builder_Block, FACE_YMIN); + float vOrigin = Atlas1D_RowId(texLoc) * Atlas1D.InvTileSize; + + float u1 = adv_minBB.x, u2 = (count - 1) + adv_maxBB.x * UV2_Scale; + float v1 = vOrigin + adv_minBB.z * Atlas1D.InvTileSize; + float v2 = vOrigin + adv_maxBB.z * Atlas1D.InvTileSize * UV2_Scale; + struct Builder1DPart* part = &Builder_Parts[adv_baseOffset + Atlas1D_Index(texLoc)]; + + PackedCol tint, white = PACKEDCOL_WHITE; + int offset = 1;// (Blocks.LightOffset[Builder_Block] >> FACE_YMIN) & 1; + PackedCol orig = Lighting.Color_YMin_Fast(x, y-offset, z); + PackedCol col0_0 = Builder_FullBright ? white : Modern_GetColorYMin(orig, x, y-offset, z, -1, -1); + PackedCol col1_0 = Builder_FullBright ? white : Modern_GetColorYMin(orig, x, y-offset, z, 1, -1); + PackedCol col1_1 = Builder_FullBright ? white : Modern_GetColorYMin(orig, x, y-offset, z, 1, 1); + PackedCol col0_1 = Builder_FullBright ? white : Modern_GetColorYMin(orig, x, y-offset, z, -1, 1); + struct VertexTextured* vertices, v; + + if (adv_tinted) { + tint = Blocks.FogCol[Builder_Block]; + col0_0 = PackedCol_Tint(col0_0, tint); col1_0 = PackedCol_Tint(col1_0, tint); + col1_1 = PackedCol_Tint(col1_1, tint); col0_1 = PackedCol_Tint(col0_1, tint); + } + + vertices = part->faces.vertices[FACE_YMIN]; + v.y = adv_y1; + v.x = adv_x1; v.z = adv_z2; v.U = u1; v.V = v2; v.Col = col0_1; *vertices++ = v; + v.z = adv_z1; v.V = v1; v.Col = col0_0; *vertices++ = v; + v.x = adv_x2 + (count - 1); v.U = u2; v.Col = col1_0; *vertices++ = v; + v.z = adv_z2; v.V = v2; v.Col = col1_1; *vertices++ = v; + part->faces.vertices[FACE_YMIN] = vertices; +} + +static PackedCol Modern_GetColorYMax(PackedCol orig, int x, int y, int z, int oX, int oZ) { + cc_bool xOccluded = Modern_IsOccluded(x + oX, y, z ); + cc_bool zOccluded = Modern_IsOccluded(x, y, z + oZ); + cc_bool xzOccluded = Modern_IsOccluded(x + oX, y, z + oZ); + + PackedCol CoX = xOccluded ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color(x + oX, y, z ); + PackedCol CoZ = zOccluded ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color(x , y, z + oZ); + PackedCol CoXoZ = (xzOccluded || (xOccluded && zOccluded)) ? PackedCol_Scale(orig, FANCY_AO) : Lighting.Color(x + oX, y, z + oZ); + + PackedCol ab = AVERAGE(CoX, CoZ); + PackedCol cd = AVERAGE(CoXoZ, orig); + return AVERAGE(ab, cd); +} +static void Modern_DrawYMax(int count, int x, int y, int z) { + TextureLoc texLoc = Block_Tex(Builder_Block, FACE_YMAX); + float vOrigin = Atlas1D_RowId(texLoc) * Atlas1D.InvTileSize; + + float u1 = adv_minBB.x, u2 = (count - 1) + adv_maxBB.x * UV2_Scale; + float v1 = vOrigin + adv_minBB.z * Atlas1D.InvTileSize; + float v2 = vOrigin + adv_maxBB.z * Atlas1D.InvTileSize * UV2_Scale; + struct Builder1DPart* part = &Builder_Parts[adv_baseOffset + Atlas1D_Index(texLoc)]; + + PackedCol tint, white = PACKEDCOL_WHITE; + int offset = 1;// (Blocks.LightOffset[Builder_Block] >> FACE_YMAX) & 1; + PackedCol orig = Lighting.Color(x, y+offset, z); + PackedCol col0_0 = Builder_FullBright ? white : Modern_GetColorYMax(orig, x, y+offset, z, -1, -1); + PackedCol col1_0 = Builder_FullBright ? white : Modern_GetColorYMax(orig, x, y+offset, z, 1, -1); + PackedCol col1_1 = Builder_FullBright ? white : Modern_GetColorYMax(orig, x, y+offset, z, 1, 1); + PackedCol col0_1 = Builder_FullBright ? white : Modern_GetColorYMax(orig, x, y+offset, z, -1, 1); + + struct VertexTextured* vertices, v; + + if (adv_tinted) { + tint = Blocks.FogCol[Builder_Block]; + col0_0 = PackedCol_Tint(col0_0, tint); col1_0 = PackedCol_Tint(col1_0, tint); + col1_1 = PackedCol_Tint(col1_1, tint); col0_1 = PackedCol_Tint(col0_1, tint); + } + + vertices = part->faces.vertices[FACE_YMAX]; + v.y = adv_y2; + v.x = adv_x1; v.z = adv_z1; v.U = u1; v.V = v1; v.Col = col0_0; *vertices++ = v; + v.z = adv_z2; v.V = v2; v.Col = col0_1; *vertices++ = v; + v.x = adv_x2 + (count - 1); v.U = u2; v.Col = col1_1; *vertices++ = v; + v.z = adv_z1; v.V = v1; v.Col = col1_0; *vertices++ = v; + part->faces.vertices[FACE_YMAX] = vertices; +} +static void Modern_RenderBlock(int index, int x, int y, int z) { + Vec3 min, max; + int count_XMin, count_XMax, count_ZMin; + int count_ZMax, count_YMin, count_YMax; + + if (Blocks.Draw[Builder_Block] == DRAW_SPRITE) { + Builder_DrawSprite(x, y, z); return; + } + + count_XMin = Builder_Counts[index + FACE_XMIN]; + count_XMax = Builder_Counts[index + FACE_XMAX]; + count_ZMin = Builder_Counts[index + FACE_ZMIN]; + count_ZMax = Builder_Counts[index + FACE_ZMAX]; + count_YMin = Builder_Counts[index + FACE_YMIN]; + count_YMax = Builder_Counts[index + FACE_YMAX]; + + if (!count_XMin && !count_XMax && !count_ZMin && + !count_ZMax && !count_YMin && !count_YMax) return; + + Builder_FullBright = Blocks.Brightness[Builder_Block]; + adv_baseOffset = (Blocks.Draw[Builder_Block] == DRAW_TRANSLUCENT) * ATLAS1D_MAX_ATLASES; + adv_tinted = Blocks.Tinted[Builder_Block]; + + min = Blocks.RenderMinBB[Builder_Block]; max = Blocks.RenderMaxBB[Builder_Block]; + adv_x1 = x + min.x; adv_y1 = y + min.y; adv_z1 = z + min.z; + adv_x2 = x + max.x; adv_y2 = y + max.y; adv_z2 = z + max.z; + + adv_minBB = Blocks.MinBB[Builder_Block]; adv_maxBB = Blocks.MaxBB[Builder_Block]; + adv_minBB.y = 1.0f - adv_minBB.y; adv_maxBB.y = 1.0f - adv_maxBB.y; + + if (count_XMin) Modern_DrawXMin(count_XMin, x, y, z); + if (count_XMax) Modern_DrawXMax(count_XMax, x, y, z); + if (count_ZMin) Modern_DrawZMin(count_ZMin, x, y, z); + if (count_ZMax) Modern_DrawZMax(count_ZMax, x, y, z); + if (count_YMin) Modern_DrawYMin(count_YMin, x, y, z); + if (count_YMax) Modern_DrawYMax(count_YMax, x, y, z); +} + +static void Modern_PrePrepareChunk(void) { + DefaultPrePrepateChunk(); + adv_bitFlags = Builder_BitFlags; +} + +static void ModernBuilder_SetActive(void) { + Builder_SetDefault(); + Builder_StretchXLiquid = Modern_StretchXLiquid; + Builder_StretchX = Modern_StretchX; + Builder_StretchZ = Modern_StretchZ; + Builder_RenderBlock = Modern_RenderBlock; + Builder_PrePrepareChunk = Modern_PrePrepareChunk; +} +#else +static void ModernBuilder_SetActive(void) { NormalBuilder_SetActive(); } +#endif /*########################################################################################################################* *---------------------------------------------------Builder interface-----------------------------------------------------* @@ -1267,7 +1625,12 @@ static void AdvBuilder_SetActive(void) { cc_bool Builder_SmoothLighting; void Builder_ApplyActive(void) { if (Builder_SmoothLighting) { - AdvBuilder_SetActive(); + if (Lighting_Mode != LIGHTING_MODE_CLASSIC) { + ModernBuilder_SetActive(); + } + else { + AdvBuilder_SetActive(); + } } else { NormalBuilder_SetActive(); } diff --git a/src/Camera.c b/src/Camera.c index 2133ab9..10f7dc4 100644 --- a/src/Camera.c +++ b/src/Camera.c @@ -27,10 +27,10 @@ void Camera_KeyLookUpdate(float delta) { /* divide by 25 to have reasonable sensitivity for default mouse sens */ float amount = (Camera.Sensitivity / 25.0f) * (1000 * delta); - if (KeyBind_IsPressed(KEYBIND_LOOK_UP)) cam_deltaY -= amount; - if (KeyBind_IsPressed(KEYBIND_LOOK_DOWN)) cam_deltaY += amount; - if (KeyBind_IsPressed(KEYBIND_LOOK_LEFT)) cam_deltaX -= amount; - if (KeyBind_IsPressed(KEYBIND_LOOK_RIGHT)) cam_deltaX += amount; + if (InputBind_IsPressed(BIND_LOOK_UP)) cam_deltaY -= amount; + if (InputBind_IsPressed(BIND_LOOK_DOWN)) cam_deltaY += amount; + if (InputBind_IsPressed(BIND_LOOK_LEFT)) cam_deltaX -= amount; + if (InputBind_IsPressed(BIND_LOOK_RIGHT)) cam_deltaX += amount; } /*########################################################################################################################* @@ -42,15 +42,17 @@ static void PerspectiveCamera_GetProjection(struct Matrix* proj) { Gfx_CalcPerspectiveMatrix(proj, fovy, aspectRatio, (float)Game_ViewDistance); } -static void PerspectiveCamera_GetView(struct LocalPlayer* p, struct Matrix* mat) { +static void PerspectiveCamera_GetView(struct Matrix* mat) { Vec3 pos = Camera.CurrentPos; - Vec2 rot = Camera.Active->GetOrientation(p); + Vec2 rot = Camera.Active->GetOrientation(); Matrix_LookRot(mat, pos, rot); Matrix_MulBy(mat, &Camera.TiltM); } -static void PerspectiveCamera_GetPickedBlock(struct LocalPlayer* p, struct RayTracer* t) { - struct Entity* e = &p->Base; +static void PerspectiveCamera_GetPickedBlock(struct RayTracer* t) { + struct LocalPlayer* p = Entities.CurPlayer; + struct Entity* e = &p->Base; + Vec3 dir = Vec3_GetDirVector(e->Yaw * MATH_DEG2RAD, e->Pitch * MATH_DEG2RAD + Camera.TiltPitch); Vec3 eyePos = Entity_GetEyePosition(e); Picking_CalcPickedBlock(&eyePos, &dir, p->ReachDistance, t); @@ -146,16 +148,20 @@ static void PerspectiveCamera_CalcViewBobbing(struct LocalPlayer* p, float t, fl /*########################################################################################################################* *---------------------------------------------------First person camera---------------------------------------------------* *#########################################################################################################################*/ -static Vec2 FirstPersonCamera_GetOrientation(struct LocalPlayer* p) { +static Vec2 FirstPersonCamera_GetOrientation(void) { + struct LocalPlayer* p = Entities.CurPlayer; struct Entity* e = &p->Base; + Vec2 v; v.x = e->Yaw * MATH_DEG2RAD; v.y = e->Pitch * MATH_DEG2RAD; return v; } -static Vec3 FirstPersonCamera_GetPosition(struct LocalPlayer* p, float t) { +static Vec3 FirstPersonCamera_GetPosition(float t) { + struct LocalPlayer* p = Entities.CurPlayer; struct Entity* e = &p->Base; + Vec3 camPos = Entity_GetEyePosition(e); float yaw = e->Yaw * MATH_DEG2RAD; PerspectiveCamera_CalcViewBobbing(p, t, 1); @@ -183,8 +189,10 @@ static struct Camera cam_FirstPerson = { #define DEF_ZOOM 3.0f static float dist_third = DEF_ZOOM, dist_forward = DEF_ZOOM; -static Vec2 ThirdPersonCamera_GetOrientation(struct LocalPlayer* p) { +static Vec2 ThirdPersonCamera_GetOrientation(void) { + struct LocalPlayer* p = Entities.CurPlayer; struct Entity* e = &p->Base; + Vec2 v; v.x = e->Yaw * MATH_DEG2RAD; v.y = e->Pitch * MATH_DEG2RAD; @@ -202,8 +210,10 @@ static float ThirdPersonCamera_GetZoom(struct LocalPlayer* p) { return dist; } -static Vec3 ThirdPersonCamera_GetPosition(struct LocalPlayer* p, float t) { +static Vec3 ThirdPersonCamera_GetPosition(float t) { + struct LocalPlayer* p = Entities.CurPlayer; struct Entity* e = &p->Base; + float dist = ThirdPersonCamera_GetZoom(p); Vec3 target, dir; Vec2 rot; @@ -212,7 +222,7 @@ static Vec3 ThirdPersonCamera_GetPosition(struct LocalPlayer* p, float t) { target = Entity_GetEyePosition(e); target.y += Camera.BobbingVer; - rot = Camera.Active->GetOrientation(p); + rot = Camera.Active->GetOrientation(); dir = Vec3_GetDirVector(rot.x, rot.y); Vec3_Negate(&dir, &dir); diff --git a/src/Camera.h b/src/Camera.h index 8d8f513..e4c17a2 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -46,12 +46,12 @@ struct Camera { /* Calculates the current projection matrix of this camera. */ void (*GetProjection)(struct Matrix* proj); /* Calculates the current modelview matrix of this camera. */ - void (*GetView)(struct LocalPlayer* p, struct Matrix* view); + void (*GetView)(struct Matrix* view); /* Returns the current orientation of the camera. */ - Vec2 (*GetOrientation)(struct LocalPlayer* p); + Vec2 (*GetOrientation)(void); /* Returns the current interpolated position of the camera. */ - Vec3 (*GetPosition)(struct LocalPlayer* p, float t); + Vec3 (*GetPosition)(float t); /* Called to update the camera's state. */ /* Typically, this is used to adjust yaw/pitch based on accumulated mouse movement. */ @@ -64,7 +64,7 @@ struct Camera { void (*LoseFocus)(void); /* Calculates selected block in the world, based on camera's current state */ - void (*GetPickedBlock)(struct LocalPlayer* p, struct RayTracer* t); + void (*GetPickedBlock)(struct RayTracer* t); /* Zooms the camera in or out when scrolling mouse wheel. */ cc_bool (*Zoom)(float amount); diff --git a/src/Chat.c b/src/Chat.c index c604ff4..b7aed82 100644 --- a/src/Chat.c +++ b/src/Chat.c @@ -21,7 +21,7 @@ static char smallAnnouncement[STRING_SIZE]; cc_string Chat_Status[5] = { String_FromArray(status[0]), String_FromArray(status[1]), String_FromArray(status[2]), String_FromArray(status[3]), String_FromArray(status[4]) }; cc_string Chat_BottomRight[3] = { String_FromArray(bottom[0]), String_FromArray(bottom[1]), String_FromArray(bottom[2]) }; -cc_string Chat_ClientStatus[2] = { String_FromArray(client[0]), String_FromArray(client[8]) }; +cc_string Chat_ClientStatus[2] = { String_FromArray(client[0]), String_FromArray(client[1]) }; cc_string Chat_Announcement = String_FromArray(announcement); cc_string Chat_BigAnnouncement = String_FromArray(bigAnnouncement); diff --git a/src/Commands.c b/src/Commands.c index b64e84f..872bd46 100644 --- a/src/Commands.c +++ b/src/Commands.c @@ -689,8 +689,8 @@ static void BlockEditCommand_Execute(const cc_string* args, int argsCount__) { Blocks.DigSounds[block] = v; } else if (String_CaselessEqualsConst(prop, "fullbright")) { if (!BlockEditCommand_GetBool(value, "Full brightness", &b)) return; - - Blocks.FullBright[block] = b; + //TODO: Fix this, brightness isn't just a bool anymore + Blocks.Brightness[block] = b; } else if (String_CaselessEqualsConst(prop, "blockslight")) { if (!BlockEditCommand_GetBool(value, "Blocks light", &b)) return; diff --git a/src/Core.h b/src/Core.h index aff7c29..924fd56 100644 --- a/src/Core.h +++ b/src/Core.h @@ -117,13 +117,33 @@ typedef cc_uint8 cc_bool; #endif #endif +/* Lowest 4 bits are for backends in same group */ +/* Rest of the bits indicate the unique group type */ + +#define CC_WIN_BACKEND_TERMINAL 0x0001 +#define CC_WIN_BACKEND_SDL_MASK 0x0010 +#define CC_WIN_BACKEND_SDL2 0x0011 +#define CC_WIN_BACKEND_SDL3 0x0012 +#define CC_WIN_BACKEND_X11 0x0021 +#define CC_WIN_BACKEND_WIN32 0x0041 +#define CC_WIN_BACKEND_COCOA 0x0081 +#define CC_WIN_BACKEND_BEOS 0x0101 +#define CC_WIN_BACKEND_ANDROID 0x0201 + +#define CC_GFX_BACKEND_SOFTGPU 0x0001 +#define CC_GFX_BACKEND_GL_MASK 0x0010 +#define CC_GFX_BACKEND_GL1 0x0011 +#define CC_GFX_BACKEND_GL2 0x0012 +#define CC_GFX_BACKEND_D3D9 0x0021 +#define CC_GFX_BACKEND_D3D11 0x0041 +#define CC_GFX_BACKEND_VULKAN 0x0081 #define CC_BUILD_NETWORKING -//#define CC_BUILD_FREETYPE #define CC_BUILD_RESOURCES #define CC_BUILD_PLUGINS #define CC_BUILD_ANIMATIONS #define CC_BUILD_FILESYSTEM +#define CC_BUILD_ADVLIGHTING /*#define CC_BUILD_GL11*/ #ifndef CC_BUILD_MANUAL @@ -147,120 +167,128 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_HTTPCLIENT #elif defined _WIN32 #define CC_BUILD_WIN - #define CC_BUILD_D3D9 - #define CC_BUILD_WINGUI #define CC_BUILD_HTTPCLIENT #define CC_BUILD_SCHANNEL #define CC_BUILD_WINMM + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_D3D9 + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_WIN32 #elif defined __ANDROID__ #define CC_BUILD_ANDROID #define CC_BUILD_MOBILE #define CC_BUILD_POSIX - #define CC_BUILD_GL - #define CC_BUILD_GLMODERN #define CC_BUILD_GLES #define CC_BUILD_EGL #define CC_BUILD_TOUCH #define CC_BUILD_OPENSLES + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL2 + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_ANDROID #elif defined __serenity__ #define CC_BUILD_SERENITY #define CC_BUILD_POSIX - #define CC_BUILD_GL - #define CC_BUILD_SDL #define CC_BUILD_CURL #define CC_BUILD_OPENAL + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_SDL2 #elif defined __linux__ #define CC_BUILD_LINUX #define CC_BUILD_POSIX - #define CC_BUILD_GL - #define CC_BUILD_X11 #define CC_BUILD_XINPUT2 #define CC_BUILD_CURL #define CC_BUILD_OPENAL + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_X11 #if defined CC_BUILD_RPI - #define CC_BUILD_GLMODERN - #define CC_BUILD_GLES - #define CC_BUILD_EGL + #define CC_BUILD_GLES + #define CC_BUILD_EGL + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL2 + #else + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 #endif #elif defined __APPLE__ #define CC_BUILD_DARWIN #define CC_BUILD_POSIX - #define CC_BUILD_GL #if defined __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ - #define CC_BUILD_MOBILE - #define CC_BUILD_GLES - #define CC_BUILD_GLMODERN - #define CC_BUILD_IOS - #define CC_BUILD_TOUCH - #define CC_BUILD_CFNETWORK + #define CC_BUILD_MOBILE + #define CC_BUILD_GLES + #define CC_BUILD_IOS + #define CC_BUILD_TOUCH + #define CC_BUILD_CFNETWORK + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL2 #else - #define CC_BUILD_COCOA - #define CC_BUILD_MACOS - #define CC_BUILD_CURL + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_COCOA + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define CC_BUILD_MACOS + #define CC_BUILD_CURL #endif #define CC_BUILD_OPENAL +#elif defined Macintosh + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTGPU + #define CC_BUILD_MACCLASSIC + #define CC_BUILD_HTTPCLIENT + #define CC_BUILD_OPENAL + #define CC_BUILD_LOWMEM + #define CC_BUILD_COOPTHREADED + #undef CC_BUILD_FREETYPE #elif defined __sun__ #define CC_BUILD_SOLARIS #define CC_BUILD_POSIX - #define CC_BUILD_GL - #define CC_BUILD_X11 #define CC_BUILD_XINPUT2 #define CC_BUILD_CURL #define CC_BUILD_OPENAL + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_X11 #elif defined __FreeBSD__ || defined __DragonFly__ #define CC_BUILD_FREEBSD #define CC_BUILD_POSIX #define CC_BUILD_BSD - #define CC_BUILD_GL - #define CC_BUILD_X11 #define CC_BUILD_XINPUT2 #define CC_BUILD_CURL - #define CC_BUILD_OPENAL + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_X11 #elif defined __OpenBSD__ #define CC_BUILD_OPENBSD #define CC_BUILD_POSIX #define CC_BUILD_BSD - #define CC_BUILD_GL - #define CC_BUILD_X11 #define CC_BUILD_XINPUT2 #define CC_BUILD_CURL #define CC_BUILD_OPENAL + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_X11 #elif defined __NetBSD__ #define CC_BUILD_NETBSD #define CC_BUILD_POSIX #define CC_BUILD_BSD - #define CC_BUILD_GL - #define CC_BUILD_X11 #define CC_BUILD_XINPUT2 #define CC_BUILD_CURL #define CC_BUILD_OPENAL + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_X11 #elif defined __HAIKU__ #define CC_BUILD_HAIKU #define CC_BUILD_POSIX - #define CC_BUILD_GL #define CC_BUILD_CURL #define CC_BUILD_OPENAL #define CC_BACKTRACE_BUILTIN + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_BEOS #elif defined __BEOS__ #define CC_BUILD_BEOS #define CC_BUILD_POSIX - #define CC_BUILD_GL #define CC_BUILD_GL11 #define CC_BUILD_HTTPCLIENT #define CC_BUILD_OPENAL #define CC_BACKTRACE_BUILTIN + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_BEOS #elif defined __sgi #define CC_BUILD_IRIX #define CC_BUILD_POSIX - #define CC_BUILD_GL - #define CC_BUILD_X11 #define CC_BUILD_CURL #define CC_BUILD_OPENAL #define CC_BIG_ENDIAN + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL1 + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_X11 #elif defined __EMSCRIPTEN__ #define CC_BUILD_WEB - #define CC_BUILD_GL - #define CC_BUILD_GLMODERN #define CC_BUILD_GLES #define CC_BUILD_TOUCH #define CC_BUILD_WEBAUDIO @@ -270,6 +298,7 @@ typedef cc_uint8 cc_bool; #undef CC_BUILD_FREETYPE #undef CC_BUILD_RESOURCES #undef CC_BUILD_PLUGINS + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL2 #elif defined __psp__ #define CC_BUILD_PSP #define CC_BUILD_CONSOLE @@ -289,7 +318,9 @@ typedef cc_uint8 cc_bool; #elif defined GEKKO #define CC_BUILD_GCWII #define CC_BUILD_CONSOLE - #define CC_BUILD_LOWMEM + #ifndef HW_RVL + #define CC_BUILD_LOWMEM + #endif #define CC_BUILD_COOPTHREADED #define CC_BUILD_HTTPCLIENT #define CC_BUILD_BEARSSL @@ -297,7 +328,6 @@ typedef cc_uint8 cc_bool; #elif defined __vita__ #define CC_BUILD_PSVITA #define CC_BUILD_CONSOLE - #define CC_BUILD_LOWMEM #define CC_BUILD_OPENAL #define CC_BUILD_HTTPCLIENT #define CC_BUILD_BEARSSL @@ -313,7 +343,6 @@ typedef cc_uint8 cc_bool; #elif defined PLAT_PS3 #define CC_BUILD_PS3 #define CC_BUILD_CONSOLE - #define CC_BUILD_LOWMEM #define CC_BUILD_OPENAL #define CC_BUILD_HTTPCLIENT #define CC_BUILD_BEARSSL @@ -347,6 +376,7 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_TOUCH #undef CC_BUILD_RESOURCES #undef CC_BUILD_ANIMATIONS /* Very costly in FPU less system */ + #undef CC_BUILD_ADVLIGHTING #elif defined __WIIU__ #define CC_BUILD_WIIU #define CC_BUILD_CONSOLE @@ -362,10 +392,9 @@ typedef cc_uint8 cc_bool; #define CC_BUILD_HTTPCLIENT #define CC_BUILD_BEARSSL #define CC_BUILD_TOUCH - #define CC_BUILD_GL - #define CC_BUILD_GLMODERN #define CC_BUILD_GLES #define CC_BUILD_EGL + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_GL2 #elif defined PLAT_PS1 #define CC_BUILD_PS1 #define CC_BUILD_CONSOLE @@ -376,14 +405,15 @@ typedef cc_uint8 cc_bool; #undef CC_BUILD_RESOURCES #undef CC_BUILD_NETWORKING #undef CC_BUILD_ANIMATIONS /* Very costly in FPU less system */ + #undef CC_BUILD_ADVLIGHTING #undef CC_BUILD_FILESYSTEM #elif defined OS2 #define CC_BUILD_OS2 #define CC_BUILD_POSIX - #define CC_BUILD_SOFTGPU - #define CC_BUILD_SDL2 #define CC_BUILD_CURL #define CC_BUILD_FREETYPE + #define DEFAULT_GFX_BACKEND CC_GFX_BACKEND_SOFTGPU + #define DEFAULT_WIN_BACKEND CC_WIN_BACKEND_SDL2 #elif defined PLAT_SATURN #define CC_BUILD_SATURN #define CC_BUILD_CONSOLE @@ -394,18 +424,29 @@ typedef cc_uint8 cc_bool; #undef CC_BUILD_RESOURCES #undef CC_BUILD_NETWORKING #undef CC_BUILD_ANIMATIONS /* Very costly in FPU less system */ + #undef CC_BUILD_ADVLIGHTING #undef CC_BUILD_FILESYSTEM #endif #endif +/* Use platform default unless override is provided via command line/makefile/etc */ +#if defined DEFAULT_WIN_BACKEND && !defined CC_WIN_BACKEND + #define CC_WIN_BACKEND DEFAULT_WIN_BACKEND +#endif +#if defined DEFAULT_GFX_BACKEND && !defined CC_GFX_BACKEND + #define CC_GFX_BACKEND DEFAULT_GFX_BACKEND +#endif + #ifdef CC_BUILD_CONSOLE #undef CC_BUILD_FREETYPE #undef CC_BUILD_PLUGINS #endif +#ifdef CC_BUILD_NETWORKING +#define CUSTOM_MODELS +#endif #ifndef CC_BUILD_LOWMEM #define EXTENDED_BLOCKS -#define CUSTOM_MODELS #endif #define EXTENDED_TEXTURES @@ -439,13 +480,7 @@ typedef struct cc_string_ { Thus it is **NOT SAFE** to allocate a string on the stack. */ #define STRING_REF -#if defined CC_BUILD_GL -/* NOTE: Although normally OpenGL object/resource IDs are 32 bit integers, */ -/* OpenGL 1.1 does actually use the full 64 bits for 'dynamic' vertex buffers */ -typedef cc_uintptr GfxResourceID; -#else typedef void* GfxResourceID; -#endif /* Contains the information to describe a 2D textured quad. */ struct Texture { diff --git a/src/Deflate.c b/src/Deflate.c index 7472886..47d3a00 100644 --- a/src/Deflate.c +++ b/src/Deflate.c @@ -33,38 +33,45 @@ cc_result GZipHeader_Read(struct Stream* s, struct GZipHeader* header) { Header_ReadU8(tmp); if (tmp != 0x1F) return GZIP_ERR_HEADER1; header->state++; - + + /* FALLTHRU */ case GZIP_STATE_HEADER2: Header_ReadU8(tmp); if (tmp != 0x8B) return GZIP_ERR_HEADER2; header->state++; - + + /* FALLTHRU */ case GZIP_STATE_COMPRESSIONMETHOD: Header_ReadU8(tmp); if (tmp != 0x08) return GZIP_ERR_METHOD; header->state++; - + + /* FALLTHRU */ case GZIP_STATE_FLAGS: Header_ReadU8(tmp); header->flags = tmp; if (header->flags & 0x04) return GZIP_ERR_FLAGS; header->state++; - + + /* FALLTHRU */ case GZIP_STATE_LASTMODIFIED: for (; header->partsRead < 4; header->partsRead++) { Header_ReadU8(tmp); } header->state++; header->partsRead = 0; - + + /* FALLTHRU */ case GZIP_STATE_COMPRESSIONFLAGS: Header_ReadU8(tmp); header->state++; - + + /* FALLTHRU */ case GZIP_STATE_OPERATINGSYSTEM: Header_ReadU8(tmp); header->state++; - + + /* FALLTHRU */ case GZIP_STATE_FILENAME: if (header->flags & 0x08) { for (; ;) { @@ -73,7 +80,8 @@ cc_result GZipHeader_Read(struct Stream* s, struct GZipHeader* header) { } } header->state++; - + + /* FALLTHRU */ case GZIP_STATE_COMMENT: if (header->flags & 0x10) { for (; ;) { @@ -82,7 +90,8 @@ cc_result GZipHeader_Read(struct Stream* s, struct GZipHeader* header) { } } header->state++; - + + /* FALLTHRU */ case GZIP_STATE_HEADERCHECKSUM: if (header->flags & 0x02) { for (; header->partsRead < 2; header->partsRead++) { @@ -117,7 +126,8 @@ cc_result ZLibHeader_Read(struct Stream* s, struct ZLibHeader* header) { if ((tmp & 0x0F) != 0x08) return ZLIB_ERR_METHOD; /* Upper 4 bits are window size (ignored) */ header->state++; - + + /* FALLTHRU */ case ZLIB_STATE_FLAGS: Header_ReadU8(tmp); if (tmp & 0x20) return ZLIB_ERR_FLAGS; @@ -243,7 +253,7 @@ static cc_result Huffman_Build(struct HuffmanTable* table, const cc_uint8* bitLe * - set fast value to specify a 'value' value, and to skip 'len' bits */ if (len <= INFLATE_FAST_BITS) { - cc_int16 packed = (cc_int16)((len << INFLATE_FAST_BITS) | value); + cc_int16 packed = (cc_int16)((len << INFLATE_FAST_LEN_SHIFT) | value); int codeword = table->firstCodewords[len] + (bl_offsets[len] - table->firstOffsets[len]); codeword <<= (INFLATE_FAST_BITS - len); @@ -273,9 +283,9 @@ static int Huffman_Decode(struct InflateState* state, struct HuffmanTable* table if (state->NumBits >= INFLATE_FAST_BITS) { packed = table->fast[Inflate_PeekBits(state, INFLATE_FAST_BITS)]; if (packed >= 0) { - bits = packed >> INFLATE_FAST_BITS; + bits = packed >> INFLATE_FAST_LEN_SHIFT; Inflate_ConsumeBits(state, bits); - return packed & 0x1FF; + return packed & INFLATE_FAST_VAL_MASK; } } @@ -523,7 +533,8 @@ void Inflate_Process(struct InflateState* s) { s->Index = len; /* Reuse for 'uncompressed length' */ s->State = INFLATE_STATE_UNCOMPRESSED_DATA; } - + + /* FALLTHRU */ case INFLATE_STATE_UNCOMPRESSED_DATA: { /* read bits left in bit buffer (slow way) */ while (s->NumBits && s->AvailOut && s->Index) { @@ -565,7 +576,8 @@ void Inflate_Process(struct InflateState* s) { s->Index = 0; s->State = INFLATE_STATE_DYNAMIC_CODELENS; } - + /* FALLTHRU */ + case INFLATE_STATE_DYNAMIC_CODELENS: { while (s->Index < s->NumCodeLens) { Inflate_EnsureBits(s, 3); @@ -582,7 +594,8 @@ void Inflate_Process(struct InflateState* s) { res = Huffman_Build(&s->Table.CodeLens, s->Buffer, INFLATE_MAX_CODELENS); if (res) { Inflate_Fail(s, res); return; } } - + + /* FALLTHRU */ case INFLATE_STATE_DYNAMIC_LITSDISTS: { count = s->NumLits + s->NumDists; while (s->Index < count) { @@ -670,13 +683,15 @@ void Inflate_Process(struct InflateState* s) { s->TmpLit = len_base[lenIdx] + Inflate_ReadBits(s, bits); s->State = INFLATE_STATE_COMPRESSED_DIST; } - + + /* FALLTHRU */ case INFLATE_STATE_COMPRESSED_DIST: { s->TmpDist = Huffman_Decode(s, &s->TableDists); if (s->TmpDist == -1) return; s->State = INFLATE_STATE_COMPRESSED_DISTEXTRA; } - + + /* FALLTHRU */ case INFLATE_STATE_COMPRESSED_DISTEXTRA: { distIdx = s->TmpDist; bits = dist_bits[distIdx]; @@ -684,7 +699,8 @@ void Inflate_Process(struct InflateState* s) { s->TmpDist = dist_base[distIdx] + Inflate_ReadBits(s, bits); s->State = INFLATE_STATE_COMPRESSED_DATA; } - + + /* FALLTHRU */ case INFLATE_STATE_COMPRESSED_DATA: { if (!s->AvailOut) return; len = s->TmpLit; dist = s->TmpDist; diff --git a/src/Deflate.h b/src/Deflate.h index 7e363bd..8ff3aa1 100644 --- a/src/Deflate.h +++ b/src/Deflate.h @@ -27,7 +27,11 @@ cc_result ZLibHeader_Read(struct Stream* s, struct ZLibHeader* header); #define INFLATE_MAX_DISTS 32 #define INFLATE_MAX_LITS_DISTS (INFLATE_MAX_LITS + INFLATE_MAX_DISTS) #define INFLATE_MAX_BITS 16 + #define INFLATE_FAST_BITS 9 +#define INFLATE_FAST_LEN_SHIFT 9 +#define INFLATE_FAST_VAL_MASK 0x1FF + #define INFLATE_WINDOW_SIZE 0x8000UL #define INFLATE_WINDOW_MASK 0x7FFFUL diff --git a/src/Entity.c b/src/Entity.c index 40ebb81..309303c 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -622,6 +622,11 @@ void LocalPlayerInput_Add(struct LocalPlayerInput* source) { LinkedList_Append(source, sources_head, sources_tail); } +void LocalPlayerInput_Remove(struct LocalPlayerInput* source) { + struct LocalPlayerInput* cur; + LinkedList_Remove(source, cur, sources_head, sources_tail); +} + float LocalPlayer_JumpHeight(struct LocalPlayer* p) { return (float)PhysicsComp_CalcMaxHeight(p->Physics.JumpVel); } @@ -650,16 +655,16 @@ static void LocalPlayer_HandleInput(struct LocalPlayer* p, float* xMoving, float *xMoving *= 0.98f; *zMoving *= 0.98f; - p->Physics.Jumping = KeyBind_IsPressed(KEYBIND_JUMP); - hacks->FlyingUp = KeyBind_IsPressed(KEYBIND_FLY_UP); - hacks->FlyingDown = KeyBind_IsPressed(KEYBIND_FLY_DOWN); + p->Physics.Jumping = InputBind_IsPressed(BIND_JUMP); + hacks->FlyingUp = InputBind_IsPressed(BIND_FLY_UP); + hacks->FlyingDown = InputBind_IsPressed(BIND_FLY_DOWN); if (hacks->WOMStyleHacks && hacks->Enabled && hacks->CanNoclip) { if (hacks->Noclip) { /* need a { } block because it's a macro */ Vec3_Set(p->Base.Velocity, 0,0,0); } - HacksComp_SetNoclip(hacks, KeyBind_IsPressed(KEYBIND_NOCLIP)); + HacksComp_SetNoclip(hacks, InputBind_IsPressed(BIND_NOCLIP)); } } @@ -667,8 +672,8 @@ static void LocalPlayer_InputSet(int key, cc_bool pressed) { struct HacksComp* hacks = &LocalPlayer_Instances[0].Hacks; if (pressed && !hacks->Enabled) return; - if (KeyBind_Claims(KEYBIND_SPEED, key)) hacks->Speeding = pressed; - if (KeyBind_Claims(KEYBIND_HALF_SPEED, key)) hacks->HalfSpeeding = pressed; + if (InputBind_Claims(BIND_SPEED, key)) hacks->Speeding = pressed; + if (InputBind_Claims(BIND_HALF_SPEED, key)) hacks->HalfSpeeding = pressed; } static void LocalPlayer_InputDown(void* obj, int key, cc_bool was) { @@ -887,7 +892,9 @@ cc_bool LocalPlayer_HandleSetSpawn(struct LocalPlayer* p) { /* Spawn is normally centered to match vanilla Minecraft classic */ if (!p->Hacks.CanNoclip) { - p->Spawn = p->Base.Position; + /* Don't want to use Position because it is interpolated between prev and next. */ + /* This means it can be halfway between stepping up a stair and clip through the floor. */ + p->Spawn = p->Base.prev.pos; } else { p->Spawn.x = Math_Floor(p->Base.Position.x) + 0.5f; p->Spawn.y = p->Base.Position.y; @@ -968,7 +975,7 @@ void LocalPlayers_MoveToSpawn(struct LocationUpdate* update) { } /* TODO: This needs to be before new map... */ - Camera.CurrentPos = Camera.Active->GetPosition(Entities.CurPlayer, 0.0f); + Camera.CurrentPos = Camera.Active->GetPosition(0.0f); } void LocalPlayer_CalcDefaultSpawn(struct LocalPlayer* p, struct LocationUpdate* update) { @@ -1062,6 +1069,7 @@ static void Entities_Free(void) { { Entities_Remove((EntityID)i); } + sources_head = NULL; } struct IGameComponent Entities_Component = { diff --git a/src/Entity.h b/src/Entity.h index 295d168..9b6119d 100644 --- a/src/Entity.h +++ b/src/Entity.h @@ -231,6 +231,7 @@ struct LocalPlayerInput { struct LocalPlayerInput* next; }; void LocalPlayerInput_Add(struct LocalPlayerInput* source); +void LocalPlayerInput_Remove(struct LocalPlayerInput* source); /* Represents the user/player's own entity. */ struct LocalPlayer { diff --git a/src/EntityComponents.h b/src/EntityComponents.h index 1fd394c..d196f0b 100644 --- a/src/EntityComponents.h +++ b/src/EntityComponents.h @@ -38,7 +38,7 @@ void TiltComp_GetCurrent(struct LocalPlayer* p, struct TiltComp* anim, float t); struct HacksComp { cc_bool IsOp; cc_bool Floating; /* true if NoClip or Flying */ - /* Speed player move at, relative to normal speed, when the 'speeding' key binding is held down */ + /* Speed player move at, relative to normal speed, when the 'speeding' input binding is active */ float SpeedMultiplier; /* Whether blocks that the player places that intersect themselves, should cause the player to be pushed back in the opposite direction of the placed block */ diff --git a/src/EntityRenderers.c b/src/EntityRenderers.c index f673a89..b14d83b 100644 --- a/src/EntityRenderers.c +++ b/src/EntityRenderers.c @@ -402,29 +402,39 @@ void EntityNames_Render(void) { } void EntityNames_RenderHovered(void) { - struct LocalPlayer* p = Entities.CurPlayer; + struct LocalPlayer* p = Entities.CurPlayer; + struct Entity* e; cc_bool allNames, hadFog; + cc_bool setupState = false; int i; if (Entities.NamesMode == NAME_MODE_NONE) return; allNames = !(Entities.NamesMode == NAME_MODE_HOVERED || Entities.NamesMode == NAME_MODE_ALL) && p->Hacks.CanSeeAllNames; - Gfx_SetAlphaTest(true); - Gfx_SetDepthTest(false); - hadFog = Gfx_GetFog(); - if (hadFog) Gfx_SetFog(false); - for (i = 0; i < ENTITIES_MAX_COUNT; i++) { - if (!Entities.List[i]) continue; - if ((i == closestEntityId || allNames) && Entities.List[i] != &p->Base) { - DrawName(Entities.List[i]); + e = Entities.List[i]; + if (!e || e == &p->Base) continue; + if (!allNames && i != closestEntityId) continue; + + /* Only alter the GPU state when actually necessary */ + if (!setupState) { + Gfx_SetAlphaTest(true); + Gfx_SetDepthTest(false); + Gfx_SetDepthWrite(false); + + setupState = true; + hadFog = Gfx_GetFog(); + if (hadFog) Gfx_SetFog(false); } + DrawName(e); } + if (!setupState) return; Gfx_SetAlphaTest(false); Gfx_SetDepthTest(true); + Gfx_SetDepthWrite(true); if (hadFog) Gfx_SetFog(true); } diff --git a/src/EnvRenderer.c b/src/EnvRenderer.c index 74b0f13..3f77a86 100644 --- a/src/EnvRenderer.c +++ b/src/EnvRenderer.c @@ -326,7 +326,7 @@ void EnvRenderer_RenderSkybox(void) { /* Rotate around camera */ pos = Camera.CurrentPos; Vec3_Set(Camera.CurrentPos, 0,0,0); - Camera.Active->GetView(Entities.CurPlayer, &view); + Camera.Active->GetView(&view); Matrix_MulBy(&m, &view); Camera.CurrentPos = pos; @@ -724,7 +724,7 @@ static void UpdateMapSides(void) { data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&sides_vb, VERTEX_FORMAT_TEXTURED, sides_vertices); - sides_fullBright = Blocks.FullBright[block]; + sides_fullBright = Blocks.Brightness[block]; color = sides_fullBright ? PACKEDCOL_WHITE : Env.ShadowCol; Block_Tint(color, block) @@ -770,7 +770,7 @@ static void UpdateMapEdges(void) { data = (struct VertexTextured*)Gfx_RecreateAndLockVb(&edges_vb, VERTEX_FORMAT_TEXTURED, edges_vertices); - edges_fullBright = Blocks.FullBright[block]; + edges_fullBright = Blocks.Brightness[block]; color = edges_fullBright ? PACKEDCOL_WHITE : Env.SunCol; Block_Tint(color, block) diff --git a/src/Errors.h b/src/Errors.h index 25abd72..45072a4 100644 --- a/src/Errors.h +++ b/src/Errors.h @@ -132,7 +132,8 @@ enum CC_ERRORS { HTTP_ERR_RELATIVE = 0xCCDED069UL, /* Unsupported relative URL format */ HTTP_ERR_INVALID_BODY= 0xCCDED06AUL, /* HTTP message doesn't have Content-Length or use Chunked transfer encoding */ HTTP_ERR_CHUNK_SIZE = 0xCCDED06BUL, /* HTTP message chunk has negative size/length */ - HTTP_ERR_TRUNCATED = 0xCCDED06CUL, /* HTTP respone header was truncated due to being too long */ + HTTP_ERR_TRUNCATED = 0xCCDED06CUL, /* HTTP response header was truncated due to being too long */ + HTTP_ERR_NO_RESPONSE = 0xCCDED06DUL, /* First attempt to read response returned 0 bytes */ SSL_ERR_CONTEXT_DEAD = 0xCCDED070UL, /* Server shutdown the SSL context and it must be recreated */ PNG_ERR_16BITSAMPLES = 0xCCDED071UL, /* Image uses 16 bit samples, which is unimplemented */ diff --git a/src/Event.c b/src/Event.c index 91cca9c..c111543 100644 --- a/src/Event.c +++ b/src/Event.c @@ -82,6 +82,7 @@ void Event_UnregisterAll(void) { WorldEvents.Loading.Count = 0; WorldEvents.MapLoaded.Count = 0; WorldEvents.EnvVarChanged.Count = 0; + WorldEvents.LightingModeChanged.Count = 0; ChatEvents.FontChanged.Count = 0; ChatEvents.ChatReceived.Count = 0; @@ -191,3 +192,10 @@ void Event_RaisePluginMessage(struct Event_PluginMessage* handlers, cc_uint8 cha handlers->Handlers[i](handlers->Objs[i], channel, data); } } + +void Event_RaiseLightingMode(struct Event_LightingMode* handlers, cc_uint8 oldMode, cc_bool fromServer) { + int i; + for (i = 0; i < handlers->Count; i++) { + handlers->Handlers[i](handlers->Objs[i], oldMode, fromServer); + } +} \ No newline at end of file diff --git a/src/Event.h b/src/Event.h index 398a6df..5952912 100644 --- a/src/Event.h +++ b/src/Event.h @@ -76,6 +76,12 @@ struct Event_PluginMessage { void* Objs[EVENT_MAX_CALLBACKS]; int Count; }; +typedef void (*Event_LightingMode_Callback)(void* obj, cc_uint8 oldMode, cc_bool fromServer); +struct Event_LightingMode { + Event_LightingMode_Callback Handlers[EVENT_MAX_CALLBACKS]; + void* Objs[EVENT_MAX_CALLBACKS]; int Count; +}; + /* Registers a callback function for the given event. */ /* NOTE: Trying to register a callback twice or over EVENT_MAX_CALLBACKS callbacks will terminate the game. */ CC_API void Event_Register(struct Event_Void* handlers, void* obj, Event_Void_Callback handler); @@ -111,6 +117,8 @@ void Event_RaiseRawMove(struct Event_RawMove* handlers, float xDelta, float yDel void Event_RaisePadAxis(struct Event_PadAxis* handlers, int port, int axis, float x, float y); /* Calls all registered callbacks for an event which has a channel and a 64 byte data argument. */ void Event_RaisePluginMessage(struct Event_PluginMessage* handlers, cc_uint8 channel, cc_uint8* data); +/* Calls all registered callbacks for an event called when the Lighting_LightingMode is changed */ +void Event_RaiseLightingMode(struct Event_LightingMode* handlers, cc_uint8 oldMode, cc_bool fromServer); void Event_UnregisterAll(void); /* NOTE: Event_UnregisterAll MUST be updated when events lists are changed */ @@ -166,6 +174,7 @@ CC_VAR extern struct _WorldEventsList { struct Event_Float Loading; /* Portion of world is decompressed/generated (Arg is progress from 0-1) */ struct Event_Void MapLoaded; /* New world has finished loading, player can now interact with it */ struct Event_Int EnvVarChanged; /* World environment variable changed by player/CPE/WoM config */ + struct Event_LightingMode LightingModeChanged; /* Lighting mode changed. */ } WorldEvents; CC_VAR extern struct _ChatEventsList { diff --git a/src/ExtMath.c b/src/ExtMath.c index 6baa884..01e7a2b 100644 --- a/src/ExtMath.c +++ b/src/ExtMath.c @@ -4,6 +4,8 @@ /* For abs(x) function */ #include +#define PI 3.141592653589793238462643383279502884197169399 + /* Sega saturn is missing these intrinsics */ #ifdef CC_BUILD_SATURN #include @@ -40,9 +42,6 @@ float sqrtf(float x) { float Math_Mod1(float x) { return x - (int)x; /* fmodf(x, 1); */ } int Math_AbsI(int x) { return abs(x); /* MSVC intrinsic */ } -float Math_SinF(float x) { return (float)Math_Sin(x); } -float Math_CosF(float x) { return (float)Math_Cos(x); } - int Math_Floor(float value) { int valueI = (int)value; return valueI > value ? valueI - 1 : valueI; @@ -80,8 +79,8 @@ float Math_ClampAngle(float degrees) { } float Math_LerpAngle(float leftAngle, float rightAngle, float t) { - /* We have to cheat a bit for angles here */ - /* Consider 350* --> 0*, we only want to travel 10* */ + /* Need to potentially adjust a bit when interpolating some angles */ + /* Consider 350* --> 0*, we only want to interpolate across the 10* */ /* But without adjusting for this case, we would interpolate back the whole 350* degrees */ cc_bool invertLeft = leftAngle > 270.0f && rightAngle < 90.0f; cc_bool invertRight = rightAngle > 270.0f && leftAngle < 90.0f; @@ -147,8 +146,6 @@ float Random_Float(RNGState* seed) { /*########################################################################################################################* *--------------------------------------------------Transcendental functions-----------------------------------------------* *#########################################################################################################################*/ -static const double SQRT2 = 1.4142135623730950488016887242096980785696718753769; - #ifdef CC_BUILD_DREAMCAST #include @@ -156,12 +153,10 @@ static const double SQRT2 = 1.4142135623730950488016887242096980785696718753769; /* TODO: Properly investigate this issue */ /* double make_dreamcast_build_compile(void) { fabs(4); } */ -double Math_Sin(double x) { return sin(x); } -double Math_Cos(double x) { return cos(x); } +float Math_SinF(float x) { return sinf(x); } +float Math_CosF(float x) { return cosf(x); } double Math_Exp2(double x) { return exp2(x); } double Math_Log2(double x) { return log2(x); } - -float Math_Atan2f(float x, float y) { return atan2f(y, x); } #else /***** Caleb's Math functions *****/ @@ -187,7 +182,7 @@ float Math_Atan2f(float x, float y) { return atan2f(y, x); } /* from the mathematical functions anyways */ /* Global constants */ -#define PI 3.141592653589793238462643383279502884197169399 +static const double SQRT2 = 1.4142135623730950488016887242096980785696718753769; #define DIV_2_PI (1.0 / (2.0 * PI)) static const cc_uint64 _DBL_NAN = 0x7FF8000000000000ULL; @@ -217,7 +212,7 @@ static double Floord(double x) { * Precision: 16.47 */ static double SinStage1(double x) { - const double A[] = { + const static double A[] = { .52359877559829885532, -.2392459620393377657e-1, .32795319441392666e-3, @@ -272,11 +267,11 @@ static double SinStage3(double x) { * Associated math function: sin(x) * Allowed input range: anything */ -double Math_Sin(double x) { +float Math_SinF(float x) { double x_div_pi; x_div_pi = x * DIV_2_PI; - return SinStage3(x_div_pi - Floord(x_div_pi)); + return (float)SinStage3(x_div_pi - Floord(x_div_pi)); } /************ @@ -289,11 +284,11 @@ double Math_Sin(double x) { * Associated math function: cos(x) * Allowed input range: anything */ -double Math_Cos(double x) { +float Math_CosF(float x) { double x_div_pi_shifted; x_div_pi_shifted = x * DIV_2_PI + 0.25; - return SinStage3(x_div_pi_shifted - Floord(x_div_pi_shifted)); + return (float)SinStage3(x_div_pi_shifted - Floord(x_div_pi_shifted)); } /************ @@ -433,7 +428,7 @@ double Math_Log2(double x) { if (x == POS_INF) return POS_INF; - if (x == NEG_INF || x == DBL_NAN || x <= 0.0) + if (x == DBL_NAN || x <= 0.0) return DBL_NAN; doi.d = x; @@ -445,7 +440,7 @@ double Math_Log2(double x) { return exponent + Log2Stage1(doi.d); } - +#endif // Approximation of atan2f using the Remez algorithm // https://math.stackexchange.com/a/1105038 @@ -468,4 +463,6 @@ float Math_Atan2f(float x, float y) { if (y < 0) r = -r; return r; } -#endif \ No newline at end of file + +double Math_Sin(double x) { return Math_SinF(x); } +double Math_Cos(double x) { return Math_CosF(x); } \ No newline at end of file diff --git a/src/ExtMath.h b/src/ExtMath.h index a4a689c..d1c840f 100644 --- a/src/ExtMath.h +++ b/src/ExtMath.h @@ -29,8 +29,8 @@ int Math_AbsI(int x); CC_API double Math_Sin(double x); CC_API double Math_Cos(double x); -float Math_SinF(float x); -float Math_CosF(float x); +CC_API float Math_SinF(float x); +CC_API float Math_CosF(float x); /* Computes atan2(y, x), intended primarily for angle calculation*/ /* Note that accuracy is only up to around 4 decimal places */ float Math_Atan2f(float x, float y); diff --git a/src/FancyLighting.c b/src/FancyLighting.c new file mode 100644 index 0000000..d9429fc --- /dev/null +++ b/src/FancyLighting.c @@ -0,0 +1,580 @@ +#include "Lighting.h" +#include "Block.h" +#include "Funcs.h" +#include "MapRenderer.h" +#include "Platform.h" +#include "World.h" +#include "Logger.h" +#include "Event.h" +#include "Game.h" +#include "String.h" +#include "Chat.h" +#include "ExtMath.h" +#include "Options.h" +#include "Queue.h" + + +struct LightNode { + IVec3 coords; /* 12 bytes */ + cc_uint8 brightness; /* 1 byte */ + /* char padding[3]; */ +}; + +static struct Queue lightQueue; +static struct Queue unlightQueue; + +/* Top face, X face, Z face, bottomY face*/ +#define PALETTE_SHADES 4 +/* One palette-group for sunlight, one palette-group for shadow */ +#define PALLETE_GROUP_COUNT 2 +#define PALETTE_COUNT (PALETTE_SHADES * PALLETE_GROUP_COUNT) + +#define PALETTE_YMAX_INDEX 0 +#define PALETTE_XSIDE_INDEX 1 +#define PALETTE_ZSIDE_INDEX 2 +#define PALETTE_YMIN_INDEX 3 + +/* Index into palettes of light colors. */ +/* There are 8 different palettes: Four block-face shades for shadowed areas and four block-face shades for sunlit areas. */ +/* A palette is a 16x16 color array indexed by a byte where the leftmost 4 bits represent lamplight level and the rightmost 4 bits represent lavalight level */ +/* E.G. myPalette[0b_0010_0001] will give us the color for lamp level 2 and lava level 1 (lowest level is 0) */ +static PackedCol* palettes[PALETTE_COUNT]; + +typedef cc_uint8* LightingChunk; +static cc_uint8* chunkLightingDataFlags; +#define CHUNK_UNCALCULATED 0 +#define CHUNK_SELF_CALCULATED 1 +#define CHUNK_ALL_CALCULATED 2 +static LightingChunk* chunkLightingData; + +#define MakePaletteIndex(lampLevel, lavaLevel) ((lampLevel << FANCY_LIGHTING_LAMP_SHIFT) | lavaLevel) +/* Fill in a palette with values based on the current light colors, shaded by the given shade value and lightened by the given ambientColor */ +static void InitPalette(PackedCol* palette, float shaded, PackedCol ambientColor) { + PackedCol lavaColor, lampColor; + int lampLevel, lavaLevel; + float curLerp; + + for (lampLevel = 0; lampLevel < FANCY_LIGHTING_LEVELS; lampLevel++) { + for (lavaLevel = 0; lavaLevel < FANCY_LIGHTING_LEVELS; lavaLevel++) { + if (lampLevel == FANCY_LIGHTING_LEVELS - 1) { + lampColor = Env.LampLightCol; + } + else { + curLerp = lampLevel / (float)(FANCY_LIGHTING_LEVELS - 1); + curLerp *= (MATH_PI / 2); + curLerp = Math_CosF(curLerp); + lampColor = PackedCol_Lerp(0, Env.LampLightCol, 1 - curLerp); + } + + curLerp = lavaLevel / (float)(FANCY_LIGHTING_LEVELS - 1); + curLerp *= (MATH_PI / 2); + curLerp = Math_CosF(curLerp); + + lavaColor = PackedCol_Lerp(0, Env.LavaLightCol, 1 - curLerp); + + /* Blend the two light colors together, then blend that with the ambient color, then shade that by the face darkness */ + palette[MakePaletteIndex(lampLevel, lavaLevel)] = + PackedCol_Scale(PackedCol_ScreenBlend(PackedCol_ScreenBlend(lampColor, lavaColor), ambientColor), shaded); + } + } +} +static void InitPalettes(void) { + int i; + for (i = 0; i < PALETTE_COUNT; i++) { + palettes[i] = (PackedCol*)Mem_Alloc(FANCY_LIGHTING_LEVELS * FANCY_LIGHTING_LEVELS, sizeof(PackedCol), "light color palette"); + } + i = 0; + InitPalette(palettes[i + PALETTE_YMAX_INDEX], 1, Env.ShadowCol); + InitPalette(palettes[i + PALETTE_XSIDE_INDEX], PACKEDCOL_SHADE_X, Env.ShadowCol); + InitPalette(palettes[i + PALETTE_ZSIDE_INDEX], PACKEDCOL_SHADE_Z, Env.ShadowCol); + InitPalette(palettes[i + PALETTE_YMIN_INDEX], PACKEDCOL_SHADE_YMIN, Env.ShadowCol); + i += PALETTE_SHADES; + InitPalette(palettes[i + PALETTE_YMAX_INDEX], 1, Env.SunCol); + InitPalette(palettes[i + PALETTE_XSIDE_INDEX], PACKEDCOL_SHADE_X, Env.SunCol); + InitPalette(palettes[i + PALETTE_ZSIDE_INDEX], PACKEDCOL_SHADE_Z, Env.SunCol); + InitPalette(palettes[i + PALETTE_YMIN_INDEX], PACKEDCOL_SHADE_YMIN, Env.SunCol); +} +static void FreePalettes(void) { + int i; + for (i = 0; i < PALETTE_COUNT; i++) { + Mem_Free(palettes[i]); + } +} + +static int chunksCount; +static void AllocState(void) { + ClassicLighting_AllocState(); + InitPalettes(); + chunksCount = World.ChunksCount; + + chunkLightingDataFlags = (cc_uint8*)Mem_AllocCleared(chunksCount, sizeof(cc_uint8), "light flags"); + chunkLightingData = (LightingChunk*)Mem_AllocCleared(chunksCount, sizeof(LightingChunk), "light chunks"); + Queue_Init(&lightQueue, sizeof(struct LightNode)); + Queue_Init(&unlightQueue, sizeof(struct LightNode)); +} + +static void FreeState(void) { + int i; + ClassicLighting_FreeState(); + + /* This function can be called multiple times without calling AllocState, so... */ + if (!chunkLightingDataFlags) return; + + FreePalettes(); + + for (i = 0; i < chunksCount; i++) { + Mem_Free(chunkLightingData[i]); + } + + Mem_Free(chunkLightingDataFlags); + Mem_Free(chunkLightingData); + chunkLightingDataFlags = NULL; + chunkLightingData = NULL; + Queue_Clear(&lightQueue); + Queue_Clear(&unlightQueue); +} + +/* Converts chunk x/y/z coordinates to the corresponding index in chunks array/list */ +#define ChunkCoordsToIndex(cx, cy, cz) (((cy) * World.ChunksZ + (cz)) * World.ChunksX + (cx)) +/* Converts local x/y/z coordinates to the corresponding index in a chunk */ +#define LocalCoordsToIndex(lx, ly, lz) ((lx) | ((lz) << CHUNK_SHIFT) | ((ly) << (CHUNK_SHIFT * 2))) +/* Converts global x/y/z coordinates to the corresponding index in a chunk */ +#define GlobalCoordsToChunkCoordsIndex(x, y, z) (LocalCoordsToIndex(x & CHUNK_MASK, y & CHUNK_MASK, z & CHUNK_MASK)) + +/* Sets the light level at this cell. Does NOT check that the cell is in bounds. */ +static void SetBrightness(cc_uint8 brightness, int x, int y, int z, cc_bool isLamp, cc_bool refreshChunk) { + cc_uint8 clearMask, shift = isLamp ? FANCY_LIGHTING_LAMP_SHIFT : 0, prevValue; + int cx = x >> CHUNK_SHIFT, lx = x & CHUNK_MASK; + int cy = y >> CHUNK_SHIFT, ly = y & CHUNK_MASK; + int cz = z >> CHUNK_SHIFT, lz = z & CHUNK_MASK; + int chunkIndex = ChunkCoordsToIndex(cx, cy, cz); + int localIndex = LocalCoordsToIndex(lx, ly, lz); + + if (chunkLightingData[chunkIndex] == NULL) { + chunkLightingData[chunkIndex] = (cc_uint8*)Mem_TryAllocCleared(CHUNK_SIZE_3, sizeof(cc_uint8)); + } + + /* 00001111 if lamp, otherwise 11110000*/ + clearMask = ~(FANCY_LIGHTING_MAX_LEVEL << shift); + + if (refreshChunk) { + prevValue = chunkLightingData[chunkIndex][localIndex]; + + chunkLightingData[chunkIndex][localIndex] &= clearMask; + chunkLightingData[chunkIndex][localIndex] |= brightness << shift; + + /* There is no reason to refresh current chunk as the builder does that automatically */ + if (prevValue != chunkLightingData[chunkIndex][localIndex]) { + if (lx == CHUNK_MAX) MapRenderer_RefreshChunk(cx + 1, cy, cz); + if (lx == 0) MapRenderer_RefreshChunk(cx - 1, cy, cz); + if (ly == CHUNK_MAX) MapRenderer_RefreshChunk(cx, cy + 1, cz); + if (ly == 0) MapRenderer_RefreshChunk(cx, cy - 1, cz); + if (lz == CHUNK_MAX) MapRenderer_RefreshChunk(cx, cy, cz + 1); + if (lz == 0) MapRenderer_RefreshChunk(cx, cy, cz - 1); + } + } + else { + chunkLightingData[chunkIndex][localIndex] &= clearMask; + chunkLightingData[chunkIndex][localIndex] |= brightness << shift; + } +} +/* Returns the light level at this cell. Does NOT check that the cell is in bounds. */ +static cc_uint8 GetBrightness(int x, int y, int z, cc_bool isLamp) { + int cx = x >> CHUNK_SHIFT, lx = x & CHUNK_MASK; + int cy = y >> CHUNK_SHIFT, ly = y & CHUNK_MASK; + int cz = z >> CHUNK_SHIFT, lz = z & CHUNK_MASK; + int chunkIndex = ChunkCoordsToIndex(cx, cy, cz), localIndex; + + if (chunkLightingData[chunkIndex] == NULL) { return 0; } + localIndex = LocalCoordsToIndex(lx, ly, lz); + + return isLamp ? + chunkLightingData[chunkIndex][localIndex] >> FANCY_LIGHTING_LAMP_SHIFT : + chunkLightingData[chunkIndex][localIndex] & FANCY_LIGHTING_MAX_LEVEL; +} + + +/* Light can never pass through a block that's full sized and blocks light */ +/* We can assume a block is full sized if none of the LightOffset flags are 0 */ +#define IsFullOpaque(thisBlock) (Blocks.BlocksLight[thisBlock] && Blocks.LightOffset[thisBlock] == 0xFF) + +/* If it's not opaque and it doesn't block light, or it is brighter than 0, we can always pass through */ +/* Light can always pass through leaves and water */ +#define IsFullTransparent(thisBlock)\ +(\ +(Blocks.Draw[thisBlock] > DRAW_OPAQUE && !Blocks.BlocksLight[thisBlock]) || \ +Blocks.Draw[thisBlock] == DRAW_TRANSPARENT_THICK || \ +Blocks.Draw[thisBlock] == DRAW_TRANSLUCENT\ +) + +static cc_bool CanLightPass(BlockID thisBlock, Face face) { + if (IsFullTransparent(thisBlock)) { return true; } + if (Blocks.Brightness[thisBlock]) { return true; } + if (IsFullOpaque(thisBlock)) { return false; } + /* Is stone's face hidden by thisBlock? TODO: Don't hardcode using stone */ + return !Block_IsFaceHidden(BLOCK_STONE, thisBlock, face); +} + +#define Light_TrySpreadInto(axis, AXIS, dir, limit, isLamp, thisFace, thatFace) \ + if (ln.coords.axis dir ## = limit && \ + CanLightPass(thisBlock, FACE_ ## AXIS ## thisFace) && \ + CanLightPass(World_GetBlock(ln.coords.x, ln.coords.y, ln.coords.z), FACE_ ## AXIS ## thatFace) && \ + GetBrightness(ln.coords.x, ln.coords.y, ln.coords.z, isLamp) < ln.brightness) { \ + Queue_Enqueue(&lightQueue, &ln); \ + } \ + +static void FlushLightQueue(cc_bool isLamp, cc_bool refreshChunk) { + struct LightNode ln; + cc_uint8 brightnessHere; + BlockID thisBlock; + + while (lightQueue.count > 0) { + ln = *(struct LightNode*)(Queue_Dequeue(&lightQueue)); + + brightnessHere = GetBrightness(ln.coords.x, ln.coords.y, ln.coords.z, isLamp); + + /* If this cell is already more lit, we can assume this cell and its neighbors have been accounted for */ + if (brightnessHere >= ln.brightness) { continue; } + if (ln.brightness == 0) { continue; } + + SetBrightness(ln.brightness, ln.coords.x, ln.coords.y, ln.coords.z, isLamp, refreshChunk); + + thisBlock = World_GetBlock(ln.coords.x, ln.coords.y, ln.coords.z); + ln.brightness--; + if (ln.brightness == 0) continue; + + ln.coords.x--; + Light_TrySpreadInto(x, X, > , 0, isLamp, MAX, MIN) + ln.coords.x += 2; + Light_TrySpreadInto(x, X, < , World.MaxX, isLamp, MIN, MAX) + ln.coords.x--; + + ln.coords.y--; + Light_TrySpreadInto(y, Y, >, 0, isLamp, MAX, MIN) + ln.coords.y += 2; + Light_TrySpreadInto(y, Y, <, World.MaxY, isLamp, MIN, MAX) + ln.coords.y--; + + ln.coords.z--; + Light_TrySpreadInto(z, Z, > , 0, isLamp, MAX, MIN) + ln.coords.z += 2; + Light_TrySpreadInto(z, Z, < , World.MaxZ, isLamp, MIN, MAX) + } +} + +cc_uint8 GetBlockBrightness(BlockID curBlock, cc_bool isLamp) { + if (isLamp) return Blocks.Brightness[curBlock] >> FANCY_LIGHTING_LAMP_SHIFT; + return Blocks.Brightness[curBlock] & FANCY_LIGHTING_MAX_LEVEL; +} + +static void CalculateChunkLightingSelf(int chunkIndex, int cx, int cy, int cz) { + int x, y, z; + /* Block coordinates */ + int chunkStartX, chunkStartY, chunkStartZ, chunkEndX, chunkEndY, chunkEndZ; + cc_uint8 brightness; + BlockID curBlock; + chunkStartX = cx * CHUNK_SIZE; + chunkStartY = cy * CHUNK_SIZE; + chunkStartZ = cz * CHUNK_SIZE; + chunkEndX = chunkStartX + CHUNK_SIZE; + chunkEndY = chunkStartY + CHUNK_SIZE; + chunkEndZ = chunkStartZ + CHUNK_SIZE; + struct LightNode entry; + + if (chunkEndX > World.Width ) { chunkEndX = World.Width; } + if (chunkEndY > World.Height) { chunkEndY = World.Height; } + if (chunkEndZ > World.Length) { chunkEndZ = World.Length; } + + for (y = chunkStartY; y < chunkEndY; y++) { + for (z = chunkStartZ; z < chunkEndZ; z++) { + for (x = chunkStartX; x < chunkEndX; x++) { + + curBlock = World_GetBlock(x, y, z); + + if (Blocks.Brightness[curBlock] > 0) { + + brightness = GetBlockBrightness(curBlock, false); + + if (brightness > 0) { + entry = (struct LightNode){ { x, y, z }, brightness }; + Queue_Enqueue(&lightQueue, &entry); + FlushLightQueue(false, false); + } + else { + /* If no lava brightness, it must use lamp brightness */ + brightness = Blocks.Brightness[curBlock] >> FANCY_LIGHTING_LAMP_SHIFT; + entry = (struct LightNode){ { x, y, z }, brightness }; + Queue_Enqueue(&lightQueue, &entry); + FlushLightQueue(true, false); + } + } + + /* Note: This code only deals with generating light from block sources. + Regular sun light is added on as a "post process" step when returning light color in the exposed API. + This has the added benefit of being able to skip allocating chunk lighting data in regions that have no light-casting blocks*/ + } + } + } + + chunkLightingDataFlags[chunkIndex] = CHUNK_SELF_CALCULATED; +} + +static void CalculateChunkLightingAll(int chunkIndex, int cx, int cy, int cz) { + int x, y, z; + /* Chunk coordinates */ + int chunkStartX, chunkStartY, chunkStartZ; + int chunkEndX, chunkEndY, chunkEndZ; + int curChunkIndex; + + chunkStartX = cx - 1; + chunkStartY = cy - 1; + chunkStartZ = cz - 1; + chunkEndX = cx + 1; + chunkEndY = cy + 1; + chunkEndZ = cz + 1; + + if (chunkStartX == -1) { chunkStartX++; } + if (chunkStartY == -1) { chunkStartY++; } + if (chunkStartZ == -1) { chunkStartZ++; } + if (chunkEndX == World.ChunksX) { chunkEndX--; } + if (chunkEndY == World.ChunksY) { chunkEndY--; } + if (chunkEndZ == World.ChunksZ) { chunkEndZ--; } + + for (y = chunkStartY; y <= chunkEndY; y++) { + for (z = chunkStartZ; z <= chunkEndZ; z++) { + for (x = chunkStartX; x <= chunkEndX; x++) { + curChunkIndex = ChunkCoordsToIndex(x, y, z); + + if (chunkLightingDataFlags[curChunkIndex] == CHUNK_UNCALCULATED) { + CalculateChunkLightingSelf(curChunkIndex, x, y, z); + } + } + } + } + chunkLightingDataFlags[chunkIndex] = CHUNK_ALL_CALCULATED; +} + + +#define Light_TryUnSpreadInto(axis, dir, limit, AXIS, thisFace, thatFace) \ + if (neighborCoords.axis dir ## = limit && \ + CanLightPass(thisBlock, FACE_ ## AXIS ## thisFace) && \ + CanLightPass(World_GetBlock(neighborCoords.x, neighborCoords.y, neighborCoords.z), FACE_ ## AXIS ## thatFace) \ + ) \ + { \ + neighborBrightness = GetBrightness(neighborCoords.x, neighborCoords.y, neighborCoords.z, isLamp); \ + neighborBlockBrightness = GetBlockBrightness(World_GetBlock(neighborCoords.x, neighborCoords.y, neighborCoords.z), isLamp); \ + /* This spot is a light caster, mark this spot as needing to be re-spread */ \ + if (neighborBlockBrightness > 0) { \ + otherNode = (struct LightNode){ { neighborCoords.x, neighborCoords.y, neighborCoords.z }, neighborBlockBrightness }; \ + Queue_Enqueue(&lightQueue, &otherNode); \ + } \ + if (neighborBrightness > 0) { \ + /* This neighbor is darker than cur spot, darken it*/ \ + if (neighborBrightness < curNode.brightness) { \ + SetBrightness(0, neighborCoords.x, neighborCoords.y, neighborCoords.z, isLamp, true); \ + otherNode = (struct LightNode){ { neighborCoords.x, neighborCoords.y, neighborCoords.z }, neighborBrightness }; \ + Queue_Enqueue(&unlightQueue, &otherNode); \ + } \ + /* This neighbor is brighter or same, mark this spot as needing to be re-spread */ \ + else { \ + /* But only if the neighbor actually *can* spread to this block */ \ + if ( \ + CanLightPass(thisBlockTrue, FACE_ ## AXIS ## thisFace) && \ + CanLightPass(World_GetBlock(neighborCoords.x, neighborCoords.y, neighborCoords.z), FACE_ ## AXIS ## thatFace) \ + ) \ + { \ + otherNode = curNode; \ + otherNode.brightness = neighborBrightness-1; \ + Queue_Enqueue(&lightQueue, &otherNode); \ + } \ + } \ + } \ + } \ + +/* Spreads darkness out from this point and relights any necessary areas afterward */ +static void CalcUnlight(int x, int y, int z, cc_uint8 brightness, cc_bool isLamp) { + int count = 0; + struct LightNode curNode, otherNode; + cc_uint8 neighborBrightness, neighborBlockBrightness; + IVec3 neighborCoords; + BlockID thisBlockTrue, thisBlock; + + SetBrightness(0, x, y, z, isLamp, true); + curNode = (struct LightNode){ { x, y, z }, brightness }; + Queue_Enqueue(&unlightQueue, &curNode); + + while (unlightQueue.count > 0) { + curNode = *(struct LightNode*)(Queue_Dequeue(&unlightQueue)); + neighborCoords = curNode.coords; + + thisBlockTrue = World_GetBlock(neighborCoords.x, neighborCoords.y, neighborCoords.z); + /* For the original cell in the queue, assume this block is air + so that light can unspread "out" of it in the case of a solid blocks. */ + thisBlock = count == 0 ? BLOCK_AIR : thisBlockTrue; + + count++; + + neighborCoords.x--; + Light_TryUnSpreadInto(x, >, 0, X, MAX, MIN) + neighborCoords.x += 2; + Light_TryUnSpreadInto(x, <, World.MaxX, X, MIN, MAX) + neighborCoords.x--; + + neighborCoords.y--; + Light_TryUnSpreadInto(y, >, 0, Y, MAX, MIN) + neighborCoords.y += 2; + Light_TryUnSpreadInto(y, <, World.MaxY, Y, MIN, MAX) + neighborCoords.y--; + + neighborCoords.z--; + Light_TryUnSpreadInto(z, >, 0, Z, MAX, MIN) + neighborCoords.z += 2; + Light_TryUnSpreadInto(z, <, World.MaxZ, Z, MIN, MAX) + } + + FlushLightQueue(isLamp, true); +} +static void CalcBlockChange(int x, int y, int z, BlockID oldBlock, BlockID newBlock, cc_bool isLamp) { + cc_uint8 oldBlockLightLevel = GetBlockBrightness(oldBlock, isLamp); + cc_uint8 newBlockLightLevel = GetBlockBrightness(newBlock, isLamp); + cc_uint8 oldLightLevelHere = GetBrightness(x, y, z, isLamp); + struct LightNode entry; + + /* Cell has no lighting and new block doesn't cast light and blocks all light, no change */ + if (!oldLightLevelHere && !newBlockLightLevel && IsFullOpaque(newBlock)) return; + + /* Cell is darker than the new block, only brighter case */ + if (oldLightLevelHere < newBlockLightLevel) { + /* brighten this spot, recalculate lighting */ + entry = (struct LightNode){ { x, y, z }, newBlockLightLevel }; + Queue_Enqueue(&lightQueue, &entry); + FlushLightQueue(isLamp, true); + return; + } + + /* Light passes through old and new, old block does not cast light, new block does not cast light; no change */ + if (IsFullTransparent(oldBlock) && IsFullTransparent(newBlock) && !oldBlockLightLevel && !newBlockLightLevel) return; + + CalcUnlight(x, y, z, oldLightLevelHere, isLamp); +} +static void OnBlockChanged(int x, int y, int z, BlockID oldBlock, BlockID newBlock) { + /* For some reason this is a possible case */ + if (oldBlock == newBlock) { return; } + + ClassicLighting_OnBlockChanged(x, y, z, oldBlock, newBlock); + + CalcBlockChange(x, y, z, oldBlock, newBlock, false); + CalcBlockChange(x, y, z, oldBlock, newBlock, true); +} +/* Invalidates/Resets lighting state for all of the blocks in the world */ +/* (e.g. because a block changed whether it is full bright or not) */ +static void Refresh(void) { + ClassicLighting_Refresh(); + FreeState(); + AllocState(); +} +static cc_bool IsLit(int x, int y, int z) { return ClassicLighting_IsLit(x, y, z); } +static cc_bool IsLit_Fast(int x, int y, int z) { return ClassicLighting_IsLit_Fast(x, y, z); } + +#define CalcForChunkIfNeeded(cx, cy, cz, chunkIndex) \ + if (chunkLightingDataFlags[chunkIndex] < CHUNK_ALL_CALCULATED) { \ + CalculateChunkLightingAll(chunkIndex, cx, cy, cz); \ + } + +static PackedCol Color_Core(int x, int y, int z, int paletteFace) { + cc_uint8 lightData; + int cx, cy, cz, chunkIndex; + int chunkCoordsIndex; + + cx = x >> CHUNK_SHIFT; + cy = y >> CHUNK_SHIFT; + cz = z >> CHUNK_SHIFT; + + chunkIndex = ChunkCoordsToIndex(cx, cy, cz); + CalcForChunkIfNeeded(cx, cy, cz, chunkIndex); + + /* There might be no light data in this chunk even after it was calculated */ + if (chunkLightingData[chunkIndex] == NULL) { + lightData = 0; + } else { + chunkCoordsIndex = GlobalCoordsToChunkCoordsIndex(x, y, z); + lightData = chunkLightingData[chunkIndex][chunkCoordsIndex]; + } + + /* This cell is exposed to sunlight */ + if (y > ClassicLighting_GetLightHeight(x, z)) { + /* Push the pointer forward into the sun lit palette section */ + paletteFace += PALETTE_SHADES; + } + + return palettes[paletteFace][lightData]; +} + +#define TRY_OOB_CASE(sun, shadow) if (!World_Contains(x, y, z)) return y >= Env.EdgeHeight ? sun : shadow +static PackedCol Color(int x, int y, int z) { + TRY_OOB_CASE(Env.SunCol, Env.ShadowCol); + return Color_Core(x, y, z, PALETTE_YMAX_INDEX); +} +static PackedCol Color_YMaxSide(int x, int y, int z) { + TRY_OOB_CASE(Env.SunCol, Env.ShadowCol); + return Color_Core(x, y, z, PALETTE_YMAX_INDEX); +} +static PackedCol Color_YMinSide(int x, int y, int z) { + TRY_OOB_CASE(Env.SunYMin, Env.ShadowYMin); + return Color_Core(x, y, z, PALETTE_YMIN_INDEX); +} +static PackedCol Color_XSide(int x, int y, int z) { + TRY_OOB_CASE(Env.SunXSide, Env.ShadowXSide); + return Color_Core(x, y, z, PALETTE_XSIDE_INDEX); +} +static PackedCol Color_ZSide(int x, int y, int z) { + TRY_OOB_CASE(Env.SunZSide, Env.ShadowZSide); + return Color_Core(x, y, z, PALETTE_ZSIDE_INDEX); +} + +static void LightHint(int startX, int startY, int startZ) { + int cx, cy, cz, chunkIndex; + ClassicLighting_LightHint(startX, startY, startZ); + /* Add 1 to startX/Z, as coordinates are for the extended chunk (18x18x18) */ + startX++; startY++; startZ++; + + cx = (startX + HALF_CHUNK_SIZE) >> CHUNK_SHIFT; + cy = (startY + HALF_CHUNK_SIZE) >> CHUNK_SHIFT; + cz = (startZ + HALF_CHUNK_SIZE) >> CHUNK_SHIFT; + + chunkIndex = ChunkCoordsToIndex(cx, cy, cz); + CalcForChunkIfNeeded(cx, cy, cz, chunkIndex); +} + +void FancyLighting_SetActive(void) { + Lighting.OnBlockChanged = OnBlockChanged; + Lighting.Refresh = Refresh; + Lighting.IsLit = IsLit; + Lighting.Color = Color; + Lighting.Color_XSide = Color_XSide; + + Lighting.IsLit_Fast = IsLit_Fast; + Lighting.Color_Sprite_Fast = Color; + Lighting.Color_YMax_Fast = Color; + Lighting.Color_YMin_Fast = Color_YMinSide; + Lighting.Color_XSide_Fast = Color_XSide; + Lighting.Color_ZSide_Fast = Color_ZSide; + + Lighting.FreeState = FreeState; + Lighting.AllocState = AllocState; + Lighting.LightHint = LightHint; +} + +static void OnEnvVariableChanged(void* obj, int envVar) { + /* This is always called, but should only do anything if fancy lighting is on */ + if (Lighting_Mode == LIGHTING_MODE_CLASSIC) { return; } + + if (envVar == ENV_VAR_SUN_COLOR || envVar == ENV_VAR_SHADOW_COLOR || envVar == ENV_VAR_LAVALIGHT_COLOR || envVar == ENV_VAR_LAMPLIGHT_COLOR) { + InitPalettes(); + } + if (envVar == ENV_VAR_LAVALIGHT_COLOR || envVar == ENV_VAR_LAMPLIGHT_COLOR) MapRenderer_Refresh(); +} + +void FancyLighting_OnInit(void) { + Event_Register_(&WorldEvents.EnvVarChanged, NULL, OnEnvVariableChanged); +} \ No newline at end of file diff --git a/src/Formats.c b/src/Formats.c index 6b948e3..af16b4b 100644 --- a/src/Formats.c +++ b/src/Formats.c @@ -798,7 +798,7 @@ static void Cw_Callback_5(struct NbtTag* tag) { if (IsTag(tag, "CollideType")) { Blocks.Collide[id] = NbtTag_U8(tag); return; } if (IsTag(tag, "Speed")) { Blocks.SpeedMultiplier[id] = NbtTag_F32(tag); return; } if (IsTag(tag, "TransmitsLight")) { Blocks.BlocksLight[id] = NbtTag_U8(tag) == 0; return; } - if (IsTag(tag, "FullBright")) { Blocks.FullBright[id] = NbtTag_U8(tag) != 0; return; } + if (IsTag(tag, "FullBright")) { Blocks.Brightness[id] = Block_ReadBrightness(NbtTag_U8(tag)); return; } if (IsTag(tag, "BlockDraw")) { Blocks.Draw[id] = NbtTag_U8(tag); return; } if (IsTag(tag, "Shape")) { Blocks.SpriteOffset[id] = NbtTag_U8(tag); return; } @@ -1546,7 +1546,7 @@ static cc_result Cw_WriteBockDef(struct Stream* stream, int b) { cur = Nbt_WriteUInt8(cur, "TransmitsLight", Blocks.BlocksLight[b] ? 0 : 1); cur = Nbt_WriteUInt8(cur, "WalkSound", Blocks.DigSounds[b]); - cur = Nbt_WriteUInt8(cur, "FullBright", Blocks.FullBright[b] ? 1 : 0); + cur = Nbt_WriteUInt8(cur, "FullBright", Block_WriteFullBright(Blocks.Brightness[b])); cur = Nbt_WriteUInt8(cur, "Shape", sprite ? 0 : (cc_uint8)(Blocks.MaxBB[b].y * 16)); cur = Nbt_WriteUInt8(cur, "BlockDraw", sprite ? Blocks.SpriteOffset[b] : Blocks.Draw[b]); diff --git a/src/Game.c b/src/Game.c index 3f7d161..c883744 100644 --- a/src/Game.c +++ b/src/Game.c @@ -483,7 +483,7 @@ void Game_SetFpsLimit(int method) { } static void UpdateViewMatrix(void) { - Camera.Active->GetView(Entities.CurPlayer, &Gfx.View); + Camera.Active->GetView(&Gfx.View); FrustumCulling_CalcFrustumEquations(&Gfx.Projection, &Gfx.View); } @@ -607,7 +607,7 @@ static CC_INLINE void Game_DrawFrame(float delta, float t) { UpdateViewMatrix(); if (!Gui_GetBlocksWorld()) { - Camera.Active->GetPickedBlock(Entities.CurPlayer, &Game_SelectedPos); /* TODO: only pick when necessary */ + Camera.Active->GetPickedBlock(&Game_SelectedPos); /* TODO: only pick when necessary */ Camera_KeyLookUpdate(delta); InputHandler_Tick(); @@ -640,7 +640,7 @@ static void DrawSplitscreen(float delta, float t, int i, int x, int y, int w, in Entities.CurPlayer = &LocalPlayer_Instances[i]; LocalPlayer_SetInterpPosition(Entities.CurPlayer, t); - Camera.CurrentPos = Camera.Active->GetPosition(Entities.CurPlayer, t); + Camera.CurrentPos = Camera.Active->GetPosition(t); Game_DrawFrame(delta, t); } @@ -675,7 +675,7 @@ static CC_INLINE void Game_RenderFrame(double delta) { if (!Window_Main.Focused && !Gui.InputGrab) Gui_ShowPauseMenu(); - if (KeyBind_IsPressed(KEYBIND_ZOOM_SCROLL) && !Gui.InputGrab) { + if (InputBind_IsPressed(BIND_ZOOM_SCROLL) && !Gui.InputGrab) { InputHandler_SetFOV(Camera.ZoomFov); } @@ -684,7 +684,7 @@ static CC_INLINE void Game_RenderFrame(double delta) { t = (float)(entTask.accumulator / entTask.interval); LocalPlayer_SetInterpPosition(Entities.CurPlayer, t); - Camera.CurrentPos = Camera.Active->GetPosition(Entities.CurPlayer, t); + Camera.CurrentPos = Camera.Active->GetPosition(t); /* NOTE: EnvRenderer_UpdateFog also also sets clear color */ EnvRenderer_UpdateFog(); AudioBackend_Tick(); diff --git a/src/Graphics.h b/src/Graphics.h index 29b5487..b84e1dc 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -186,7 +186,7 @@ CC_API void Gfx_UnlockVb(GfxResourceID vb); /* Special case of Gfx_Create/LockVb for building chunks in Builder.c */ GfxResourceID Gfx_CreateVb2(void* vertices, VertexFormat fmt, int count); #endif -#ifdef CC_BUILD_GLMODERN +#if CC_GFX_BACKEND == CC_GFX_BACKEND_GL2 /* Special case Gfx_BindVb for use with Gfx_DrawIndexedTris_T2fC4b */ void Gfx_BindVb_Textured(GfxResourceID vb); #else diff --git a/src/Graphics_3DS.c b/src/Graphics_3DS.c index 36c8d53..422666a 100644 --- a/src/Graphics_3DS.c +++ b/src/Graphics_3DS.c @@ -439,7 +439,7 @@ void Gfx_SetFaceCulling(cc_bool enabled) { void Gfx_SetAlphaArgBlend(cc_bool enabled) { } -void Gfx_SetAlphaBlending(cc_bool enabled) { +static void SetAlphaBlend(cc_bool enabled) { if (enabled) { C3D_AlphaBlend(GPU_BLEND_ADD, GPU_BLEND_ADD, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA, GPU_SRC_ALPHA, GPU_ONE_MINUS_SRC_ALPHA); } else { @@ -447,7 +447,7 @@ void Gfx_SetAlphaBlending(cc_bool enabled) { } } -void Gfx_SetAlphaTest(cc_bool enabled) { +static void SetAlphaTest(cc_bool enabled) { C3D_AlphaTest(enabled, GPU_GREATER, 0x7F); } @@ -806,7 +806,7 @@ void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float matrix->row1.y = -2.0f / width; matrix->row4.y = 1.0f; - matrix->row3.z = 1.0f / (zNear - zFar); + matrix->row3.z = 1.0f / (zNear - zFar); matrix->row4.z = 0.5f * (zNear + zFar) / (zNear - zFar) - 0.5f; matrix->row4.w = 1.0f; } diff --git a/src/Graphics_D3D11.c b/src/Graphics_D3D11.c index 19f57f6..a6005ac 100644 --- a/src/Graphics_D3D11.c +++ b/src/Graphics_D3D11.c @@ -1,9 +1,9 @@ #include "Core.h" -#ifdef CC_BUILD_D3D11 +#if CC_GFX_BACKEND == CC_GFX_BACKEND_D3D11 #include "_GraphicsBase.h" #include "Errors.h" #include "Window.h" -#include "_D3D11Shaders.h" +#include "../misc/windows/D3D11Shaders.h" /* Avoid pointless includes */ #define WIN32_LEAN_AND_MEAN @@ -691,7 +691,7 @@ void Gfx_SetFaceCulling(cc_bool enabled) { static ID3D11SamplerState* ps_samplers[2]; static ID3D11PixelShader* ps_shaders[12]; static ID3D11Buffer* ps_cBuffer; -static cc_bool ps_alphaTesting, ps_mipmaps; +static cc_bool ps_mipmaps; static float ps_fogEnd, ps_fogDensity; static PackedCol ps_fogColor; static int ps_fogMode; @@ -725,7 +725,7 @@ static void PS_CreateShaders(void) { static int PS_CalcShaderIndex(void) { int idx = gfx_format == VERTEX_FORMAT_COLOURED ? 0 : 1; - if (ps_alphaTesting) idx += 2; + if (gfx_alphaTest) idx += 2; if (gfx_fogEnabled) { // uncomment when it works @@ -822,8 +822,7 @@ static void PS_Free(void) { PS_FreeConstants(); } -void Gfx_SetAlphaTest(cc_bool enabled) { - ps_alphaTesting = enabled; +static void SetAlphaTest(cc_bool enabled) { PS_UpdateShader(); } // unnecessary? check if any performance is gained, probably irrelevant @@ -887,10 +886,10 @@ void Gfx_DisableMipmaps(void) { static ID3D11RenderTargetView* backbuffer; static ID3D11Texture2D* depthbuffer; static ID3D11DepthStencilView* depthbufferView; -static ID3D11BlendState* om_blendStates[4]; +static ID3D11BlendState* om_blendStates[16 * 2]; static ID3D11DepthStencilState* om_depthStates[4]; static float gfx_clearColor[4]; -static cc_bool gfx_alphaBlending, gfx_colorEnabled = true; +static cc_bool gfx_channels[4] = { true, true, true, true }; static cc_bool gfx_depthTest, gfx_depthWrite; static void OM_Clear(GfxBuffers buffers) { @@ -972,8 +971,14 @@ static void OM_CreateBlendStates(void) { for (int i = 0; i < Array_Elems(om_blendStates); i++) { - desc.RenderTarget[0].RenderTargetWriteMask = (i & 1) ? D3D11_COLOR_WRITE_ENABLE_ALL : 0; - desc.RenderTarget[0].BlendEnable = (i & 2) != 0; + int mask = 0; + if (i & 0x01) mask |= D3D11_COLOR_WRITE_ENABLE_RED; + if (i & 0x02) mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; + if (i & 0x04) mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; + if (i & 0x08) mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; + + desc.RenderTarget[0].RenderTargetWriteMask = mask; + desc.RenderTarget[0].BlendEnable = (i & 0x10) != 0; hr = ID3D11Device_CreateBlendState(device, &desc, &om_blendStates[i]); if (hr) Logger_Abort2(hr, "Failed to create blend state"); @@ -981,7 +986,8 @@ static void OM_CreateBlendStates(void) { } static void OM_UpdateBlendState(void) { - ID3D11BlendState* blendState = om_blendStates[gfx_colorEnabled | (gfx_alphaBlending << 1)]; + int idx = (gfx_channels[0]) | (gfx_channels[1] << 1) | (gfx_channels[2] << 2) | (gfx_channels[3] << 3) | (gfx_alphaBlend << 4); + ID3D11BlendState* blendState = om_blendStates[idx]; ID3D11DeviceContext_OMSetBlendState(context, blendState, NULL, 0xffffffff); } @@ -1030,15 +1036,16 @@ void Gfx_SetDepthWrite(cc_bool enabled) { OM_UpdateDepthState(); } -void Gfx_SetAlphaBlending(cc_bool enabled) { - gfx_alphaBlending = enabled; +static void SetAlphaBlend(cc_bool enabled) { OM_UpdateBlendState(); } static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { - gfx_colorEnabled = r; + gfx_channels[0] = r; + gfx_channels[1] = g; + gfx_channels[2] = b; + gfx_channels[3] = a; OM_UpdateBlendState(); - // TODO all channels } void Gfx_DepthOnlyRendering(cc_bool depthOnly) { diff --git a/src/Graphics_D3D9.c b/src/Graphics_D3D9.c index 8cf140a..91ef33a 100644 --- a/src/Graphics_D3D9.c +++ b/src/Graphics_D3D9.c @@ -1,5 +1,5 @@ #include "Core.h" -#ifdef CC_BUILD_D3D9 +#if CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9 #include "_GraphicsBase.h" #include "Errors.h" #include "Window.h" @@ -394,7 +394,7 @@ void Gfx_DisableMipmaps(void) { *-----------------------------------------------------State management----------------------------------------------------* *#########################################################################################################################*/ static D3DFOGMODE gfx_fogMode = D3DFOG_NONE; -static cc_bool gfx_alphaTesting, gfx_alphaBlending; +static cc_bool gfx_alphaBlending; static cc_bool gfx_depthTesting, gfx_depthWriting; static PackedCol gfx_clearColor, gfx_fogColor; static float gfx_fogEnd = -1.0f, gfx_fogDensity = -1.0f; @@ -455,18 +455,12 @@ void Gfx_SetFogMode(FogFunc func) { IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, mode); } -void Gfx_SetAlphaTest(cc_bool enabled) { - if (gfx_alphaTesting == enabled) return; - gfx_alphaTesting = enabled; - +static void SetAlphaTest(cc_bool enabled) { if (Gfx.LostContext) return; IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, enabled); } -void Gfx_SetAlphaBlending(cc_bool enabled) { - if (gfx_alphaBlending == enabled) return; - gfx_alphaBlending = enabled; - +static void SetAlphaBlend(cc_bool enabled) { if (Gfx.LostContext) return; IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, enabled); } @@ -529,7 +523,7 @@ void Gfx_DepthOnlyRendering(cc_bool depthOnly) { static void D3D9_RestoreRenderStates(void) { union IntAndFloat raw; - IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, gfx_alphaTesting); + IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, gfx_alphaTest); IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, gfx_alphaBlending); IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, gfx_fogEnabled); diff --git a/src/Graphics_Dreamcast.c b/src/Graphics_Dreamcast.c index baaa9f0..615c1e0 100644 --- a/src/Graphics_Dreamcast.c +++ b/src/Graphics_Dreamcast.c @@ -18,19 +18,22 @@ static cc_bool renderingDisabled; *#########################################################################################################################*/ static void InitGLState(void) { glClearDepth(1.0f); - glDepthMask(GL_TRUE); - glShadeModel(GL_SMOOTH); - - glDisable(GL_ALPHA_TEST); - glDisable(GL_CULL_FACE); - glDisable(GL_BLEND); - glDisable(GL_DEPTH_TEST); - glDisable(GL_TEXTURE_2D); - glDisable(GL_FOG); + GPUSetAlphaCutOff(127); + + ALPHA_TEST_ENABLED = GL_FALSE; + CULLING_ENABLED = GL_FALSE; + BLEND_ENABLED = GL_FALSE; + DEPTH_TEST_ENABLED = GL_FALSE; + DEPTH_MASK_ENABLED = GL_TRUE; + TEXTURES_ENABLED = GL_FALSE; + FOG_ENABLED = GL_FALSE; + + STATE_DIRTY = GL_TRUE; } void Gfx_Create(void) { if (!Gfx.Created) glKosInit(); + Gfx_SetViewport(0, 0, Game.Width, Game.Height); InitGLState(); @@ -52,15 +55,21 @@ void Gfx_Free(void) { Gfx_FreeState(); } -#define gl_Toggle(cap) if (enabled) { glEnable(cap); } else { glDisable(cap); } - /*########################################################################################################################* *-----------------------------------------------------State management----------------------------------------------------* *#########################################################################################################################*/ static PackedCol gfx_clearColor; -void Gfx_SetFaceCulling(cc_bool enabled) { gl_Toggle(GL_CULL_FACE); } -void Gfx_SetAlphaBlending(cc_bool enabled) { gl_Toggle(GL_BLEND); } + +void Gfx_SetFaceCulling(cc_bool enabled) { + CULLING_ENABLED = enabled; + STATE_DIRTY = GL_TRUE; +} + +static void SetAlphaBlend(cc_bool enabled) { + BLEND_ENABLED = enabled; + STATE_DIRTY = GL_TRUE; +} void Gfx_SetAlphaArgBlend(cc_bool enabled) { } void Gfx_ClearColor(PackedCol color) { @@ -77,10 +86,24 @@ static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { // TODO: Doesn't work } -void Gfx_SetDepthWrite(cc_bool enabled) { glDepthMask(enabled); } -void Gfx_SetDepthTest(cc_bool enabled) { gl_Toggle(GL_DEPTH_TEST); } +void Gfx_SetDepthWrite(cc_bool enabled) { + if (DEPTH_MASK_ENABLED == enabled) return; + + DEPTH_MASK_ENABLED = enabled; + STATE_DIRTY = GL_TRUE; +} -void Gfx_SetAlphaTest(cc_bool enabled) { gl_Toggle(GL_ALPHA_TEST); } +void Gfx_SetDepthTest(cc_bool enabled) { + if (DEPTH_TEST_ENABLED == enabled) return; + + DEPTH_TEST_ENABLED = enabled; + STATE_DIRTY = GL_TRUE; +} + +static void SetAlphaTest(cc_bool enabled) { + ALPHA_TEST_ENABLED = enabled; + STATE_DIRTY = GL_TRUE; +} void Gfx_DepthOnlyRendering(cc_bool depthOnly) { // don't need a fake second pass in this case @@ -353,7 +376,10 @@ static FogFunc gfx_fogMode = -1; void Gfx_SetFog(cc_bool enabled) { gfx_fogEnabled = enabled; - if (enabled) { glEnable(GL_FOG); } else { glDisable(GL_FOG); } + if (FOG_ENABLED == enabled) return; + + FOG_ENABLED = enabled; + STATE_DIRTY = GL_TRUE; } void Gfx_SetFogCol(PackedCol color) { @@ -372,7 +398,7 @@ static void UpdateFog(void) { if (gfx_fogMode == FOG_LINEAR) { pvr_fog_table_linear(0.0f, gfx_fogEnd); } else if (gfx_fogMode == FOG_EXP) { - pvr_fog_table_exp(gfx_fogDensity); + pvr_fog_table_exp(gfx_fogDensity); } else if (gfx_fogMode == FOG_EXP2) { pvr_fog_table_exp2(gfx_fogDensity); } @@ -453,8 +479,6 @@ static void Gfx_FreeState(void) { FreeDefaultResources(); } static void Gfx_RestoreState(void) { InitDefaultResources(); gfx_format = -1; - - glAlphaFunc(GL_GREATER, 0.5f); } cc_bool Gfx_WarnIfNecessary(void) { @@ -467,30 +491,34 @@ cc_bool Gfx_WarnIfNecessary(void) { *#########################################################################################################################*/ #define VB_PTR gfx_vertices static const void* VERTEX_PTR; +extern void apply_poly_header(PolyHeader* header, PolyList* activePolyList); -extern void DrawColouredQuads(const void* src, Vertex* dst, int numQuads); -extern void DrawTexturedQuads(const void* src, Vertex* dst, int numQuads); +extern Vertex* DrawColouredQuads(const void* src, Vertex* dst, int numQuads); +extern Vertex* DrawTexturedQuads(const void* src, Vertex* dst, int numQuads); void DrawQuads(int count) { if (!count) return; - Vertex* start = submitVertices(count); - - if (TEXTURES_ENABLED) { - DrawTexturedQuads(VERTEX_PTR, start, count >> 2); - } else { - DrawColouredQuads(VERTEX_PTR, start, count >> 2); + PolyList* output = _glActivePolyList(); + AlignedVectorHeader* hdr = &output->vector.hdr; + + uint32_t header_required = (hdr->size == 0) || STATE_DIRTY; + // Reserve room for the vertices and header + Vertex* beg = aligned_vector_reserve(&output->vector, hdr->size + (header_required) + count); + + if (header_required) { + apply_poly_header((PolyHeader*)beg, output); + STATE_DIRTY = GL_FALSE; + beg++; + hdr->size += 1; } -} - + Vertex* end; -static void SetupVertices(int startVertex) { - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED; - gldcVertexPointer(SIZEOF_VERTEX_TEXTURED, (void*)(VB_PTR + offset)); + if (TEXTURES_ENABLED) { + end = DrawTexturedQuads(VERTEX_PTR, beg, count >> 2); } else { - cc_uint32 offset = startVertex * SIZEOF_VERTEX_COLOURED; - gldcVertexPointer(SIZEOF_VERTEX_COLOURED, (void*)(VB_PTR + offset)); + end = DrawColouredQuads(VERTEX_PTR, beg, count >> 2); } + hdr->size += (end - beg); } void Gfx_SetVertexFormat(VertexFormat fmt) { @@ -498,11 +526,8 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { gfx_format = fmt; gfx_stride = strideSizes[fmt]; - if (fmt == VERTEX_FORMAT_TEXTURED) { - glEnable(GL_TEXTURE_2D); - } else { - glDisable(GL_TEXTURE_2D); - } + TEXTURES_ENABLED = fmt == VERTEX_FORMAT_TEXTURED; + STATE_DIRTY = GL_TRUE; } void Gfx_DrawVb_Lines(int verticesCount) { @@ -512,10 +537,10 @@ void Gfx_DrawVb_Lines(int verticesCount) { void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { if (gfx_format == VERTEX_FORMAT_TEXTURED) { - VERTEX_PTR = gfx_vertices + startVertex * SIZEOF_VERTEX_TEXTURED; - } else { - VERTEX_PTR = gfx_vertices + startVertex * SIZEOF_VERTEX_COLOURED; - } + VERTEX_PTR = gfx_vertices + startVertex * SIZEOF_VERTEX_TEXTURED; + } else { + VERTEX_PTR = gfx_vertices + startVertex * SIZEOF_VERTEX_COLOURED; + } DrawQuads(verticesCount); } @@ -544,9 +569,8 @@ cc_result Gfx_TakeScreenshot(struct Stream* output) { } void Gfx_GetApiInfo(cc_string* info) { - GLint freeMem, usedMem; - glGetIntegerv(GL_FREE_TEXTURE_MEMORY_KOS, &freeMem); - glGetIntegerv(GL_USED_TEXTURE_MEMORY_KOS, &usedMem); + GLint freeMem = _glFreeTextureMemory(); + GLint usedMem = _glUsedTextureMemory(); float freeMemMB = freeMem / (1024.0 * 1024.0); float usedMemMB = usedMem / (1024.0 * 1024.0); @@ -571,6 +595,7 @@ void Gfx_ClearBuffers(GfxBuffers buffers) { } void Gfx_EndFrame(void) { + pvr_wait_ready(); glKosSwapBuffers(); if (gfx_minFrameMs) LimitFPS(); } @@ -579,14 +604,26 @@ void Gfx_OnWindowResize(void) { Gfx_SetViewport(0, 0, Game.Width, Game.Height); } +extern float VP_COL_HWIDTH, VP_TEX_HWIDTH; +extern float VP_COL_HHEIGHT, VP_TEX_HHEIGHT; +extern float VP_COL_X_PLUS_HWIDTH, VP_TEX_X_PLUS_HWIDTH; +extern float VP_COL_Y_PLUS_HHEIGHT, VP_TEX_Y_PLUS_HHEIGHT; + void Gfx_SetViewport(int x, int y, int w, int h) { if (x == 0 && y == 0 && w == Game.Width && h == Game.Height) { - glDisable(GL_SCISSOR_TEST); + SCISSOR_TEST_ENABLED = GL_FALSE; } else { - glEnable(GL_SCISSOR_TEST); + SCISSOR_TEST_ENABLED = GL_TRUE; } + STATE_DIRTY = GL_TRUE; glViewport(x, y, w, h); glScissor (x, y, w, h); + + VP_COL_HWIDTH = VP_TEX_HWIDTH = w * 0.5f; + VP_COL_HHEIGHT = VP_TEX_HHEIGHT = h * -0.5f; + + VP_COL_X_PLUS_HWIDTH = VP_TEX_X_PLUS_HWIDTH = x + w * 0.5f; + VP_COL_Y_PLUS_HHEIGHT = VP_TEX_Y_PLUS_HHEIGHT = y + h * 0.5f; } #endif diff --git a/src/Graphics_GCWii.c b/src/Graphics_GCWii.c index 923b0cf..66ea4e7 100644 --- a/src/Graphics_GCWii.c +++ b/src/Graphics_GCWii.c @@ -187,7 +187,7 @@ void Gfx_SetFaceCulling(cc_bool enabled) { GX_SetCullMode(enabled ? GX_CULL_FRONT : GX_CULL_NONE); } -void Gfx_SetAlphaBlending(cc_bool enabled) { +static void SetAlphaBlend(cc_bool enabled) { if (enabled) { GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); } else { @@ -212,9 +212,7 @@ static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { static cc_bool depth_write = true, depth_test = true; static void UpdateDepthState(void) { - // match Desktop behaviour, where disabling depth testing also disables depth writing - // TODO do we actually need to & here? - GX_SetZMode(depth_test, GX_LEQUAL, depth_write & depth_test); + GX_SetZMode(depth_test, GX_LEQUAL, depth_write); } void Gfx_SetDepthWrite(cc_bool enabled) { @@ -409,7 +407,7 @@ void Gfx_SetFogEnd(float value) { void Gfx_SetFogMode(FogFunc func) { } -void Gfx_SetAlphaTest(cc_bool enabled) { +static void SetAlphaTest(cc_bool enabled) { if (enabled) { GX_SetAlphaCompare(GX_GREATER, 127, GX_AOP_AND, GX_ALWAYS, 0); } else { @@ -560,7 +558,7 @@ static void Draw_ColouredTriangles(int verticesCount, int startVertex) { struct VertexColoured* v = (struct VertexColoured*)gfx_vertices + startVertex + i; GX_Position3f32(v->x, v->y, v->z); - GX_Color4u8(PackedCol_R(v->Col), PackedCol_G(v->Col), PackedCol_B(v->Col), PackedCol_A(v->Col)); + GX_Color1u32(v->Col); } GX_End(); } @@ -572,7 +570,7 @@ static void Draw_TexturedTriangles(int verticesCount, int startVertex) { struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; GX_Position3f32(v->x, v->y, v->z); - GX_Color4u8(PackedCol_R(v->Col), PackedCol_G(v->Col), PackedCol_B(v->Col), PackedCol_A(v->Col)); + GX_Color1u32(v->Col); GX_TexCoord2f32(v->U, v->V); } GX_End(); diff --git a/src/Graphics_GL1.c b/src/Graphics_GL1.c index ea26aa5..26beeb8 100644 --- a/src/Graphics_GL1.c +++ b/src/Graphics_GL1.c @@ -1,5 +1,9 @@ +/* Silence deprecation warnings on modern macOS/iOS */ +#define GL_SILENCE_DEPRECATION +#define GLES_SILENCE_DEPRECATION + #include "Core.h" -#if defined CC_BUILD_GL && !defined CC_BUILD_GLMODERN +#if CC_GFX_BACKEND == CC_GFX_BACKEND_GL1 #include "_GraphicsBase.h" #include "Errors.h" #include "Window.h" @@ -9,16 +13,16 @@ */ #if defined CC_BUILD_WIN -/* Avoid pointless includes */ -#define WIN32_LEAN_AND_MEAN -#define NOSERVICE -#define NOMCX -#define NOIME -#include -#define GLAPI WINGDIAPI + /* Avoid pointless includes */ + #define WIN32_LEAN_AND_MEAN + #define NOSERVICE + #define NOMCX + #define NOIME + #include + #define GLAPI WINGDIAPI #else -#define GLAPI extern -#define APIENTRY + #define GLAPI extern + #define APIENTRY #endif /* === BEGIN OPENGL HEADERS === */ typedef unsigned int GLenum; @@ -47,6 +51,7 @@ typedef cc_uintptr GLpointer; #define GL_LINES 0x0001 #define GL_TRIANGLES 0x0004 +#define GL_QUADS 0x0007 #define GL_BLEND 0x0BE2 #define GL_SRC_ALPHA 0x0302 @@ -104,50 +109,10 @@ typedef cc_uintptr GLpointer; #define GL_STATIC_DRAW 0x88E4 #define GL_DYNAMIC_DRAW 0x88E8 -GLAPI void APIENTRY glAlphaFunc(GLenum func, GLfloat ref); -GLAPI void APIENTRY glBindTexture(GLenum target, GLuint texture); -GLAPI void APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor); -GLAPI void APIENTRY glCallList(GLuint list); -GLAPI void APIENTRY glClear(GLuint mask); -GLAPI void APIENTRY glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GLAPI void APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -GLAPI void APIENTRY glColorPointer(GLint size, GLenum type, GLsizei stride, GLpointer pointer); -GLAPI void APIENTRY glDeleteLists(GLuint list, GLsizei range); -GLAPI void APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures); -GLAPI void APIENTRY glDepthFunc(GLenum func); -GLAPI void APIENTRY glDepthMask(GLboolean flag); -GLAPI void APIENTRY glDisable(GLenum cap); -GLAPI void APIENTRY glDisableClientState(GLenum array); -GLAPI void APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count); -GLAPI void APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); -GLAPI void APIENTRY glEnable(GLenum cap); -GLAPI void APIENTRY glEnableClientState(GLenum array); -GLAPI void APIENTRY glEndList(void); -GLAPI void APIENTRY glFogf(GLenum pname, GLfloat param); -GLAPI void APIENTRY glFogfv(GLenum pname, const GLfloat* params); -GLAPI void APIENTRY glFogi(GLenum pname, GLint param); -GLAPI void APIENTRY glFogiv(GLenum pname, const GLint* params); -GLAPI GLuint APIENTRY glGenLists(GLsizei range); -GLAPI void APIENTRY glGenTextures(GLsizei n, GLuint* textures); -GLAPI GLenum APIENTRY glGetError(void); -GLAPI void APIENTRY glGetFloatv(GLenum pname, GLfloat* params); -GLAPI void APIENTRY glGetIntegerv(GLenum pname, GLint* params); -GLAPI const GLubyte* APIENTRY glGetString(GLenum name); -GLAPI void APIENTRY glHint(GLenum target, GLenum mode); -GLAPI void APIENTRY glLoadIdentity(void); -GLAPI void APIENTRY glLoadMatrixf(const GLfloat* m); -GLAPI void APIENTRY glMatrixMode(GLenum mode); -GLAPI void APIENTRY glNewList(GLuint list, GLenum mode); -GLAPI void APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); -GLAPI void APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, GLpointer pointer); -GLAPI void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); -GLAPI void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param); -GLAPI void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); -GLAPI void APIENTRY glVertexPointer(GLint size, GLenum type, GLsizei stride, GLpointer pointer); -GLAPI void APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height); +#define GL_FUNC(_retType, name) GLAPI _retType APIENTRY name +#include "_GL1Funcs.h" /* === END OPENGL HEADERS === */ - #if defined CC_BUILD_GL11 static GLuint activeList; #define gl_DYNAMICLISTID 1234567891 @@ -161,12 +126,15 @@ static void (APIENTRY *_glGenBuffers)(GLsizei n, GLuint *buffers); static void (APIENTRY *_glBufferData)(GLenum target, cc_uintptr size, const GLvoid* data, GLenum usage); static void (APIENTRY *_glBufferSubData)(GLenum target, cc_uintptr offset, cc_uintptr size, const GLvoid* data); #endif -#include "_GLShared.h" -typedef void (*GL_SetupVBFunc)(void); -typedef void (*GL_SetupVBRangeFunc)(int startVertex); -static GL_SetupVBFunc gfx_setupVBFunc; -static GL_SetupVBRangeFunc gfx_setupVBRangeFunc; +static void GLContext_GetAll(const struct DynamicLibSym* syms, int count) { + int i; + for (i = 0; i < count; i++) + { + *syms[i].symAddr = GLContext_GetAddress(syms[i].name); + } +} + #if defined CC_BUILD_WIN && !defined CC_BUILD_GL11 /* Note the following about calling OpenGL functions on Windows */ @@ -179,50 +147,72 @@ static GL_SetupVBRangeFunc gfx_setupVBRangeFunc; /* call [glDrawElements] --> opengl32.dll thunk--> GL driver thunk --> GL driver implementation */ /* call [_glDrawElements] --> GL driver thunk --> GL driver implementation */ -static void (APIENTRY *_glColorPointer)(GLint size, GLenum type, GLsizei stride, GLpointer pointer); -static void (APIENTRY *_glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); -static void (APIENTRY *_glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, GLpointer pointer); -static void (APIENTRY *_glVertexPointer)(GLint size, GLenum type, GLsizei stride, GLpointer pointer); +#undef GL_FUNC +#define GL_FUNC(_retType, name) typedef _retType (APIENTRY *FP_ ## name) +#include "_GL1Funcs.h" + +static FP_glColorPointer _glColorPointer; +static FP_glTexCoordPointer _glTexCoordPointer; +static FP_glVertexPointer _glVertexPointer; + +static FP_glDrawArrays _glDrawArrays; +static FP_glDrawElements _glDrawElements; + +static FP_glBindTexture _glBindTexture; +static FP_glDeleteTextures _glDeleteTextures; +static FP_glGenTextures _glGenTextures; +static FP_glTexImage2D _glTexImage2D; +static FP_glTexSubImage2D _glTexSubImage2D; static const struct DynamicLibSym coreFuncs[] = { DynamicLib_Sym2("glColorPointer", glColorPointer), - DynamicLib_Sym2("glTexCoordPointer", glTexCoordPointer), DynamicLib_Sym2("glDrawElements", glDrawElements), - DynamicLib_Sym2("glVertexPointer", glVertexPointer) + DynamicLib_Sym2("glTexCoordPointer", glTexCoordPointer), + DynamicLib_Sym2("glVertexPointer", glVertexPointer), + + DynamicLib_Sym2("glDrawArrays", glDrawArrays), + DynamicLib_Sym2("glDrawElements", glDrawElements), + + DynamicLib_Sym2("glBindTexture", glBindTexture), + DynamicLib_Sym2("glDeleteTextures", glDeleteTextures), + DynamicLib_Sym2("glGenTextures", glGenTextures), + DynamicLib_Sym2("glTexImage2D", glTexImage2D), + DynamicLib_Sym2("glTexSubImage2D", glTexSubImage2D), }; + static void LoadCoreFuncs(void) { GLContext_GetAll(coreFuncs, Array_Elems(coreFuncs)); } #else #define _glColorPointer glColorPointer -#define _glDrawElements glDrawElements #define _glTexCoordPointer glTexCoordPointer #define _glVertexPointer glVertexPointer + +#define _glDrawArrays glDrawArrays +#define _glDrawElements glDrawElements + +#define _glBindTexture glBindTexture +#define _glDeleteTextures glDeleteTextures +#define _glGenTextures glGenTextures +#define _glTexImage2D glTexImage2D +#define _glTexSubImage2D glTexSubImage2D #endif +typedef void (*GL_SetupVBFunc)(void); +typedef void (*GL_SetupVBRangeFunc)(int startVertex); +static GL_SetupVBFunc gfx_setupVBFunc; +static GL_SetupVBRangeFunc gfx_setupVBRangeFunc; +#include "_GLShared.h" /*########################################################################################################################* *-------------------------------------------------------Index buffers-----------------------------------------------------* *#########################################################################################################################*/ #ifndef CC_BUILD_GL11 -static GfxResourceID GL_GenBuffer(void) { - GLuint id; - _glGenBuffers(1, &id); - return id; -} - -static void GL_DelBuffer(GfxResourceID id) { - GLuint gl_id = (GLuint)id; - _glDeleteBuffers(1, &gl_id); -} - -static GfxResourceID (*_genBuffer)(void) = GL_GenBuffer; -static void (*_delBuffer)(GfxResourceID id) = GL_DelBuffer; - GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { cc_uint16 indices[GFX_MAX_INDICES]; - GfxResourceID id = _genBuffer(); + GfxResourceID id = NULL; cc_uint32 size = count * sizeof(cc_uint16); + _glGenBuffers(1, (GLuint*)&id); fillFunc(indices, count, obj); _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, id); _glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, indices, GL_STATIC_DRAW); @@ -234,7 +224,8 @@ void Gfx_BindIb(GfxResourceID ib) { _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib); void Gfx_DeleteIb(GfxResourceID* ib) { GfxResourceID id = *ib; if (!id) return; - _delBuffer(id); + + _glDeleteBuffers(1, (GLuint*)&id); *ib = 0; } #else @@ -249,7 +240,8 @@ void Gfx_DeleteIb(GfxResourceID* ib) { } *#########################################################################################################################*/ #ifndef CC_BUILD_GL11 static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { - GfxResourceID id = _genBuffer(); + GfxResourceID id = NULL; + _glGenBuffers(1, (GLuint*)&id); _glBindBuffer(GL_ARRAY_BUFFER, id); return id; } @@ -260,7 +252,7 @@ void Gfx_BindVb(GfxResourceID vb) { void Gfx_DeleteVb(GfxResourceID* vb) { GfxResourceID id = *vb; - if (id) _delBuffer(id); + if (id) _glDeleteBuffers(1, (GLuint*)&id); *vb = 0; } @@ -275,10 +267,10 @@ void Gfx_UnlockVb(GfxResourceID vb) { static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { return glGenLists(1); } -void Gfx_BindVb(GfxResourceID vb) { activeList = (GLuint)vb; } +void Gfx_BindVb(GfxResourceID vb) { activeList = ptr_to_uint(vb); } void Gfx_DeleteVb(GfxResourceID* vb) { - GLuint id = (GLuint)(*vb); + GLuint id = ptr_to_uint(*vb); if (id) glDeleteLists(id, 1); *vb = 0; } @@ -326,9 +318,10 @@ GfxResourceID Gfx_CreateVb2(void* vertices, VertexFormat fmt, int count) { *#########################################################################################################################*/ #ifndef CC_BUILD_GL11 static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { - GfxResourceID id = _genBuffer(); + GfxResourceID id = NULL; cc_uint32 size = maxVertices * strideSizes[fmt]; + _glGenBuffers(1, (GLuint*)&id); _glBindBuffer(GL_ARRAY_BUFFER, id); _glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); return id; @@ -340,7 +333,7 @@ void Gfx_BindDynamicVb(GfxResourceID vb) { void Gfx_DeleteDynamicVb(GfxResourceID* vb) { GfxResourceID id = *vb; - if (id) _delBuffer(id); + if (id) _glDeleteBuffers(1, (GLuint*)&id); *vb = 0; } @@ -365,21 +358,21 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { void Gfx_BindDynamicVb(GfxResourceID vb) { activeList = gl_DYNAMICLISTID; - dynamicListData = (void*)vb; + dynamicListData = vb; } void Gfx_DeleteDynamicVb(GfxResourceID* vb) { - void* addr = (void*)(*vb); + void* addr = *vb; if (addr) Mem_Free(addr); *vb = 0; } -void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return (void*)vb; } +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { return vb; } void Gfx_UnlockDynamicVb(GfxResourceID vb) { Gfx_BindDynamicVb(vb); } void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { Gfx_BindDynamicVb(vb); - Mem_Copy((void*)vb, vertices, vCount * gfx_stride); + Mem_Copy(vb, vertices, vCount * gfx_stride); } #endif @@ -443,7 +436,7 @@ void Gfx_SetVertexFormat(VertexFormat fmt) { void Gfx_DrawVb_Lines(int verticesCount) { gfx_setupVBFunc(); - glDrawArrays(GL_LINES, 0, verticesCount); + _glDrawArrays(GL_LINES, 0, verticesCount); } void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { @@ -479,7 +472,7 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ void Gfx_BindTexture(GfxResourceID texId) { - glBindTexture(GL_TEXTURE_2D, (GLuint)texId); + _glBindTexture(GL_TEXTURE_2D, ptr_to_uint(texId)); } @@ -534,7 +527,7 @@ void Gfx_SetFogMode(FogFunc func) { gfx_fogMode = func; } -void Gfx_SetAlphaTest(cc_bool enabled) { +static void SetAlphaTest(cc_bool enabled) { if (enabled) { glEnable(GL_ALPHA_TEST); } else { glDisable(GL_ALPHA_TEST); } } @@ -621,71 +614,147 @@ static void GLBackend_Init(void) { MakeIndices(gl_indices, GFX_MAX_INDICES, NULL #else #if defined CC_BUILD_WIN -/* On 32 bit windows, can replace the gl function drawing with these 1.1 fallbacks */ -/* (note that this only works on 32 bit system, as OpenGL IDs are 32 bit integers) */ +static FP_glDrawElements _realDrawElements; +static FP_glColorPointer _realColorPointer; +static FP_glTexCoordPointer _realTexCoordPointer; +static FP_glVertexPointer _realVertexPointer; -/* fake vertex buffer objects with client side pointers */ -typedef struct fake_buffer { cc_uint8* data; } fake_buffer; -static fake_buffer* cur_ib; -static fake_buffer* cur_vb; -#define fake_GetBuffer(target) (target == GL_ELEMENT_ARRAY_BUFFER ? &cur_ib : &cur_vb); +/* On Windows, can replace the GL function drawing with these 1.1 fallbacks */ +/* fake vertex buffer objects by using client side pointers instead */ +typedef struct legacy_buffer { cc_uint8* data; } legacy_buffer; +static legacy_buffer* cur_ib; +static legacy_buffer* cur_vb; +#define legacy_GetBuffer(target) (target == GL_ELEMENT_ARRAY_BUFFER ? &cur_ib : &cur_vb); -static void APIENTRY fake_bindBuffer(GLenum target, GfxResourceID src) { - fake_buffer** buffer = fake_GetBuffer(target); - *buffer = (fake_buffer*)src; +static void APIENTRY legacy_genBuffer(GLsizei n, GLuint* buffer) { + GfxResourceID* dst = (GfxResourceID*)buffer; + *dst = Mem_TryAllocCleared(1, sizeof(legacy_buffer)); } -static GfxResourceID GenFakeBuffer(void) { - return (GfxResourceID)Mem_TryAllocCleared(1, sizeof(fake_buffer)); +static void APIENTRY legacy_deleteBuffer(GLsizei n, const GLuint* buffer) { + GfxResourceID* dst = (GfxResourceID*)buffer; + Mem_Free(*dst); } -static void DelFakeBuffer(GfxResourceID id) { - Mem_Free((void*)id); +static void APIENTRY legacy_bindBuffer(GLenum target, GfxResourceID src) { + legacy_buffer** buffer = legacy_GetBuffer(target); + *buffer = (legacy_buffer*)src; } -static void APIENTRY fake_bufferData(GLenum target, cc_uintptr size, const GLvoid* data, GLenum usage) { - fake_buffer* buffer = *fake_GetBuffer(target); +static void APIENTRY legacy_bufferData(GLenum target, cc_uintptr size, const GLvoid* data, GLenum usage) { + legacy_buffer* buffer = *legacy_GetBuffer(target); Mem_Free(buffer->data); buffer->data = Mem_TryAlloc(size, 1); if (data) Mem_Copy(buffer->data, data, size); } -static void APIENTRY fake_bufferSubData(GLenum target, cc_uintptr offset, cc_uintptr size, const GLvoid* data) { - fake_buffer* buffer = *fake_GetBuffer(target); + +static void APIENTRY legacy_bufferSubData(GLenum target, cc_uintptr offset, cc_uintptr size, const GLvoid* data) { + legacy_buffer* buffer = *legacy_GetBuffer(target); Mem_Copy(buffer->data, data, size); } -/* wglGetProcAddress doesn't work with OpenGL 1.1 software rasteriser, so call GL functions directly */ -static void APIENTRY fake_drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) { - glDrawElements(mode, count, type, (cc_uintptr)indices + cur_ib->data); + +static void APIENTRY gl10_bindTexture(GLenum target, GLuint texture) { + } -static void APIENTRY fake_colorPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { - glColorPointer(size, type, stride, (cc_uintptr)cur_vb->data + offset); +static void APIENTRY gl10_deleteTexture(GLsizei n, const GLuint* textures) { + } -static void APIENTRY fake_texCoordPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { - glTexCoordPointer(size, type, stride, (cc_uintptr)cur_vb->data + offset); +static void APIENTRY gl10_genTexture(GLsizei n, GLuint* textures) { + } -static void APIENTRY fake_vertexPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { - glVertexPointer(size, type, stride, (cc_uintptr)cur_vb->data + offset); +static void APIENTRY gl10_texImage(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) { + +} +static void APIENTRY gl10_texSubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) { + } -static void OpenGL11Fallback(void) { +static cc_uint8* gl10_vb; +static void APIENTRY gl10_drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) { + /* TODO */ + int i; + glBegin(GL_QUADS); + count = (count * 4) / 6; + + if (gfx_format == VERTEX_FORMAT_TEXTURED) { + struct VertexTextured* src = (struct VertexTextured*)gl10_vb; + for (i = 0; i < count; i++, src++) + { + glColor4ub(PackedCol_R(src->Col), PackedCol_G(src->Col), PackedCol_B(src->Col), PackedCol_A(src->Col)); + glTexCoord2f(src->U, src->V); + glVertex3f(src->x, src->y, src->z); + } + } else { + struct VertexColoured* src = (struct VertexColoured*)gl10_vb; + for (i = 0; i < count; i++, src++) + { + glColor4ub(PackedCol_R(src->Col), PackedCol_G(src->Col), PackedCol_B(src->Col), PackedCol_A(src->Col)); + glVertex3f(src->x, src->y, src->z); + } + } + + glEnd(); +} +static void APIENTRY gl10_colorPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { +} +static void APIENTRY gl10_texCoordPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { +} +static void APIENTRY gl10_vertexPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { + gl10_vb = cur_vb->data + offset; +} + + +static void APIENTRY gl11_drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) { + _realDrawElements(mode, count, type, (cc_uintptr)indices + cur_ib->data); +} +static void APIENTRY gl11_colorPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { + _realColorPointer(size, type, stride, (cc_uintptr)cur_vb->data + offset); +} +static void APIENTRY gl11_texCoordPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { + _realTexCoordPointer(size, type, stride, (cc_uintptr)cur_vb->data + offset); +} +static void APIENTRY gl11_vertexPointer(GLint size, GLenum type, GLsizei stride, GLpointer offset) { + _realVertexPointer(size, type, stride, (cc_uintptr)cur_vb->data + offset); +} + + +static void FallbackOpenGL(void) { Window_ShowDialog("Performance warning", "Your system only supports only OpenGL 1.1\n" \ "This is usually caused by graphics drivers not being installed\n\n" \ "As such you will likely experience very poor performance"); customMipmapsLevels = false; - _glBindBuffer = fake_bindBuffer; _delBuffer = DelFakeBuffer; - _genBuffer = GenFakeBuffer; _glBufferData = fake_bufferData; - _glBufferSubData = fake_bufferSubData; + _glGenBuffers = legacy_genBuffer; + _glDeleteBuffers = legacy_deleteBuffer; + _glBindBuffer = legacy_bindBuffer; + _glBufferData = legacy_bufferData; + _glBufferSubData = legacy_bufferSubData; + + _realDrawElements = _glDrawElements; _realColorPointer = _glColorPointer; + _realTexCoordPointer = _glTexCoordPointer; _realVertexPointer = _glVertexPointer; + + _glDrawElements = gl11_drawElements; _glColorPointer = gl11_colorPointer; + _glTexCoordPointer = gl11_texCoordPointer; _glVertexPointer = gl11_vertexPointer; + + /* OpenGL 1.0 fallback support */ + if (_realDrawElements) return; + Window_ShowDialog("Performance warning", "OpenGL 1.0 only support, expect awful performance"); + + _glDrawElements = gl10_drawElements; _glColorPointer = gl10_colorPointer; + _glTexCoordPointer = gl10_texCoordPointer; _glVertexPointer = gl10_vertexPointer; - _glDrawElements = fake_drawElements; _glColorPointer = fake_colorPointer; - _glTexCoordPointer = fake_texCoordPointer; _glVertexPointer = fake_vertexPointer; + _glBindTexture = gl10_bindTexture; + _glGenTextures = gl10_genTexture; + _glDeleteTextures = gl10_deleteTexture; + _glTexImage2D = gl10_texImage; + _glTexSubImage2D = gl10_texSubImage; } #else /* No point in even trying for other systems */ -static void OpenGL11Fallback(void) { +static void FallbackOpenGL(void) { Logger_FailToStart("Only OpenGL 1.1 supported.\n\n" \ "Compile the game with CC_BUILD_GL11, or ask on the ClassiCube forums for it"); } @@ -719,7 +788,7 @@ static void GLBackend_Init(void) { } else if (String_CaselessContains(&extensions, &vboExt)) { GLContext_GetAll(arbVboFuncs, Array_Elems(arbVboFuncs)); } else { - OpenGL11Fallback(); + FallbackOpenGL(); } } #endif diff --git a/src/Graphics_GL2.c b/src/Graphics_GL2.c index e1aa6c6..1d19256 100644 --- a/src/Graphics_GL2.c +++ b/src/Graphics_GL2.c @@ -1,27 +1,31 @@ +/* Silence deprecation warnings on modern macOS/iOS */ +#define GL_SILENCE_DEPRECATION +#define GLES_SILENCE_DEPRECATION + #include "Core.h" -#if defined CC_BUILD_GL && defined CC_BUILD_GLMODERN +#if CC_GFX_BACKEND == CC_GFX_BACKEND_GL2 #include "_GraphicsBase.h" #include "Errors.h" #include "Window.h" /* OpenGL 2.0 backend (alternative modern-ish backend) */ #if defined CC_BUILD_WIN -/* Avoid pointless includes */ -#define WIN32_LEAN_AND_MEAN -#define NOSERVICE -#define NOMCX -#define NOIME -#include -#include + /* Avoid pointless includes */ + #define WIN32_LEAN_AND_MEAN + #define NOSERVICE + #define NOMCX + #define NOIME + #include + #include #elif defined CC_BUILD_IOS -#include + #include #elif defined CC_BUILD_MACOS -#include + #include #elif defined CC_BUILD_GLES -#include + #include #else -#define GL_GLEXT_PROTOTYPES -#include + #define GL_GLEXT_PROTOTYPES + #include #endif /* Windows gl.h only supplies up to OpenGL 1.1 headers */ @@ -85,6 +89,12 @@ static const struct DynamicLibSym core_funcs[] = { /* === END OPENGL HEADERS === */ #endif +#define _glBindTexture glBindTexture +#define _glDeleteTextures glDeleteTextures +#define _glGenTextures glGenTextures +#define _glTexImage2D glTexImage2D +#define _glTexSubImage2D glTexSubImage2D + #include "_GLShared.h" static GfxResourceID white_square; @@ -106,13 +116,15 @@ GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { fillFunc(indices, count, obj); glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, indices, GL_STATIC_DRAW); - return id; + return uint_to_ptr(id); } -void Gfx_BindIb(GfxResourceID ib) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, (GLuint)ib); } +void Gfx_BindIb(GfxResourceID ib) { + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ptr_to_uint(ib)); +} void Gfx_DeleteIb(GfxResourceID* ib) { - GLuint id = (GLuint)(*ib); + GLuint id = ptr_to_uint(*ib); if (!id) return; glDeleteBuffers(1, &id); *ib = 0; @@ -123,15 +135,16 @@ void Gfx_DeleteIb(GfxResourceID* ib) { *------------------------------------------------------Vertex buffers-----------------------------------------------------* *#########################################################################################################################*/ static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { - return GL_GenAndBind(GL_ARRAY_BUFFER); + GLuint id = GL_GenAndBind(GL_ARRAY_BUFFER); + return uint_to_ptr(id); } void Gfx_BindVb(GfxResourceID vb) { - glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); + glBindBuffer(GL_ARRAY_BUFFER, ptr_to_uint(vb)); } void Gfx_DeleteVb(GfxResourceID* vb) { - GLuint id = (GLuint)(*vb); + GLuint id = ptr_to_uint(*vb); if (id) glDeleteBuffers(1, &id); *vb = 0; } @@ -153,15 +166,15 @@ static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { cc_uint32 size = maxVertices * strideSizes[fmt]; glBufferData(GL_ARRAY_BUFFER, size, NULL, GL_DYNAMIC_DRAW); - return id; + return uint_to_ptr(id); } void Gfx_BindDynamicVb(GfxResourceID vb) { - glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); + glBindBuffer(GL_ARRAY_BUFFER, ptr_to_uint(vb)); } void Gfx_DeleteDynamicVb(GfxResourceID* vb) { - GLuint id = (GLuint)(*vb); + GLuint id = ptr_to_uint(*vb); if (id) glDeleteBuffers(1, &id); *vb = 0; } @@ -171,13 +184,13 @@ void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { } void Gfx_UnlockDynamicVb(GfxResourceID vb) { - glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); + glBindBuffer(GL_ARRAY_BUFFER, ptr_to_uint(vb)); glBufferSubData(GL_ARRAY_BUFFER, 0, tmpSize, tmpData); } void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { cc_uint32 size = vCount * gfx_stride; - glBindBuffer(GL_ARRAY_BUFFER, (GLuint)vb); + glBindBuffer(GL_ARRAY_BUFFER, ptr_to_uint(vb)); glBufferSubData(GL_ARRAY_BUFFER, 0, size, vertices); } @@ -202,7 +215,7 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { /* cached uniforms (cached for multiple programs */ static struct Matrix _view, _proj, _mvp; -static cc_bool gfx_alphaTest, gfx_texTransform; +static cc_bool gfx_texTransform; static float _texX, _texY; static PackedCol gfx_fogColor; static float gfx_fogEnd = -1.0f, gfx_fogDensity = -1.0f; @@ -465,7 +478,7 @@ void Gfx_BindTexture(GfxResourceID texId) { /* WebGL/OpenGL ES - pure black 1x1 texture */ /* So for consistency, always use a 1x1 pure white texture */ if (!texId) texId = white_square; - glBindTexture(GL_TEXTURE_2D, (GLuint)texId); + glBindTexture(GL_TEXTURE_2D, ptr_to_uint(texId)); } @@ -500,7 +513,7 @@ void Gfx_SetFogMode(FogFunc func) { SwitchProgram(); } -void Gfx_SetAlphaTest(cc_bool enabled) { gfx_alphaTest = enabled; SwitchProgram(); } +static void SetAlphaTest(cc_bool enabled) { SwitchProgram(); } void Gfx_DepthOnlyRendering(cc_bool depthOnly) { cc_bool enabled = !depthOnly; @@ -542,7 +555,11 @@ void Gfx_DisableTextureOffset(void) { *#########################################################################################################################*/ static void GLBackend_Init(void) { #ifdef CC_BUILD_WIN - GLContext_GetAll(core_funcs, Array_Elems(core_funcs)); + int i; + for (i = 0; i < Array_Elems(core_funcs); i++) + { + core_funcs[i].symAddr = GLContext_GetAddress(core_funcs[i].name); + } #endif #ifdef CC_BUILD_GLES @@ -617,27 +634,27 @@ static GL_SetupVBFunc gfx_setupVBFunc; static GL_SetupVBRangeFunc gfx_setupVBRangeFunc; static void GL_SetupVbColoured(void) { - glVertexAttribPointer(0, 3, GL_FLOAT, false, SIZEOF_VERTEX_COLOURED, (void*)0); - glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, SIZEOF_VERTEX_COLOURED, (void*)12); + glVertexAttribPointer(0, 3, GL_FLOAT, false, SIZEOF_VERTEX_COLOURED, uint_to_ptr( 0)); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, SIZEOF_VERTEX_COLOURED, uint_to_ptr(12)); } static void GL_SetupVbTextured(void) { - glVertexAttribPointer(0, 3, GL_FLOAT, false, SIZEOF_VERTEX_TEXTURED, (void*)0); - glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, SIZEOF_VERTEX_TEXTURED, (void*)12); - glVertexAttribPointer(2, 2, GL_FLOAT, false, SIZEOF_VERTEX_TEXTURED, (void*)16); + glVertexAttribPointer(0, 3, GL_FLOAT, false, SIZEOF_VERTEX_TEXTURED, uint_to_ptr( 0)); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, SIZEOF_VERTEX_TEXTURED, uint_to_ptr(12)); + glVertexAttribPointer(2, 2, GL_FLOAT, false, SIZEOF_VERTEX_TEXTURED, uint_to_ptr(16)); } static void GL_SetupVbColoured_Range(int startVertex) { cc_uint32 offset = startVertex * SIZEOF_VERTEX_COLOURED; - glVertexAttribPointer(0, 3, GL_FLOAT, false, SIZEOF_VERTEX_COLOURED, (void*)(offset)); - glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, SIZEOF_VERTEX_COLOURED, (void*)(offset + 12)); + glVertexAttribPointer(0, 3, GL_FLOAT, false, SIZEOF_VERTEX_COLOURED, uint_to_ptr(offset )); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, SIZEOF_VERTEX_COLOURED, uint_to_ptr(offset + 12)); } static void GL_SetupVbTextured_Range(int startVertex) { cc_uint32 offset = startVertex * SIZEOF_VERTEX_TEXTURED; - glVertexAttribPointer(0, 3, GL_FLOAT, false, SIZEOF_VERTEX_TEXTURED, (void*)(offset)); - glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, SIZEOF_VERTEX_TEXTURED, (void*)(offset + 12)); - glVertexAttribPointer(2, 2, GL_FLOAT, false, SIZEOF_VERTEX_TEXTURED, (void*)(offset + 16)); + glVertexAttribPointer(0, 3, GL_FLOAT, false, SIZEOF_VERTEX_TEXTURED, uint_to_ptr(offset )); + glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, true, SIZEOF_VERTEX_TEXTURED, uint_to_ptr(offset + 12)); + glVertexAttribPointer(2, 2, GL_FLOAT, false, SIZEOF_VERTEX_TEXTURED, uint_to_ptr(offset + 16)); } void Gfx_SetVertexFormat(VertexFormat fmt) { diff --git a/src/Graphics_N64.c b/src/Graphics_N64.c index 1b26f04..b895cb9 100644 --- a/src/Graphics_N64.c +++ b/src/Graphics_N64.c @@ -237,7 +237,7 @@ void Gfx_DisableMipmaps(void) { } *-----------------------------------------------------State management----------------------------------------------------* *#########################################################################################################################*/ void Gfx_SetFaceCulling(cc_bool enabled) { gl_Toggle(GL_CULL_FACE); } -void Gfx_SetAlphaBlending(cc_bool enabled) { gl_Toggle(GL_BLEND); } +static void SetAlphaBlend(cc_bool enabled) { gl_Toggle(GL_BLEND); } void Gfx_SetAlphaArgBlend(cc_bool enabled) { } static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { @@ -377,7 +377,7 @@ void Gfx_SetFogEnd(float value) { void Gfx_SetFogMode(FogFunc func) { } -void Gfx_SetAlphaTest(cc_bool enabled) { +static void SetAlphaTest(cc_bool enabled) { if (enabled) { glEnable(GL_ALPHA_TEST); } else { glDisable(GL_ALPHA_TEST); } } diff --git a/src/Graphics_NDS.c b/src/Graphics_NDS.c index ba081ea..d01cb09 100644 --- a/src/Graphics_NDS.c +++ b/src/Graphics_NDS.c @@ -176,7 +176,7 @@ void Gfx_SetFaceCulling(cc_bool enabled) { glPolyFmt(POLY_ALPHA(31) | (enabled ? POLY_CULL_BACK : POLY_CULL_NONE)); } -void Gfx_SetAlphaBlending(cc_bool enabled) { +static void SetAlphaBlend(cc_bool enabled) { /*if (enabled) { glEnable(GL_BLEND); } else { @@ -376,7 +376,7 @@ void Gfx_SetFogEnd(float value) { void Gfx_SetFogMode(FogFunc func) { } -void Gfx_SetAlphaTest(cc_bool enabled) { +static void SetAlphaTest(cc_bool enabled) { if (enabled) { //glEnable(GL_ALPHA_TEST); } else { diff --git a/src/Graphics_PS1.c b/src/Graphics_PS1.c index ce21f15..c841e00 100644 --- a/src/Graphics_PS1.c +++ b/src/Graphics_PS1.c @@ -36,6 +36,8 @@ static RenderBuffer buffers[2]; static cc_uint8* next_packet; static int active_buffer; static RenderBuffer* buffer; +static void* lastPoly; +static cc_bool cullingEnabled; static void OnBufferUpdated(void) { buffer = &buffers[active_buffer]; @@ -100,7 +102,7 @@ void Gfx_FreeState(void) { void Gfx_Create(void) { Gfx.MaxTexWidth = 128; - Gfx.MaxTexHeight = 128; + Gfx.MaxTexHeight = 256; Gfx.Created = true; Gfx_RestoreState(); @@ -126,30 +128,41 @@ void Gfx_Free(void) { // VRAM can be divided into texture pages // 32 texture pages total - each page is 64 x 256 // 10 texture pages are occupied by the doublebuffered display -// 22 texture packs are usable, and are then divided into -// - 4 pages for 256 wide textures, 8 for 128 wide, 10 for 64 -#define TPAGE_START_HOR 5 -#define TPAGES_PER_HALF 16 - +// 22 texture pages are usable for textures +// These 22 pages are then divided into: +// - 5 for 128+ wide horizontal, 6 otherwise +// - 11 pages for vertical textures #define TPAGE_WIDTH 64 #define TPAGE_HEIGHT 256 -#define MAX_TEX_PAGES 22 -static cc_uint8 vram_used[(MAX_TEX_PAGES * TPAGE_HEIGHT) / 8]; +#define TPAGES_PER_HALF 16 + +// Horizontally oriented textures (first group of 16) +#define TPAGE_START_HOR 5 +#define MAX_HOR_TEX_PAGES 11 +#define MAX_HOR_TEX_LINES (MAX_HOR_TEX_PAGES * TPAGE_HEIGHT) +// Horizontally oriented textures (second group of 16) +#define TPAGE_START_VER (16 + 5) +#define MAX_VER_TEX_PAGES 11 +#define MAX_VER_TEX_LINES (MAX_VER_TEX_PAGES * TPAGE_WIDTH) + +static cc_uint8 vram_used[(MAX_HOR_TEX_LINES + MAX_VER_TEX_LINES) / 8]; #define VRAM_SetUsed(line) (vram_used[(line) / 8] |= (1 << ((line) % 8))) #define VRAM_UnUsed(line) (vram_used[(line) / 8] &= ~(1 << ((line) % 8))) #define VRAM_IsUsed(line) (vram_used[(line) / 8] & (1 << ((line) % 8))) -static void VRAM_GetBlockRange(int width, int* beg, int* end) { - if (width >= 256) { - *beg = 0; - *end = 4 * TPAGE_HEIGHT; +#define VRAM_BoundingAxis(width, height) height > width ? width : height + +static void VRAM_GetBlockRange(int width, int height, int* beg, int* end) { + if (height > width) { + *beg = MAX_HOR_TEX_LINES; + *end = MAX_HOR_TEX_LINES + MAX_VER_TEX_LINES; } else if (width >= 128) { - *beg = 4 * TPAGE_HEIGHT; - *end = 12 * TPAGE_HEIGHT; + *beg = 0; + *end = 5 * TPAGE_HEIGHT; } else { - *beg = 12 * TPAGE_HEIGHT; - *end = 22 * TPAGE_HEIGHT; + *beg = 5 * TPAGE_HEIGHT; + *end = MAX_HOR_TEX_LINES; } } @@ -163,7 +176,7 @@ static cc_bool VRAM_IsRangeFree(int beg, int end) { static int VRAM_FindFreeBlock(int width, int height) { int beg, end; - VRAM_GetBlockRange(width, &beg, &end); + VRAM_GetBlockRange(width, height, &beg, &end); // TODO kinda inefficient for (int i = beg; i < end - height; i++) @@ -175,13 +188,41 @@ static int VRAM_FindFreeBlock(int width, int height) { return -1; } +static void VRAM_AllocBlock(int line, int width, int height) { + int lines = VRAM_BoundingAxis(width, height); + for (int i = line; i < line + lines; i++) + { + VRAM_SetUsed(i); + } +} + +static void VRAM_FreeBlock(int line, int width, int height) { + int lines = VRAM_BoundingAxis(width, height); + for (int i = line; i < line + lines; i++) + { + VRAM_UnUsed(i); + } +} + +static int VRAM_CalcPage(int line) { + if (line < MAX_HOR_TEX_LINES) { + return TPAGE_START_HOR + (line / TPAGE_HEIGHT); + } else { + line -= MAX_HOR_TEX_LINES; + return TPAGE_START_VER + (line / TPAGE_WIDTH); + } +} + + #define TEXTURES_MAX_COUNT 64 typedef struct GPUTexture { cc_uint16 width, height; + cc_uint8 width_mask, height_mask; cc_uint16 line, tpage; + cc_uint8 xOffset, yOffset; } GPUTexture; static GPUTexture textures[TEXTURES_MAX_COUNT]; -static GPUTexture* active_tex; +static GPUTexture* curTex; #define BGRA8_to_PS1(src) \ ((src[2] & 0xF8) >> 3) | ((src[1] & 0xF8) << 2) | ((src[0] & 0xF8) << 7) | ((src[3] & 0x80) << 8) @@ -205,28 +246,30 @@ static void* AllocTextureAt(int i, struct Bitmap* bmp, int rowWidth) { int line = VRAM_FindFreeBlock(bmp->width, bmp->height); if (line == -1) { Mem_Free(tmp); return NULL; } - tex->width = bmp->width; - tex->height = bmp->height; + tex->width = bmp->width; tex->width_mask = bmp->width - 1; + tex->height = bmp->height; tex->height_mask = bmp->height - 1; tex->line = line; - int page = TPAGE_START_HOR + (line / TPAGE_HEIGHT); - // In bottom half of VRAM? Need to offset horizontally again - if (page >= TPAGES_PER_HALF) page += TPAGE_START_HOR; - - int pageX = (page % TPAGES_PER_HALF); - int pageY = (page / TPAGES_PER_HALF); + int page = VRAM_CalcPage(line); + int pageX = (page % TPAGES_PER_HALF); + int pageY = (page / TPAGES_PER_HALF); + tex->tpage = (2 << 7) | (pageY << 4) | pageX; - for (int i = tex->line; i < tex->line + tex->height; i++) - { - VRAM_SetUsed(i); + VRAM_AllocBlock(line, bmp->width, bmp->height); + if (bmp->height > bmp->width) { + tex->xOffset = line % TPAGE_WIDTH; + tex->yOffset = 0; + } else { + tex->xOffset = 0; + tex->yOffset = line % TPAGE_HEIGHT; } - tex->tpage = (2 << 7) | (pageY << 4) | pageX; + Platform_Log3("%i x %i = %i", &bmp->width, &bmp->height, &line); Platform_Log3(" at %i (%i, %i)", &page, &pageX, &pageY); RECT rect; - rect.x = pageX * TPAGE_WIDTH; - rect.y = pageY * TPAGE_HEIGHT + (line % TPAGE_HEIGHT); + rect.x = pageX * TPAGE_WIDTH + tex->xOffset; + rect.y = pageY * TPAGE_HEIGHT + tex->yOffset; rect.w = bmp->width; rect.h = bmp->height; @@ -251,7 +294,7 @@ static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 void Gfx_BindTexture(GfxResourceID texId) { if (!texId) texId = white_square; - active_tex = (GPUTexture*)texId; + curTex = (GPUTexture*)texId; } void Gfx_DeleteTexture(GfxResourceID* texId) { @@ -259,10 +302,7 @@ void Gfx_DeleteTexture(GfxResourceID* texId) { if (!data) return; GPUTexture* tex = (GPUTexture*)data; - for (int i = tex->line; i < tex->line + tex->height; i++) - { - VRAM_UnUsed(i); - } + VRAM_FreeBlock(tex->line, tex->width, tex->height); tex->width = 0; tex->height = 0; *texId = NULL; } @@ -285,13 +325,13 @@ void Gfx_SetFogEnd(float value) { } void Gfx_SetFogMode(FogFunc func) { } void Gfx_SetFaceCulling(cc_bool enabled) { - // TODO + cullingEnabled = enabled; } -void Gfx_SetAlphaTest(cc_bool enabled) { +static void SetAlphaTest(cc_bool enabled) { } -void Gfx_SetAlphaBlending(cc_bool enabled) { +static void SetAlphaBlend(cc_bool enabled) { } void Gfx_SetAlphaArgBlend(cc_bool enabled) { } @@ -530,8 +570,77 @@ static void Transform(Vec3* result, struct VertexTextured* a, const struct Matri } cc_bool VERTEX_LOGGING; -static void DrawColouredQuads(int verticesCount, int startVertex) { + +static void DrawColouredQuads2D(int verticesCount, int startVertex) { return; + for (int i = 0; i < verticesCount; i += 4) + { + struct VertexColoured* v = (struct VertexColoured*)gfx_vertices + startVertex + i; + + POLY_F4* poly = new_primitive(sizeof(POLY_F4)); + setPolyF4(poly); + + poly->x0 = v[1].x; poly->y0 = v[1].y; + poly->x1 = v[0].x; poly->y1 = v[0].y; + poly->x2 = v[2].x; poly->y2 = v[2].y; + poly->x3 = v[3].x; poly->y3 = v[3].y; + + poly->r0 = PackedCol_R(v->Col); + poly->g0 = PackedCol_G(v->Col); + poly->b0 = PackedCol_B(v->Col); + + if (lastPoly) { + setaddr(poly, getaddr(lastPoly)); setaddr(lastPoly, poly); + } else { + addPrim(&buffer->ot[0], poly); + } + lastPoly = poly; + } +} + +static void DrawTexturedQuads2D(int verticesCount, int startVertex) { + int uOffset = curTex->xOffset, vOffset = curTex->yOffset; + + for (int i = 0; i < verticesCount; i += 4) + { + struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; + + POLY_FT4* poly = new_primitive(sizeof(POLY_FT4)); + setPolyFT4(poly); + poly->tpage = curTex->tpage; + poly->clut = 0; + + // TODO & instead of % + poly->x0 = v[1].x; poly->y0 = v[1].y; + poly->x1 = v[0].x; poly->y1 = v[0].y; + poly->x2 = v[2].x; poly->y2 = v[2].y; + poly->x3 = v[3].x; poly->y3 = v[3].y; + + poly->u0 = ((int)(v[1].U * 0.99f * curTex->width) & curTex->width_mask) + uOffset; + poly->v0 = ((int)(v[1].V * curTex->height) & curTex->height_mask) + vOffset; + poly->u1 = ((int)(v[0].U * 0.99f * curTex->width) & curTex->width_mask) + uOffset; + poly->v1 = ((int)(v[0].V * curTex->height) & curTex->height_mask) + vOffset; + poly->u2 = ((int)(v[2].U * 0.99f * curTex->width) & curTex->width_mask) + uOffset; + poly->v2 = ((int)(v[2].V * curTex->height) & curTex->height_mask) + vOffset; + poly->u3 = ((int)(v[3].U * 0.99f * curTex->width) & curTex->width_mask) + uOffset; + poly->v3 = ((int)(v[3].V * curTex->height) & curTex->height_mask) + vOffset; + + // https://problemkaputt.de/psxspx-gpu-rendering-attributes.htm + // "For untextured graphics, 8bit RGB values of FFh are brightest. However, for texture blending, 8bit values of 80h are brightest" + poly->r0 = PackedCol_R(v->Col) >> 1; + poly->g0 = PackedCol_G(v->Col) >> 1; + poly->b0 = PackedCol_B(v->Col) >> 1; + + if (lastPoly) { + setaddr(poly, getaddr(lastPoly)); setaddr(lastPoly, poly); + } else { + addPrim(&buffer->ot[0], poly); + } + lastPoly = poly; + } +} + +static void DrawColouredQuads3D(int verticesCount, int startVertex) { for (int i = 0; i < verticesCount; i += 4) { struct VertexColoured* v = (struct VertexColoured*)gfx_vertices + startVertex + i; @@ -562,13 +671,12 @@ static void DrawColouredQuads(int verticesCount, int startVertex) { poly->b0 = PackedCol_B(v->Col); //if (VERTEX_LOGGING) Platform_Log4("OUT: %i, %i, %i (%i)", &X, &Y, &Z, &p); - // TODO: 2D shouldn't use AddPrim, draws in the wrong way addPrim(&buffer->ot[p >> 2], poly); } } -static void DrawTexturedQuads(int verticesCount, int startVertex) { - int pageOffset = active_tex->line % TPAGE_HEIGHT; +static void DrawTexturedQuads3D(int verticesCount, int startVertex) { + int uOffset = curTex->xOffset, vOffset = curTex->yOffset; for (int i = 0; i < verticesCount; i += 4) { @@ -576,7 +684,7 @@ static void DrawTexturedQuads(int verticesCount, int startVertex) { POLY_FT4* poly = new_primitive(sizeof(POLY_FT4)); setPolyFT4(poly); - poly->tpage = active_tex->tpage; + poly->tpage = curTex->tpage; poly->clut = 0; Vec3 coords[4]; @@ -586,12 +694,28 @@ static void DrawTexturedQuads(int verticesCount, int startVertex) { Transform(&coords[3], &v[3], &mvp); // TODO & instead of % - poly->x0 = coords[1].x; poly->y0 = coords[1].y; poly->u0 = (int)(v[1].U * active_tex->width) % active_tex->width; poly->v0 = ((int)(v[1].V * active_tex->height) % active_tex->height) + pageOffset; - poly->x1 = coords[0].x; poly->y1 = coords[0].y; poly->u1 = (int)(v[0].U * active_tex->width) % active_tex->width; poly->v1 = ((int)(v[0].V * active_tex->height) % active_tex->height) + pageOffset; - poly->x2 = coords[2].x; poly->y2 = coords[2].y; poly->u2 = (int)(v[2].U * active_tex->width) % active_tex->width; poly->v2 = ((int)(v[2].V * active_tex->height) % active_tex->height) + pageOffset; - poly->x3 = coords[3].x; poly->y3 = coords[3].y; poly->u3 = (int)(v[3].U * active_tex->width) % active_tex->width; poly->v3 = ((int)(v[3].V * active_tex->height) % active_tex->height) + pageOffset; - - //int P = active_tex->height, page = poly->tpage & 0xFF, ll = active_tex->line % TPAGE_HEIGHT; + poly->x0 = coords[1].x; poly->y0 = coords[1].y; + poly->x1 = coords[0].x; poly->y1 = coords[0].y; + poly->x2 = coords[2].x; poly->y2 = coords[2].y; + poly->x3 = coords[3].x; poly->y3 = coords[3].y; + + if (cullingEnabled) { + // https://gamedev.stackexchange.com/questions/203694/how-to-make-backface-culling-work-correctly-in-both-orthographic-and-perspective + int signA = (poly->x0 - poly->x1) * (poly->y2 - poly->y1); + int signB = (poly->x2 - poly->x1) * (poly->y0 - poly->y1); + if (signA > signB) continue; + } + + poly->u0 = ((int)(v[1].U * curTex->width) & curTex->width_mask) + uOffset; + poly->v0 = ((int)(v[1].V * curTex->height) & curTex->height_mask) + vOffset; + poly->u1 = ((int)(v[0].U * curTex->width) & curTex->width_mask) + uOffset; + poly->v1 = ((int)(v[0].V * curTex->height) & curTex->height_mask) + vOffset; + poly->u2 = ((int)(v[2].U * curTex->width) & curTex->width_mask) + uOffset; + poly->v2 = ((int)(v[2].V * curTex->height) & curTex->height_mask) + vOffset; + poly->u3 = ((int)(v[3].U * curTex->width) & curTex->width_mask) + uOffset; + poly->v3 = ((int)(v[3].V * curTex->height) & curTex->height_mask) + vOffset; + + //int P = curTex->height, page = poly->tpage & 0xFF, ll = curTex->yOffset; //Platform_Log4("XYZ: %f3 x %i, %i, %i", &v[0].V, &P, &page, &ll); int p = (coords[0].z + coords[1].z + coords[2].z + coords[3].z) / 4; if (p < 0 || p >= OT_LENGTH) continue; @@ -600,9 +724,9 @@ static void DrawTexturedQuads(int verticesCount, int startVertex) { //if (VERTEX_LOGGING) Platform_Log3("IN: %i, %i, %i", &X, &Y, &Z); X = poly->x1; Y = poly->y1, Z = coords[0].z; - poly->r0 = PackedCol_R(v->Col); - poly->g0 = PackedCol_G(v->Col); - poly->b0 = PackedCol_B(v->Col); + poly->r0 = PackedCol_R(v->Col) >> 1; + poly->g0 = PackedCol_G(v->Col) >> 1; + poly->b0 = PackedCol_B(v->Col) >> 1; //if (VERTEX_LOGGING) Platform_Log4("OUT: %i, %i, %i (%i)", &X, &Y, &Z, &p); // TODO: 2D shouldn't use AddPrim, draws in the wrong way @@ -678,24 +802,29 @@ static void DrawTexturedQuads(int verticesCount, int startVertex) { } }*/ -void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - DrawTexturedQuads(verticesCount, startVertex); +static void DrawQuads(int verticesCount, int startVertex) { + if (gfx_rendering2D && gfx_format == VERTEX_FORMAT_TEXTURED) { + DrawTexturedQuads2D(verticesCount, startVertex); + } else if (gfx_rendering2D) { + DrawColouredQuads2D(verticesCount, startVertex); + } else if (gfx_format == VERTEX_FORMAT_TEXTURED) { + DrawTexturedQuads3D(verticesCount, startVertex); } else { - DrawColouredQuads(verticesCount, startVertex); + DrawColouredQuads3D(verticesCount, startVertex); } } + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { + DrawQuads(verticesCount, startVertex); +} + void Gfx_DrawVb_IndexedTris(int verticesCount) { - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - DrawTexturedQuads(verticesCount, 0); - } else { - DrawColouredQuads(verticesCount, 0); - } + DrawQuads(verticesCount, 0); } void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { - DrawTexturedQuads(verticesCount, startVertex); + DrawTexturedQuads3D(verticesCount, startVertex); } @@ -711,6 +840,7 @@ cc_bool Gfx_WarnIfNecessary(void) { } void Gfx_BeginFrame(void) { + lastPoly = NULL; } void Gfx_EndFrame(void) { @@ -735,4 +865,14 @@ void Gfx_GetApiInfo(cc_string* info) { } cc_bool Gfx_TryRestoreContext(void) { return true; } + +void Gfx_Begin2D(int width, int height) { + gfx_rendering2D = true; + Gfx_SetAlphaBlending(true); +} + +void Gfx_End2D(void) { + gfx_rendering2D = false; + Gfx_SetAlphaBlending(false); +} #endif diff --git a/src/Graphics_PS2.c b/src/Graphics_PS2.c index 383bd86..424eadd 100644 --- a/src/Graphics_PS2.c +++ b/src/Graphics_PS2.c @@ -243,8 +243,6 @@ void Gfx_DisableMipmaps(void) { } *------------------------------------------------------State management---------------------------------------------------* *#########################################################################################################################*/ static int clearR, clearG, clearB; -static cc_bool gfx_alphaBlend; -static cc_bool gfx_alphaTest; static cc_bool gfx_depthTest; static cc_bool stateDirty; @@ -274,13 +272,11 @@ void Gfx_SetFaceCulling(cc_bool enabled) { // TODO } -void Gfx_SetAlphaTest(cc_bool enabled) { - gfx_alphaTest = enabled; - stateDirty = true; +static void SetAlphaTest(cc_bool enabled) { + stateDirty = true; } -void Gfx_SetAlphaBlending(cc_bool enabled) { - gfx_alphaBlend = enabled; +static void SetAlphaBlend(cc_bool enabled) { // TODO update primitive state } @@ -486,10 +482,10 @@ static Vector4 TransformVertex(struct VertexTextured* pos) { } //#define VCopy(dst, src) dst.x = vp_hwidth * (1 + src.x / src.w); dst.y = vp_hheight * (1 - src.y / src.w); dst.z = src.z / src.w; dst.w = src.w; -static xyz_t FinishVertex(struct Vector4 src) { - float x = (vp_hwidth/2048) * (src.x / src.w); - float y = (vp_hheight/2048) * (src.y / src.w); - float z = src.z / src.w; +static xyz_t FinishVertex(struct Vector4 src, float invW) { + float x = (vp_hwidth /2048) * (src.x * invW); + float y = (vp_hheight/2048) * (src.y * invW); + float z = src.z * invW; int originX = ftoi4(2048); int originY = ftoi4(2048); @@ -522,7 +518,7 @@ static void DrawTriangle(Vector4 v0, Vector4 v1, Vector4 v2, struct VertexTextur for (int i = 0; i < 3; i++) { float Q = 1.0f / verts[i].w; - xyz_t xyz = FinishVertex(verts[i]); + xyz_t xyz = FinishVertex(verts[i], Q); color_t color; texel_t texel; @@ -547,7 +543,7 @@ static void DrawTriangle(Vector4 v0, Vector4 v1, Vector4 v2, struct VertexTextur *dw++ = xyz.xyz; } dw++; // one more to even out number of doublewords - q = dw; + q = (qword_t*)dw; } static void DrawTriangles(int verticesCount, int startVertex) { diff --git a/src/Graphics_PS3.c b/src/Graphics_PS3.c index 3283ba3..4fec40d 100644 --- a/src/Graphics_PS3.c +++ b/src/Graphics_PS3.c @@ -286,37 +286,28 @@ void Gfx_SetFaceCulling(cc_bool enabled) { rsxSetCullFaceEnable(context, enabled); } -void Gfx_SetAlphaBlending(cc_bool enabled) { +static void SetAlphaBlend(cc_bool enabled) { rsxSetBlendEnable(context, enabled); } void Gfx_SetAlphaArgBlend(cc_bool enabled) { } void Gfx_ClearColor(PackedCol color) { - cc_uint32 R = PackedCol_R(color); - cc_uint32 G = PackedCol_G(color); - cc_uint32 B = PackedCol_B(color); - - clearColor = B | (G << 8) | (R << 16) | (0xFF << 24); -} + cc_uint32 R = PackedCol_R(color); + cc_uint32 G = PackedCol_G(color); + cc_uint32 B = PackedCol_B(color); -static cc_bool depth_write = true, depth_test = true; -static void UpdateDepthState(void) { - // match Desktop behaviour, where disabling depth testing also disables depth writing - rsxSetDepthWriteEnable(context, depth_write & depth_test); - rsxSetDepthTestEnable(context, depth_test); + clearColor = B | (G << 8) | (R << 16) | (0xFF << 24); } void Gfx_SetDepthWrite(cc_bool enabled) { - depth_write = enabled; - UpdateDepthState(); + rsxSetDepthWriteEnable(context, enabled); } void Gfx_SetDepthTest(cc_bool enabled) { - depth_test = enabled; - UpdateDepthState(); + rsxSetDepthTestEnable(context, enabled); } -void Gfx_SetAlphaTest(cc_bool enabled) { +static void SetAlphaTest(cc_bool enabled) { rsxSetAlphaTestEnable(context, enabled); } diff --git a/src/Graphics_PSP.c b/src/Graphics_PSP.c index 82b53a9..6ed8efc 100644 --- a/src/Graphics_PSP.c +++ b/src/Graphics_PSP.c @@ -163,7 +163,7 @@ void Gfx_BindTexture(GfxResourceID texId) { *#########################################################################################################################*/ static PackedCol gfx_clearColor; void Gfx_SetFaceCulling(cc_bool enabled) { GU_Toggle(GU_CULL_FACE); } -void Gfx_SetAlphaBlending(cc_bool enabled) { GU_Toggle(GU_BLEND); } +static void SetAlphaBlend(cc_bool enabled) { GU_Toggle(GU_BLEND); } void Gfx_SetAlphaArgBlend(cc_bool enabled) { } void Gfx_ClearColor(PackedCol color) { @@ -377,7 +377,7 @@ void Gfx_SetFogMode(FogFunc func) { /* TODO: Implemen fake exp/exp2 fog */ } -void Gfx_SetAlphaTest(cc_bool enabled) { GU_Toggle(GU_ALPHA_TEST); } +static void SetAlphaTest(cc_bool enabled) { GU_Toggle(GU_ALPHA_TEST); } void Gfx_DepthOnlyRendering(cc_bool depthOnly) { cc_bool enabled = !depthOnly; diff --git a/src/Graphics_PSVita.c b/src/Graphics_PSVita.c index c96a799..da791c2 100644 --- a/src/Graphics_PSVita.c +++ b/src/Graphics_PSVita.c @@ -8,7 +8,6 @@ // TODO track last frame used on static cc_bool gfx_depthOnly; -static cc_bool gfx_alphaTesting, gfx_alphaBlending; static int frontBufferIndex, backBufferIndex; // Inspired from // https://github.com/xerpi/gxmfun/blob/master/source/main.c @@ -242,11 +241,11 @@ static void FP_SwitchActive(void) { // [normal rendering, blend rendering, no rendering] if (gfx_depthOnly) { index += 2; - } else if (gfx_alphaBlending) { + } else if (gfx_alphaBlend) { index += 1; } - if (gfx_alphaTesting) index += 2 * 3; + if (gfx_alphaTest) index += 2 * 3; FragmentProgram* FP = &FP_list[index]; if (FP == FP_Active) return; @@ -964,13 +963,11 @@ void Gfx_SetFogMode(FogFunc func) { // TODO } -void Gfx_SetAlphaTest(cc_bool enabled) { - gfx_alphaTesting = enabled; +static void SetAlphaTest(cc_bool enabled) { FP_SwitchActive(); } -void Gfx_SetAlphaBlending(cc_bool enabled) { - gfx_alphaBlending = enabled; +static void SetAlphaBlend(cc_bool enabled) { FP_SwitchActive(); } @@ -996,34 +993,18 @@ static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { // TODO } -static cc_bool depth_write = true, depth_test = true; -static void UpdateDepthWrite(void) { - // match Desktop behaviour, where disabling depth testing also disables depth writing - // TODO do we actually need to & here? - cc_bool enabled = depth_write & depth_test; - +void Gfx_SetDepthWrite(cc_bool enabled) { int mode = enabled ? SCE_GXM_DEPTH_WRITE_ENABLED : SCE_GXM_DEPTH_WRITE_DISABLED; sceGxmSetFrontDepthWriteEnable(gxm_context, mode); sceGxmSetBackDepthWriteEnable(gxm_context, mode); } -static void UpdateDepthFunction(void) { - int func = depth_test ? SCE_GXM_DEPTH_FUNC_LESS_EQUAL : SCE_GXM_DEPTH_FUNC_ALWAYS; +void Gfx_SetDepthTest(cc_bool enabled) { + int func = enabled ? SCE_GXM_DEPTH_FUNC_LESS_EQUAL : SCE_GXM_DEPTH_FUNC_ALWAYS; sceGxmSetFrontDepthFunc(gxm_context, func); sceGxmSetBackDepthFunc(gxm_context, func); } -void Gfx_SetDepthWrite(cc_bool enabled) { - depth_write = enabled; - UpdateDepthWrite(); -} - -void Gfx_SetDepthTest(cc_bool enabled) { - depth_test = enabled; - UpdateDepthWrite(); - UpdateDepthFunction(); -} - /*########################################################################################################################* *---------------------------------------------------------Matrices--------------------------------------------------------* @@ -1119,8 +1100,7 @@ void Gfx_ClearBuffers(GfxBuffers buffers) { clear_vertices[3] = (struct VertexColoured){-1.0f, 1.0f, 1.0f, clear_color }; Gfx_SetAlphaTest(false); - // can't use Gfx_SetDepthTest because that also affects depth writing - depth_test = false; UpdateDepthFunction(); + Gfx_SetDepthTest(false); Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); Gfx_LoadIdentityMatrix(MATRIX_VIEW); @@ -1128,6 +1108,6 @@ void Gfx_ClearBuffers(GfxBuffers buffers) { Gfx_BindVb(clearVB); Gfx_DrawVb_IndexedTris(4); - depth_test = true; UpdateDepthFunction(); + Gfx_SetDepthTest(true); } #endif diff --git a/src/Graphics_Saturn.c b/src/Graphics_Saturn.c index 0949fde..e91937d 100644 --- a/src/Graphics_Saturn.c +++ b/src/Graphics_Saturn.c @@ -1,446 +1,565 @@ -#include "Core.h" -#if defined CC_BUILD_SATURN -#include "_GraphicsBase.h" -#include "Errors.h" -#include "Window.h" -#include -#include -#include -#include - - -#define SCREEN_WIDTH 320 -#define SCREEN_HEIGHT 224 - -#define PRIMITIVE_DRAW_MODE_NORMAL (0) -#define PRIMITIVE_DRAW_MODE_MESH (1) -#define PRIMITIVE_DRAW_MODE_SHADOW (2) -#define PRIMITIVE_DRAW_MODE_HALF_LUMINANCE (3) -#define PRIMITIVE_DRAW_MODE_HALF_TRANSPARENT (4) -#define PRIMITIVE_DRAW_MODE_GOURAUD_SHADING (5) -#define PRIMITIVE_DRAW_MODE_GOURAUD_HALF_LUM (6) -#define PRIMITIVE_DRAW_MODE_GOURAUD_HALF_TRANS (7) -#define PRIMITIVE_DRAW_MODE_COUNT (8) - -#define PRIMITIVE_COLOR RGB1555(1, 31, 0, 31) - -#define CMDS_COUNT 400 - -static PackedCol clear_color; -static vdp1_cmdt_t cmdts_all[CMDS_COUNT]; -static int cmdts_count; -static vdp1_vram_partitions_t _vdp1_vram_partitions; - -static vdp1_cmdt_t* NextPrimitive(void) { - if (cmdts_count >= CMDS_COUNT) Logger_Abort("Too many VDP1 commands"); - return &cmdts_all[cmdts_count++]; -} - -static vdp1_cmdt_draw_mode_t _primitive_draw_mode = { - .raw = 0x0000 -}; - -static int16_vec2_t clear_points[4]; - - -// TODO: how to use VDP1 erase ?? -static void UpdateVDP1Env(void) { - vdp1_env_t env; - vdp1_env_default_init(&env); - - int R = PackedCol_R(clear_color); - int G = PackedCol_G(clear_color); - int B = PackedCol_B(clear_color); - env.erase_color = RGB1555(1, R >> 3, G >> 3, B >> 3); - - vdp1_env_set(&env); -} - -// TODO: should be SCREEN_WIDTH/2 instead ? -static void _primitive_init(void) { - clear_points[0].x = 0; - clear_points[0].y = SCREEN_WIDTH - 1; - - clear_points[1].x = SCREEN_WIDTH - 1; - clear_points[1].y = SCREEN_HEIGHT - 1; - - clear_points[2].x = SCREEN_HEIGHT - 1; - clear_points[2].y = 0; - - clear_points[3].x = 0; - clear_points[3].y = 0; -} - -static GfxResourceID white_square; -void Gfx_RestoreState(void) { - InitDefaultResources(); - - // 2x2 dummy white texture - struct Bitmap bmp; - BitmapCol pixels[4] = { BitmapColor_RGB(255, 0, 0), BITMAPCOLOR_WHITE, BITMAPCOLOR_WHITE, BITMAPCOLOR_WHITE }; - Bitmap_Init(bmp, 2, 2, pixels); - white_square = Gfx_CreateTexture(&bmp, 0, false); -} - -void Gfx_FreeState(void) { - FreeDefaultResources(); - Gfx_DeleteTexture(&white_square); -} - -void Gfx_Create(void) { - if (!Gfx.Created) { - vdp1_vram_partitions_get(&_vdp1_vram_partitions); -// TODO less ram for gourad base - vdp2_scrn_back_color_set(VDP2_VRAM_ADDR(3, 0x01FFFE), - RGB1555(1, 0, 3, 15)); - vdp2_sprite_priority_set(0, 6); - - UpdateVDP1Env(); - _primitive_init(); - } - - Gfx.MaxTexWidth = 128; - Gfx.MaxTexHeight = 128; - Gfx.Created = true; -} - -void Gfx_Free(void) { - Gfx_FreeState(); -} - - -/*########################################################################################################################* -*---------------------------------------------------------Textures--------------------------------------------------------* -*#########################################################################################################################*/ -static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - return NULL; -} - -void Gfx_BindTexture(GfxResourceID texId) { -} - -void Gfx_DeleteTexture(GfxResourceID* texId) { -} - -void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { - // TODO -} - -void Gfx_EnableMipmaps(void) { } -void Gfx_DisableMipmaps(void) { } - - -/*########################################################################################################################* -*------------------------------------------------------State management---------------------------------------------------* -*#########################################################################################################################*/ -void Gfx_SetFog(cc_bool enabled) { } -void Gfx_SetFogCol(PackedCol col) { } -void Gfx_SetFogDensity(float value) { } -void Gfx_SetFogEnd(float value) { } -void Gfx_SetFogMode(FogFunc func) { } - -void Gfx_SetFaceCulling(cc_bool enabled) { - // TODO -} - -void Gfx_SetAlphaTest(cc_bool enabled) { -} - -void Gfx_SetAlphaBlending(cc_bool enabled) { -} - -void Gfx_SetAlphaArgBlend(cc_bool enabled) { } - -void Gfx_ClearBuffers(GfxBuffers buffers) { -} - -void Gfx_ClearColor(PackedCol color) { - if (color == clear_color) return; - - clear_color = color; - UpdateVDP1Env(); -} - -void Gfx_SetDepthTest(cc_bool enabled) { -} - -void Gfx_SetDepthWrite(cc_bool enabled) { - // TODO -} - -static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { - // TODO -} - -void Gfx_DepthOnlyRendering(cc_bool depthOnly) { - cc_bool enabled = !depthOnly; - SetColorWrite(enabled & gfx_colorMask[0], enabled & gfx_colorMask[1], - enabled & gfx_colorMask[2], enabled & gfx_colorMask[3]); -} - - -/*########################################################################################################################* -*-------------------------------------------------------Index buffers-----------------------------------------------------* -*#########################################################################################################################*/ -GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { - return (void*)1; -} - -void Gfx_BindIb(GfxResourceID ib) { } -void Gfx_DeleteIb(GfxResourceID* ib) { } - - -/*########################################################################################################################* -*-------------------------------------------------------Vertex buffers----------------------------------------------------* -*#########################################################################################################################*/ -static void* gfx_vertices; - -static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { - return Mem_TryAlloc(count, strideSizes[fmt]); -} - -void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } - -void Gfx_DeleteVb(GfxResourceID* vb) { - GfxResourceID data = *vb; - if (data) Mem_Free(data); - *vb = 0; -} - -void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { - return vb; -} - -void Gfx_UnlockVb(GfxResourceID vb) { - gfx_vertices = vb; -} - - -static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { - return Mem_TryAlloc(maxVertices, strideSizes[fmt]); -} - -void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } - -void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { - return vb; -} - -void Gfx_UnlockDynamicVb(GfxResourceID vb) { - gfx_vertices = vb; -} - -void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } - - -/*########################################################################################################################* -*---------------------------------------------------------Matrices--------------------------------------------------------* -*#########################################################################################################################*/ -static struct Matrix _view, _proj, mvp; - -void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { - if (type == MATRIX_VIEW) _view = *matrix; - if (type == MATRIX_PROJECTION) _proj = *matrix; - - Matrix_Mul(&mvp, &_view, &_proj); -} - -void Gfx_LoadIdentityMatrix(MatrixType type) { - Gfx_LoadMatrix(type, &Matrix_Identity); -} - -void Gfx_EnableTextureOffset(float x, float y) { - // TODO -} - -void Gfx_DisableTextureOffset(void) { - // TODO -} - -void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) { - /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh */ - /* The simplified calculation below uses: L = 0, R = width, T = 0, B = height */ - /* NOTE: This calculation is shared with Direct3D 11 backend */ - *matrix = Matrix_Identity; - - matrix->row1.x = 2.0f / width; - matrix->row2.y = -2.0f / height; - matrix->row3.z = 1.0f / (zNear - zFar); - - matrix->row4.x = -1.0f; - matrix->row4.y = 1.0f; - matrix->row4.z = zNear / (zNear - zFar); -} - -static float Cotangent(float x) { return Math_CosF(x) / Math_SinF(x); } -void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, float zFar) { - float zNear = 0.01f; - /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh */ - float c = Cotangent(0.5f * fov); - *matrix = Matrix_Identity; - - matrix->row1.x = c / aspect; - matrix->row2.y = c; - matrix->row3.z = zFar / (zNear - zFar); - matrix->row3.w = -1.0f; - matrix->row4.z = (zNear * zFar) / (zNear - zFar); - matrix->row4.w = 0.0f; -} - - -/*########################################################################################################################* -*---------------------------------------------------------Rendering-------------------------------------------------------* -*#########################################################################################################################*/ -void Gfx_SetVertexFormat(VertexFormat fmt) { - gfx_format = fmt; - gfx_stride = strideSizes[fmt]; -} - -void Gfx_DrawVb_Lines(int verticesCount) { - -} - -static void Transform(Vec3* result, struct VertexTextured* a, const struct Matrix* mat) { - /* a could be pointing to result - therefore can't directly assign X/Y/Z */ - float x = a->x * mat->row1.x + a->y * mat->row2.x + a->z * mat->row3.x + mat->row4.x; - float y = a->x * mat->row1.y + a->y * mat->row2.y + a->z * mat->row3.y + mat->row4.y; - float z = a->x * mat->row1.z + a->y * mat->row2.z + a->z * mat->row3.z + mat->row4.z; - float w = a->x * mat->row1.w + a->y * mat->row2.w + a->z * mat->row3.w + mat->row4.w; - - result->x = (x/w) * (320/2); - result->y = (y/w) * -(224/2); - result->z = (z/w) * 1024; -} - -#define IsPointCulled(vec) vec.x < -10000 || vec.x > 10000 || vec.y < -10000 || vec.y > 10000 || vec.z < 0 || vec.z > 1024 - -static void DrawTexturedQuads(int verticesCount, int startVertex) { - for (int i = 0; i < verticesCount; i += 4) - { - struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; - - Vec3 coords[4]; - Transform(&coords[0], &v[0], &mvp); - Transform(&coords[1], &v[1], &mvp); - Transform(&coords[2], &v[2], &mvp); - Transform(&coords[3], &v[3], &mvp); - - int16_vec2_t points[4]; - points[0].x = coords[0].x; points[0].y = coords[0].y; - points[1].x = coords[1].x; points[1].y = coords[1].y; - points[2].x = coords[2].x; points[2].y = coords[2].y; - points[3].x = coords[3].x; points[3].y = coords[3].y; - - if (IsPointCulled(coords[0])) continue; - if (IsPointCulled(coords[1])) continue; - if (IsPointCulled(coords[2])) continue; - if (IsPointCulled(coords[3])) continue; - - int R = PackedCol_R(v->Col); - int G = PackedCol_G(v->Col); - int B = PackedCol_B(v->Col); - - vdp1_cmdt_t* cmd; - - cmd = NextPrimitive(); - vdp1_cmdt_polygon_set(cmd); - vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); - vdp1_cmdt_draw_mode_set(cmd, _primitive_draw_mode); - vdp1_cmdt_vtx_set(cmd, points); - } -} - -void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - DrawTexturedQuads(verticesCount, startVertex); - } -} - -void Gfx_DrawVb_IndexedTris(int verticesCount) { - if (gfx_format == VERTEX_FORMAT_TEXTURED) { - DrawTexturedQuads(verticesCount, 0); - } -} - -void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { - DrawTexturedQuads(verticesCount, startVertex); -} - - -/*########################################################################################################################* -*---------------------------------------------------------Other/Misc------------------------------------------------------* -*#########################################################################################################################*/ -cc_result Gfx_TakeScreenshot(struct Stream* output) { - return ERR_NOT_SUPPORTED; -} - -cc_bool Gfx_WarnIfNecessary(void) { - return false; -} - -void Gfx_BeginFrame(void) { - Platform_LogConst("FRAME BEG"); - cmdts_count = 0; - - static const int16_vec2_t system_clip_coord = { SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 }; - static const int16_vec2_t local_coord_center = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 }; - - vdp1_cmdt_t* cmd; - - cmd = NextPrimitive(); - vdp1_cmdt_system_clip_coord_set(cmd); - vdp1_cmdt_vtx_system_clip_coord_set(cmd, system_clip_coord); - - cmd = NextPrimitive(); - vdp1_cmdt_local_coord_set(cmd); - vdp1_cmdt_vtx_local_coord_set(cmd, local_coord_center); - - int R = PackedCol_R(clear_color); - int G = PackedCol_G(clear_color); - int B = PackedCol_B(clear_color); - - cmd = NextPrimitive(); - vdp1_cmdt_polygon_set(cmd); - vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); // TODO VDP1 erase - vdp1_cmdt_draw_mode_set(cmd, _primitive_draw_mode); - vdp1_cmdt_vtx_set(cmd, clear_points); -} - -void Gfx_EndFrame(void) { - Platform_LogConst("FRAME END"); - vdp1_cmdt_t* cmd; - - cmd = NextPrimitive(); - vdp1_cmdt_end_set(cmd); - - vdp1_cmdt_list_t cmdt_list; - cmdt_list.cmdts = cmdts_all; - cmdt_list.count = cmdts_count; - vdp1_sync_cmdt_list_put(&cmdt_list, 0); - - vdp1_sync_render(); - vdp1_sync(); - vdp2_sync(); - vdp2_sync_wait(); - - if (gfx_minFrameMs) LimitFPS(); -} - -void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) { - gfx_minFrameMs = minFrameMs; - gfx_vsync = vsync; -} - -void Gfx_OnWindowResize(void) { - // TODO -} - -void Gfx_SetViewport(int x, int y, int w, int h) { } - -void Gfx_GetApiInfo(cc_string* info) { - String_AppendConst(info, "-- Using Saturn --\n"); - PrintMaxTextureInfo(info); -} - -cc_bool Gfx_TryRestoreContext(void) { return true; } -#endif +#include "Core.h" +#if defined CC_BUILD_SATURN +#include "_GraphicsBase.h" +#include "Errors.h" +#include "Window.h" +#include +#include + + +#define SCREEN_WIDTH 320 +#define SCREEN_HEIGHT 224 + +#define PRIMITIVE_DRAW_MODE_NORMAL (0) +#define PRIMITIVE_DRAW_MODE_MESH (1) +#define PRIMITIVE_DRAW_MODE_SHADOW (2) +#define PRIMITIVE_DRAW_MODE_HALF_LUMINANCE (3) +#define PRIMITIVE_DRAW_MODE_HALF_TRANSPARENT (4) +#define PRIMITIVE_DRAW_MODE_GOURAUD_SHADING (5) +#define PRIMITIVE_DRAW_MODE_GOURAUD_HALF_LUM (6) +#define PRIMITIVE_DRAW_MODE_GOURAUD_HALF_TRANS (7) +#define PRIMITIVE_DRAW_MODE_COUNT (8) + +#define CMDS_COUNT 400 + +static PackedCol clear_color; +static vdp1_cmdt_t cmdts_all[CMDS_COUNT]; +static int cmdts_count; +static vdp1_vram_partitions_t _vdp1_vram_partitions; + +static vdp1_cmdt_t* NextPrimitive(void) { + if (cmdts_count >= CMDS_COUNT) Logger_Abort("Too many VDP1 commands"); + return &cmdts_all[cmdts_count++]; +} + +static const vdp1_cmdt_draw_mode_t color_draw_mode = { + .raw = 0x0000 +}; +static const vdp1_cmdt_draw_mode_t texture_draw_mode = { + .cc_mode = PRIMITIVE_DRAW_MODE_GOURAUD_SHADING +}; + +static void UpdateVDP1Env(void) { + vdp1_env_t env; + vdp1_env_default_init(&env); + + int R = PackedCol_R(clear_color); + int G = PackedCol_G(clear_color); + int B = PackedCol_B(clear_color); + env.erase_color = RGB1555(1, R >> 3, G >> 3, B >> 3); + + vdp1_env_set(&env); +} + +static void CalcGouraudColours(void) { + for (int i = 0; i < 1024; i++) + { + // 1024 = 10 bits, divided into RRR GGGG BBB + int r_idx = (i & 0x007) >> 0, R = r_idx << (5 - 3); + int g_idx = (i & 0x078) >> 3, G = g_idx << (5 - 4); + int b_idx = (i & 0x380) >> 7, B = b_idx << (5 - 3); + rgb1555_t gouraud = RGB1555(1, R, G, B); + + vdp1_gouraud_table_t* cur = &_vdp1_vram_partitions.gouraud_base[i]; + cur->colors[0] = gouraud; + cur->colors[1] = gouraud; + cur->colors[2] = gouraud; + cur->colors[3] = gouraud; + } +} + +static GfxResourceID white_square; +void Gfx_RestoreState(void) { + InitDefaultResources(); + + // 2x2 dummy white texture + struct Bitmap bmp; + BitmapCol pixels[4] = { BitmapColor_RGB(255, 0, 0), BITMAPCOLOR_WHITE, BITMAPCOLOR_WHITE, BITMAPCOLOR_WHITE }; + Bitmap_Init(bmp, 2, 2, pixels); + white_square = Gfx_CreateTexture(&bmp, 0, false); +} + +void Gfx_FreeState(void) { + FreeDefaultResources(); + Gfx_DeleteTexture(&white_square); +} + +void Gfx_Create(void) { + if (!Gfx.Created) { + vdp1_vram_partitions_get(&_vdp1_vram_partitions); + // TODO less ram for gourad base + vdp2_scrn_back_color_set(VDP2_VRAM_ADDR(3, 0x01FFFE), + RGB1555(1, 0, 3, 15)); + vdp2_sprite_priority_set(0, 6); + + UpdateVDP1Env(); + CalcGouraudColours(); + } + + Gfx.MinTexWidth = 8; + Gfx.MinTexHeight = 8; + Gfx.MaxTexWidth = 128; + Gfx.MaxTexHeight = 128; + Gfx.Created = true; +} + +void Gfx_Free(void) { + Gfx_FreeState(); +} + + +/*########################################################################################################################* +*---------------------------------------------------------Textures--------------------------------------------------------* +*#########################################################################################################################*/ +#define BGRA8_to_SATURN(src) \ + ((src[2] & 0xF8) >> 3) | ((src[1] & 0xF8) << 2) | ((src[0] & 0xF8) << 7) | ((src[3] & 0x80) << 8) + +static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { + cc_uint16* tmp = Mem_TryAlloc(bmp->width * bmp->height, 2); + if (!tmp) return NULL; + + for (int y = 0; y < bmp->height; y++) + { + cc_uint32* src = bmp->scan0 + y * rowWidth; + cc_uint16* dst = tmp + y * bmp->width; + + for (int x = 0; x < bmp->width; x++) + { + cc_uint8* color = (cc_uint8*)&src[x]; + dst[x] = BGRA8_to_SATURN(color); + dst[x] = 0xFEEE; + } + } + + scu_dma_transfer(0, _vdp1_vram_partitions.texture_base, tmp, bmp->width * bmp->height * 2); + scu_dma_transfer_wait(0); + Mem_Free(tmp); + return (void*)1; +} + +void Gfx_BindTexture(GfxResourceID texId) { +} + +void Gfx_DeleteTexture(GfxResourceID* texId) { +} + +void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { + // TODO +} + +void Gfx_EnableMipmaps(void) { } +void Gfx_DisableMipmaps(void) { } + + +/*########################################################################################################################* +*------------------------------------------------------State management---------------------------------------------------* +*#########################################################################################################################*/ +void Gfx_SetFog(cc_bool enabled) { } +void Gfx_SetFogCol(PackedCol col) { } +void Gfx_SetFogDensity(float value) { } +void Gfx_SetFogEnd(float value) { } +void Gfx_SetFogMode(FogFunc func) { } + +void Gfx_SetFaceCulling(cc_bool enabled) { + // TODO +} + +static void SetAlphaTest(cc_bool enabled) { +} + +static void SetAlphaBlend(cc_bool enabled) { +} + +void Gfx_SetAlphaArgBlend(cc_bool enabled) { } + +void Gfx_ClearBuffers(GfxBuffers buffers) { +} + +void Gfx_ClearColor(PackedCol color) { + if (color == clear_color) return; + + clear_color = color; + UpdateVDP1Env(); +} + +void Gfx_SetDepthTest(cc_bool enabled) { +} + +void Gfx_SetDepthWrite(cc_bool enabled) { + // TODO +} + +static void SetColorWrite(cc_bool r, cc_bool g, cc_bool b, cc_bool a) { + // TODO +} + +void Gfx_DepthOnlyRendering(cc_bool depthOnly) { + cc_bool enabled = !depthOnly; + SetColorWrite(enabled & gfx_colorMask[0], enabled & gfx_colorMask[1], + enabled & gfx_colorMask[2], enabled & gfx_colorMask[3]); +} + + +/*########################################################################################################################* +*-------------------------------------------------------Index buffers-----------------------------------------------------* +*#########################################################################################################################*/ +GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { + return (void*)1; +} + +void Gfx_BindIb(GfxResourceID ib) { } +void Gfx_DeleteIb(GfxResourceID* ib) { } + + +/*########################################################################################################################* +*-------------------------------------------------------Vertex buffers----------------------------------------------------* +*#########################################################################################################################*/ +static void* gfx_vertices; + +static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { + return Mem_TryAlloc(count, strideSizes[fmt]); +} + +void Gfx_BindVb(GfxResourceID vb) { gfx_vertices = vb; } + +void Gfx_DeleteVb(GfxResourceID* vb) { + GfxResourceID data = *vb; + if (data) Mem_Free(data); + *vb = 0; +} + +void* Gfx_LockVb(GfxResourceID vb, VertexFormat fmt, int count) { + return vb; +} + +void Gfx_UnlockVb(GfxResourceID vb) { + gfx_vertices = vb; +} + + +static GfxResourceID Gfx_AllocDynamicVb(VertexFormat fmt, int maxVertices) { + return Mem_TryAlloc(maxVertices, strideSizes[fmt]); +} + +void Gfx_BindDynamicVb(GfxResourceID vb) { Gfx_BindVb(vb); } + +void* Gfx_LockDynamicVb(GfxResourceID vb, VertexFormat fmt, int count) { + return vb; +} + +void Gfx_UnlockDynamicVb(GfxResourceID vb) { + gfx_vertices = vb; +} + +void Gfx_DeleteDynamicVb(GfxResourceID* vb) { Gfx_DeleteVb(vb); } + + +/*########################################################################################################################* +*---------------------------------------------------------Matrices--------------------------------------------------------* +*#########################################################################################################################*/ +static struct Matrix _view, _proj, mvp; + +void Gfx_LoadMatrix(MatrixType type, const struct Matrix* matrix) { + if (type == MATRIX_VIEW) _view = *matrix; + if (type == MATRIX_PROJECTION) _proj = *matrix; + + Matrix_Mul(&mvp, &_view, &_proj); +} + +void Gfx_LoadIdentityMatrix(MatrixType type) { + Gfx_LoadMatrix(type, &Matrix_Identity); +} + +void Gfx_EnableTextureOffset(float x, float y) { + // TODO +} + +void Gfx_DisableTextureOffset(void) { + // TODO +} + +void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) { + /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh */ + /* The simplified calculation below uses: L = 0, R = width, T = 0, B = height */ + /* NOTE: This calculation is shared with Direct3D 11 backend */ + *matrix = Matrix_Identity; + + matrix->row1.x = 2.0f / width; + matrix->row2.y = -2.0f / height; + matrix->row3.z = 1.0f / (zNear - zFar); + + matrix->row4.x = -1.0f; + matrix->row4.y = 1.0f; + matrix->row4.z = zNear / (zNear - zFar); +} + +static float Cotangent(float x) { return Math_CosF(x) / Math_SinF(x); } +void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, float zFar) { + float zNear = 0.01f; + /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh */ + float c = Cotangent(0.5f * fov); + *matrix = Matrix_Identity; + + matrix->row1.x = c / aspect; + matrix->row2.y = c; + matrix->row3.z = zFar / (zNear - zFar); + matrix->row3.w = -1.0f; + matrix->row4.z = (zNear * zFar) / (zNear - zFar); + matrix->row4.w = 0.0f; +} + + +/*########################################################################################################################* +*---------------------------------------------------------Rendering-------------------------------------------------------* +*#########################################################################################################################*/ +void Gfx_SetVertexFormat(VertexFormat fmt) { + gfx_format = fmt; + gfx_stride = strideSizes[fmt]; +} + +void Gfx_DrawVb_Lines(int verticesCount) { + +} + +static void Transform(Vec3* result, struct VertexTextured* a, const struct Matrix* mat) { + /* a could be pointing to result - therefore can't directly assign X/Y/Z */ + float x = a->x * mat->row1.x + a->y * mat->row2.x + a->z * mat->row3.x + mat->row4.x; + float y = a->x * mat->row1.y + a->y * mat->row2.y + a->z * mat->row3.y + mat->row4.y; + float z = a->x * mat->row1.z + a->y * mat->row2.z + a->z * mat->row3.z + mat->row4.z; + float w = a->x * mat->row1.w + a->y * mat->row2.w + a->z * mat->row3.w + mat->row4.w; + + result->x = (x/w) * (SCREEN_WIDTH / 2); + result->y = (y/w) * -(SCREEN_HEIGHT / 2); + result->z = (z/w) * 1024; +} + +#define IsPointCulled(vec) vec.x < -2048 || vec.x > 2048 || vec.y < -2048 || vec.y > 2048 || vec.z < 0 || vec.z > 1024 + +static void DrawColouredQuads2D(int verticesCount, int startVertex) { + for (int i = 0; i < verticesCount; i += 4) + { + struct VertexColoured* v = (struct VertexColoured*)gfx_vertices + startVertex + i; + + int16_vec2_t points[4]; + points[0].x = (int)v[0].x - SCREEN_WIDTH / 2; points[0].y = (int)v[0].y - SCREEN_HEIGHT / 2; + points[1].x = (int)v[1].x - SCREEN_WIDTH / 2; points[1].y = (int)v[1].y - SCREEN_HEIGHT / 2; + points[2].x = (int)v[2].x - SCREEN_WIDTH / 2; points[2].y = (int)v[2].y - SCREEN_HEIGHT / 2; + points[3].x = (int)v[3].x - SCREEN_WIDTH / 2; points[3].y = (int)v[3].y - SCREEN_HEIGHT / 2; + + int R = PackedCol_R(v->Col); + int G = PackedCol_G(v->Col); + int B = PackedCol_B(v->Col); + + vdp1_cmdt_t* cmd; + + cmd = NextPrimitive(); + vdp1_cmdt_polygon_set(cmd); + vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); + vdp1_cmdt_draw_mode_set(cmd, color_draw_mode); + vdp1_cmdt_vtx_set(cmd, points); + } +} + +static void DrawTexturedQuads2D(int verticesCount, int startVertex) { + for (int i = 0; i < verticesCount; i += 4) + { + struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; + + int16_vec2_t points[4]; + points[0].x = (int)v[0].x - SCREEN_WIDTH / 2; points[0].y = (int)v[0].y - SCREEN_HEIGHT / 2; + points[1].x = (int)v[1].x - SCREEN_WIDTH / 2; points[1].y = (int)v[1].y - SCREEN_HEIGHT / 2; + points[2].x = (int)v[2].x - SCREEN_WIDTH / 2; points[2].y = (int)v[2].y - SCREEN_HEIGHT / 2; + points[3].x = (int)v[3].x - SCREEN_WIDTH / 2; points[3].y = (int)v[3].y - SCREEN_HEIGHT / 2; + + int R = PackedCol_R(v->Col); + int G = PackedCol_G(v->Col); + int B = PackedCol_B(v->Col); + + vdp1_cmdt_t* cmd; + + cmd = NextPrimitive(); + vdp1_cmdt_polygon_set(cmd); + vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); + vdp1_cmdt_draw_mode_set(cmd, color_draw_mode); + vdp1_cmdt_vtx_set(cmd, points); + + /*cmd = NextPrimitive(); + vdp1_cmdt_distorted_sprite_set(cmd); + vdp1_cmdt_char_size_set(cmd, 8, 8); + vdp1_cmdt_char_base_set(cmd, (vdp1_vram_t)_vdp1_vram_partitions.texture_base); + vdp1_cmdt_draw_mode_set(cmd, texture_draw_mode); + vdp1_cmdt_vtx_set(cmd, points);*/ + } +} + +static void DrawColouredQuads3D(int verticesCount, int startVertex) { + for (int i = 0; i < verticesCount; i += 4) + { + struct VertexColoured* v = (struct VertexColoured*)gfx_vertices + startVertex + i; + + Vec3 coords[4]; + Transform(&coords[0], &v[0], &mvp); + Transform(&coords[1], &v[1], &mvp); + Transform(&coords[2], &v[2], &mvp); + Transform(&coords[3], &v[3], &mvp); + + int16_vec2_t points[4]; + points[0].x = coords[0].x; points[0].y = coords[0].y; + points[1].x = coords[1].x; points[1].y = coords[1].y; + points[2].x = coords[2].x; points[2].y = coords[2].y; + points[3].x = coords[3].x; points[3].y = coords[3].y; + + if (IsPointCulled(coords[0])) continue; + if (IsPointCulled(coords[1])) continue; + if (IsPointCulled(coords[2])) continue; + if (IsPointCulled(coords[3])) continue; + + int R = PackedCol_R(v->Col); + int G = PackedCol_G(v->Col); + int B = PackedCol_B(v->Col); + + vdp1_cmdt_t* cmd; + + cmd = NextPrimitive(); + vdp1_cmdt_polygon_set(cmd); + vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); + vdp1_cmdt_draw_mode_set(cmd, color_draw_mode); + vdp1_cmdt_vtx_set(cmd, points); + } +} + +static void DrawTexturedQuads3D(int verticesCount, int startVertex) { + for (int i = 0; i < verticesCount; i += 4) + { + struct VertexTextured* v = (struct VertexTextured*)gfx_vertices + startVertex + i; + + Vec3 coords[4]; + Transform(&coords[0], &v[0], &mvp); + Transform(&coords[1], &v[1], &mvp); + Transform(&coords[2], &v[2], &mvp); + Transform(&coords[3], &v[3], &mvp); + + int16_vec2_t points[4]; + points[0].x = coords[0].x; points[0].y = coords[0].y; + points[1].x = coords[1].x; points[1].y = coords[1].y; + points[2].x = coords[2].x; points[2].y = coords[2].y; + points[3].x = coords[3].x; points[3].y = coords[3].y; + + if (IsPointCulled(coords[0])) continue; + if (IsPointCulled(coords[1])) continue; + if (IsPointCulled(coords[2])) continue; + if (IsPointCulled(coords[3])) continue; + + int R = PackedCol_R(v->Col); + int G = PackedCol_G(v->Col); + int B = PackedCol_B(v->Col); + + vdp1_cmdt_t* cmd; + + cmd = NextPrimitive(); + vdp1_cmdt_polygon_set(cmd); + vdp1_cmdt_color_set(cmd, RGB1555(1, R >> 3, G >> 3, B >> 3)); + vdp1_cmdt_draw_mode_set(cmd, color_draw_mode); + vdp1_cmdt_vtx_set(cmd, points); + + /*cmd = NextPrimitive(); + vdp1_cmdt_distorted_sprite_set(cmd); + vdp1_cmdt_char_size_set(cmd, 8, 8); + vdp1_cmdt_char_base_set(cmd, (vdp1_vram_t)_vdp1_vram_partitions.texture_base); + vdp1_cmdt_draw_mode_set(cmd, texture_draw_mode); + vdp1_cmdt_vtx_set(cmd, points);*/ + } +} + +void Gfx_DrawVb_IndexedTris_Range(int verticesCount, int startVertex) { + if (gfx_rendering2D) { + if (gfx_format == VERTEX_FORMAT_TEXTURED) { + DrawTexturedQuads2D(verticesCount, startVertex); + } else { + DrawColouredQuads2D(verticesCount, startVertex); + } + } else { + if (gfx_format == VERTEX_FORMAT_TEXTURED) { + DrawTexturedQuads3D(verticesCount, startVertex); + } else { + DrawColouredQuads3D(verticesCount, startVertex); + } + } +} + +void Gfx_DrawVb_IndexedTris(int verticesCount) { + Gfx_DrawVb_IndexedTris_Range(verticesCount, 0); +} + +void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { + DrawTexturedQuads3D(verticesCount, startVertex); +} + + +/*########################################################################################################################* +*---------------------------------------------------------Other/Misc------------------------------------------------------* +*#########################################################################################################################*/ +cc_result Gfx_TakeScreenshot(struct Stream* output) { + return ERR_NOT_SUPPORTED; +} + +cc_bool Gfx_WarnIfNecessary(void) { + return false; +} + +void Gfx_BeginFrame(void) { + Platform_LogConst("FRAME BEG"); + cmdts_count = 0; + + static const int16_vec2_t system_clip_coord = { SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1 }; + static const int16_vec2_t local_coord_center = { SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 }; + + vdp1_cmdt_t* cmd; + + cmd = NextPrimitive(); + vdp1_cmdt_system_clip_coord_set(cmd); + vdp1_cmdt_vtx_system_clip_coord_set(cmd, system_clip_coord); + + cmd = NextPrimitive(); + vdp1_cmdt_local_coord_set(cmd); + vdp1_cmdt_vtx_local_coord_set(cmd, local_coord_center); +} + +void Gfx_EndFrame(void) { + Platform_LogConst("FRAME END"); + vdp1_cmdt_t* cmd; + + cmd = NextPrimitive(); + vdp1_cmdt_end_set(cmd); + + vdp1_cmdt_list_t cmdt_list; + cmdt_list.cmdts = cmdts_all; + cmdt_list.count = cmdts_count; + vdp1_sync_cmdt_list_put(&cmdt_list, 0); + + vdp1_sync_render(); + vdp1_sync(); + vdp2_sync(); + vdp2_sync_wait(); + + if (gfx_minFrameMs) LimitFPS(); +} + +void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) { + gfx_minFrameMs = minFrameMs; + gfx_vsync = vsync; +} + +void Gfx_OnWindowResize(void) { + // TODO +} + +void Gfx_SetViewport(int x, int y, int w, int h) { } + +void Gfx_GetApiInfo(cc_string* info) { + String_AppendConst(info, "-- Using Saturn --\n"); + PrintMaxTextureInfo(info); +} + +cc_bool Gfx_TryRestoreContext(void) { return true; } +#endif diff --git a/src/Graphics_SoftGPU.c b/src/Graphics_SoftGPU.c index 5b19f26..7753940 100644 --- a/src/Graphics_SoftGPU.c +++ b/src/Graphics_SoftGPU.c @@ -1,17 +1,14 @@ #include "Core.h" -#if defined CC_BUILD_SOFTGPU +#if CC_GFX_BACKEND == CC_GFX_BACKEND_SOFTGPU #include "_GraphicsBase.h" #include "Errors.h" #include "Window.h" static cc_bool faceCulling; -static int width, height; +static int fb_width, fb_height; static struct Bitmap fb_bmp; static float vp_hwidth, vp_hheight; -static int sc_maxX, sc_maxY; - -static cc_bool alphaBlending; -static cc_bool alphaTest; +static int fb_maxX, fb_maxY; static PackedCol* colorBuffer; static PackedCol clearColor; @@ -66,6 +63,7 @@ typedef struct CCTexture { static CCTexture* curTexture; static BitmapCol* curTexPixels; static int curTexWidth, curTexHeight; +static int texWidthMask, texHeightMask; void Gfx_BindTexture(GfxResourceID texId) { if (!texId) texId = white_square; @@ -75,6 +73,9 @@ void Gfx_BindTexture(GfxResourceID texId) { curTexPixels = tex->pixels; curTexWidth = tex->width; curTexHeight = tex->height; + + texWidthMask = (1 << Math_ilog2(tex->width)) - 1; + texHeightMask = (1 << Math_ilog2(tex->height)) - 1; } void Gfx_DeleteTexture(GfxResourceID* texId) { @@ -115,18 +116,18 @@ void Gfx_SetFaceCulling(cc_bool enabled) { faceCulling = enabled; } -void Gfx_SetAlphaTest(cc_bool enabled) { - alphaTest = enabled; +static void SetAlphaTest(cc_bool enabled) { + /* Uses value from Gfx_SetAlphaTest */ } -void Gfx_SetAlphaBlending(cc_bool enabled) { - alphaBlending = enabled; +static void SetAlphaBlend(cc_bool enabled) { + /* Uses value from Gfx_SetAlphaBlending */ } void Gfx_SetAlphaArgBlend(cc_bool enabled) { } void Gfx_ClearBuffers(GfxBuffers buffers) { - int i, size = width * height; + int i, size = fb_width * fb_height; if (buffers & GFX_BUFFER_COLOR) { for (i = 0; i < size; i++) colorBuffer[i] = clearColor; @@ -242,35 +243,34 @@ void Gfx_DisableTextureOffset(void) { } void Gfx_CalcOrthoMatrix(struct Matrix* matrix, float width, float height, float zNear, float zFar) { - /* Transposed, source https://learn.microsoft.com/en-us/windows/win32/opengl/glortho */ + /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixorthooffcenterrh */ /* The simplified calculation below uses: L = 0, R = width, T = 0, B = height */ + /* NOTE: This calculation is shared with Direct3D 11 backend */ *matrix = Matrix_Identity; matrix->row1.x = 2.0f / width; matrix->row2.y = -2.0f / height; - matrix->row3.z = -2.0f / (zFar - zNear); + matrix->row3.z = 1.0f / (zNear - zFar); matrix->row4.x = -1.0f; matrix->row4.y = 1.0f; - matrix->row4.z = -(zFar + zNear) / (zFar - zNear); + matrix->row4.z = zNear / (zNear - zFar); } static float Cotangent(float x) { return Math_CosF(x) / Math_SinF(x); } void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, float zFar) { float zNear = 0.1f; - float c = Cotangent(0.5f * fov); - /* Transposed, source https://learn.microsoft.com/en-us/windows/win32/opengl/glfrustum */ - /* For pos FOV based perspective matrix, left/right/top/bottom are calculated as: */ - /* left = -c * aspect, right = c * aspect, bottom = -c, top = c */ - /* Calculations are simplified because of left/right and top/bottom symmetry */ + /* Source https://learn.microsoft.com/en-us/windows/win32/direct3d9/d3dxmatrixperspectivefovrh */ + /* NOTE: This calculation is shared with Direct3D 11 backend */ + float c = Cotangent(0.5f * fov); *matrix = Matrix_Identity; matrix->row1.x = c / aspect; matrix->row2.y = c; - matrix->row3.z = -(zFar + zNear) / (zFar - zNear); + matrix->row3.z = zFar / (zNear - zFar); matrix->row3.w = -1.0f; - matrix->row4.z = -(2.0f * zFar * zNear) / (zFar - zNear); + matrix->row4.z = (zNear * zFar) / (zNear - zFar); matrix->row4.w = 0.0f; } @@ -278,96 +278,111 @@ void Gfx_CalcPerspectiveMatrix(struct Matrix* matrix, float fov, float aspect, f /*########################################################################################################################* *---------------------------------------------------------Rendering-------------------------------------------------------* *#########################################################################################################################*/ -typedef struct Vector4 { float x, y, z, w; } Vector4; typedef struct Vector3 { float x, y, z; } Vector3; typedef struct Vector2 { float x, y; } Vector2; +typedef struct Vertex_ { + float x, y, z, w; + float u, v; + PackedCol c; +} Vertex; -static void TransformVertex(int index, Vector4* frag, Vector2* uv, PackedCol* color) { +static void TransformVertex(int index, Vertex* vertex) { // TODO: avoid the multiply, just add down in DrawTriangles char* ptr = (char*)gfx_vertices + index * gfx_stride; Vector3* pos = (Vector3*)ptr; - Vector4 coord; + struct Vec4 coord; coord.x = pos->x * mvp.row1.x + pos->y * mvp.row2.x + pos->z * mvp.row3.x + mvp.row4.x; coord.y = pos->x * mvp.row1.y + pos->y * mvp.row2.y + pos->z * mvp.row3.y + mvp.row4.y; coord.z = pos->x * mvp.row1.z + pos->y * mvp.row2.z + pos->z * mvp.row3.z + mvp.row4.z; coord.w = pos->x * mvp.row1.w + pos->y * mvp.row2.w + pos->z * mvp.row3.w + mvp.row4.w; float invW = 1.0f / coord.w; - frag->x = vp_hwidth * (1 + coord.x * invW); - frag->y = vp_hheight * (1 - coord.y * invW); - frag->z = coord.z * invW; - frag->w = invW; + vertex->x = vp_hwidth * (1 + coord.x * invW); + vertex->y = vp_hheight * (1 - coord.y * invW); + vertex->z = coord.z * invW; + vertex->w = invW; if (gfx_format != VERTEX_FORMAT_TEXTURED) { struct VertexColoured* v = (struct VertexColoured*)ptr; - *color = v->Col; + vertex->c = v->Col; } else { struct VertexTextured* v = (struct VertexTextured*)ptr; - *color = v->Col; - uv->x = (v->U + texOffsetX) * invW; - uv->y = (v->V + texOffsetY) * invW; + vertex->u = (v->U + texOffsetX) * invW; + vertex->v = (v->V + texOffsetY) * invW; + vertex->c = v->Col; } } - -static int MultiplyColours(PackedCol vColor, BitmapCol tColor) { - int a1 = PackedCol_A(vColor), a2 = BitmapCol_A(tColor); - int a = ( a1 * a2 ) / 255; - int r1 = PackedCol_R(vColor), r2 = BitmapCol_R(tColor); - int r = ( r1 * r2 ) / 255; - int g1 = PackedCol_G(vColor), g2 = BitmapCol_G(tColor); - int g = ( g1 * g2 ) / 255; - int b1 = PackedCol_B(vColor), b2 = BitmapCol_B(tColor); - int b = ( b1 * b2 ) / 255; - return PackedCol_Make(r, g, b, a); -} - -static void DrawTriangle(Vector4 frag1, Vector4 frag2, Vector4 frag3, - Vector2 uv1, Vector2 uv2, Vector2 uv3, PackedCol color) { - int x1 = (int)frag1.x, y1 = (int)frag1.y; - int x2 = (int)frag2.x, y2 = (int)frag2.y; - int x3 = (int)frag3.x, y3 = (int)frag3.y; - int minX = min(x1, min(x2, x3)); - int minY = min(y1, min(y2, y3)); - int maxX = max(x1, max(x2, x3)); - int maxY = max(y1, max(y2, y3)); - - // TODO backface culling + +// Ensure it's inlined, whereas Math_FloorF might not be +static CC_INLINE int FastFloor(float value) { + int valueI = (int)value; + return valueI > value ? valueI - 1 : valueI; +} + +#define edgeFunction(ax,ay, bx,by, cx,cy) (((bx) - (ax)) * ((cy) - (ay)) - ((by) - (ay)) * ((cx) - (ax))) + +static void DrawTriangle(Vertex* V0, Vertex* V1, Vertex* V2) { + int x0 = (int)V0->x, y0 = (int)V0->y; + int x1 = (int)V1->x, y1 = (int)V1->y; + int x2 = (int)V2->x, y2 = (int)V2->y; + int minX = min(x0, min(x1, x2)); + int minY = min(y0, min(y1, y2)); + int maxX = max(x0, max(x1, x2)); + int maxY = max(y0, max(y1, y2)); + + int area = edgeFunction(x0,y0, x1,y1, x2,y2); if (faceCulling) { // https://gamedev.stackexchange.com/questions/203694/how-to-make-backface-culling-work-correctly-in-both-orthographic-and-perspective - int sign = (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); - if (sign > 0) return; + if (area < 0) return; } // Reject triangles completely outside - if (minX < 0 && maxX < 0 || minX >= width && maxX >= width ) return; - if (minY < 0 && maxY < 0 || minY >= height && maxY >= height) return; + if (maxX < 0 || minX > fb_maxX) return; + if (maxY < 0 || minY > fb_maxY) return; // Perform scissoring - minX = max(minX, 0); maxX = min(maxX, sc_maxX); - minY = max(minY, 0); maxY = min(maxY, sc_maxY); + minX = max(minX, 0); maxX = min(maxX, fb_maxX); + minY = max(minY, 0); maxY = min(maxY, fb_maxY); // NOTE: W in frag variables below is actually 1/W - float factor = 1.0f / ((y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3)); + float factor = 1.0f / area; + float w0 = V0->w, w1 = V1->w, w2 = V2->w; // TODO proper clipping - if (frag1.w <= 0 || frag2.w <= 0 || frag3.w <= 0) return; + if (w0 <= 0 || w1 <= 0 || w2 <= 0) return; + + float z0 = V0->z, z1 = V1->z, z2 = V2->z; + float u0 = V0->u, u1 = V1->u, u2 = V2->u; + float v0 = V0->v, v1 = V1->v, v2 = V2->v; + PackedCol color = V0->c; - for (int y = minY; y <= maxY; y++) { - float yy = y + 0.5f; - for (int x = minX; x <= maxX; x++) { - float xx = x + 0.5f; - - float ic0 = ((y2 - y3) * (xx - x3) + (x3 - x2) * (yy - y3)) * factor; - if (ic0 < 0 || ic0 > 1) continue; - float ic1 = ((y3 - y1) * (xx - x3) + (x1 - x3) * (yy - y3)) * factor; - if (ic1 < 0 || ic1 > 1) continue; - float ic2 = 1.0f - ic0 - ic1; - if (ic2 < 0 || ic2 > 1) continue; - - int index = y * width + x; - float w = 1 / (ic0 * frag1.w + ic1 * frag2.w + ic2 * frag3.w); - float z = (ic0 * frag1.z + ic1 * frag2.z + ic2 * frag3.z) * w; + // https://fgiesen.wordpress.com/2013/02/10/optimizing-the-basic-rasterizer/ + // Essentially these are the deltas of edge functions between X/Y and X/Y + 1 (i.e. one X/Y step) + int dx01 = y0 - y1, dy01 = x1 - x0; + int dx12 = y1 - y2, dy12 = x2 - x1; + int dx20 = y2 - y0, dy20 = x0 - x2; + + float bc0_start = edgeFunction(x1,y1, x2,y2, minX+0.5f,minY+0.5f); + float bc1_start = edgeFunction(x2,y2, x0,y0, minX+0.5f,minY+0.5f); + float bc2_start = edgeFunction(x0,y0, x1,y1, minX+0.5f,minY+0.5f); + + for (int y = minY; y <= maxY; y++, bc0_start += dy12, bc1_start += dy20, bc2_start += dy01) + { + float bc0 = bc0_start; + float bc1 = bc1_start; + float bc2 = bc2_start; + + for (int x = minX; x <= maxX; x++, bc0 += dx12, bc1 += dx20, bc2 += dx01) + { + float ic0 = bc0 * factor; + float ic1 = bc1 * factor; + float ic2 = bc2 * factor; + if (ic0 < 0 || ic1 < 0 || ic2 < 0) continue; + + int index = y * fb_width + x; + float w = 1 / (ic0 * w0 + ic1 * w1 + ic2 * w2); + float z = (ic0 * z0 + ic1 * z1 + ic2 * z2) * w; if (depthTest && (z < 0 || z > depthBuffer[index])) continue; if (!colWrite) { @@ -375,33 +390,41 @@ static void DrawTriangle(Vector4 frag1, Vector4 frag2, Vector4 frag3, continue; } - PackedCol fragColor = color; + int R, G, B, A; if (gfx_format == VERTEX_FORMAT_TEXTURED) { - float u = (ic0 * uv1.x + ic1 * uv2.x + ic2 * uv3.x) * w; - float v = (ic0 * uv1.y + ic1 * uv2.y + ic2 * uv3.y) * w; - int texX = ((int)(Math_AbsF(u - Math_Floor(u)) * curTexWidth )) % curTexWidth; // TODO avoid slow % - int texY = ((int)(Math_AbsF(v - Math_Floor(v)) * curTexHeight)) % curTexHeight; + float u = (ic0 * u0 + ic1 * u1 + ic2 * u2) * w; + float v = (ic0 * v0 + ic1 * v1 + ic2 * v2) * w; + int texX = ((int)(Math_AbsF(u - FastFloor(u)) * curTexWidth )) & texWidthMask; + int texY = ((int)(Math_AbsF(v - FastFloor(v)) * curTexHeight)) & texHeightMask; int texIndex = texY * curTexWidth + texX; - fragColor = MultiplyColours(fragColor, curTexPixels[texIndex]); + BitmapCol tColor = curTexPixels[texIndex]; + int a1 = PackedCol_A(color), a2 = BitmapCol_A(tColor); + A = ( a1 * a2 ) >> 8; + int r1 = PackedCol_R(color), r2 = BitmapCol_R(tColor); + R = ( r1 * r2 ) >> 8; + int g1 = PackedCol_G(color), g2 = BitmapCol_G(tColor); + G = ( g1 * g2 ) >> 8; + int b1 = PackedCol_B(color), b2 = BitmapCol_B(tColor); + B = ( b1 * b2 ) >> 8; + } else { + R = PackedCol_R(color); + G = PackedCol_G(color); + B = PackedCol_B(color); + A = PackedCol_A(color); } - int R = PackedCol_R(fragColor); - int G = PackedCol_G(fragColor); - int B = PackedCol_B(fragColor); - int A = PackedCol_A(fragColor); - - if (alphaBlending) { - PackedCol dst = colorBuffer[index]; + if (gfx_alphaBlend) { + BitmapCol dst = colorBuffer[index]; int dstR = BitmapCol_R(dst); int dstG = BitmapCol_G(dst); int dstB = BitmapCol_B(dst); - R = (R * A) / 255 + (dstR * (255 - A)) / 255; - G = (G * A) / 255 + (dstG * (255 - A)) / 255; - B = (B * A) / 255 + (dstB * (255 - A)) / 255; + R = (R * A + dstR * (255 - A)) >> 8; + G = (G * A + dstG * (255 - A)) >> 8; + B = (B * A + dstB * (255 - A)) >> 8; } - if (alphaTest && A < 0x80) continue; + if (gfx_alphaTest && A < 0x80) continue; if (depthWrite) depthBuffer[index] = z; colorBuffer[index] = BitmapCol_Make(R, G, B, 0xFF); @@ -410,24 +433,19 @@ static void DrawTriangle(Vector4 frag1, Vector4 frag2, Vector4 frag3, } void DrawQuads(int startVertex, int verticesCount) { - Vector4 frag[4]; - Vector2 uv[4]; - PackedCol color[4]; + Vertex vertices[4]; int j = startVertex; // 4 vertices = 1 quad = 2 triangles for (int i = 0; i < verticesCount / 4; i++, j += 4) { - TransformVertex(j + 0, &frag[0], &uv[0], &color[0]); - TransformVertex(j + 1, &frag[1], &uv[1], &color[1]); - TransformVertex(j + 2, &frag[2], &uv[2], &color[2]); - TransformVertex(j + 3, &frag[3], &uv[3], &color[3]); + TransformVertex(j + 0, &vertices[0]); + TransformVertex(j + 1, &vertices[1]); + TransformVertex(j + 2, &vertices[2]); + TransformVertex(j + 3, &vertices[3]); - DrawTriangle(frag[0], frag[1], frag[2], - uv[0], uv[1], uv[2], color[0]); - - DrawTriangle(frag[2], frag[3], frag[0], - uv[2], uv[3], uv[0], color[2]); + DrawTriangle(&vertices[0], &vertices[2], &vertices[1]); + DrawTriangle(&vertices[2], &vertices[0], &vertices[3]); } } @@ -455,7 +473,9 @@ void Gfx_DrawIndexedTris_T2fC4b(int verticesCount, int startVertex) { *---------------------------------------------------------Other/Misc------------------------------------------------------* *#########################################################################################################################*/ cc_result Gfx_TakeScreenshot(struct Stream* output) { - return ERR_NOT_SUPPORTED; + struct Bitmap bmp; + Bitmap_Init(bmp, fb_width, fb_height, colorBuffer); + return Png_Encode(&bmp, output, NULL, false, NULL); } cc_bool Gfx_WarnIfNecessary(void) { @@ -465,7 +485,7 @@ cc_bool Gfx_WarnIfNecessary(void) { void Gfx_BeginFrame(void) { } void Gfx_EndFrame(void) { - Rect2D r = { 0, 0, width, height }; + Rect2D r = { 0, 0, fb_width, fb_height }; Window_DrawFramebuffer(r, &fb_bmp); } @@ -477,17 +497,17 @@ void Gfx_SetFpsLimit(cc_bool vsync, float minFrameMs) { void Gfx_OnWindowResize(void) { if (depthBuffer) DestroyBuffers(); - fb_bmp.width = width = Game.Width; - fb_bmp.height = height = Game.Height; + fb_bmp.width = fb_width = Game.Width; + fb_bmp.height = fb_height = Game.Height; - vp_hwidth = width / 2.0f; - vp_hheight = height / 2.0f; + vp_hwidth = fb_width / 2.0f; + vp_hheight = fb_height / 2.0f; - sc_maxX = width - 1; - sc_maxY = height - 1; + fb_maxX = fb_width - 1; + fb_maxY = fb_height - 1; Window_AllocFramebuffer(&fb_bmp); - depthBuffer = Mem_Alloc(width * height, 4, "depth buffer"); + depthBuffer = Mem_Alloc(fb_width * fb_height, 4, "depth buffer"); colorBuffer = fb_bmp.scan0; } diff --git a/src/Graphics_WiiU.c b/src/Graphics_WiiU.c index 7cc5991..ea565fa 100644 --- a/src/Graphics_WiiU.c +++ b/src/Graphics_WiiU.c @@ -177,16 +177,16 @@ void Gfx_SetFogMode(FogFunc func) { // TODO } -void Gfx_SetAlphaTest(cc_bool enabled) { +static void SetAlphaTest(cc_bool enabled) { GX2SetAlphaTest(enabled, GX2_COMPARE_FUNC_GEQUAL, 0.5f); } -void Gfx_SetAlphaBlending(cc_bool enabled) { +static void SetAlphaBlend(cc_bool enabled) { GX2SetBlendControl(GX2_RENDER_TARGET_0, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD, true, GX2_BLEND_MODE_SRC_ALPHA, GX2_BLEND_MODE_INV_SRC_ALPHA, GX2_BLEND_COMBINE_MODE_ADD); - GX2SetColorControl(GX2_LOGIC_OP_COPY, enabled, FALSE, TRUE); + GX2SetColorControl(GX2_LOGIC_OP_COPY, enabled, FALSE, TRUE); } void Gfx_SetAlphaArgBlend(cc_bool enabled) { diff --git a/src/Graphics_Xbox.c b/src/Graphics_Xbox.c index e4c0d93..6fcdedb 100644 --- a/src/Graphics_Xbox.c +++ b/src/Graphics_Xbox.c @@ -299,13 +299,13 @@ void Gfx_SetFaceCulling(cc_bool enabled) { void Gfx_SetAlphaArgBlend(cc_bool enabled) { } -void Gfx_SetAlphaBlending(cc_bool enabled) { +static void SetAlphaBlend(cc_bool enabled) { uint32_t* p = pb_begin(); p = pb_push1(p, NV097_SET_BLEND_ENABLE, enabled); pb_end(p); } -void Gfx_SetAlphaTest(cc_bool enabled) { +static void SetAlphaTest(cc_bool enabled) { uint32_t* p = pb_begin(); p = pb_push1(p, NV097_SET_ALPHA_TEST_ENABLE, enabled); pb_end(p); @@ -396,7 +396,6 @@ void Gfx_EndFrame(void) { *----------------------------------------------------------Buffers--------------------------------------------------------* *#########################################################################################################################*/ static cc_uint8* gfx_vertices; -static cc_uint16* gfx_indices; static void* AllocBuffer(int count, int elemSize) { return MmAllocateContiguousMemoryEx(count * elemSize, 0, MAX_RAM_ADDR, 16, PAGE_WRITECOMBINE | PAGE_READWRITE); @@ -410,16 +409,12 @@ static void FreeBuffer(GfxResourceID* buffer) { GfxResourceID Gfx_CreateIb2(int count, Gfx_FillIBFunc fillFunc, void* obj) { - void* ib = AllocBuffer(count, sizeof(cc_uint16)); - if (!ib) Logger_Abort("Failed to allocate memory for index buffer"); - - fillFunc(ib, count, obj); - return ib; + return (void*)1; } -void Gfx_BindIb(GfxResourceID ib) { gfx_indices = ib; } +void Gfx_BindIb(GfxResourceID ib) { } -void Gfx_DeleteIb(GfxResourceID* ib) { FreeBuffer(ib); } +void Gfx_DeleteIb(GfxResourceID* ib) { } static GfxResourceID Gfx_AllocStaticVb(VertexFormat fmt, int count) { @@ -476,6 +471,18 @@ void Gfx_SetFog(cc_bool enabled) { } void Gfx_SetFogCol(PackedCol color) { + int R = PackedCol_R(color); + int G = PackedCol_G(color); + int B = PackedCol_B(color); + int A = PackedCol_A(color); + + uint32_t* p = pb_begin(); + p = pb_push1(p, NV097_SET_FOG_COLOR, + MASK(NV097_SET_FOG_COLOR_RED, R) | + MASK(NV097_SET_FOG_COLOR_GREEN, G) | + MASK(NV097_SET_FOG_COLOR_BLUE, B) | + MASK(NV097_SET_FOG_COLOR_ALPHA, A)); + pb_end(p); } void Gfx_SetFogDensity(float value) { @@ -655,16 +662,16 @@ static void DrawArrays(int mode, int start, int count) { uint32_t *p = pb_begin(); p = pb_push1(p, NV097_SET_BEGIN_END, mode); - // NV097_DRAW_ARRAYS_COUNT is an 8 bit mask, so must be < 256 + // NV097_DRAW_ARRAYS_COUNT is an 8 bit mask, so must be <= 256 while (count > 0) { - int batch_count = min(count, 64); // TODO increase? + int batch_count = min(count, 256); p = pb_push1(p, 0x40000000 | NV097_DRAW_ARRAYS, MASK(NV097_DRAW_ARRAYS_COUNT, (batch_count-1)) | MASK(NV097_DRAW_ARRAYS_START_INDEX, start)); - start += batch_count; + start += batch_count; count -= batch_count; } @@ -676,9 +683,7 @@ void Gfx_DrawVb_Lines(int verticesCount) { DrawArrays(NV097_SET_BEGIN_END_OP_LINES, 0, verticesCount); } -#define MAX_BATCH 120 static void DrawIndexedVertices(int verticesCount, int startVertex) { - // TODO switch to indexed rendering DrawArrays(NV097_SET_BEGIN_END_OP_QUADS, startVertex, verticesCount); } diff --git a/src/Graphics_Xbox360.c b/src/Graphics_Xbox360.c index 745729c..f657f16 100644 --- a/src/Graphics_Xbox360.c +++ b/src/Graphics_Xbox360.c @@ -82,7 +82,7 @@ static void Gfx_FreeState(void) { static void Gfx_RestoreState(void) { InitDefaultResources(); Gfx_SetFaceCulling(false); - Gfx_SetAlphaBlending(false); + SetAlphaBlend(false); Xe_SetAlphaFunc(xe, XE_CMP_GREATER); Xe_SetAlphaRef(xe, 0.5f); @@ -155,11 +155,11 @@ void Gfx_SetFogMode(FogFunc func) { // TODO } -void Gfx_SetAlphaTest(cc_bool enabled) { +static void SetAlphaTest(cc_bool enabled) { Xe_SetAlphaTestEnable(xe, enabled); } -void Gfx_SetAlphaBlending(cc_bool enabled) { +static void SetAlphaBlend(cc_bool enabled) { if (enabled) { Xe_SetBlendControl(xe, XE_BLEND_SRCALPHA, XE_BLENDOP_ADD, XE_BLEND_INVSRCALPHA, diff --git a/src/Gui.c b/src/Gui.c index e6f7bd7..670d863 100644 --- a/src/Gui.c +++ b/src/Gui.c @@ -35,7 +35,7 @@ static CC_NOINLINE int GetWindowScale(void) { /* Use larger UI scaling on mobile */ /* TODO move this DPI scaling elsewhere.,. */ #ifndef CC_BUILD_DUALSCREEN - if (!Gui.TouchUI) { + if (!Gui_TouchUI) { #endif widthScale /= DisplayInfo.ScaleX; heightScale /= DisplayInfo.ScaleY; diff --git a/src/Gui.h b/src/Gui.h index cf2fcb3..43878f7 100644 --- a/src/Gui.h +++ b/src/Gui.h @@ -55,6 +55,12 @@ CC_VAR extern struct _GuiData { cc_bool TouchUI; } Gui; +#ifdef CC_BUILD_TOUCH +#define Gui_TouchUI Gui.TouchUI +#else +#define Gui_TouchUI false +#endif + float Gui_Scale(float value); float Gui_GetHotbarScale(void); float Gui_GetInventoryScale(void); diff --git a/src/HeldBlockRenderer.c b/src/HeldBlockRenderer.c index b0b603a..20df0f6 100644 --- a/src/HeldBlockRenderer.c +++ b/src/HeldBlockRenderer.c @@ -36,6 +36,7 @@ static void HeldBlockRenderer_RenderModel(void) { Gfx_SetFaceCulling(true); Gfx_SetDepthTest(false); + Gfx_SetDepthWrite(false); /* TODO: Need to properly reallocate per model VB here */ if (Blocks.Draw[held_block] == DRAW_GAS) { @@ -43,7 +44,6 @@ static void HeldBlockRenderer_RenderModel(void) { SetHeldModel(model); Vec3_Set(held_entity.ModelScale, 1.0f,1.0f,1.0f); - Gfx_SetAlphaTest(true); Model_RenderArm(model, &held_entity); Gfx_SetAlphaTest(false); } else { @@ -57,6 +57,7 @@ static void HeldBlockRenderer_RenderModel(void) { } Gfx_SetDepthTest(true); + Gfx_SetDepthWrite(true); Gfx_SetFaceCulling(false); } diff --git a/src/Http_Worker.c b/src/Http_Worker.c index 5bf5470..817a01d 100644 --- a/src/Http_Worker.c +++ b/src/Http_Worker.c @@ -41,6 +41,14 @@ static void Http_ParseCookie(struct HttpRequest* req, const cc_string* value) { EntryList_Set(req->cookies, &name, &data, '='); } +static void Http_ParseContentLength(struct HttpRequest* req, const cc_string* value) { + int contentLen = 0; + Convert_ParseInt(value, &contentLen); + + if (contentLen <= 0) return; + req->contentLength = contentLen; +} + /* Parses a HTTP header */ static void Http_ParseHeader(struct HttpRequest* req, const cc_string* line) { static const cc_string httpVersion = String_FromConst("HTTP"); @@ -58,11 +66,11 @@ static void Http_ParseHeader(struct HttpRequest* req, const cc_string* line) { if (String_CaselessEqualsConst(&name, "ETag")) { String_CopyToRawArray(req->etag, &value); } else if (String_CaselessEqualsConst(&name, "Content-Length")) { - Convert_ParseInt(&value, &req->contentLength); + Http_ParseContentLength(req, &value); } else if (String_CaselessEqualsConst(&name, "X-Dropbox-Content-Length")) { /* dropbox stopped returning Content-Length header since switching to chunked transfer */ /* https://www.dropboxforum.com/t5/Discuss-Dropbox-Developer-API/Dropbox-media-can-t-be-access-by-azure-blob/td-p/575458 */ - Convert_ParseInt(&value, &req->contentLength); + Http_ParseContentLength(req, &value); } else if (String_CaselessEqualsConst(&name, "Last-Modified")) { String_CopyToRawArray(req->lastModified, &value); } else if (req->cookies && String_CaselessEqualsConst(&name, "Set-Cookie")) { @@ -558,6 +566,7 @@ static cc_result ConnectionPool_Open(struct HttpConnection** conn, const struct *--------------------------------------------------------HttpClient-------------------------------------------------------* *#########################################################################################################################*/ enum HTTP_RESPONSE_STATE { + HTTP_RESPONSE_STATE_INITIAL, HTTP_RESPONSE_STATE_HEADER, HTTP_RESPONSE_STATE_DATA, HTTP_RESPONSE_STATE_CHUNK_HEADER, @@ -583,7 +592,7 @@ struct HttpClientState { }; static void HttpClientState_Reset(struct HttpClientState* state) { - state->state = HTTP_RESPONSE_STATE_HEADER; + state->state = HTTP_RESPONSE_STATE_INITIAL; state->chunked = 0; state->dataLeft = 0; state->autoClose = false; @@ -705,6 +714,9 @@ static cc_result HttpClient_Process(struct HttpClientState* state, char* buffer, while (offset < total) { switch (state->state) { + case HTTP_RESPONSE_STATE_INITIAL: + state->state = HTTP_RESPONSE_STATE_HEADER; + break; case HTTP_RESPONSE_STATE_HEADER: { @@ -836,8 +848,8 @@ static cc_result HttpClient_ParseResponse(struct HttpClientState* state) { if (res) return res; if (total == 0) { - Platform_LogConst("Http read unexpectedly returned 0"); - return ERR_END_OF_STREAM; + Platform_Log1("Http read unexpectedly returned 0 in state %i", &state->state); + return state->state == HTTP_RESPONSE_STATE_INITIAL ? HTTP_ERR_NO_RESPONSE : ERR_END_OF_STREAM; } if (dst != buffer) { @@ -915,6 +927,11 @@ static cc_result HttpBackend_Do(struct HttpRequest* req, cc_string* urlStr) { res = HttpBackend_PerformRequest(&state); retried = true; } + if (res == HTTP_ERR_NO_RESPONSE && !retried) { + Platform_LogConst("Resetting connection due to empty response.."); + res = HttpBackend_PerformRequest(&state); + retried = true; + } if (res || !HttpClient_IsRedirect(req)) break; if (redirects >= 20) return HTTP_ERR_REDIRECTS; @@ -1360,10 +1377,10 @@ static void Http_Init(void) { RequestList_Init(&pendingReqs); RequestList_Init(&processedReqs); - workerWaitable = Waitable_Create(); - pendingMutex = Mutex_Create(); - processedMutex = Mutex_Create(); - curRequestMutex = Mutex_Create(); + workerWaitable = Waitable_Create("HTTP wakeup"); + pendingMutex = Mutex_Create("HTTP pending"); + processedMutex = Mutex_Create("HTTP processed"); + curRequestMutex = Mutex_Create("HTTP current"); Thread_Run(&workerThread, WorkerLoop, 128 * 1024, "HTTP"); } diff --git a/src/Input.c b/src/Input.c index cc4235a..ff23188 100644 --- a/src/Input.c +++ b/src/Input.c @@ -190,7 +190,8 @@ static void ClearTouches(void) { } "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",\ "U", "V", "W", "X", "Y", "Z" #define Pad_Names \ -"PAD_A", "PAD_B", "PAD_X", "PAD_Y", "PAD_L", "PAD_R", "PAD_Z", \ +"PAD_A", "PAD_B", "PAD_X", "PAD_Y", "PAD_L", "PAD_R", \ +"PAD_Z", "PAD_C", "PAD_D", \ "PAD_LEFT", "PAD_RIGHT", "PAD_UP", "PAD_DOWN", \ "PAD_START", "PAD_SELECT", "PAD_ZL", "PAD_ZR", \ "PAD_LSTICK", "PAD_RSTICK", \ @@ -215,8 +216,16 @@ static const char* const storageNames[INPUT_COUNT] = { "Keypad0", "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "KeypadDivide", "KeypadMultiply", "KeypadSubtract", - "KeypadAdd", "KeypadDecimal", "KeypadEnter", - "XButton1", "XButton2", "LeftMouse", "RightMouse", "MiddleMouse", + "KeypadAdd", "KeypadDecimal", "KeypadEnter", + + "VolumeMute", "VolumeUp", "VolumeDown", "Sleep", + "MediaNext", "MediaPrev", "MediaPlay", "MediaStop", + "BrowserPrev", "BrowserNext", "BrowserRefresh", "BrowserStop", "BrowserSsearch", "BrowserFavorites", "BrowserHome", + "LaunchMail", "LaunchMedia", "LaunchApp1", "LaunchCalc", + + "XButton1", "XButton2", "XButton3", "XButton4", "XButton5", "XButton6", + "LeftMouse", "RightMouse", "MiddleMouse", + "WheelUp", "WheelDown", "WheelLeft", "WheelRight", Pad_Names }; @@ -239,7 +248,15 @@ const char* const Input_DisplayNames[INPUT_COUNT] = { "NUMPAD5", "NUMPAD6", "NUMPAD7", "NUMPAD8", "NUMPAD9", "DIVIDE", "MULTIPLY", "SUBTRACT", "ADD", "DECIMAL", "NUMPADENTER", - "XBUTTON1", "XBUTTON2", "LMOUSE", "RMOUSE", "MMOUSE", + + "VOLUMEMUTE", "VOLUMEUP", "VOLUMEDOWN", "SLEEP", + "MEDIANEXT", "MEDIAPREV", "MEDIAPLAY", "MEDIASTOP", + "BROWSERPREV", "BROWSERNEXT", "BROWSERREFRESH", "BROWSERSTOP", "BROWSERSEARCH", "BROWSERFAVORITES", "BROWSERHOME", + "LAUNCHMAIL", "LAUNCHMEDIA", "LAUNCHAPP1", "LAUNCHCALC", + + "XBUTTON1", "XBUTTON2", "XBUTTON3", "XBUTTON4", "XBUTTON5", "XBUTTON6", + "LMOUSE", "RMOUSE", "MMOUSE", + "WHEELUP", "WHEELDOWN", "WHEELLEFT", "WHEELRIGHT", Pad_Names }; @@ -314,8 +331,35 @@ void Pointer_SetPressed(int idx, cc_bool pressed) { } } -void Mouse_ScrollWheel(float delta) { +static float scrollingVAcc; +void Mouse_ScrollVWheel(float delta) { + int steps = Utils_AccumulateWheelDelta(&scrollingVAcc, delta); Event_RaiseFloat(&InputEvents.Wheel, delta); + + if (steps > 0) { + for (; steps != 0; steps--) + Input_SetPressed(CCWHEEL_UP); + Input_SetReleased(CCWHEEL_UP); + } else if (steps < 0) { + for (; steps != 0; steps++) + Input_SetPressed(CCWHEEL_DOWN); + Input_SetReleased(CCWHEEL_DOWN); + } +} + +static float scrollingHAcc; +void Mouse_ScrollHWheel(float delta) { + int steps = Utils_AccumulateWheelDelta(&scrollingHAcc, delta); + + if (steps > 0) { + for (; steps != 0; steps--) + Input_SetPressed(CCWHEEL_RIGHT); + Input_SetReleased(CCWHEEL_RIGHT); + } else if (steps < 0) { + for (; steps != 0; steps++) + Input_SetPressed(CCWHEEL_LEFT); + Input_SetReleased(CCWHEEL_LEFT); + } } void Pointer_SetPosition(int idx, int x, int y) { @@ -333,38 +377,56 @@ void Pointer_SetPosition(int idx, int x, int y) { /*########################################################################################################################* *---------------------------------------------------------Keybinds--------------------------------------------------------* *#########################################################################################################################*/ -cc_uint8 KeyBinds_Gamepad[KEYBIND_COUNT]; -cc_uint8 KeyBinds_Normal[KEYBIND_COUNT]; - -const cc_uint8 KeyBind_GamepadDefaults[KEYBIND_COUNT] = { - CCPAD_UP, CCPAD_DOWN, CCPAD_LEFT, CCPAD_RIGHT, /* Movement */ - CCPAD_A, 0, CCPAD_START, CCPAD_Y, /* Jump, SetSpawn, OpenChat */ - CCPAD_X, 0, CCPAD_START, 0, /* Inventory, EnterChat */ - 0, 0, 0, 0, 0, /* Hacks */ - 0, 0, 0, 0, /* LAlt - F11 */ - 0, 0, 0, 0, /* F5 - C */ - 0, CCPAD_L, 0, CCPAD_R, - 0, 0, 0, - 0,0,0, 0,0,0,0, - 0,0,0, 0,0,0, 0,0,0, /* Hotbar slots */ - CCPAD_ZL, CCPAD_ZR +BindMapping PadBind_Mappings[BIND_COUNT]; +BindMapping KeyBind_Mappings[BIND_COUNT]; + +const BindMapping PadBind_Defaults[BIND_COUNT] = { + { CCPAD_UP, 0 }, { CCPAD_DOWN, 0 }, /* BIND_FORWARD, BIND_BACK */ + { CCPAD_LEFT, 0 }, { CCPAD_RIGHT, 0 }, /* BIND_LEFT, BIND_RIGHT */ + { CCPAD_A, 0 }, { 0, 0 }, /* BIND_JUMP, BIND_RESPAWN */ + { CCPAD_START, 0 }, { CCPAD_Y, 0 }, /* BIND_SET_SPAWN, BIND_CHAT */ + { CCPAD_X, 0 }, { 0, 0 }, /* BIND_INVENTORY, BIND_FOG */ + { CCPAD_START, 0 }, { 0, 0 }, /* BIND_SEND_CHAT, BIND_TABLIST */ + { CCPAD_B, CCPAD_L},{ CCPAD_B, CCPAD_X},/* BIND_SPEED, BIND_NOCLIP */ + { CCPAD_B, CCPAD_R }, /* BIND_FLY */ + {CCPAD_B,CCPAD_UP},{CCPAD_B,CCPAD_DOWN},/* BIND_FLY_UP, BIND_FLY_DOWN */ + { 0, 0 }, { 0, 0 }, /* BIND_EXT_INPUT, BIND_HIDE_FPS */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* BIND_SCREENSHOT, BIND_FULLSCREEN, BIND_THIRD_PERSON, BIND_HIDE_GUI */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, /* BIND_AXIS_LINES, BIND_ZOOM_SCROLL, BIND_HALF_SPEED */ + { CCPAD_L, 0 }, { 0, 0 },{ CCPAD_R, 0 },/* BIND_DELETE_BLOCK, BIND_PICK_BLOCK, BIND_PLACE_BLOCK */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, /* BIND_AUTOROTATE, BIND_HOTBAR_SWITCH, BIND_SMOOTH_CAMERA */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, /* BIND_DROP_BLOCK, BIND_IDOVERLAY, BIND_BREAK_LIQUIDS */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* BIND_LOOK_UP, BIND_LOOK_DOWN, BIND_LOOK_RIGHT, BIND_LOOK_LEFT */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, /* BIND_HOTBAR_1, BIND_HOTBAR_2, BIND_HOTBAR_3 */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, /* BIND_HOTBAR_4, BIND_HOTBAR_5, BIND_HOTBAR_6 */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, /* BIND_HOTBAR_7, BIND_HOTBAR_8, BIND_HOTBAR_9 */ + { CCPAD_ZL, 0 }, { CCPAD_ZR, 0 } /* BIND_HOTBAR_LEFT, BIND_HOTBAR_RIGHT */ }; -const cc_uint8 KeyBind_NormalDefaults[KEYBIND_COUNT] = { - 'W', 'S', 'A', 'D', - CCKEY_SPACE, 'R', CCKEY_ENTER, 'T', - 'B', 'F', CCKEY_ENTER, CCKEY_TAB, - CCKEY_LSHIFT, 'X', 'Z', 'Q', 'E', - CCKEY_LALT, CCKEY_F3, CCKEY_F12, CCKEY_F11, - CCKEY_F5, CCKEY_F1, CCKEY_F7, 'C', - CCKEY_LCTRL, CCMOUSE_L, CCMOUSE_M, CCMOUSE_R, - CCKEY_F6, CCKEY_LALT, CCKEY_F8, - 'G', CCKEY_F10, 0, - 0, 0, 0, 0, - '1','2','3', '4','5','6', '7','8','9', - 0, 0 + +const BindMapping KeyBind_Defaults[BIND_COUNT] = { + { 'W', 0 }, { 'S', 0 }, { 'A', 0 }, { 'D', 0 }, /* BIND_FORWARD - BIND_RIGHT */ + { CCKEY_SPACE, 0 }, { 'R', 0 }, /* BIND_JUMP, BIND_RESPAWN */ + { CCKEY_ENTER, 0 }, { 'T', 0 }, /* BIND_SET_SPAWN, BIND_CHAT */ + { 'B', 0 }, { 'F', 0 }, /* BIND_INVENTORY, BIND_FOG */ + { CCKEY_ENTER, 0 }, { CCKEY_TAB, 0 }, /* BIND_SEND_CHAT, BIND_TABLIST */ + { CCKEY_LSHIFT, 0 }, { 'X', 0}, { 'Z', 0 }, /* BIND_SPEED, BIND_NOCLIP, BIND_FLY */ + { 'Q', 0 }, { 'E', 0 }, /* BIND_FLY_UP, BIND_FLY_DOWN */ + { CCKEY_LALT, 0 }, { CCKEY_F3, 0 }, /* BIND_EXT_INPUT, BIND_HIDE_FPS */ + { CCKEY_F12, 0 }, { CCKEY_F11, 0 }, /* BIND_SCREENSHOT, BIND_FULLSCREEN */ + { CCKEY_F5, 0 }, { CCKEY_F1, 0 }, /* BIND_THIRD_PERSON, BIND_HIDE_GUI */ + { CCKEY_F7, 0 }, { 'C', 0 }, { CCKEY_LCTRL, 0 },/* BIND_AXIS_LINES, BIND_ZOOM_SCROLL, BIND_HALF_SPEED */ + { CCMOUSE_L, 0},{ CCMOUSE_M, 0},{ CCMOUSE_R, 0},/* BIND_DELETE_BLOCK, BIND_PICK_BLOCK, BIND_PLACE_BLOCK */ + { CCKEY_F6, 0 }, { CCKEY_LALT, 0 }, /* BIND_AUTOROTATE, BIND_HOTBAR_SWITCH */ + { CCKEY_F8, 0 }, { 'G', 0 }, /* BIND_SMOOTH_CAMERA, BIND_DROP_BLOCK */ + { CCKEY_F10, 0 }, { 0, 0 }, /* BIND_IDOVERLAY, BIND_BREAK_LIQUIDS */ + { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, /* BIND_LOOK_UP, BIND_LOOK_DOWN, BIND_LOOK_RIGHT, BIND_LOOK_LEFT */ + { '1', 0 }, { '2', 0 }, { '3', 0 }, /* BIND_HOTBAR_1, BIND_HOTBAR_2, BIND_HOTBAR_3 */ + { '4', 0 }, { '5', 0 }, { '6', 0 }, /* BIND_HOTBAR_4, BIND_HOTBAR_5, BIND_HOTBAR_6 */ + { '7', 0 }, { '8', 0 }, { '9', 0 }, /* BIND_HOTBAR_7, BIND_HOTBAR_8, BIND_HOTBAR_9 */ + { 0, 0 }, { 0, 0 } /* BIND_HOTBAR_LEFT, BIND_HOTBAR_RIGHT */ }; -static const char* const keybindNames[KEYBIND_COUNT] = { +static const char* const bindNames[BIND_COUNT] = { "Forward", "Back", "Left", "Right", "Jump", "Respawn", "SetSpawn", "Chat", "Inventory", "ToggleFog", "SendChat", "PlayerList", @@ -381,45 +443,121 @@ static const char* const keybindNames[KEYBIND_COUNT] = { "HotbarLeft", "HotbarRight" }; -cc_bool KeyBind_IsPressed(KeyBind binding) { - return Input.Pressed[KeyBinds_Normal[binding]] || - Input.Pressed[KeyBinds_Gamepad[binding]]; + +#define BindMapping2_Claims(mapping, btn) (Input.Pressed[(mapping)->button1] && (mapping)->button2 == btn) +static cc_bool Mappings_DoesClaim(InputBind binding, int btn, BindMapping* mappings) { + BindMapping* bind = &mappings[binding]; + int i; + if (bind->button2) return BindMapping2_Claims(bind, btn); + + /* Two button mapping takes priority over one button mapping */ + for (i = 0; i < BIND_COUNT; i++) + { + if (mappings[i].button2 && BindMapping2_Claims(&mappings[i], btn)) return false; + } + return bind->button1 == btn; +} + +static cc_bool Mappings_IsPressed(InputBind binding, BindMapping* mappings) { + BindMapping* bind = &mappings[binding]; + int btn = bind->button1; + int i; + + if (!Input.Pressed[btn]) return false; + if (bind->button2) return Input.Pressed[bind->button2]; + + /* Two button mappings to the button takes priority one button mapping */ + for (i = 0; i < BIND_COUNT; i++) + { + bind = &mappings[i]; + if (!bind->button2) continue; + if (!(bind->button1 == btn || bind->button2 == btn)) continue; + + if (Input.Pressed[bind->button1] && Input.Pressed[bind->button2]) return false; + } + return true; } -static void KeyBind_Load(const char* prefix, cc_uint8* keybinds, const cc_uint8* defaults) { + +cc_bool InputBind_Claims(InputBind binding, int btn) { + return Mappings_DoesClaim(binding, btn, KeyBind_Mappings) || + Mappings_DoesClaim(binding, btn, PadBind_Mappings); +} + +cc_bool InputBind_IsPressed(InputBind binding) { + return Mappings_IsPressed(binding, KeyBind_Mappings) || + Mappings_IsPressed(binding, PadBind_Mappings); +} + +static void KeyBind_Load(const char* prefix, BindMapping* keybinds, const BindMapping* defaults) { cc_string name; char nameBuffer[STRING_SIZE + 1]; - int mapping, i; + BindMapping mapping; + cc_string str, part1, part2; + int i; String_InitArray_NT(name, nameBuffer); - for (i = 0; i < KEYBIND_COUNT; i++) + for (i = 0; i < BIND_COUNT; i++) { name.length = 0; - String_Format1(&name, prefix, keybindNames[i]); + String_Format1(&name, prefix, bindNames[i]); name.buffer[name.length] = '\0'; + + if (!Options_UNSAFE_Get(name.buffer, &str)) { + keybinds[i] = defaults[i]; + continue; + } - mapping = Options_GetEnum(name.buffer, defaults[i], storageNames, INPUT_COUNT); - if (mapping == CCKEY_ESCAPE) mapping = defaults[i]; + String_UNSAFE_Separate(&str, ',', &part1, &part2); + mapping.button1 = Utils_ParseEnum(&part1, defaults[i].button1, storageNames, INPUT_COUNT); + mapping.button2 = Utils_ParseEnum(&part2, defaults[i].button2, storageNames, INPUT_COUNT); + if (mapping.button1 == CCKEY_ESCAPE) mapping = defaults[i]; keybinds[i] = mapping; } } -void KeyBind_Set(KeyBind binding, int key, cc_uint8* binds) { +static void InputBind_Set(InputBind binding, int btn, BindMapping* binds, const char* fmt) { cc_string name; char nameBuffer[STRING_SIZE]; cc_string value; String_InitArray(name, nameBuffer); - String_Format1(&name, binds == KeyBinds_Gamepad ? "pad-%c" : "key-%c", - keybindNames[binding]); - value = String_FromReadonly(storageNames[key]); + String_Format1(&name, fmt, bindNames[binding]); + value = String_FromReadonly(storageNames[btn]); Options_SetString(&name, &value); - binds[binding] = key; + + BindMapping_Set(&binds[binding], btn, 0); +} + +void KeyBind_Set(InputBind binding, int btn) { + InputBind_Set(binding, btn, KeyBind_Mappings, "key-%c"); +} + +void PadBind_Set(InputBind binding, int btn) { + InputBind_Set(binding, btn, PadBind_Mappings, "pad-%c"); } -/* Initialises and loads key bindings from options */ +static void InputBind_ResetOption(InputBind binding, const char* fmt) { + cc_string name; char nameBuffer[STRING_SIZE]; + String_InitArray(name, nameBuffer); + + String_Format1(&name, fmt, bindNames[binding]); + Options_SetString(&name, &String_Empty); +} + +void KeyBind_Reset(InputBind binding) { + InputBind_ResetOption(binding, "key-%c"); + KeyBind_Mappings[binding] = KeyBind_Defaults[binding]; +} + +void PadBind_Reset(InputBind binding) { + InputBind_ResetOption(binding, "pad-%c"); + PadBind_Mappings[binding] = PadBind_Defaults[binding]; +} + +/* Initialises and loads input bindings from options */ static void KeyBind_Init(void) { - KeyBind_Load("key-%c", KeyBinds_Normal, KeyBind_NormalDefaults); - KeyBind_Load("pad-%c", KeyBinds_Gamepad, KeyBind_GamepadDefaults); + KeyBind_Load("key-%c", KeyBind_Mappings, KeyBind_Defaults); + KeyBind_Load("pad-%c", PadBind_Mappings, PadBind_Defaults); } @@ -928,9 +1066,9 @@ void InputHandler_Tick(void) { /* elapsed time using DateTime_CurrentUTC_MS() instead */ input_lastClick = now; - left = KeyBind_IsPressed(KEYBIND_DELETE_BLOCK); - middle = KeyBind_IsPressed(KEYBIND_PICK_BLOCK); - right = KeyBind_IsPressed(KEYBIND_PLACE_BLOCK); + left = InputBind_IsPressed(BIND_DELETE_BLOCK); + middle = InputBind_IsPressed(BIND_PICK_BLOCK); + right = InputBind_IsPressed(BIND_PLACE_BLOCK); #ifdef CC_BUILD_TOUCH if (Input_TouchMode) { @@ -995,7 +1133,7 @@ cc_bool Input_HandleMouseWheel(float delta) { hotbar = Input_IsAltPressed() || Input_IsCtrlPressed() || Input_IsShiftPressed(); if (!hotbar && Camera.Active->Zoom(delta)) return true; - if (!KeyBind_IsPressed(KEYBIND_ZOOM_SCROLL)) return false; + if (!InputBind_IsPressed(BIND_ZOOM_SCROLL)) return false; h = &Entities.CurPlayer->Hacks; if (!h->Enabled || !h->CanUseThirdPerson) return false; @@ -1013,15 +1151,13 @@ static void InputHandler_CheckZoomFov(void* obj) { } static cc_bool HandleBlockKey(int key) { - if (Gui.InputGrab) return false; - - if (KeyBind_Claims(KEYBIND_DELETE_BLOCK, key)) { + if (InputBind_Claims(BIND_DELETE_BLOCK, key)) { MouseStatePress(MOUSE_LEFT); InputHandler_DeleteBlock(); - } else if (KeyBind_Claims(KEYBIND_PLACE_BLOCK, key)) { + } else if (InputBind_Claims(BIND_PLACE_BLOCK, key)) { MouseStatePress(MOUSE_RIGHT); InputHandler_PlaceBlock(); - } else if (KeyBind_Claims(KEYBIND_PICK_BLOCK, key)) { + } else if (InputBind_Claims(BIND_PICK_BLOCK, key)) { MouseStatePress(MOUSE_MIDDLE); InputHandler_PickBlock(); } else { @@ -1031,32 +1167,32 @@ static cc_bool HandleBlockKey(int key) { } static cc_bool HandleNonClassicKey(int key) { - if (KeyBind_Claims(KEYBIND_HIDE_GUI, key)) { + if (InputBind_Claims(BIND_HIDE_GUI, key)) { Game_HideGui = !Game_HideGui; - } else if (KeyBind_Claims(KEYBIND_SMOOTH_CAMERA, key)) { + } else if (InputBind_Claims(BIND_SMOOTH_CAMERA, key)) { InputHandler_Toggle(key, &Camera.Smooth, " &eSmooth camera is &aenabled", " &eSmooth camera is &cdisabled"); - } else if (KeyBind_Claims(KEYBIND_AXIS_LINES, key)) { + } else if (InputBind_Claims(BIND_AXIS_LINES, key)) { InputHandler_Toggle(key, &AxisLinesRenderer_Enabled, " &eAxis lines (&4X&e, &2Y&e, &1Z&e) now show", " &eAxis lines no longer show"); - } else if (KeyBind_Claims(KEYBIND_AUTOROTATE, key)) { + } else if (InputBind_Claims(BIND_AUTOROTATE, key)) { InputHandler_Toggle(key, &AutoRotate_Enabled, " &eAuto rotate is &aenabled", " &eAuto rotate is &cdisabled"); - } else if (KeyBind_Claims(KEYBIND_THIRD_PERSON, key)) { + } else if (InputBind_Claims(BIND_THIRD_PERSON, key)) { Camera_CycleActive(); - } else if (KeyBind_Claims(KEYBIND_DROP_BLOCK, key)) { + } else if (InputBind_Claims(BIND_DROP_BLOCK, key)) { if (Inventory_CheckChangeSelected() && Inventory_SelectedBlock != BLOCK_AIR) { /* Don't assign SelectedIndex directly, because we don't want held block switching positions if they already have air in their inventory hotbar. */ Inventory_Set(Inventory.SelectedIndex, BLOCK_AIR); Event_RaiseVoid(&UserEvents.HeldBlockChanged); } - } else if (KeyBind_Claims(KEYBIND_IDOVERLAY, key)) { + } else if (InputBind_Claims(BIND_IDOVERLAY, key)) { TexIdsOverlay_Show(); - } else if (KeyBind_Claims(KEYBIND_BREAK_LIQUIDS, key)) { + } else if (InputBind_Claims(BIND_BREAK_LIQUIDS, key)) { InputHandler_Toggle(key, &Game_BreakableLiquids, " &eBreakable liquids is &aenabled", " &eBreakable liquids is &cdisabled"); @@ -1067,11 +1203,11 @@ static cc_bool HandleNonClassicKey(int key) { } static cc_bool HandleCoreKey(int key) { - if (KeyBind_Claims(KEYBIND_HIDE_FPS, key)) { + if (InputBind_Claims(BIND_HIDE_FPS, key)) { Gui.ShowFPS = !Gui.ShowFPS; - } else if (KeyBind_Claims(KEYBIND_FULLSCREEN, key)) { + } else if (InputBind_Claims(BIND_FULLSCREEN, key)) { Game_ToggleFullscreen(); - } else if (KeyBind_Claims(KEYBIND_FOG, key)) { + } else if (InputBind_Claims(BIND_FOG, key)) { Game_CycleViewDistance(); } else if (key == CCKEY_F5 && Game_ClassicMode) { int weather = Env.Weather == WEATHER_SUNNY ? WEATHER_RAINY : WEATHER_SUNNY; @@ -1102,15 +1238,15 @@ static void HandleHotkeyDown(int key) { static cc_bool HandleLocalPlayerKey(int key) { struct LocalPlayer* p = Entities.CurPlayer; - if (KeyBind_Claims(KEYBIND_RESPAWN, key)) { + if (InputBind_Claims(BIND_RESPAWN, key)) { return LocalPlayer_HandleRespawn(p); - } else if (KeyBind_Claims(KEYBIND_SET_SPAWN, key)) { + } else if (InputBind_Claims(BIND_SET_SPAWN, key)) { return LocalPlayer_HandleSetSpawn(p); - } else if (KeyBind_Claims(KEYBIND_FLY, key)) { + } else if (InputBind_Claims(BIND_FLY, key)) { return LocalPlayer_HandleFly(p); - } else if (KeyBind_Claims(KEYBIND_NOCLIP, key)) { + } else if (InputBind_Claims(BIND_NOCLIP, key)) { return LocalPlayer_HandleNoclip(p); - } else if (KeyBind_Claims(KEYBIND_JUMP, key)) { + } else if (InputBind_Claims(BIND_JUMP, key)) { return LocalPlayer_HandleJump(p); } return false; @@ -1183,7 +1319,7 @@ static void OnInputDown(void* obj, int key, cc_bool was) { if (InputHandler_IsShutdown(key)) { /* TODO: Do we need a separate exit function in Game class? */ Window_RequestClose(); return; - } else if (KeyBind_Claims(KEYBIND_SCREENSHOT, key) && !was) { + } else if (InputBind_Claims(BIND_SCREENSHOT, key) && !was) { Game_ScreenshotRequested = true; return; } @@ -1192,8 +1328,9 @@ static void OnInputDown(void* obj, int key, cc_bool was) { s->dirty = true; if (s->VTABLE->HandlesInputDown(s, key)) return; } + if (Gui.InputGrab) return; - if (Input_IsPauseButton(key) && !Gui.InputGrab) { + if (Input_IsPauseButton(key)) { #ifdef CC_BUILD_WEB /* Can't do this in KeyUp, because pressing escape without having */ /* explicitly disabled mouse lock means a KeyUp event isn't sent. */ @@ -1217,7 +1354,7 @@ static void OnInputUp(void* obj, int key) { struct Screen* s; int i; - if (KeyBind_Claims(KEYBIND_ZOOM_SCROLL, key)) Camera_SetFov(Camera.DefaultFov); + if (InputBind_Claims(BIND_ZOOM_SCROLL, key)) Camera_SetFov(Camera.DefaultFov); #ifdef CC_BUILD_WEB /* When closing menus (which reacquires mouse focus) in key down, */ /* this still leaves the cursor visible. But if this is instead */ @@ -1235,18 +1372,18 @@ static void OnInputUp(void* obj, int key) { } if (Gui.InputGrab) return; - if (KeyBind_Claims(KEYBIND_DELETE_BLOCK, key)) MouseStateRelease(MOUSE_LEFT); - if (KeyBind_Claims(KEYBIND_PLACE_BLOCK, key)) MouseStateRelease(MOUSE_RIGHT); - if (KeyBind_Claims(KEYBIND_PICK_BLOCK, key)) MouseStateRelease(MOUSE_MIDDLE); + if (InputBind_Claims(BIND_DELETE_BLOCK, key)) MouseStateRelease(MOUSE_LEFT); + if (InputBind_Claims(BIND_PLACE_BLOCK, key)) MouseStateRelease(MOUSE_RIGHT); + if (InputBind_Claims(BIND_PICK_BLOCK, key)) MouseStateRelease(MOUSE_MIDDLE); } static void OnFocusChanged(void* obj) { if (!Window_Main.Focused) Input_Clear(); } static void PlayerInputNormal(struct LocalPlayer* p, float* xMoving, float* zMoving) { - if (KeyBind_IsPressed(KEYBIND_FORWARD)) *zMoving -= 1; - if (KeyBind_IsPressed(KEYBIND_BACK)) *zMoving += 1; - if (KeyBind_IsPressed(KEYBIND_LEFT)) *xMoving -= 1; - if (KeyBind_IsPressed(KEYBIND_RIGHT)) *xMoving += 1; + if (InputBind_IsPressed(BIND_FORWARD)) *zMoving -= 1; + if (InputBind_IsPressed(BIND_BACK)) *zMoving += 1; + if (InputBind_IsPressed(BIND_LEFT)) *xMoving -= 1; + if (InputBind_IsPressed(BIND_RIGHT)) *xMoving += 1; } static struct LocalPlayerInput normalInput = { PlayerInputNormal }; diff --git a/src/Input.h b/src/Input.h index 35fff1e..1933dec 100644 --- a/src/Input.h +++ b/src/Input.h @@ -41,11 +41,19 @@ enum InputButtons { CCKEY_KP5, CCKEY_KP6, CCKEY_KP7, CCKEY_KP8, CCKEY_KP9, CCKEY_KP_DIVIDE, CCKEY_KP_MULTIPLY, CCKEY_KP_MINUS, CCKEY_KP_PLUS, CCKEY_KP_DECIMAL, CCKEY_KP_ENTER, + + CCKEY_VOLUME_MUTE, CCKEY_VOLUME_UP, CCKEY_VOLUME_DOWN, CCKEY_SLEEP, + CCKEY_MEDIA_NEXT, CCKEY_MEDIA_PREV, CCKEY_MEDIA_PLAY, CCKEY_MEDIA_STOP, + CCKEY_BROWSER_PREV, CCKEY_BROWSER_NEXT, CCKEY_BROWSER_REFRESH, CCKEY_BROWSER_STOP, CCKEY_BROWSER_SEARCH, CCKEY_BROWSER_FAVORITES, CCKEY_BROWSER_HOME, + CCKEY_LAUNCH_MAIL, CCKEY_LAUNCH_MEDIA, CCKEY_LAUNCH_APP1, CCKEY_LAUNCH_CALC, /* NOTE: RMOUSE must be before MMOUSE for PlayerClick compatibility */ - CCMOUSE_X1, CCMOUSE_X2, CCMOUSE_L, CCMOUSE_R, CCMOUSE_M, + CCMOUSE_X1, CCMOUSE_X2, CCMOUSE_X3, CCMOUSE_X4, CCMOUSE_X5, CCMOUSE_X6, + CCMOUSE_L, CCMOUSE_R, CCMOUSE_M, + CCWHEEL_UP, CCWHEEL_DOWN, CCWHEEL_LEFT, CCWHEEL_RIGHT, - CCPAD_A, CCPAD_B, CCPAD_X, CCPAD_Y, CCPAD_L, CCPAD_R, CCPAD_Z, + CCPAD_A, CCPAD_B, CCPAD_X, CCPAD_Y, CCPAD_L, CCPAD_R, + CCPAD_Z, CCPAD_C, CCPAD_D, CCPAD_LEFT, CCPAD_RIGHT, CCPAD_UP, CCPAD_DOWN, CCPAD_START, CCPAD_SELECT, CCPAD_ZL, CCPAD_ZR, CCPAD_LSTICK, CCPAD_RSTICK, @@ -139,48 +147,60 @@ void Input_RemoveTouch(long id, int x, int y); /* Data for mouse and touch */ extern struct Pointer { int x, y; } Pointers[INPUT_MAX_POINTERS]; -/* Raises InputEvents.Wheel with the given wheel delta. */ -void Mouse_ScrollWheel(float delta); -/* Sets X and Y position of the given pointer, always raising PointerEvents.Moved. */ +/* Raises appropriate events for a mouse vertical scroll */ +void Mouse_ScrollVWheel(float delta); +/* Raises appropriate events for a mouse horizontal scroll */ +void Mouse_ScrollHWheel(float delta); +/* Sets X and Y position of the given pointer, then raises appropriate events */ void Pointer_SetPosition(int idx, int x, int y); -/* Enumeration of all key bindings. */ -enum KeyBind_ { - KEYBIND_FORWARD, KEYBIND_BACK, KEYBIND_LEFT, KEYBIND_RIGHT, - KEYBIND_JUMP, KEYBIND_RESPAWN, KEYBIND_SET_SPAWN, KEYBIND_CHAT, - KEYBIND_INVENTORY, KEYBIND_FOG, KEYBIND_SEND_CHAT, KEYBIND_TABLIST, - KEYBIND_SPEED, KEYBIND_NOCLIP, KEYBIND_FLY, KEYBIND_FLY_UP, KEYBIND_FLY_DOWN, - KEYBIND_EXT_INPUT, KEYBIND_HIDE_FPS, KEYBIND_SCREENSHOT, KEYBIND_FULLSCREEN, - KEYBIND_THIRD_PERSON, KEYBIND_HIDE_GUI, KEYBIND_AXIS_LINES, KEYBIND_ZOOM_SCROLL, - KEYBIND_HALF_SPEED, KEYBIND_DELETE_BLOCK, KEYBIND_PICK_BLOCK, KEYBIND_PLACE_BLOCK, - KEYBIND_AUTOROTATE, KEYBIND_HOTBAR_SWITCH, KEYBIND_SMOOTH_CAMERA, - KEYBIND_DROP_BLOCK, KEYBIND_IDOVERLAY, KEYBIND_BREAK_LIQUIDS, - KEYBIND_LOOK_UP, KEYBIND_LOOK_DOWN, KEYBIND_LOOK_RIGHT, KEYBIND_LOOK_LEFT, - KEYBIND_HOTBAR_1, KEYBIND_HOTBAR_2, KEYBIND_HOTBAR_3, - KEYBIND_HOTBAR_4, KEYBIND_HOTBAR_5, KEYBIND_HOTBAR_6, - KEYBIND_HOTBAR_7, KEYBIND_HOTBAR_8, KEYBIND_HOTBAR_9, - KEYBIND_HOTBAR_LEFT, KEYBIND_HOTBAR_RIGHT, - KEYBIND_COUNT +/* Enumeration of all input bindings. */ +enum InputBind_ { + BIND_FORWARD, BIND_BACK, BIND_LEFT, BIND_RIGHT, + BIND_JUMP, BIND_RESPAWN, BIND_SET_SPAWN, BIND_CHAT, + BIND_INVENTORY, BIND_FOG, BIND_SEND_CHAT, BIND_TABLIST, + BIND_SPEED, BIND_NOCLIP, BIND_FLY, BIND_FLY_UP, BIND_FLY_DOWN, + BIND_EXT_INPUT, BIND_HIDE_FPS, BIND_SCREENSHOT, BIND_FULLSCREEN, + BIND_THIRD_PERSON, BIND_HIDE_GUI, BIND_AXIS_LINES, BIND_ZOOM_SCROLL, + BIND_HALF_SPEED, BIND_DELETE_BLOCK, BIND_PICK_BLOCK, BIND_PLACE_BLOCK, + BIND_AUTOROTATE, BIND_HOTBAR_SWITCH, BIND_SMOOTH_CAMERA, + BIND_DROP_BLOCK, BIND_IDOVERLAY, BIND_BREAK_LIQUIDS, + BIND_LOOK_UP, BIND_LOOK_DOWN, BIND_LOOK_RIGHT, BIND_LOOK_LEFT, + BIND_HOTBAR_1, BIND_HOTBAR_2, BIND_HOTBAR_3, + BIND_HOTBAR_4, BIND_HOTBAR_5, BIND_HOTBAR_6, + BIND_HOTBAR_7, BIND_HOTBAR_8, BIND_HOTBAR_9, + BIND_HOTBAR_LEFT, BIND_HOTBAR_RIGHT, + BIND_COUNT }; -typedef int KeyBind; - -/* The keyboard/mouse buttons that are bound to each key binding */ -extern cc_uint8 KeyBinds_Normal[KEYBIND_COUNT]; -/* The gamepad buttons that are bound to each key binding */ -extern cc_uint8 KeyBinds_Gamepad[KEYBIND_COUNT]; -/* Default keyboard/mouse button that each key binding is bound to */ -extern const cc_uint8 KeyBind_NormalDefaults[KEYBIND_COUNT]; -/* Default gamepad button that each key binding is bound to */ -extern const cc_uint8 KeyBind_GamepadDefaults[KEYBIND_COUNT]; -#define KeyBind_GetDefaults() (Input.GamepadSource ? KeyBind_GamepadDefaults : KeyBind_NormalDefaults) - -/* Whether the given keyboard/mouse or gamepad button is bound to the given keybinding */ -#define KeyBind_Claims(binding, btn) (KeyBinds_Normal[binding] == (btn) || KeyBinds_Gamepad[binding] == (btn)) -/* Gets whether the key bound to the given key binding is pressed. */ -CC_API cc_bool KeyBind_IsPressed(KeyBind binding); -/* Set the key that the given key binding is bound to. (also updates options list) */ -void KeyBind_Set(KeyBind binding, int key, cc_uint8* binds); +typedef int InputBind; +typedef struct BindMapping_ { cc_uint8 button1, button2; } BindMapping; +#define BindMapping_Set(mapping, btn1, btn2) (mapping)->button1 = btn1; (mapping)->button2 = btn2; + +/* The keyboard/mouse buttons that are bound to each input binding */ +extern BindMapping KeyBind_Mappings[BIND_COUNT]; +/* The gamepad buttons that are bound to each input binding */ +extern BindMapping PadBind_Mappings[BIND_COUNT]; +/* Default keyboard/mouse button that each input binding is bound to */ +extern const BindMapping KeyBind_Defaults[BIND_COUNT]; +/* Default gamepad button that each input binding is bound to */ +extern const BindMapping PadBind_Defaults[BIND_COUNT]; + +/* InputBind_IsPressed is what should be used, but export KeyBind_IsPressed for backwards compatibility */ +#define InputBind_IsPressed KeyBind_IsPressed +/* Whether the given binding should be triggered in response to given input button being pressed */ +CC_API cc_bool InputBind_Claims(InputBind binding, int btn); +/* Gets whether the given input binding is currently being triggered */ +CC_API cc_bool InputBind_IsPressed(InputBind binding); + +/* Sets the key/mouse button that the given input binding is bound to */ +void KeyBind_Set(InputBind binding, int btn); +/* Sets the gamepad button that the given input binding is bound to */ +void PadBind_Set(InputBind binding, int btn); +/* Resets the key/mouse button that the given input binding is bound to */ +void KeyBind_Reset(InputBind binding); +/* Resets the gamepad button that the given input binding is bound to*/ +void PadBind_Reset(InputBind binding); /* Gamepad axes. Default behaviour is: */ diff --git a/src/IsometricDrawer.c b/src/IsometricDrawer.c index b57a4ab..88e4013 100644 --- a/src/IsometricDrawer.c +++ b/src/IsometricDrawer.c @@ -87,7 +87,7 @@ static void IsometricDrawer_Angled(BlockID block, float size) { Drawer.Z1 = scale * (1.0f - min.z * 2.0f); Drawer.Z2 = scale * (1.0f - max.z * 2.0f); - bright = Blocks.FullBright[block]; + bright = Blocks.Brightness[block]; Drawer.Tinted = Blocks.Tinted[block]; Drawer.TintCol = Blocks.FogCol[block]; @@ -129,7 +129,7 @@ void IsometricDrawer_AddBatch(BlockID block, float size, float x, float y) { iso_posX = x; iso_posY = y; /* See comment in Gfx_Make2DQuad() for why 0.5 is subtracted in D3D9 */ /* TODO pass as arguments? test diff */ -#ifdef CC_BUILD_D3D9 +#if CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9 iso_posX -= 0.5f; iso_posY -= 0.5f; #endif diff --git a/src/LScreens.c b/src/LScreens.c index 4d8df2b..1463b1f 100644 --- a/src/LScreens.c +++ b/src/LScreens.c @@ -283,7 +283,6 @@ static struct ColoursScreen { struct LLabel lblRGB[COLOURS_NUM_COLS]; struct LInput iptColours[COLOURS_NUM_ENTRIES]; struct LCheckbox cbClassic; - float colourAcc; } ColoursScreen; #define COLOURSSCREEN_MAX_WIDGETS 25 @@ -373,14 +372,11 @@ static void ColoursScreen_AdjustSelected(struct LScreen* s, int delta) { ColoursScreen_TextChanged(w); } -static void ColoursScreen_MouseWheel(struct LScreen* s_, float delta) { - struct ColoursScreen* s = (struct ColoursScreen*)s_; - int steps = Utils_AccumulateWheelDelta(&s->colourAcc, delta); - ColoursScreen_AdjustSelected(s_, steps); -} - static void ColoursScreen_KeyDown(struct LScreen* s, int key, cc_bool was) { int delta = Input_CalcDelta(key, 1, 10); + if (key == CCWHEEL_UP) delta = +1; + if (key == CCWHEEL_DOWN) delta = -1; + if (delta) { ColoursScreen_AdjustSelected(s, delta); } else { @@ -423,7 +419,6 @@ static void ColoursScreen_Activated(struct LScreen* s_) { struct ColoursScreen* s = (struct ColoursScreen*)s_; ColoursScreen_AddWidgets(s); - s->colourAcc = 0; LCheckbox_Set(&s->cbClassic, Launcher_Theme.ClassicBackground); ColoursScreen_UpdateAll(s); } @@ -437,7 +432,6 @@ void ColoursScreen_SetActive(void) { s->Activated = ColoursScreen_Activated; s->KeyDown = ColoursScreen_KeyDown; - s->MouseWheel = ColoursScreen_MouseWheel; s->title = "Custom theme"; s->onEscapeWidget = (struct LWidget*)&s->btnBack; @@ -893,16 +887,20 @@ static void MainScreen_Activated(struct LScreen* s_) { s->iptPassword.inputType = KEYBOARD_TYPE_PASSWORD; s->lblUpdate.small = true; +#ifdef CC_BUILD_NETWORKING LInput_Add(s, &s->iptUsername, 280, "Username..", main_iptUsername); LInput_Add(s, &s->iptPassword, 280, "Password..", main_iptPassword); LButton_Add(s, &s->btnLogin, 100, 35, "Sign in", MainScreen_Login, main_btnLogin); LButton_Add(s, &s->btnResume, 100, 35, "Resume", MainScreen_Resume, main_btnResume); +#endif LLabel_Add(s, &s->lblStatus, "", main_lblStatus); +#ifdef CC_BUILD_NETWORKING LButton_Add(s, &s->btnDirect, 200, 35, "Direct connect", SwitchToDirectConnect, main_btnDirect); +#endif LButton_Add(s, &s->btnSPlayer, 200, 35, "Singleplayer", MainScreen_Singleplayer, main_btnSPlayer); #ifdef CC_BUILD_SPLITSCREEN @@ -1049,7 +1047,12 @@ void MainScreen_SetActive(void) { s->LoadState = MainScreen_Load; s->Tick = MainScreen_Tick; s->title = "ClassiCube"; + +#ifdef CC_BUILD_NETWORKING s->onEnterWidget = (struct LWidget*)&s->btnLogin; +#else + s->onEnterWidget = (struct LWidget*)&s->btnSPlayer; +#endif Launcher_SetScreen((struct LScreen*)s); } diff --git a/src/Launcher.c b/src/Launcher.c index 4b1e7f4..0f992be 100644 --- a/src/Launcher.c +++ b/src/Launcher.c @@ -290,15 +290,13 @@ void Launcher_Run(void) { Platform_LogConst("undoing components"); Drawer2D_Component.Free(); Http_Component.Free(); -#else +#endif + if (Launcher_ShouldUpdate) { const char* action; cc_result res = Updater_Start(&action); if (res) Logger_SysWarn(res, action); } - - if (Window_Main.Exists) Window_RequestClose(); -#endif } diff --git a/src/Lighting.c b/src/Lighting.c index 8af48cb..52a6bfc 100644 --- a/src/Lighting.c +++ b/src/Lighting.c @@ -7,9 +7,29 @@ #include "Logger.h" #include "Event.h" #include "Game.h" +#include "String.h" +#include "Chat.h" +#include "ExtMath.h" +#include "Options.h" +#include "Builder.h" + +const char* const LightingMode_Names[LIGHTING_MODE_COUNT] = { "Classic", "Fancy" }; + +cc_uint8 Lighting_Mode; +cc_bool Lighting_ModeLockedByServer; +cc_bool Lighting_ModeSetByServer; +cc_uint8 Lighting_ModeUserCached; struct _Lighting Lighting; #define Lighting_Pack(x, z) ((x) + World.Width * (z)) +void Lighting_SetMode(cc_uint8 mode, cc_bool fromServer) { + cc_uint8 oldMode = Lighting_Mode; + Lighting_Mode = mode; + + Event_RaiseLightingMode(&WorldEvents.LightingModeChanged, oldMode, fromServer); +} + + /*########################################################################################################################* *----------------------------------------------------Classic lighting-----------------------------------------------------* *#########################################################################################################################*/ @@ -46,18 +66,18 @@ static int ClassicLighting_CalcHeightAt(int x, int maxY, int z, int hIndex) { return -10; } -static int ClassicLighting_GetLightHeight(int x, int z) { +int ClassicLighting_GetLightHeight(int x, int z) { int hIndex = Lighting_Pack(x, z); int lightH = classic_heightmap[hIndex]; return lightH == HEIGHT_UNCALCULATED ? ClassicLighting_CalcHeightAt(x, World.Height - 1, z, hIndex) : lightH; } /* Outside color is same as sunlight color, so we reuse when possible */ -static cc_bool ClassicLighting_IsLit(int x, int y, int z) { +cc_bool ClassicLighting_IsLit(int x, int y, int z) { return y > ClassicLighting_GetLightHeight(x, z); } -static cc_bool ClassicLighting_IsLit_Fast(int x, int y, int z) { +cc_bool ClassicLighting_IsLit_Fast(int x, int y, int z) { return y > classic_heightmap[Lighting_Pack(x, z)]; } @@ -66,6 +86,12 @@ static PackedCol ClassicLighting_Color(int x, int y, int z) { return y > ClassicLighting_GetLightHeight(x, z) ? Env.SunCol : Env.ShadowCol; } +static PackedCol SmoothLighting_Color(int x, int y, int z) { + if (!World_Contains(x, y, z)) return Env.SunCol; + if (Blocks.Brightness[World_GetBlock(x, y, z)]) return Env.SunCol; + return y > ClassicLighting_GetLightHeight(x, z) ? Env.SunCol : Env.ShadowCol; +} + static PackedCol ClassicLighting_Color_XSide(int x, int y, int z) { if (!World_Contains(x, y, z)) return Env.SunXSide; return y > ClassicLighting_GetLightHeight(x, z) ? Env.SunXSide : Env.ShadowXSide; @@ -91,7 +117,7 @@ static PackedCol ClassicLighting_Color_ZSide_Fast(int x, int y, int z) { return y > classic_heightmap[Lighting_Pack(x, z)] ? Env.SunZSide : Env.ShadowZSide; } -static void ClassicLighting_Refresh(void) { +void ClassicLighting_Refresh(void) { int i; for (i = 0; i < World.Width * World.Length; i++) { classic_heightmap[i] = HEIGHT_UNCALCULATED; @@ -229,7 +255,7 @@ static void ClassicLighting_RefreshAffected(int x, int y, int z, BlockID block, } } -static void ClassicLighting_OnBlockChanged(int x, int y, int z, BlockID oldBlock, BlockID newBlock) { +void ClassicLighting_OnBlockChanged(int x, int y, int z, BlockID oldBlock, BlockID newBlock) { int hIndex = Lighting_Pack(x, z); int lightH = classic_heightmap[hIndex]; int newHeight; @@ -348,7 +374,7 @@ static void Heightmap_FinishCoverage(int x1, int z1, int xCount, int zCount) { } -static void ClassicLighting_LightHint(int startX, int startZ) { +void ClassicLighting_LightHint(int startX, int startY, int startZ) { int x1 = max(startX, 0), x2 = min(World.Width, startX + EXTCHUNK_SIZE); int z1 = max(startZ, 0), z2 = min(World.Length, startZ + EXTCHUNK_SIZE); int xCount = x2 - x1, zCount = z2 - z1; @@ -360,12 +386,12 @@ static void ClassicLighting_LightHint(int startX, int startZ) { } } -static void ClassicLighting_FreeState(void) { +void ClassicLighting_FreeState(void) { Mem_Free(classic_heightmap); classic_heightmap = NULL; } -static void ClassicLighting_AllocState(void) { +void ClassicLighting_AllocState(void) { classic_heightmap = (cc_int16*)Mem_TryAlloc(World.Width * World.Length, 2); if (classic_heightmap) { ClassicLighting_Refresh(); @@ -375,10 +401,13 @@ static void ClassicLighting_AllocState(void) { } static void ClassicLighting_SetActive(void) { + cc_bool smoothLighting = false; + if (!Game_ClassicMode) smoothLighting = Options_GetBool(OPT_SMOOTH_LIGHTING, false); + Lighting.OnBlockChanged = ClassicLighting_OnBlockChanged; Lighting.Refresh = ClassicLighting_Refresh; Lighting.IsLit = ClassicLighting_IsLit; - Lighting.Color = ClassicLighting_Color; + Lighting.Color = smoothLighting ? SmoothLighting_Color : ClassicLighting_Color; Lighting.Color_XSide = ClassicLighting_Color_XSide; Lighting.IsLit_Fast = ClassicLighting_IsLit_Fast; @@ -397,8 +426,43 @@ static void ClassicLighting_SetActive(void) { /*########################################################################################################################* *---------------------------------------------------Lighting component----------------------------------------------------* *#########################################################################################################################*/ +static void Lighting_ApplyActive(void) { + if (Lighting_Mode != LIGHTING_MODE_CLASSIC) { + FancyLighting_SetActive(); + } else { + ClassicLighting_SetActive(); + } +} + +static void Lighting_SwitchActive(void) { + Lighting.FreeState(); + Lighting_ApplyActive(); + Lighting.AllocState(); +} -static void OnInit(void) { ClassicLighting_SetActive(); } +static void Lighting_HandleModeChanged(void* obj, cc_uint8 oldMode, cc_bool fromServer) { + if (Lighting_Mode == oldMode) return; + Builder_ApplyActive(); + + if (World.Loaded) { + Lighting_SwitchActive(); + MapRenderer_Refresh(); + } else { + Lighting_ApplyActive(); + } +} + +static void OnInit(void) { + Lighting_Mode = Options_GetEnum(OPT_LIGHTING_MODE, LIGHTING_MODE_CLASSIC, LightingMode_Names, LIGHTING_MODE_COUNT); + Lighting_ModeLockedByServer = false; + Lighting_ModeSetByServer = false; + Lighting_ModeUserCached = Lighting_Mode; + + FancyLighting_OnInit(); + Lighting_ApplyActive(); + + Event_Register_(&WorldEvents.LightingModeChanged, NULL, Lighting_HandleModeChanged); +} static void OnReset(void) { Lighting.FreeState(); } static void OnNewMapLoaded(void) { Lighting.AllocState(); } @@ -408,4 +472,4 @@ struct IGameComponent Lighting_Component = { OnReset, /* Reset */ OnReset, /* OnNewMap */ OnNewMapLoaded /* OnNewMapLoaded */ -}; +}; \ No newline at end of file diff --git a/src/Lighting.h b/src/Lighting.h index e8c30f7..20344d7 100644 --- a/src/Lighting.h +++ b/src/Lighting.h @@ -11,17 +11,39 @@ Copyright 2014-2023 ClassiCube | Licensed under BSD-3 struct IGameComponent; extern struct IGameComponent Lighting_Component; +enum LightingMode { + LIGHTING_MODE_CLASSIC, LIGHTING_MODE_FANCY, LIGHTING_MODE_COUNT +}; +extern const char* const LightingMode_Names[LIGHTING_MODE_COUNT]; +extern cc_uint8 Lighting_Mode; + +extern cc_bool Lighting_ModeLockedByServer; +/* True if the current lighting mode has been set by the server instead of the client */ +extern cc_bool Lighting_ModeSetByServer; +/* The lighting mode that was set by the client before being set by the server */ +extern cc_uint8 Lighting_ModeUserCached; +void Lighting_SetMode(cc_uint8 mode, cc_bool fromServer); + + +/* How much ambient occlusion to apply in fancy lighting where 1.0f = none and 0.0f = maximum*/ +#define FANCY_AO 0.5F +/* How many unique "levels" of light there are when fancy lighting is used. */ +#define FANCY_LIGHTING_LEVELS 16 +#define FANCY_LIGHTING_MAX_LEVEL (FANCY_LIGHTING_LEVELS - 1) +/* How many bits to shift lamplight level to the left when storing it in a byte along with lavalight level. */ +#define FANCY_LIGHTING_LAMP_SHIFT 4 +/* A byte that fills the lamp level area with ones. Equivalent to 0b_1111_0000 */ +#define FANCY_LIGHTING_LAMP_MASK 0xF0 + CC_VAR extern struct _Lighting { /* Releases/Frees the per-level lighting state */ void (*FreeState)(void); /* Allocates the per-level lighting state */ /* (called after map has been fully loaded) */ void (*AllocState)(void); - /* Equivalent to (but far more optimised form of) - * for x = startX; x < startX + 18; x++ - * for z = startZ; z < startZ + 18; z++ - * CalcLight(x, maxY, z) */ - void (*LightHint)(int startX, int startZ); + /* Quickly calculates lighting for the blocks in the region */ + /* [x, y, z] to [x + 18, y + 18, z + 18] */ + void (*LightHint)(int startX, int startY, int startZ); /* Called when a block is changed to update internal lighting state. */ /* NOTE: Implementations ***MUST*** mark all chunks affected by this lighting change as needing to be refreshed. */ @@ -49,4 +71,18 @@ CC_VAR extern struct _Lighting { PackedCol (*Color_XSide_Fast)(int x, int y, int z); PackedCol (*Color_ZSide_Fast)(int x, int y, int z); } Lighting; + +void FancyLighting_SetActive(void); +void FancyLighting_OnInit(void); + +/* Expose ClassicLighting functions for reuse in Fancy lighting */ +void ClassicLighting_Refresh(void); +void ClassicLighting_FreeState(void); +void ClassicLighting_AllocState(void); +int ClassicLighting_GetLightHeight(int x, int z); +void ClassicLighting_LightHint(int startX, int startY, int startZ); +cc_bool ClassicLighting_IsLit(int x, int y, int z); +cc_bool ClassicLighting_IsLit_Fast(int x, int y, int z); +void ClassicLighting_OnBlockChanged(int x, int y, int z, BlockID oldBlock, BlockID newBlock); + #endif diff --git a/src/Logger.c b/src/Logger.c index 9b2d2aa..d74ba3b 100644 --- a/src/Logger.c +++ b/src/Logger.c @@ -1239,13 +1239,13 @@ static void CloseLogFile(void) { } #endif -#if defined CC_BUILD_D3D11 +#if CC_GFX_BACKEND == CC_GFX_BACKEND_D3D11 #define GFX_BACKEND " (Direct3D11)" -#elif defined CC_BUILD_D3D9 +#elif CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9 #define GFX_BACKEND " (Direct3D9)" -#elif defined CC_BUILD_GLMODERN +#elif CC_GFX_BACKEND == CC_GFX_BACKEND_GL2 #define GFX_BACKEND " (ModernGL)" -#elif defined CC_BUILD_GL +#elif CC_GFX_BACKEND == CC_GFX_BACKEND_GL1 #define GFX_BACKEND " (OpenGL)" #else #define GFX_BACKEND " (Unknown)" diff --git a/src/Menus.c b/src/Menus.c index 774a31f..db79d14 100644 --- a/src/Menus.c +++ b/src/Menus.c @@ -27,12 +27,14 @@ #include "Deflate.h" #include "Stream.h" #include "Builder.h" +#include "Lighting.h" #include "Logger.h" #include "Options.h" #include "Input.h" #include "Utils.h" #include "Errors.h" #include "SystemFonts.h" +#include "Lighting.h" /* Describes a menu option button */ struct MenuOptionDesc { @@ -240,7 +242,6 @@ static struct ListScreen { struct ButtonWidget btns[LIST_SCREEN_ITEMS]; struct ButtonWidget left, right, done, action; struct FontDesc font; - float wheelAcc; int currentIndex; Widget_LeftClick EntryClick, DoneClick, ActionClick; const char* actionText; @@ -373,28 +374,22 @@ static int ListScreen_KeyDown(void* screen, int key) { ListScreen_PageClick(s, false); } else if (Input_IsRightButton(key) || key == CCKEY_PAGEDOWN) { ListScreen_PageClick(s, true); + } else if (key == CCWHEEL_UP) { + ListScreen_SetCurrentIndex(s, s->currentIndex - 1); + } else if (key == CCWHEEL_DOWN) { + ListScreen_SetCurrentIndex(s, s->currentIndex + 1); } else { Menu_InputDown(screen, key); } return true; } -static int ListScreen_MouseScroll(void* screen, float delta) { - struct ListScreen* s = (struct ListScreen*)screen; - int steps = Utils_AccumulateWheelDelta(&s->wheelAcc, delta); - - if (steps) ListScreen_SetCurrentIndex(s, s->currentIndex - steps); - return true; -} - static void ListScreen_Init(void* screen) { struct ListScreen* s = (struct ListScreen*)screen; int i, width; s->widgets = list_widgets; s->numWidgets = 0; s->maxWidgets = Array_Elems(list_widgets); - - s->wheelAcc = 0.0f; s->currentIndex = 0; for (i = 0; i < LIST_SCREEN_ITEMS; i++) @@ -454,7 +449,7 @@ static const struct ScreenVTABLE ListScreen_VTABLE = { ListScreen_Init, Screen_NullUpdate, ListScreen_Free, ListScreen_Render, Screen_BuildMesh, ListScreen_KeyDown, Screen_InputUp, Screen_TKeyPress, Screen_TText, - Menu_PointerDown, Screen_PointerUp, Menu_PointerMove, ListScreen_MouseScroll, + Menu_PointerDown, Screen_PointerUp, Menu_PointerMove, Screen_TMouseScroll, ListScreen_Layout, ListScreen_ContextLost, ListScreen_ContextRecreated }; void ListScreen_Show(void) { @@ -514,7 +509,7 @@ static void PauseScreen_CheckHacksAllowed(void* screen) { struct PauseScreen* s = (struct PauseScreen*)screen; if (Gui.ClassicMenu) return; - Widget_SetDisabled(&s->btns[4], + Widget_SetDisabled(&s->btns[1], !Entities.CurPlayer->Hacks.CanAnyHacks); /* select texture pack */ s->dirty = true; } @@ -541,11 +536,11 @@ static void PauseScreen_Init(void* screen) { struct PauseScreen* s = (struct PauseScreen*)screen; static const struct SimpleButtonDesc descs[] = { { -160, -50, "Options...", Menu_SwitchOptions }, + { -160, 0, "Change texture pack...", Menu_SwitchTexPacks }, + { -160, 50, "Hotkeys...", Menu_SwitchHotkeys }, { 160, -50, "Generate new level...", Menu_SwitchGenLevel }, { 160, 0, "Load level...", Menu_SwitchLoadLevel }, - { 160, 50, "Save level...", Menu_SwitchSaveLevel }, - { -160, 0, "Change texture pack...", Menu_SwitchTexPacks }, - { -160, 50, "Hotkeys...", Menu_SwitchHotkeys } + { 160, 50, "Save level...", Menu_SwitchSaveLevel } }; s->widgets = pause_widgets; s->numWidgets = 0; @@ -559,8 +554,8 @@ static void PauseScreen_Init(void* screen) { s->maxVertices = Screen_CalcDefaultMaxVertices(s); if (Server.IsSinglePlayer) return; - s->btns[1].flags = WIDGET_FLAG_DISABLED; - s->btns[2].flags = WIDGET_FLAG_DISABLED; + s->btns[3].flags = WIDGET_FLAG_DISABLED; + s->btns[4].flags = WIDGET_FLAG_DISABLED; } static void PauseScreen_Free(void* screen) { @@ -659,7 +654,7 @@ static const char* const optsGroup_descs[8] = { "&eMusic/Sound, view bobbing, and more", "&eGui scale, font settings, and more", "&eFPS limit, view distance, entity names/shadows", - "&eSet key bindings, bind keys to act as mouse clicks", + "&eSet key and mouse bindings", "&eChat options", "&eHacks allowed, jump settings, and more", "&eEnv colours, water level, weather, and more", @@ -1948,15 +1943,26 @@ static struct KeyBindsScreen { static struct Widget* key_widgets[KEYBINDS_MAX_BTNS + 5]; +static BindMapping KeyBindsScreen_GetBinding(struct KeyBindsScreen* s, int i) { + const BindMapping* curBinds; + + curBinds = binds_gamepad ? PadBind_Mappings : KeyBind_Mappings; + return curBinds[s->binds[i]]; +} + static void KeyBindsScreen_Update(struct KeyBindsScreen* s, int i) { cc_string text; char textBuffer[STRING_SIZE]; - const cc_uint8* curBinds; + BindMapping curBind; String_InitArray(text, textBuffer); - curBinds = binds_gamepad ? KeyBinds_Gamepad : KeyBinds_Normal; + curBind = KeyBindsScreen_GetBinding(s, i); - String_Format2(&text, s->curI == i ? "> %c: %c <" : "%c: %c", - s->descs[i], Input_DisplayNames[curBinds[s->binds[i]]]); + String_Format4(&text, s->curI == i ? "> %c: %c%c%c <" : "%c: %c%c%c", + s->descs[i], + Input_DisplayNames[curBind.button1], + curBind.button2 ? " + " : "", + curBind.button2 ? Input_DisplayNames[curBind.button2] : ""); + ButtonWidget_Set(&s->buttons[i], &text, &s->titleFont); s->dirty = true; } @@ -1974,20 +1980,35 @@ static void KeyBindsScreen_OnBindingClick(void* screen, void* widget) { if (old >= 0) KeyBindsScreen_Update(s, old); } +static void KeyBindsScreen_ResetBinding(InputBind bind) { + if (binds_gamepad) { + PadBind_Reset(bind); + } else { + KeyBind_Reset(bind); + } +} + +static void KeyBindsScreen_UpdateBinding(InputBind bind, int key) { + if (binds_gamepad) { + PadBind_Set(bind, key); + } else { + KeyBind_Set(bind, key); + } +} + static int KeyBindsScreen_KeyDown(void* screen, int key) { struct KeyBindsScreen* s = (struct KeyBindsScreen*)screen; - const cc_uint8* defaults; - cc_uint8* curBinds; - KeyBind bind; + InputBind bind; int idx; if (s->curI == -1) return Menu_InputDown(s, key); - curBinds = binds_gamepad ? KeyBinds_Gamepad : KeyBinds_Normal; - defaults = binds_gamepad ? KeyBind_GamepadDefaults : KeyBind_NormalDefaults; - bind = s->binds[s->curI]; - if (Input_IsEscapeButton(key)) key = defaults[bind]; - KeyBind_Set(bind, key, curBinds); + + if (Input_IsEscapeButton(key)) { + KeyBindsScreen_ResetBinding(bind); + } else { + KeyBindsScreen_UpdateBinding(bind, key); + } idx = s->curI; s->curI = -1; @@ -2113,7 +2134,7 @@ static void KeyBindsScreen_Show(int bindsCount, const cc_uint8* binds, const cha *------------------------------------------------ClassicBindingsScreen----------------------------------------------------* *#########################################################################################################################*/ void ClassicBindingsScreen_Show(void) { - static const cc_uint8 binds[] = { KEYBIND_FORWARD, KEYBIND_BACK, KEYBIND_JUMP, KEYBIND_CHAT, KEYBIND_SET_SPAWN, KEYBIND_LEFT, KEYBIND_RIGHT, KEYBIND_INVENTORY, KEYBIND_FOG, KEYBIND_RESPAWN }; + static const cc_uint8 binds[] = { BIND_FORWARD, BIND_BACK, BIND_JUMP, BIND_CHAT, BIND_SET_SPAWN, BIND_LEFT, BIND_RIGHT, BIND_INVENTORY, BIND_FOG, BIND_RESPAWN }; static const char* const descs[] = { "Forward", "Back", "Jump", "Chat", "Save location", "Left", "Right", "Build", "Toggle fog", "Load location" }; binds_gamepad = false; @@ -2132,7 +2153,7 @@ void ClassicBindingsScreen_Show(void) { *----------------------------------------------ClassicHacksBindingsScreen-------------------------------------------------* *#########################################################################################################################*/ void ClassicHacksBindingsScreen_Show(void) { - static const cc_uint8 binds[6] = { KEYBIND_SPEED, KEYBIND_NOCLIP, KEYBIND_HALF_SPEED, KEYBIND_FLY, KEYBIND_FLY_UP, KEYBIND_FLY_DOWN }; + static const cc_uint8 binds[6] = { BIND_SPEED, BIND_NOCLIP, BIND_HALF_SPEED, BIND_FLY, BIND_FLY_UP, BIND_FLY_DOWN }; static const char* const descs[6] = { "Speed", "Noclip", "Half speed", "Fly", "Fly up", "Fly down" }; binds_gamepad = false; @@ -2146,7 +2167,7 @@ void ClassicHacksBindingsScreen_Show(void) { *-------------------------------------------------NormalBindingsScreen----------------------------------------------------* *#########################################################################################################################*/ void NormalBindingsScreen_Show(void) { - static const cc_uint8 binds[] = { KEYBIND_FORWARD, KEYBIND_BACK, KEYBIND_JUMP, KEYBIND_CHAT, KEYBIND_SET_SPAWN, KEYBIND_TABLIST, KEYBIND_LEFT, KEYBIND_RIGHT, KEYBIND_INVENTORY, KEYBIND_FOG, KEYBIND_RESPAWN, KEYBIND_SEND_CHAT }; + static const cc_uint8 binds[] = { BIND_FORWARD, BIND_BACK, BIND_JUMP, BIND_CHAT, BIND_SET_SPAWN, BIND_TABLIST, BIND_LEFT, BIND_RIGHT, BIND_INVENTORY, BIND_FOG, BIND_RESPAWN, BIND_SEND_CHAT }; static const char* const descs[] = { "Forward", "Back", "Jump", "Chat", "Set spawn", "Player list", "Left", "Right", "Inventory", "Toggle fog", "Respawn", "Send chat" }; KeyBindsScreen_Reset(NULL, Menu_SwitchBindsHacks, 250); @@ -2159,7 +2180,7 @@ void NormalBindingsScreen_Show(void) { *--------------------------------------------------HacksBindingsScreen----------------------------------------------------* *#########################################################################################################################*/ void HacksBindingsScreen_Show(void) { - static const cc_uint8 binds[] = { KEYBIND_SPEED, KEYBIND_NOCLIP, KEYBIND_HALF_SPEED, KEYBIND_ZOOM_SCROLL, KEYBIND_FLY, KEYBIND_FLY_UP, KEYBIND_FLY_DOWN, KEYBIND_THIRD_PERSON }; + static const cc_uint8 binds[] = { BIND_SPEED, BIND_NOCLIP, BIND_HALF_SPEED, BIND_ZOOM_SCROLL, BIND_FLY, BIND_FLY_UP, BIND_FLY_DOWN, BIND_THIRD_PERSON }; static const char* const descs[] = { "Speed", "Noclip", "Half speed", "Scroll zoom", "Fly", "Fly up", "Fly down", "Third person" }; KeyBindsScreen_Reset(Menu_SwitchBindsNormal, Menu_SwitchBindsOther, 260); @@ -2172,7 +2193,7 @@ void HacksBindingsScreen_Show(void) { *--------------------------------------------------OtherBindingsScreen----------------------------------------------------* *#########################################################################################################################*/ void OtherBindingsScreen_Show(void) { - static const cc_uint8 binds[] = { KEYBIND_EXT_INPUT, KEYBIND_HIDE_FPS, KEYBIND_HIDE_GUI, KEYBIND_HOTBAR_SWITCH, KEYBIND_DROP_BLOCK,KEYBIND_SCREENSHOT, KEYBIND_FULLSCREEN, KEYBIND_AXIS_LINES, KEYBIND_AUTOROTATE, KEYBIND_SMOOTH_CAMERA, KEYBIND_IDOVERLAY, KEYBIND_BREAK_LIQUIDS }; + static const cc_uint8 binds[] = { BIND_EXT_INPUT, BIND_HIDE_FPS, BIND_HIDE_GUI, BIND_HOTBAR_SWITCH, BIND_DROP_BLOCK,BIND_SCREENSHOT, BIND_FULLSCREEN, BIND_AXIS_LINES, BIND_AUTOROTATE, BIND_SMOOTH_CAMERA, BIND_IDOVERLAY, BIND_BREAK_LIQUIDS }; static const char* const descs[] = { "Show ext input", "Hide FPS", "Hide gui", "Hotbar switching", "Drop block", "Screenshot", "Fullscreen", "Show axis lines", "Auto-rotate", "Smooth camera", "ID overlay", "Breakable liquids" }; KeyBindsScreen_Reset(Menu_SwitchBindsHacks, Menu_SwitchBindsMouse, 260); @@ -2185,7 +2206,7 @@ void OtherBindingsScreen_Show(void) { *--------------------------------------------------MouseBindingsScreen----------------------------------------------------* *#########################################################################################################################*/ void MouseBindingsScreen_Show(void) { - static const cc_uint8 binds[] = { KEYBIND_DELETE_BLOCK, KEYBIND_PICK_BLOCK, KEYBIND_PLACE_BLOCK, KEYBIND_LOOK_UP, KEYBIND_LOOK_DOWN, KEYBIND_LOOK_LEFT, KEYBIND_LOOK_RIGHT }; + static const cc_uint8 binds[] = { BIND_DELETE_BLOCK, BIND_PICK_BLOCK, BIND_PLACE_BLOCK, BIND_LOOK_UP, BIND_LOOK_DOWN, BIND_LOOK_LEFT, BIND_LOOK_RIGHT }; static const char* const descs[] = { "Delete block", "Pick block", "Place block", "Look Up", "Look Down", "Look Left", "Look Right" }; KeyBindsScreen_Reset(Menu_SwitchBindsOther, Menu_SwitchBindsHotbar, 260); @@ -2199,8 +2220,8 @@ void MouseBindingsScreen_Show(void) { *-------------------------------------------------HotbarBindingsScreen----------------------------------------------------* *#########################################################################################################################*/ void HotbarBindingsScreen_Show(void) { - static const cc_uint8 binds[] = { KEYBIND_HOTBAR_1,KEYBIND_HOTBAR_2,KEYBIND_HOTBAR_3, KEYBIND_HOTBAR_4,KEYBIND_HOTBAR_5,KEYBIND_HOTBAR_6, KEYBIND_HOTBAR_7,KEYBIND_HOTBAR_8,KEYBIND_HOTBAR_9, - KEYBIND_HOTBAR_LEFT, KEYBIND_HOTBAR_RIGHT }; + static const cc_uint8 binds[] = { BIND_HOTBAR_1,BIND_HOTBAR_2,BIND_HOTBAR_3, BIND_HOTBAR_4,BIND_HOTBAR_5,BIND_HOTBAR_6, BIND_HOTBAR_7,BIND_HOTBAR_8,BIND_HOTBAR_9, + BIND_HOTBAR_LEFT, BIND_HOTBAR_RIGHT }; static const char* const descs[] = { "Slot #1","Slot #2","Slot #3", "Slot #4","Slot #5","Slot #6", "Slot #7","Slot #8","Slot #9", "Slot left","Slot right" }; KeyBindsScreen_Reset(Menu_SwitchBindsMouse, NULL, 260); @@ -2387,7 +2408,7 @@ static struct MenuOptionsScreen { Screen_Body const char* descriptions[MENUOPTS_MAX_OPTS + 1]; struct ButtonWidget* activeBtn; - InitMenuOptions DoInit, DoRecreateExtra, OnHacksChanged; + InitMenuOptions DoInit, DoRecreateExtra, OnHacksChanged, OnLightingModeServerChanged; int numButtons; struct FontDesc titleFont, textFont; struct TextGroupWidget extHelp; @@ -2574,7 +2595,7 @@ static void MenuOptionsScreen_Input(void* screen, void* widget) { String_InitArray(value, valueBuffer); btn->GetValue(&value); desc = (struct MenuInputDesc*)btn->meta.ptr; - MenuInputOverlay_Show(desc, &value, MenuOptionsScreen_OnDone, Gui.TouchUI); + MenuInputOverlay_Show(desc, &value, MenuOptionsScreen_OnDone, Gui_TouchUI); } static void MenuOptionsScreen_OnHacksChanged(void* screen) { @@ -2582,6 +2603,14 @@ static void MenuOptionsScreen_OnHacksChanged(void* screen) { if (s->OnHacksChanged) s->OnHacksChanged(s); s->dirty = true; } +static void MenuOptionsScreen_OnLightingModeServerChanged(void* screen, cc_uint8 oldMode, cc_bool fromServer) { + struct MenuOptionsScreen* s = (struct MenuOptionsScreen*)screen; + /* This event only actually matters if it's from the server */ + if (fromServer) { + if (s->OnLightingModeServerChanged) s->OnLightingModeServerChanged(s); + s->dirty = true; + } +} static void MenuOptionsScreen_Init(void* screen) { struct MenuOptionsScreen* s = (struct MenuOptionsScreen*)screen; @@ -2604,6 +2633,7 @@ static void MenuOptionsScreen_Init(void* screen) { TextGroupWidget_Create(&s->extHelp, 5, s->extHelpTextures, MenuOptionsScreen_GetDesc); s->extHelp.lines = 0; Event_Register_(&UserEvents.HackPermsChanged, screen, MenuOptionsScreen_OnHacksChanged); + Event_Register_(&WorldEvents.LightingModeChanged, screen, MenuOptionsScreen_OnLightingModeServerChanged); s->maxVertices = Screen_CalcDefaultMaxVertices(s); } @@ -2627,6 +2657,7 @@ static void MenuOptionsScreen_Render(void* screen, float delta) { static void MenuOptionsScreen_Free(void* screen) { struct MenuOptionsScreen* s = (struct MenuOptionsScreen*)screen; Event_Unregister_(&UserEvents.HackPermsChanged, screen, MenuOptionsScreen_OnHacksChanged); + Event_Unregister_(&WorldEvents.LightingModeChanged, screen, MenuOptionsScreen_OnLightingModeServerChanged); Gui_RemoveCore((struct Screen*)&MenuInputOverlay); } @@ -2866,6 +2897,10 @@ void EnvSettingsScreen_Show(void) { /*########################################################################################################################* *--------------------------------------------------GraphicsOptionsScreen--------------------------------------------------* *#########################################################################################################################*/ +static void GraphicsOptionsScreen_CheckLightingModeAllowed(struct MenuOptionsScreen* s) { + Widget_SetDisabled(s->widgets[4], Lighting_ModeLockedByServer); +} + static void GraphicsOptionsScreen_GetViewDist(cc_string* v) { String_AppendInt(v, Game_ViewDistance); } static void GraphicsOptionsScreen_SetViewDist(const cc_string* v) { Game_UserSetViewDistance(Menu_Int(v)); } @@ -2876,6 +2911,15 @@ static void GraphicsOptionsScreen_SetSmooth(const cc_string* v) { MapRenderer_Refresh(); } +static void GraphicsOptionsScreen_GetLighting(cc_string* v) { String_AppendConst(v, LightingMode_Names[Lighting_Mode]); } +static void GraphicsOptionsScreen_SetLighting(const cc_string* v) { + cc_uint8 mode = Utils_ParseEnum(v, 0, LightingMode_Names, LIGHTING_MODE_COUNT); + Options_Set(OPT_LIGHTING_MODE, v); + + Lighting_ModeSetByServer = false; + Lighting_SetMode(mode, false); +} + static void GraphicsOptionsScreen_GetCamera(cc_string* v) { Menu_GetBool(v, Camera.Smooth); } static void GraphicsOptionsScreen_SetCamera(const cc_string* v) { Camera.Smooth = Menu_SetBool(v, OPT_CAMERA_SMOOTH); } @@ -2911,9 +2955,10 @@ static void GraphicsOptionsScreen_InitWidgets(struct MenuOptionsScreen* s) { MenuOptionsScreen_GetFPS, MenuOptionsScreen_SetFPS }, { -1, -50, "View distance", MenuOptionsScreen_Input, GraphicsOptionsScreen_GetViewDist, GraphicsOptionsScreen_SetViewDist }, - { -1, 0, "Advanced lighting", MenuOptionsScreen_Bool, + { -1, 0, "Smooth lighting", MenuOptionsScreen_Bool, GraphicsOptionsScreen_GetSmooth, GraphicsOptionsScreen_SetSmooth }, - + { -1, 50, "Lighting mode", MenuOptionsScreen_Enum, + GraphicsOptionsScreen_GetLighting, GraphicsOptionsScreen_SetLighting }, { 1, -150, "Smooth camera", MenuOptionsScreen_Bool, GraphicsOptionsScreen_GetCamera, GraphicsOptionsScreen_SetCamera }, { 1, -100, "Names", MenuOptionsScreen_Enum, @@ -2930,7 +2975,11 @@ static void GraphicsOptionsScreen_InitWidgets(struct MenuOptionsScreen* s) { { 1, 50, "Anaglyph 3D", MenuOptionsScreen_Bool, ClassicOptionsScreen_GetAnaglyph, ClassicOptionsScreen_SetAnaglyph } }; + + s->OnLightingModeServerChanged = GraphicsOptionsScreen_CheckLightingModeAllowed; + MenuOptionsScreen_AddButtons(s, buttons, Array_Elems(buttons), Menu_SwitchOptions); + GraphicsOptionsScreen_CheckLightingModeAllowed(s); s->descriptions[0] = "&eChange the smoothness of the smooth camera."; s->descriptions[1] = \ @@ -2938,14 +2987,22 @@ static void GraphicsOptionsScreen_InitWidgets(struct MenuOptionsScreen* s) { "&e30/60/120/144 FPS: &fRenders 30/60/120/144 frames at most each second.\n" \ "&eNoLimit: &fRenders as many frames as possible each second.\n" \ "&cNoLimit is pointless - it wastefully renders frames that you don't even see!"; - s->descriptions[3] = "&cNote: &eSmooth lighting is still experimental and can heavily reduce performance."; - s->descriptions[5] = \ + s->descriptions[3] = \ + "&eSmooth lighting smooths lighting and adds a minor glow to bright blocks.\n" \ + "&cNote: &eThis setting may reduce performance."; + s->descriptions[4] = \ + "&eClassic: &fTwo levels of light, sun and shadow.\n" \ + " Good for performance.\n" \ + "&eFancy: &fBright blocks cast a much wider range of light\n" \ + " May heavily reduce performance.\n" \ + "&cNote: &eIn multiplayer, this option may be changed or locked by the server."; + s->descriptions[6] = \ "&eNone: &fNo names of players are drawn.\n" \ "&eHovered: &fName of the targeted player is drawn see-through.\n" \ "&eAll: &fNames of all other players are drawn normally.\n" \ "&eAllHovered: &fAll names of players are drawn see-through.\n" \ "&eAllUnscaled: &fAll names of players are drawn see-through without scaling."; - s->descriptions[6] = \ + s->descriptions[7] = \ "&eNone: &fNo entity shadows are drawn.\n" \ "&eSnapToBlock: &fA square shadow is shown on block you are directly above.\n" \ "&eCircle: &fA circular shadow is shown across the blocks you are above.\n" \ @@ -2956,8 +3013,9 @@ void GraphicsOptionsScreen_Show(void) { MenuInput_Float(menuOpts_descs[0], 1, 100, 20); MenuInput_Enum(menuOpts_descs[1], FpsLimit_Names, FPS_LIMIT_COUNT); MenuInput_Int(menuOpts_descs[2], 8, 4096, 512); - MenuInput_Enum(menuOpts_descs[5], NameMode_Names, NAME_MODE_COUNT); - MenuInput_Enum(menuOpts_descs[6], ShadowMode_Names, SHADOW_MODE_COUNT); + MenuInput_Enum(menuOpts_descs[4], LightingMode_Names, LIGHTING_MODE_COUNT) + MenuInput_Enum(menuOpts_descs[6], NameMode_Names, NAME_MODE_COUNT); + MenuInput_Enum(menuOpts_descs[7], ShadowMode_Names, SHADOW_MODE_COUNT); MenuOptionsScreen_Show(GraphicsOptionsScreen_InitWidgets); } @@ -3180,7 +3238,7 @@ static void HacksSettingsScreen_InitWidgets(struct MenuOptionsScreen* s) { HacksSettingsScreen_GetClipping, HacksSettingsScreen_SetClipping }, { -1, 0, "Jump height", MenuOptionsScreen_Input, HacksSettingsScreen_GetJump, HacksSettingsScreen_SetJump }, - { -1, 50, "WOM style hacks", MenuOptionsScreen_Bool, + { -1, 50, "WoM style hacks", MenuOptionsScreen_Bool, HacksSettingsScreen_GetWOMHacks, HacksSettingsScreen_SetWOMHacks }, { 1, -150, "Full block stepping", MenuOptionsScreen_Bool, @@ -3201,6 +3259,11 @@ static void HacksSettingsScreen_InitWidgets(struct MenuOptionsScreen* s) { s->descriptions[2] = "&eIf &fON&e, then the third person cameras will limit\nðeir zoom distance if they hit a solid block."; s->descriptions[3] = "&eSets how many blocks high you can jump up.\n&eNote: You jump much higher when holding down the Speed key binding."; + s->descriptions[4] = \ + "&eIf &fON&e, gives you a triple jump which increases speed massively,\n" \ + "&ealong with older noclip style. This is based on the \"World of Minecraft\"\n" \ + "&eclassic client mod, which popularized hacks conventions and controls\n" \ + "&ebefore ClassiCube was created."; s->descriptions[7] = \ "&eIf &fON&e, placing blocks that intersect your own position cause\n" \ "ðe block to be placed, and you to be moved out of the way.\n" \ @@ -3689,7 +3752,7 @@ static void TexIdsOverlay_Render(void* screen, float delta) { static int TexIdsOverlay_KeyDown(void* screen, int key) { struct Screen* s = (struct Screen*)screen; - if (KeyBind_Claims(KEYBIND_IDOVERLAY, key)) { Gui_Remove(s); return true; } + if (InputBind_Claims(BIND_IDOVERLAY, key)) { Gui_Remove(s); return true; } return false; } diff --git a/src/Model.c b/src/Model.c index 967a82d..7df5d52 100644 --- a/src/Model.c +++ b/src/Model.c @@ -139,8 +139,8 @@ void Model_SetupState(struct Model* model, struct Entity* e) { Models.Cols[5] = Models.Cols[4]; yawDelta = e->Yaw - e->RotY; - Models.cosHead = (float)Math_Cos(yawDelta * MATH_DEG2RAD); - Models.sinHead = (float)Math_Sin(yawDelta * MATH_DEG2RAD); + Models.cosHead = Math_CosF(yawDelta * MATH_DEG2RAD); + Models.sinHead = Math_SinF(yawDelta * MATH_DEG2RAD); Models.Active = model; } @@ -233,9 +233,9 @@ void Model_DrawRotate(float angleX, float angleY, float angleZ, struct ModelPart struct ModelVertex* src = &model->vertices[part->offset]; struct VertexTextured* dst = &Models.Vertices[model->index]; - float cosX = (float)Math_Cos(-angleX), sinX = (float)Math_Sin(-angleX); - float cosY = (float)Math_Cos(-angleY), sinY = (float)Math_Sin(-angleY); - float cosZ = (float)Math_Cos(-angleZ), sinZ = (float)Math_Sin(-angleZ); + float cosX = Math_CosF(-angleX), sinX = Math_SinF(-angleX); + float cosY = Math_CosF(-angleY), sinY = Math_SinF(-angleY); + float cosZ = Math_CosF(-angleZ), sinZ = Math_SinF(-angleZ); float t, x = part->rotX, y = part->rotY, z = part->rotZ; struct ModelVertex v; @@ -516,7 +516,28 @@ static void Models_TextureChanged(void* obj, struct Stream* stream, const cc_str /*########################################################################################################################* *------------------------------------------------------Custom Models------------------------------------------------------* *#########################################################################################################################*/ -struct CustomModel custom_models[MAX_CUSTOM_MODELS]; +#ifdef CC_BUILD_LOWMEM +static struct CustomModel* custom_models; + +struct CustomModel* CustomModel_Get(int id) { + if (id >= MAX_CUSTOM_MODELS) return NULL; + + /* TODO log message if allocation fails? */ + if (!custom_models) + custom_models = Mem_TryAlloc(MAX_CUSTOM_MODELS, sizeof(struct CustomModel)); + + if (!custom_models) return NULL; + return &custom_models[id]; +} +#else +static struct CustomModel custom_models[MAX_CUSTOM_MODELS]; + +struct CustomModel* CustomModel_Get(int id) { + if (id >= MAX_CUSTOM_MODELS) return NULL; + + return &custom_models[id]; +} +#endif void CustomModel_BuildPart(struct CustomModel* cm, struct CustomModelPartDef* part) { float x1 = part->min.x, y1 = part->min.y, z1 = part->min.z; @@ -818,6 +839,7 @@ static void CustomModel_DrawArm(struct Entity* e) { struct CustomModel* cm = (struct CustomModel*)Models.Active; int i; if (!cm->numArmParts) return; + Gfx_SetAlphaTest(true); Models.uScale = 1.0f / cm->uScale; Models.vScale = 1.0f / cm->vScale; @@ -880,6 +902,8 @@ void CustomModel_Undefine(struct CustomModel* cm) { static void CustomModel_FreeAll(void) { int i; + if (!custom_models) return; + for (i = 0; i < MAX_CUSTOM_MODELS; i++) { CustomModel_Undefine(&custom_models[i]); @@ -952,6 +976,7 @@ static void HumanModel_DrawCore(struct Entity* e, struct ModelSet* model, cc_boo static void HumanModel_DrawArmCore(struct Entity* e, struct ModelSet* model) { struct ModelLimbs* set; int type, num; + Gfx_SetAlphaTest(true); type = Models.skinType; set = &model->limbs[type & 0x3]; @@ -1854,6 +1879,7 @@ static void SkeletonModel_Draw(struct Entity* e) { } static void SkeletonModel_DrawArm(struct Entity* e) { + Gfx_SetAlphaTest(true); Model_LockVB(e, MODEL_BOX_VERTICES); Model_DrawArmPart(&skeleton_rightArm); @@ -1935,9 +1961,9 @@ static void SpiderModel_Draw(struct Entity* e) { Model_DrawPart(&spider_link); Model_DrawPart(&spider_end); - rotX = (float)Math_Sin(e->Anim.WalkTime) * e->Anim.Swing * MATH_PI; - rotZ = (float)Math_Cos(e->Anim.WalkTime * 2) * e->Anim.Swing * MATH_PI / 16.0f; - rotY = (float)Math_Sin(e->Anim.WalkTime * 2) * e->Anim.Swing * MATH_PI / 32.0f; + rotX = Math_SinF(e->Anim.WalkTime) * e->Anim.Swing * MATH_PI; + rotZ = Math_CosF(e->Anim.WalkTime * 2) * e->Anim.Swing * MATH_PI / 16.0f; + rotY = Math_SinF(e->Anim.WalkTime * 2) * e->Anim.Swing * MATH_PI / 32.0f; Models.Rotation = ROTATE_ORDER_XZY; Model_DrawRotate(rotX, quarterPi + rotY, eighthPi + rotZ, &spider_leftLeg, false); @@ -2190,8 +2216,8 @@ static void BlockModel_Draw(struct Entity* e) { bModel_index = 0; if (Blocks.Draw[bModel_block] == DRAW_GAS) return; - if (Blocks.FullBright[bModel_block]) { - for (i = 0; i < FACE_COUNT; i++) + if (Blocks.Brightness[bModel_block]) { + for (i = 0; i < FACE_COUNT; i++) { Models.Cols[i] = PACKEDCOL_WHITE; } @@ -2309,12 +2335,11 @@ static void DrawBlockTransform(struct Entity* e, float dispX, float dispY, float } static void HoldModel_Draw(struct Entity* e) { - static float handBob; - static float handIdle; - + float handBob; + float handIdle; RecalcProperties(e); - handBob = (float)Math_Sin(e->Anim.WalkTime * 2.0f) * e->Anim.Swing * MATH_PI / 16.0f; + handBob = Math_SinF(e->Anim.WalkTime * 2.0f) * e->Anim.Swing * MATH_PI / 16.0f; handIdle = e->Anim.RightArmX * (1.0f - e->Anim.Swing); e->Anim.RightArmX = 0.5f + handBob + handIdle; diff --git a/src/Model.h b/src/Model.h index 7f074d4..2992270 100644 --- a/src/Model.h +++ b/src/Model.h @@ -292,8 +292,7 @@ struct CustomModel { struct CustomModelPart parts[MAX_CUSTOM_MODEL_PARTS]; }; -extern struct CustomModel custom_models[MAX_CUSTOM_MODELS]; - +struct CustomModel* CustomModel_Get(int id); void CustomModel_BuildPart(struct CustomModel* cm, struct CustomModelPartDef* part); void CustomModel_Register(struct CustomModel* cm); void CustomModel_Undefine(struct CustomModel* cm); diff --git a/src/Options.h b/src/Options.h index 7110556..3c5d5e7 100644 --- a/src/Options.h +++ b/src/Options.h @@ -23,6 +23,7 @@ Copyright 2014-2023 ClassiCube | Licensed under BSD-3 #define OPT_ENTITY_SHADOW "entityshadow" #define OPT_RENDER_TYPE "normal" #define OPT_SMOOTH_LIGHTING "gfx-smoothlighting" +#define OPT_LIGHTING_MODE "gfx-lightingmode" #define OPT_MIPMAPS "gfx-mipmaps" #define OPT_CHAT_LOGGING "chat-logging" #define OPT_WINDOW_WIDTH "window-width" diff --git a/src/PackedCol.c b/src/PackedCol.c index 3d4ecdb..1e03924 100644 --- a/src/PackedCol.c +++ b/src/PackedCol.c @@ -24,6 +24,27 @@ PackedCol PackedCol_Tint(PackedCol a, PackedCol b) { return (a & PACKEDCOL_A_MASK) | (R << PACKEDCOL_R_SHIFT) | (G << PACKEDCOL_G_SHIFT) | (B << PACKEDCOL_B_SHIFT); } +PackedCol PackedCol_ScreenBlend(PackedCol a, PackedCol b) { + PackedCol finalColor, aInverted, bInverted; + cc_uint8 R, G, B; + /* With Screen blend mode, the values of the pixels in the two layers are inverted, multiplied, and then inverted again. */ + R = 255 - PackedCol_R(a); + G = 255 - PackedCol_G(a); + B = 255 - PackedCol_B(a); + aInverted = PackedCol_Make(R, G, B, 255); + + R = 255 - PackedCol_R(b); + G = 255 - PackedCol_G(b); + B = 255 - PackedCol_B(b); + bInverted = PackedCol_Make(R, G, B, 255); + + finalColor = PackedCol_Tint(aInverted, bInverted); + R = 255 - PackedCol_R(finalColor); + G = 255 - PackedCol_G(finalColor); + B = 255 - PackedCol_B(finalColor); + return PackedCol_Make(R, G, B, 255); +} + void PackedCol_GetShaded(PackedCol normal, PackedCol* xSide, PackedCol* zSide, PackedCol* yMin) { *xSide = PackedCol_Scale(normal, PACKEDCOL_SHADE_X); *zSide = PackedCol_Scale(normal, PACKEDCOL_SHADE_Z); diff --git a/src/PackedCol.h b/src/PackedCol.h index 8990128..5321d9c 100644 --- a/src/PackedCol.h +++ b/src/PackedCol.h @@ -6,7 +6,7 @@ */ typedef cc_uint32 PackedCol; -#if defined CC_BUILD_D3D9 || defined CC_BUILD_XBOX || defined CC_BUILD_DREAMCAST +#if (CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9) || defined CC_BUILD_XBOX || defined CC_BUILD_DREAMCAST #define PACKEDCOL_B_SHIFT 0 #define PACKEDCOL_G_SHIFT 8 #define PACKEDCOL_R_SHIFT 16 @@ -48,6 +48,8 @@ CC_API PackedCol PackedCol_Scale(PackedCol value, float t); CC_API PackedCol PackedCol_Lerp(PackedCol a, PackedCol b, float t); /* Multiplies RGB components of the two given colours. */ CC_API PackedCol PackedCol_Tint(PackedCol a, PackedCol b); +/* Adds the two colors together in a way that gives a brighter result. */ +CC_API PackedCol PackedCol_ScreenBlend(PackedCol a, PackedCol b); CC_NOINLINE int PackedCol_DeHex(char hex); CC_NOINLINE cc_bool PackedCol_Unhex(const char* src, int* dst, int count); diff --git a/src/Particle.c b/src/Particle.c index b8c4079..403900c 100644 --- a/src/Particle.c +++ b/src/Particle.c @@ -245,7 +245,7 @@ static void TerrainParticle_Render(struct TerrainParticle* p, float t, struct Ve Vec3_Lerp(&pos, &p->base.lastPos, &p->base.nextPos, t); size.x = p->base.size * 0.015625f; size.y = size.x; - if (!Blocks.FullBright[p->block]) { + if (!Blocks.Brightness[p->block]) { x = Math_Floor(pos.x); y = Math_Floor(pos.y); z = Math_Floor(pos.z); col = Lighting.Color_XSide(x, y, z); } diff --git a/src/Platform.h b/src/Platform.h index 19b2c1b..ca4b932 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -150,11 +150,15 @@ CC_API void* Mem_AllocCleared(cc_uint32 numElems, cc_uint32 elemsSize, const cha CC_API void* Mem_Realloc(void* mem, cc_uint32 numElems, cc_uint32 elemsSize, const char* place); /* Frees an allocated a block of memory. Does nothing when passed NULL. */ CC_API void Mem_Free(void* mem); + /* Sets the contents of a block of memory to the given value. */ -void Mem_Set(void* dst, cc_uint8 value, cc_uint32 numBytes); +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes); /* Copies a block of memory to another block of memory. */ /* NOTE: These blocks MUST NOT overlap. */ -void Mem_Copy(void* dst, const void* src, cc_uint32 numBytes); +void* Mem_Copy(void* dst, const void* src, unsigned numBytes); +/* Moves a block of memory to another block of memory. */ +/* NOTE: These blocks can overlap. */ +void* Mem_Move(void* dst, const void* src, unsigned numBytes); /* Returns non-zero if the two given blocks of memory have equal contents. */ int Mem_Equal(const void* a, const void* b, cc_uint32 numBytes); @@ -222,7 +226,7 @@ CC_API void Thread_Detach(void* handle); CC_API void Thread_Join(void* handle); /* Allocates a new mutex. (used to synchronise access to a shared resource) */ -CC_API void* Mutex_Create(void); +CC_API void* Mutex_Create(const char* name); /* Frees an allocated mutex. */ CC_API void Mutex_Free(void* handle); /* Locks the given mutex, blocking other threads from entering. */ @@ -231,7 +235,7 @@ CC_API void Mutex_Lock(void* handle); CC_API void Mutex_Unlock(void* handle); /* Allocates a new waitable. (used to conditionally wake-up a blocked thread) */ -CC_API void* Waitable_Create(void); +CC_API void* Waitable_Create(const char* name); /* Frees an allocated waitable. */ CC_API void Waitable_Free(void* handle); /* Signals a waitable, waking up blocked threads. */ diff --git a/src/Platform_3DS.c b/src/Platform_3DS.c index 87df96c..09c27d6 100644 --- a/src/Platform_3DS.c +++ b/src/Platform_3DS.c @@ -228,7 +228,7 @@ void Thread_Join(void* handle) { threadFree(thread); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { LightLock* lock = (LightLock*)Mem_Alloc(1, sizeof(LightLock), "mutex"); LightLock_Init(lock); return lock; @@ -246,7 +246,7 @@ void Mutex_Unlock(void* handle) { LightLock_Unlock((LightLock*)handle); } -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { LightEvent* event = (LightEvent*)Mem_Alloc(1, sizeof(LightEvent), "waitable"); LightEvent_Init(event, RESET_ONESHOT); return event; @@ -311,8 +311,7 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a if (!cur->ai_addrlen) break; // TODO citra returns empty addresses past first one? does that happen on real hardware too? - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); } freeaddrinfo(result); diff --git a/src/Platform_BeOS.cpp b/src/Platform_BeOS.cpp new file mode 100644 index 0000000..77a3bca --- /dev/null +++ b/src/Platform_BeOS.cpp @@ -0,0 +1,110 @@ +#include "Core.h" +#if defined CC_BUILD_BEOS || defined CC_BUILD_HAIKU +extern "C" { +#include "Platform.h" +#include "String.h" +#include "Funcs.h" +#include "Utils.h" +} +#include +#include +#include + +/*########################################################################################################################* +*--------------------------------------------------------Platform---------------------------------------------------------* +*#########################################################################################################################*/ +cc_uint64 Stopwatch_Measure(void) { + return system_time(); +} + +cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { + if (end < beg) return 0; + return end - beg; +} + +cc_result Process_StartOpen(const cc_string* args) { + static const cc_string https_protocol = String_FromConst("https://"); + char str[NATIVE_STR_LEN]; + String_EncodeUtf8(str, args); + + cc_bool https = String_CaselessStarts(args, &https_protocol); + const char* mime = https ? "application/x-vnd.Be.URL.https" : "application/x-vnd.Be.URL.http"; + + char* argv[] = { str, NULL }; + return be_roster->Launch(mime, 1, argv); +} + + +/*########################################################################################################################* +*-----------------------------------------------------BeOS threading------------------------------------------------------* +*#########################################################################################################################*/ +// NOTE: BeOS only, as haiku uses the more efficient pthreads implementation in Platform_Posix.c +#if defined CC_BUILD_BEOS +void Thread_Sleep(cc_uint32 milliseconds) { snooze(milliseconds * 1000); } + +static int32 ExecThread(void* param) { + ((Thread_StartFunc)param)(); + return 0; +} + +void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { + thread_id thread = spawn_thread(ExecThread, name, B_NORMAL_PRIORITY, func); + *handle = (void*)thread; + + resume_thread(thread); +} + +void Thread_Detach(void* handle) { } + +void Thread_Join(void* handle) { + thread_id thread = (thread_id)handle; + wait_for_thread(thread, NULL); +} + +void* Mutex_Create(const char* name) { + sem_id id = create_sem(1, name); + return (void*)id; +} + +void Mutex_Free(void* handle) { + sem_id id = (sem_id)handle; + delete_sem(id); +} + +void Mutex_Lock(void* handle) { + sem_id id = (sem_id)handle; + acquire_sem(id); +} + +void Mutex_Unlock(void* handle) { + sem_id id = (sem_id)handle; + release_sem(id); +} + +void* Waitable_Create(const char* name) { + sem_id id = create_sem(0, name); + return (void*)id; +} + +void Waitable_Free(void* handle) { + sem_id id = (sem_id)handle; + delete_sem(id); +} + +void Waitable_Signal(void* handle) { + sem_id id = (sem_id)handle; + release_sem(id); +} + +void Waitable_Wait(void* handle) { + sem_id id = (sem_id)handle; + acquire_sem(id); +} + +void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { + int microseconds = milliseconds * 1000; + sem_id id = (sem_id)handle; + acquire_sem_etc(id, 1, B_RELATIVE_TIMEOUT, microseconds); +} +#endif +#endif diff --git a/src/Platform_Dreamcast.c b/src/Platform_Dreamcast.c index 0962842..b2332a6 100644 --- a/src/Platform_Dreamcast.c +++ b/src/Platform_Dreamcast.c @@ -272,7 +272,7 @@ void Thread_Join(void* handle) { thd_join((kthread_t*)handle, NULL); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { mutex_t* ptr = (mutex_t*)Mem_Alloc(1, sizeof(mutex_t), "mutex"); int res = mutex_init(ptr, MUTEX_TYPE_NORMAL); if (res) Logger_Abort2(errno, "Creating mutex"); @@ -295,7 +295,7 @@ void Mutex_Unlock(void* handle) { if (res) Logger_Abort2(errno, "Unlocking mutex"); } -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { semaphore_t* ptr = (semaphore_t*)Mem_Alloc(1, sizeof(semaphore_t), "waitable"); int res = sem_init(ptr, 0); if (res) Logger_Abort2(errno, "Creating waitable"); @@ -368,8 +368,7 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next, i++) { - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); } freeaddrinfo(result); diff --git a/src/Platform_GCWii.c b/src/Platform_GCWii.c index 9f660cd..3c1895a 100644 --- a/src/Platform_GCWii.c +++ b/src/Platform_GCWii.c @@ -272,7 +272,7 @@ void Thread_Join(void* handle) { Mem_Free(ptr); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { mutex_t* ptr = (mutex_t*)Mem_Alloc(1, sizeof(mutex_t), "mutex"); int res = LWP_MutexInit(ptr, false); if (res) Logger_Abort2(res, "Creating mutex"); @@ -305,7 +305,7 @@ struct WaitData { int signalled; // For when Waitable_Signal is called before Waitable_Wait }; -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { struct WaitData* ptr = (struct WaitData*)Mem_Alloc(1, sizeof(struct WaitData), "waitable"); int res; diff --git a/src/Platform_MacClassic.c b/src/Platform_MacClassic.c new file mode 100644 index 0000000..2314817 --- /dev/null +++ b/src/Platform_MacClassic.c @@ -0,0 +1,447 @@ +#include "Core.h" +#if defined CC_BUILD_MACCLASSIC + +#include "_PlatformBase.h" +#include "Stream.h" +#include "ExtMath.h" +#include "SystemFonts.h" +#include "Funcs.h" +#include "Window.h" +#include "Utils.h" +#include "Errors.h" +#include "PackedCol.h" +#include +#include +#include + +#undef true +#undef false +#include +#include +#include +#include + +const cc_result ReturnCode_FileShareViolation = 1000000000; /* TODO: not used apparently */ +const cc_result ReturnCode_FileNotFound = ENOENT; +const cc_result ReturnCode_SocketInProgess = EINPROGRESS; +const cc_result ReturnCode_SocketWouldBlock = EWOULDBLOCK; +const cc_result ReturnCode_DirectoryExists = EEXIST; + +#if TARGET_CPU_68K +const char* Platform_AppNameSuffix = " MAC 68k"; +#else +const char* Platform_AppNameSuffix = " MAC PPC"; +#endif +cc_bool Platform_SingleProcess = true; +static long sysVersion; + + +/*########################################################################################################################* +*---------------------------------------------------Imported headers------------------------------------------------------* +*#########################################################################################################################*/ +// On 68k these are implemented using direct 68k opcodes +// On PPC these are implemented using function calls +#if TARGET_CPU_68K + #define MAC_SYSAPI(_type) static _type + #define MAC_ONEWORDINLINE(w1) = w1 + #define MAC_TWOWORDINLINE(w1,w2) = {w1, w2} + #define MAC_THREEWORDINLINE(w1,w2,w3) = {w1, w2, w3} + #define MAC_FOURWORDINLINE(w1,w2,w3,w4) = {w1, w2, w3, w4} +#else + #define MAC_SYSAPI(_type) extern pascal _type + #define MAC_ONEWORDINLINE(w1) + #define MAC_TWOWORDINLINE(w1,w2) + #define MAC_THREEWORDINLINE(w1,w2,w3) + #define MAC_FOURWORDINLINE(w1,w2,w3,w4) +#endif +typedef unsigned long MAC_FourCharCode; + +// ==================================== IMPORTS FROM TIMER.H ==================================== +// Availability: in InterfaceLib 7.1 and later +MAC_SYSAPI(void) Microseconds(cc_uint64* microTickCount) MAC_FOURWORDINLINE(0xA193, 0x225F, 0x22C8, 0x2280); + +/*########################################################################################################################* +*---------------------------------------------------------Memory----------------------------------------------------------* +*#########################################################################################################################*/ +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } + +void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + return size ? NewPtr(size) : NULL; +} + +void* Mem_TryAllocCleared(cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + return size ? NewPtrClear(size) : NULL; +} + +void* Mem_TryRealloc(void* mem, cc_uint32 numElems, cc_uint32 elemsSize) { + cc_uint32 size = CalcMemSize(numElems, elemsSize); + if (!size) return NULL; + if (!mem) return NewPtr(size); + + // Try to resize in place + MemError(); + SetPtrSize(mem, size); + if (!MemError()) return mem; + + void* newMem = NewPtr(size); + if (!newMem) return NULL; + + Mem_Copy(newMem, mem, GetPtrSize(mem)); + return newMem; +} + +void Mem_Free(void* mem) { + if (mem) DisposePtr(mem); +} + + +/*########################################################################################################################* +*------------------------------------------------------Logging/Time-------------------------------------------------------* +*#########################################################################################################################*/ +ssize_t _consolewrite(int fd, const void *buf, size_t count); + +void Platform_Log(const char* msg, int len) { + _consolewrite(0, msg, len); + _consolewrite(0, "\n", 1); +} + +// classic macOS uses an epoch of 1904 +#define EPOCH_ADJUSTMENT 2082866400UL + +static time_t gettod(void) { + unsigned long secs; + GetDateTime(&secs); + return secs - EPOCH_ADJUSTMENT; +} + +TimeMS DateTime_CurrentUTC(void) { + time_t secs = gettod(); + return (cc_uint64)secs + UNIX_EPOCH_SECONDS; +} + +void DateTime_CurrentLocal(struct DateTime* t) { + struct tm loc_time; + time_t secs = gettod(); + localtime_r(&secs, &loc_time); + + t->year = loc_time.tm_year + 1900; + t->month = loc_time.tm_mon + 1; + t->day = loc_time.tm_mday; + t->hour = loc_time.tm_hour; + t->minute = loc_time.tm_min; + t->second = loc_time.tm_sec; +} + + +/*########################################################################################################################* +*--------------------------------------------------------Stopwatch--------------------------------------------------------* +*#########################################################################################################################*/ +#define MS_PER_SEC 1000000ULL + +cc_uint64 Stopwatch_Measure(void) { + cc_uint64 count; + if (sysVersion < 0x7000) { + // 60 ticks a second + count = TickCount(); + return count * MS_PER_SEC / 60; + } + + Microseconds(&count); + return count; +} + +cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { + if (end < beg) return 0; + return end - beg; +} + + +/*########################################################################################################################* +*-----------------------------------------------------Directory/File------------------------------------------------------* +*#########################################################################################################################*/ +void Directory_GetCachePath(cc_string* path) { } + +cc_result Directory_Create(const cc_string* path) { + return 0; // TODO +} + +int File_Exists(const cc_string* path) { + return 0; +} + +cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCallback callback) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Open(cc_file* file, const cc_string* path) { + return ReturnCode_FileNotFound; +} + +cc_result File_Create(cc_file* file, const cc_string* path) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_OpenOrCreate(cc_file* file, const cc_string* path) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) { + long cnt = count; + int res = FSRead(file, &cnt, data); + + *bytesRead = cnt; + return res; +} + +cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32* bytesWrote) { + long cnt = count; + int res = FSWrite(file, &cnt, data); + + *bytesWrote = cnt; + return res; +} + +cc_result File_Close(cc_file file) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Seek(cc_file file, int offset, int seekType) { + static cc_uint8 modes[] = { fsFromStart, fsFromMark, fsFromLEOF }; + SetFPos(file, modes[seekType], offset); + return 0; +} + +cc_result File_Position(cc_file file, cc_uint32* pos) { + return ERR_NOT_SUPPORTED; +} + +cc_result File_Length(cc_file file, cc_uint32* len) { + return ERR_NOT_SUPPORTED; +} + + +/*########################################################################################################################* +*--------------------------------------------------------Threading--------------------------------------------------------* +*#########################################################################################################################*/ +void Thread_Sleep(cc_uint32 milliseconds) { + long delay = milliseconds * 1000 / 60; + long final; + Delay(delay, &final); +} + +void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* name) { + *handle = NULL; + // TODO +} + +void Thread_Detach(void* handle) { + // TODO +} + +void Thread_Join(void* handle) { + // TODO +} + +void* Mutex_Create(const char* name) { + return NULL; +} + +void Mutex_Free(void* handle) { + // TODO +} + +void Mutex_Lock(void* handle) { + // TODO +} + +void Mutex_Unlock(void* handle) { + // TODO +} + +void* Waitable_Create(const char* name) { + return NULL; +} + +void Waitable_Free(void* handle) { + // TODO +} + +void Waitable_Signal(void* handle) { + // TODO +} + +void Waitable_Wait(void* handle) { + // TODO +} + +void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { + // TODO +} + + +/*########################################################################################################################* +*--------------------------------------------------------Font/Text--------------------------------------------------------* +*#########################################################################################################################*/ +static void FontDirCallback(const cc_string* path, void* obj) { + SysFonts_Register(path, NULL); +} + +void Platform_LoadSysFonts(void) { + int i; + static const cc_string dirs[] = { + String_FromConst("/usr/share/fonts"), + String_FromConst("/usr/local/share/fonts") + }; + + for (i = 0; i < Array_Elems(dirs); i++) { + Directory_Enum(&dirs[i], NULL, FontDirCallback); + } +} + + +/*########################################################################################################################* +*---------------------------------------------------------Socket----------------------------------------------------------* +*#########################################################################################################################*/ +cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* addrs, int* numValidAddrs) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Connect(cc_socket* s, cc_sockaddr* addr, cc_bool nonblocking) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Read(cc_socket s, cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_Write(cc_socket s, const cc_uint8* data, cc_uint32 count, cc_uint32* modified) { + return ERR_NOT_SUPPORTED; +} + +void Socket_Close(cc_socket s) { + +} + +cc_result Socket_CheckReadable(cc_socket s, cc_bool* readable) { + return ERR_NOT_SUPPORTED; +} + +cc_result Socket_CheckWritable(cc_socket s, cc_bool* writable) { + return ERR_NOT_SUPPORTED; +} + + +/*########################################################################################################################* +*-----------------------------------------------------Process/Module------------------------------------------------------* +*#########################################################################################################################*/ +cc_bool Process_OpenSupported = false; +static char gameArgs[GAME_MAX_CMDARGS][STRING_SIZE]; +static int gameNumArgs; + +int Platform_GetCommandLineArgs(int argc, STRING_REF char** argv, cc_string* args) { + int count = gameNumArgs; + for (int i = 0; i < count; i++) + { + args[i] = String_FromRawArray(gameArgs[i]); + } + + // clear arguments so after game is closed, launcher is started + gameNumArgs = 0; + return count; +} + +cc_result Platform_SetDefaultCurrentDirectory(int argc, char **argv) { + return 0; +} + +cc_result Process_StartGame2(const cc_string* args, int numArgs) { + for (int i = 0; i < numArgs; i++) + { + String_CopyToRawArray(gameArgs[i], &args[i]); + } + + gameNumArgs = numArgs; + return 0; +} + +void Process_Exit(cc_result code) { + ExitToShell(); + for(;;) { } +} + +cc_result Process_StartOpen(const cc_string* args) { + return ERR_NOT_SUPPORTED; +} + + +/*########################################################################################################################* +*--------------------------------------------------------Updater----------------------------------------------------------* +*#########################################################################################################################*/ +cc_bool Updater_Supported = false; +cc_bool Updater_Clean(void) { return true; } + +const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; + +cc_result Updater_Start(const char** action) { + return ERR_NOT_SUPPORTED; +} + +cc_result Updater_GetBuildTime(cc_uint64* timestamp) { + return ERR_NOT_SUPPORTED; +} + +cc_result Updater_MarkExecutable(void) { + return ERR_NOT_SUPPORTED; +} + +cc_result Updater_SetNewBuildTime(cc_uint64 timestamp) { + return ERR_NOT_SUPPORTED; +} + + +/*########################################################################################################################* +*-------------------------------------------------------Dynamic lib-------------------------------------------------------* +*#########################################################################################################################*/ +const cc_string DynamicLib_Ext = String_FromConst(".dylib"); + +void* DynamicLib_Load2(const cc_string* path) { + return NULL; +} + +void* DynamicLib_Get2(void* lib, const char* name) { + return NULL; +} + +cc_bool DynamicLib_DescribeError(cc_string* dst) { + return false; +} + + +/*########################################################################################################################* +*--------------------------------------------------------Platform---------------------------------------------------------* +*#########################################################################################################################*/ +void Platform_Free(void) { } + +cc_bool Platform_DescribeError(cc_result res, cc_string* dst) { + // TODO + return false; +} + +void Platform_Init(void) { + Gestalt(gestaltSystemVersion, &sysVersion); + Platform_Log1("Running on Mac OS %h", &sysVersion); + Platform_LoadSysFonts(); +} + +cc_result Platform_Encrypt(const void* data, int len, cc_string* dst) { + return ERR_NOT_SUPPORTED; +} + +cc_result Platform_Decrypt(const void* data, int len, cc_string* dst) { + return ERR_NOT_SUPPORTED; +} +#endif diff --git a/src/Platform_N64.c b/src/Platform_N64.c index 81cf6b5..61afcd5 100644 --- a/src/Platform_N64.c +++ b/src/Platform_N64.c @@ -180,7 +180,7 @@ void Thread_Detach(void* handle) { void Thread_Join(void* handle) { } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { return NULL; } @@ -193,7 +193,7 @@ void Mutex_Lock(void* handle) { void Mutex_Unlock(void* handle) { } -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { return NULL; } diff --git a/src/Platform_NDS.c b/src/Platform_NDS.c index b0194b3..0376581 100644 --- a/src/Platform_NDS.c +++ b/src/Platform_NDS.c @@ -139,10 +139,10 @@ cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCall return ERR_NOT_SUPPORTED; } -static cc_result File_Do(cc_file* file, const cc_string* path, int mode) { +static cc_result File_Do(cc_file* file, const cc_string* path, int mode, const char* type) { char str[NATIVE_STR_LEN]; GetNativePath(str, path); - Platform_Log1("Open %c", str); + Platform_Log2("%c %c", type, str); *file = open(str, mode, 0); return *file == -1 ? errno : 0; @@ -150,17 +150,17 @@ static cc_result File_Do(cc_file* file, const cc_string* path, int mode) { cc_result File_Open(cc_file* file, const cc_string* path) { if (!fat_available) return ReturnCode_FileNotFound; - return File_Do(file, path, O_RDONLY); + return File_Do(file, path, O_RDONLY, "Open"); } cc_result File_Create(cc_file* file, const cc_string* path) { if (!fat_available) return ENOTSUP; - return File_Do(file, path, O_RDWR | O_CREAT | O_TRUNC); + return File_Do(file, path, O_RDWR | O_CREAT | O_TRUNC, "Create"); } cc_result File_OpenOrCreate(cc_file* file, const cc_string* path) { if (!fat_available) return ENOTSUP; - return File_Do(file, path, O_RDWR | O_CREAT); + return File_Do(file, path, O_RDWR | O_CREAT, "Update"); } cc_result File_Read(cc_file file, void* data, cc_uint32 count, cc_uint32* bytesRead) { @@ -219,6 +219,7 @@ static void InitFilesystem(void) { char* dir = fatGetDefaultCwd(); if (dir) { + Platform_Log1("CWD: %c", dir); root_path.buffer = dir; root_path.length = String_Length(dir); } @@ -244,7 +245,7 @@ void Thread_Detach(void* handle) { void Thread_Join(void* handle) { } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { return NULL; } @@ -257,7 +258,7 @@ void Mutex_Lock(void* handle) { void Mutex_Unlock(void* handle) { } -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { return NULL; } @@ -421,9 +422,11 @@ static void InitNetworking(void) { *--------------------------------------------------------Platform---------------------------------------------------------* *#########################################################################################################################*/ void Platform_Init(void) { + cc_bool dsiMode = isDSiMode(); + Platform_Log1("Running in %c mode", dsiMode ? "DSi" : "DS"); + InitFilesystem(); InitNetworking(); - cpuStartTiming(1); } void Platform_Free(void) { } diff --git a/src/Platform_PS1.c b/src/Platform_PS1.c index f4ad6f5..63513fc 100644 --- a/src/Platform_PS1.c +++ b/src/Platform_PS1.c @@ -160,7 +160,7 @@ void Thread_Detach(void* handle) { void Thread_Join(void* handle) { } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { return NULL; } @@ -173,7 +173,7 @@ void Mutex_Lock(void* handle) { void Mutex_Unlock(void* handle) { } -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { return NULL; } diff --git a/src/Platform_PS2.c b/src/Platform_PS2.c index 8adb545..6ac07c5 100644 --- a/src/Platform_PS2.c +++ b/src/Platform_PS2.c @@ -15,14 +15,15 @@ #include #include #include +#include #include #include -#include #include #include #include -#include +#include #include +#include #include #include #include @@ -251,7 +252,7 @@ void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* int thdID = CreateThread(&thread); if (thdID < 0) Logger_Abort2(thdID, "Creating thread"); - *handle = thdID; + *handle = (void*)thdID; int res = StartThread(thdID, (void*)func); if (res < 0) Logger_Abort2(res, "Running thread"); @@ -275,7 +276,7 @@ void Thread_Join(void* handle) { } } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { ee_sema_t sema = { 0 }; sema.init_count = 1; sema.max_count = 1; @@ -306,7 +307,7 @@ void Mutex_Unlock(void* handle) { if (res < 0) Logger_Abort2(res, "Unlocking mutex"); } -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { ee_sema_t sema = { 0 }; sema.init_count = 0; sema.max_count = 1; @@ -473,8 +474,7 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next, i++) { - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); } freeaddrinfo(result); diff --git a/src/Platform_PS3.c b/src/Platform_PS3.c index b4c15a2..87b9d74 100644 --- a/src/Platform_PS3.c +++ b/src/Platform_PS3.c @@ -260,7 +260,7 @@ void Thread_Join(void* handle) { Mem_Free(thread); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { sys_mutex_attr_t attr; sysMutexAttrInitialize(attr); @@ -289,7 +289,7 @@ void Mutex_Unlock(void* handle) { if (res) Logger_Abort2(res, "Unlocking mutex"); } -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { sys_sem_attr_t attr = { 0 }; attr.attr_protocol = SYS_SEM_ATTR_PROTOCOL; attr.attr_pshared = SYS_SEM_ATTR_PSHARED; diff --git a/src/Platform_PSP.c b/src/Platform_PSP.c index 32fa8f4..53c013b 100644 --- a/src/Platform_PSP.c +++ b/src/Platform_PSP.c @@ -226,7 +226,7 @@ void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* int threadID = sceKernelCreateThread(name, ExecThread, CC_THREAD_PRIORITY, stackSize, CC_THREAD_ATTRS, NULL); - *handle = (int)threadID; + *handle = (void*)threadID; sceKernelStartThread(threadID, sizeof(func_), (void*)&func_); } @@ -239,9 +239,9 @@ void Thread_Join(void* handle) { sceKernelDeleteThread((int)handle); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { SceLwMutexWorkarea* ptr = (SceLwMutexWorkarea*)Mem_Alloc(1, sizeof(SceLwMutexWorkarea), "mutex"); - int res = sceKernelCreateLwMutex(ptr, "CC mutex", 0, 0, NULL); + int res = sceKernelCreateLwMutex(ptr, name, 0, 0, NULL); if (res) Logger_Abort2(res, "Creating mutex"); return ptr; } @@ -262,8 +262,8 @@ void Mutex_Unlock(void* handle) { if (res) Logger_Abort2(res, "Unlocking mutex"); } -void* Waitable_Create(void) { - int evid = sceKernelCreateEventFlag("CC event", PSP_EVENT_WAITMULTIPLE, 0, NULL); +void* Waitable_Create(const char* name) { + int evid = sceKernelCreateEventFlag(name, PSP_EVENT_WAITMULTIPLE, 0, NULL); if (evid < 0) Logger_Abort2(evid, "Creating waitable"); return (void*)evid; } diff --git a/src/Platform_PSVita.c b/src/Platform_PSVita.c index afefa92..8cca278 100644 --- a/src/Platform_PSVita.c +++ b/src/Platform_PSVita.c @@ -222,9 +222,9 @@ void Thread_Join(void* handle) { sceKernelDeleteThread((int)handle); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { SceKernelLwMutexWork* ptr = (SceKernelLwMutexWork*)Mem_Alloc(1, sizeof(SceKernelLwMutexWork), "mutex"); - int res = sceKernelCreateLwMutex(ptr, "CC mutex", 0, 0, NULL); + int res = sceKernelCreateLwMutex(ptr, name, 0, 0, NULL); if (res) Logger_Abort2(res, "Creating mutex"); return ptr; } @@ -245,8 +245,8 @@ void Mutex_Unlock(void* handle) { if (res) Logger_Abort2(res, "Unlocking mutex"); } -void* Waitable_Create(void) { - int evid = sceKernelCreateEventFlag("CC event", SCE_EVENT_WAITMULTIPLE, 0, NULL); +void* Waitable_Create(const char* name) { + int evid = sceKernelCreateEventFlag(name, SCE_EVENT_WAITMULTIPLE, 0, NULL); if (evid < 0) Logger_Abort2(evid, "Creating waitable"); return (void*)evid; } diff --git a/src/Platform_Posix.c b/src/Platform_Posix.c index 5a95592..bef2091 100644 --- a/src/Platform_Posix.c +++ b/src/Platform_Posix.c @@ -73,8 +73,9 @@ cc_bool Platform_SingleProcess; /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ -void Mem_Set(void* dst, cc_uint8 value, cc_uint32 numBytes) { memset(dst, value, numBytes); } -void Mem_Copy(void* dst, const void* src, cc_uint32 numBytes) { memcpy(dst, src, numBytes); } +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); @@ -388,7 +389,7 @@ void Thread_Join(void* handle) { Mem_Free(ptr); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { pthread_mutex_t* ptr = (pthread_mutex_t*)Mem_Alloc(1, sizeof(pthread_mutex_t), "mutex"); int res = pthread_mutex_init(ptr, NULL); if (res) Logger_Abort2(res, "Creating mutex"); @@ -417,7 +418,7 @@ struct WaitData { int signalled; /* For when Waitable_Signal is called before Waitable_Wait */ }; -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { struct WaitData* ptr = (struct WaitData*)Mem_Alloc(1, sizeof(struct WaitData), "waitable"); int res; @@ -594,15 +595,13 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next) { if (cur->ai_family != AF_INET) continue; - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; i++; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); i++; } for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next) { if (cur->ai_family == AF_INET) continue; - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; i++; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); i++; } freeaddrinfo(result); @@ -1006,27 +1005,19 @@ cc_bool Updater_Clean(void) { return true; } #elif defined CC_BUILD_LINUX #if __x86_64__ const struct UpdaterInfo Updater_Info = { - #ifndef CC_BUILD_GLMODERN - "", 1, { { "OpenGL", "ClassiCube" } } - #else - "&eModernGL is recommended for newer machines (2010 or later)", 2, + "&eModernGL is recommended for newer machines (2015 or later)", 2, { { "ModernGL", "cc-nix64-gl2" }, { "OpenGL", "ClassiCube" } } - #endif }; #elif __i386__ const struct UpdaterInfo Updater_Info = { - #ifndef CC_BUILD_GLMODERN - "", 1, { { "OpenGL", "ClassiCube.32" } } - #else - "&eModernGL is recommended for newer machines (2010 or later)", 2, + "&eModernGL is recommended for newer machines (2015 or later)", 2, { { "ModernGL", "cc-nix32-gl2" }, { "OpenGL", "ClassiCube.32" } } - #endif }; #else const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; @@ -1034,27 +1025,19 @@ cc_bool Updater_Clean(void) { return true; } #elif defined CC_BUILD_MACOS #if __x86_64__ const struct UpdaterInfo Updater_Info = { - #ifndef CC_BUILD_GLMODERN - "", 1, { { "OpenGL", "ClassiCube.64.osx" } } - #else - "&eModernGL is recommended for newer machines (2010 or later)", 2, + "&eModernGL is recommended for newer machines (2015 or later)", 2, { { "ModernGL", "cc-osx64-gl2" }, { "OpenGL", "ClassiCube.64.osx" } } - #endif }; #elif __i386__ const struct UpdaterInfo Updater_Info = { - #ifndef CC_BUILD_GLMODERN - "", 1, { { "OpenGL", "ClassiCube.osx" } } - #else - "&eModernGL is recommended for newer machines (2010 or later)", 2, + "&eModernGL is recommended for newer machines (2015 or later)", 2, { { "ModernGL", "cc-osx32-gl2" }, { "OpenGL", "ClassiCube.osx" } } - #endif }; #else const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; @@ -1065,6 +1048,20 @@ cc_bool Updater_Clean(void) { return true; } #else const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; #endif +#elif defined CC_BUILD_FREEBSD + #if __x86_64__ + const struct UpdaterInfo Updater_Info = { "", 1, { { "OpenGL", "cc-fbsd64-gl1" } } }; + #elif __i386__ + const struct UpdaterInfo Updater_Info = { "", 1, { { "OpenGL", "cc-fbsd32-gl1" } } }; + #else + const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; + #endif +#elif defined CC_BUILD_NETBSD + #if __x86_64__ + const struct UpdaterInfo Updater_Info = { "", 1, { { "OpenGL", "cc-netbsd64-gl1" } } }; + #else + const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; + #endif #else const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; #endif diff --git a/src/Platform_Saturn.c b/src/Platform_Saturn.c index a390794..e0f37d4 100644 --- a/src/Platform_Saturn.c +++ b/src/Platform_Saturn.c @@ -64,13 +64,17 @@ cc_uint64 Stopwatch_Measure(void) { cc_uint64 Stopwatch_ElapsedMicroseconds(cc_uint64 beg, cc_uint64 end) { if (end < beg) return 0; - return (end - beg); // TODO measure time + cc_uint32 delta = end - beg; + + // TODO still wrong?? and overflows?? and PAL detection ??? + return (delta * 1000) / CPU_FRT_NTSC_320_128_COUNT_1MS; } static void ovf_handler(void) { overflow_count++; } static void Stopwatch_Init(void) { - cpu_frt_init(CPU_FRT_CLOCK_DIV_8); + //cpu_frt_init(CPU_FRT_CLOCK_DIV_8); + cpu_frt_init(CPU_FRT_CLOCK_DIV_128); cpu_frt_ovi_set(ovf_handler); cpu_frt_interrupt_priority_set(15); @@ -147,7 +151,7 @@ void Thread_Detach(void* handle) { void Thread_Join(void* handle) { } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { return NULL; } @@ -160,7 +164,7 @@ void Mutex_Lock(void* handle) { void Mutex_Unlock(void* handle) { } -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { return NULL; } diff --git a/src/Platform_Switch.c b/src/Platform_Switch.c index 271e31f..ebe1cc3 100644 --- a/src/Platform_Switch.c +++ b/src/Platform_Switch.c @@ -252,7 +252,7 @@ void Thread_Join(void* handle) { Mem_Free(thread); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { Mutex* mutex = (Mutex*)Mem_Alloc(1, sizeof(Mutex), "mutex"); mutexInit(mutex); return mutex; @@ -277,7 +277,7 @@ struct WaitData { int signalled; // For when Waitable_Signal is called before Waitable_Wait }; -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { struct WaitData* ptr = (struct WaitData*)Mem_Alloc(1, sizeof(struct WaitData), "waitable"); mutexInit(&ptr->mutex); @@ -326,7 +326,7 @@ void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { } /* -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { LEvent* ptr = (LEvent*)Mem_Alloc(1, sizeof(LEvent), "waitable"); leventInit(ptr, false, true); return ptr; @@ -384,15 +384,13 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next) { if (cur->ai_family != AF_INET) continue; - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; i++; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); i++; } for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next) { if (cur->ai_family == AF_INET) continue; - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; i++; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); i++; } freeaddrinfo(result); diff --git a/src/Platform_Web.c b/src/Platform_Web.c index 2fd8627..49cf7e4 100644 --- a/src/Platform_Web.c +++ b/src/Platform_Web.c @@ -43,8 +43,9 @@ cc_bool Platform_SingleProcess; /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ -void Mem_Set(void* dst, cc_uint8 value, cc_uint32 numBytes) { memset(dst, value, numBytes); } -void Mem_Copy(void* dst, const void* src, cc_uint32 numBytes) { memcpy(dst, src, numBytes); } +void* Mem_Set(void* dst, cc_uint8 value, cc_uint32 numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, cc_uint32 numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, cc_uint32 numBytes) { return memmove(dst, src, numBytes); } void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); @@ -227,12 +228,12 @@ cc_result File_Length(cc_file file, cc_uint32* len) { /* No real threading support with emscripten backend */ void Thread_Sleep(cc_uint32 milliseconds) { } -void* Mutex_Create(void) { return NULL; } +void* Mutex_Create(const char* name) { return NULL; } void Mutex_Free(void* handle) { } void Mutex_Lock(void* handle) { } void Mutex_Unlock(void* handle) { } -void* Waitable_Create(void) { return NULL; } +void* Waitable_Create(const char* name) { return NULL; } void Waitable_Free(void* handle) { } void Waitable_Signal(void* handle) { } void Waitable_Wait(void* handle) { } diff --git a/src/Platform_WiiU.c b/src/Platform_WiiU.c index a102a97..34b753c 100644 --- a/src/Platform_WiiU.c +++ b/src/Platform_WiiU.c @@ -202,7 +202,7 @@ cc_result File_Close(cc_file file) { } cc_result File_Seek(cc_file file, int offset, int seekType) { - static cc_uint8 modes[3] = { SEEK_SET, SEEK_CUR, SEEK_END }; + static cc_uint8 modes[] = { SEEK_SET, SEEK_CUR, SEEK_END }; return lseek(file, offset, modes[seekType]) == -1 ? errno : 0; } @@ -254,10 +254,10 @@ void Thread_Join(void* handle) { OSJoinThread((OSThread*)handle, &result); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { OSFastMutex* mutex = (OSFastMutex*)Mem_Alloc(1, sizeof(OSFastMutex), "mutex"); - OSFastMutex_Init(mutex, "CC mutex"); + OSFastMutex_Init(mutex, name); return mutex; } @@ -273,7 +273,7 @@ void Mutex_Unlock(void* handle) { OSFastMutex_Unlock((OSFastMutex*)handle); } -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { OSEvent* event = (OSEvent*)Mem_Alloc(1, sizeof(OSEvent), "waitable"); OSInitEvent(event, false, OS_EVENT_MODE_AUTO); @@ -331,15 +331,13 @@ static cc_result ParseHost(const char* host, int port, cc_sockaddr* addrs, int* for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next) { if (cur->ai_family != AF_INET) continue; - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; i++; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); i++; } for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next) { if (cur->ai_family == AF_INET) continue; - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; i++; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); i++; } freeaddrinfo(result); diff --git a/src/Platform_Windows.c b/src/Platform_Windows.c index a063355..fe645f2 100644 --- a/src/Platform_Windows.c +++ b/src/Platform_Windows.c @@ -29,6 +29,9 @@ typedef struct _CRYPTOAPI_BLOB { DWORD cbData; BYTE* pbData; } DATA_BLOB; + +static BOOL (WINAPI *_CryptProtectData )(DATA_BLOB* dataIn, PCWSTR dataDescr, PVOID entropy, PVOID reserved, PVOID promptStruct, DWORD flags, DATA_BLOB* dataOut); +static BOOL (WINAPI *_CryptUnprotectData)(DATA_BLOB* dataIn, PWSTR* dataDescr, PVOID entropy, PVOID reserved, PVOID promptStruct, DWORD flags, DATA_BLOB* dataOut); /* === END wincrypt.h === */ static HANDLE heap; @@ -43,8 +46,43 @@ cc_bool Platform_SingleProcess; /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ -void Mem_Set(void* dst, cc_uint8 value, cc_uint32 numBytes) { memset(dst, value, numBytes); } -void Mem_Copy(void* dst, const void* src, cc_uint32 numBytes) { memcpy(dst, src, numBytes); } +#ifdef CC_BUILD_NOSTDLIB +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { + char* dp = (char*)dst; + + while (numBytes--) *dp++ = value; /* TODO optimise */ + return dst; +} + +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { + char* sp = (char*)src; + char* dp = (char*)dst; + + while (numBytes--) *dp++ = *sp++; /* TODO optimise */ + return dst; +} + +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { + char* sp = (char*)src; + char* dp = (char*)dst; + + /* Check if destination range overlaps source range */ + /* If this happens, then need to copy backwards */ + if (dp >= sp && dp < (sp + numBytes)) { + sp += numBytes; + dp += numBytes; + + while (numBytes--) *--dp = *--sp; + } else { + while (numBytes--) *dp++ = *sp++; + } + return dst; +} +#else +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } +#endif void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); @@ -316,7 +354,7 @@ void Thread_Join(void* handle) { Thread_Detach(handle); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { CRITICAL_SECTION* ptr = (CRITICAL_SECTION*)Mem_Alloc(1, sizeof(CRITICAL_SECTION), "mutex"); InitializeCriticalSection(ptr); return ptr; @@ -329,7 +367,7 @@ void Mutex_Free(void* handle) { void Mutex_Lock(void* handle) { EnterCriticalSection((CRITICAL_SECTION*)handle); } void Mutex_Unlock(void* handle) { LeaveCriticalSection((CRITICAL_SECTION*)handle); } -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { void* handle = CreateEventA(NULL, false, false, NULL); if (!handle) { Logger_Abort2(GetLastError(), "Creating waitable"); @@ -518,15 +556,13 @@ static cc_result ParseHostNew(char* host, int port, cc_sockaddr* addrs, int* num for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next) { if (cur->ai_family != AF_INET) continue; - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; i++; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); i++; } for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next) { if (cur->ai_family == AF_INET) continue; - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; i++; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); i++; } _freeaddrinfo(result); @@ -725,18 +761,29 @@ cc_result Process_StartOpen(const cc_string* args) { #define UPDATE_SRC TEXT(UPDATE_FILE) cc_bool Updater_Supported = true; +#if defined _M_IX86 const struct UpdaterInfo Updater_Info = { "&eDirect3D 9 is recommended", 2, { -#if _WIN64 - { "Direct3D9", "ClassiCube.64.exe" }, - { "OpenGL", "ClassiCube.64-opengl.exe" } -#else { "Direct3D9", "ClassiCube.exe" }, { "OpenGL", "ClassiCube.opengl.exe" } -#endif } }; +#elif defined _M_X64 +const struct UpdaterInfo Updater_Info = { + "&eDirect3D 9 is recommended", 2, + { + { "Direct3D9", "ClassiCube.64.exe" }, + { "OpenGL", "ClassiCube.64-opengl.exe" } + } +}; +#elif defined _M_ARM64 +const struct UpdaterInfo Updater_Info = { "", 1, { { "Direct3D11", "cc-arm64-d3d11.exe" } } }; +#elif defined _M_ARM +const struct UpdaterInfo Updater_Info = { "", 1, { { "Direct3D11", "cc-arm32-d3d11.exe" } } }; +#else +const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; +#endif cc_bool Updater_Clean(void) { return DeleteFile(UPDATE_TMP) || GetLastError() == ERROR_FILE_NOT_FOUND; @@ -953,8 +1000,6 @@ cc_bool Platform_DescribeError(cc_result res, cc_string* dst) { /*########################################################################################################################* *-------------------------------------------------------Encryption--------------------------------------------------------* *#########################################################################################################################*/ -static BOOL (WINAPI *_CryptProtectData )(DATA_BLOB* dataIn, PCWSTR dataDescr, PVOID entropy, PVOID reserved, PVOID promptStruct, DWORD flags, DATA_BLOB* dataOut); -static BOOL (WINAPI *_CryptUnprotectData)(DATA_BLOB* dataIn, PWSTR* dataDescr, PVOID entropy, PVOID reserved, PVOID promptStruct, DWORD flags, DATA_BLOB* dataOut); static void LoadCryptFuncs(void) { static const struct DynamicLibSym funcs[] = { diff --git a/src/Platform_Xbox.c b/src/Platform_Xbox.c index cea3e78..77851e3 100644 --- a/src/Platform_Xbox.c +++ b/src/Platform_Xbox.c @@ -111,7 +111,7 @@ cc_result Directory_Create(const cc_string* path) { } int File_Exists(const cc_string* path) { - if (!hdd_mounted) return ERR_NOT_SUPPORTED; + if (!hdd_mounted) return 0; char str[NATIVE_STR_LEN]; DWORD attribs; @@ -164,7 +164,7 @@ cc_result Directory_Enum(const cc_string* dirPath, void* obj, Directory_EnumCall } while (FindNextFileA(find, &eA)); res = GetLastError(); /* return code from FindNextFile */ - FindClose(find); + NtClose(find); return res == ERROR_NO_MORE_FILES ? 0 : res; } @@ -203,7 +203,8 @@ cc_result File_Write(cc_file file, const void* data, cc_uint32 count, cc_uint32* } cc_result File_Close(cc_file file) { - return CloseHandle(file) ? 0 : GetLastError(); + NTSTATUS status = NtClose(file); + return NT_SUCCESS(status) ? 0 : status; } cc_result File_Seek(cc_file file, int offset, int seekType) { @@ -225,7 +226,15 @@ cc_result File_Length(cc_file file, cc_uint32* len) { /*########################################################################################################################* *--------------------------------------------------------Threading--------------------------------------------------------* -*#############################################################################################################p############*/ +*##########################################################################################################################*/ +static void WaitForSignal(HANDLE handle, LARGE_INTEGER* duration) { + for (;;) + { + NTSTATUS status = NtWaitForSingleObjectEx((HANDLE)handle, UserMode, FALSE, duration); + if (status != STATUS_ALERTED) break; + } +} + void Thread_Sleep(cc_uint32 milliseconds) { Sleep(milliseconds); } static DWORD WINAPI ExecThread(void* param) { Thread_StartFunc func = (Thread_StartFunc)param; @@ -243,17 +252,16 @@ void Thread_Run(void** handle, Thread_StartFunc func, int stackSize, const char* } void Thread_Detach(void* handle) { - if (!CloseHandle((HANDLE)handle)) { - Logger_Abort2(GetLastError(), "Freeing thread handle"); - } + NTSTATUS status = NtClose((HANDLE)handle); + if (!NT_SUCCESS(status)) Logger_Abort2(status, "Freeing thread handle"); } void Thread_Join(void* handle) { - WaitForSingleObject((HANDLE)handle, INFINITE); + WaitForSignal((HANDLE)handle, NULL); Thread_Detach(handle); } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { CRITICAL_SECTION* ptr = (CRITICAL_SECTION*)Mem_Alloc(1, sizeof(CRITICAL_SECTION), "mutex"); RtlInitializeCriticalSection(ptr); return ptr; @@ -263,30 +271,41 @@ void Mutex_Free(void* handle) { RtlDeleteCriticalSection((CRITICAL_SECTION*)handle); Mem_Free(handle); } -void Mutex_Lock(void* handle) { RtlEnterCriticalSection((CRITICAL_SECTION*)handle); } -void Mutex_Unlock(void* handle) { RtlLeaveCriticalSection((CRITICAL_SECTION*)handle); } -void* Waitable_Create(void) { - void* handle = CreateEventA(NULL, false, false, NULL); - if (!handle) { - Logger_Abort2(GetLastError(), "Creating waitable"); - } +void Mutex_Lock(void* handle) { + RtlEnterCriticalSection((CRITICAL_SECTION*)handle); +} + +void Mutex_Unlock(void* handle) { + RtlLeaveCriticalSection((CRITICAL_SECTION*)handle); +} + +void* Waitable_Create(const char* name) { + HANDLE handle; + NTSTATUS status = NtCreateEvent(&handle, NULL, SynchronizationEvent, false); + + if (!NT_SUCCESS(status)) Logger_Abort2(status, "Creating waitable"); return handle; } void Waitable_Free(void* handle) { - if (!CloseHandle((HANDLE)handle)) { - Logger_Abort2(GetLastError(), "Freeing waitable"); - } + NTSTATUS status = NtClose((HANDLE)handle); + if (!NT_SUCCESS(status)) Logger_Abort2(status, "Freeing waitable"); +} + +void Waitable_Signal(void* handle) { + NtSetEvent((HANDLE)handle, NULL); } -void Waitable_Signal(void* handle) { NtSetEvent((HANDLE)handle, NULL); } void Waitable_Wait(void* handle) { - WaitForSingleObject((HANDLE)handle, INFINITE); + WaitForSignal((HANDLE)handle, NULL); } void Waitable_WaitFor(void* handle, cc_uint32 milliseconds) { - WaitForSingleObject((HANDLE)handle, milliseconds); + LARGE_INTEGER duration; + duration.QuadPart = ((LONGLONG)milliseconds) * -10000; // negative for relative timeout + + WaitForSignal((HANDLE)handle, &duration); } @@ -317,8 +336,7 @@ cc_result Socket_ParseAddress(const cc_string* address, int port, cc_sockaddr* a for (cur = result; cur && i < SOCKET_MAX_ADDRS; cur = cur->ai_next, i++) { - Mem_Copy(addrs[i].data, cur->ai_addr, cur->ai_addrlen); - addrs[i].size = cur->ai_addrlen; + SocketAddr_Set(&addrs[i], cur->ai_addr, cur->ai_addrlen); } lwip_freeaddrinfo(result); @@ -397,18 +415,20 @@ static void InitHDD(void) { } else { hdd_mounted = nxMountDrive('E', "\\Device\\Harddisk0\\Partition1\\"); } - - if (!hdd_mounted) { - Platform_LogConst("Failed to mount E:/ from Data partition"); - return; - } - Directory_Create(&String_Empty); // create root ClassiCube folder + + if (!hdd_mounted) { + Platform_LogConst("Failed to mount E:/ from Data partition"); + return; + } + Directory_Create(&String_Empty); // create root ClassiCube folder } void Platform_Init(void) { InitHDD(); Stopwatch_Init(); +#ifndef CC_BUILD_CXBX nxNetInit(NULL); +#endif } void Platform_Free(void) { diff --git a/src/Platform_Xbox360.c b/src/Platform_Xbox360.c index 0bd3e6e..0eaf831 100644 --- a/src/Platform_Xbox360.c +++ b/src/Platform_Xbox360.c @@ -205,7 +205,7 @@ void Thread_Detach(void* handle) {// TODO void Thread_Join(void* handle) {// TODO } -void* Mutex_Create(void) { +void* Mutex_Create(const char* name) { return Mem_AllocCleared(1, sizeof(int), "mutex"); } @@ -215,7 +215,7 @@ void Mutex_Free(void* handle) { void Mutex_Lock(void* handle) { } // TODO void Mutex_Unlock(void* handle) { } // TODO -void* Waitable_Create(void) { +void* Waitable_Create(const char* name) { return NULL; // TODO } diff --git a/src/Protocol.c b/src/Protocol.c index 084325b..31324f5 100644 --- a/src/Protocol.c +++ b/src/Protocol.c @@ -88,6 +88,7 @@ static struct CpeExt customModels_Ext = { "CustomModels", 2 }, pluginMessages_Ext = { "PluginMessages", 1 }, extTeleport_Ext = { "ExtEntityTeleport", 1 }, + lightingMode_Ext = { "LightingMode", 1 }, extTextures_Ext = { "ExtendedTextures", 1 }, extBlocks_Ext = { "ExtendedBlocks", 1 }; @@ -97,7 +98,7 @@ static struct CpeExt* cpe_clientExtensions[] = { &messageTypes_Ext, &hackControl_Ext, &playerClick_Ext, &fullCP437_Ext, &longerMessages_Ext, &blockDefs_Ext, &blockDefsExt_Ext, &bulkBlockUpdate_Ext, &textColors_Ext, &envMapAspect_Ext, &entityProperty_Ext, &extEntityPos_Ext, &twoWayPing_Ext, &invOrder_Ext, &instantMOTD_Ext, &fastMap_Ext, &setHotbar_Ext, &setSpawnpoint_Ext, &velControl_Ext, - &customParticles_Ext, &pluginMessages_Ext, &extTeleport_Ext, + &customParticles_Ext, &pluginMessages_Ext, &extTeleport_Ext, &lightingMode_Ext, #ifdef CUSTOM_MODELS &customModels_Ext, #endif @@ -1155,17 +1156,21 @@ static void CPE_SetEnvCol(cc_uint8* data) { c = PackedCol_Make(data[2], data[4], data[6], 255); if (variable == 0) { - Env_SetSkyCol(invalid ? ENV_DEFAULT_SKY_COLOR : c); - } else if (variable == 1) { - Env_SetCloudsCol(invalid ? ENV_DEFAULT_CLOUDS_COLOR : c); - } else if (variable == 2) { - Env_SetFogCol(invalid ? ENV_DEFAULT_FOG_COLOR : c); - } else if (variable == 3) { - Env_SetShadowCol(invalid ? ENV_DEFAULT_SHADOW_COLOR : c); - } else if (variable == 4) { - Env_SetSunCol(invalid ? ENV_DEFAULT_SUN_COLOR : c); - } else if (variable == 5) { - Env_SetSkyboxCol(invalid ? ENV_DEFAULT_SKYBOX_COLOR : c); + Env_SetSkyCol(invalid ? ENV_DEFAULT_SKY_COLOR : c); + } else if (variable == 1) { + Env_SetCloudsCol(invalid ? ENV_DEFAULT_CLOUDS_COLOR : c); + } else if (variable == 2) { + Env_SetFogCol(invalid ? ENV_DEFAULT_FOG_COLOR : c); + } else if (variable == 3) { + Env_SetShadowCol(invalid ? ENV_DEFAULT_SHADOW_COLOR : c); + } else if (variable == 4) { + Env_SetSunCol(invalid ? ENV_DEFAULT_SUN_COLOR : c); + } else if (variable == 5) { + Env_SetSkyboxCol(invalid ? ENV_DEFAULT_SKYBOX_COLOR : c); + } else if (variable == 6) { + Env_SetLavaLightCol(invalid ? ENV_DEFAULT_LAVALIGHT_COLOR : c); + } else if (variable == 7) { + Env_SetLampLightCol(invalid ? ENV_DEFAULT_LAMPLIGHT_COLOR : c); } } @@ -1526,6 +1531,30 @@ static void CPE_ExtEntityTeleport(cc_uint8* data) { Classic_ReadAbsoluteLocation(data, id, flags); } +static void CPE_LightingMode(cc_uint8* data) { + cc_uint8 mode = *data++; + cc_bool locked = *data++ != 0; + + if (mode == 0) { + if (!Lighting_ModeSetByServer) return; + /* locked is ignored with mode 0 and always set to false */ + Lighting_ModeLockedByServer = false; + Lighting_ModeSetByServer = false; + + Lighting_SetMode(Lighting_ModeUserCached, true); + return; + } + /* Convert from Network mode (0 = no change, 1 = classic, 2 = fancy) to client mode (0 = classic, 1 = fancy) */ + mode--; + if (mode >= LIGHTING_MODE_COUNT) return; + + if (!Lighting_ModeSetByServer) Lighting_ModeUserCached = Lighting_Mode; + Lighting_ModeLockedByServer = locked; + Lighting_ModeSetByServer = true; + + Lighting_SetMode(mode, true); +} + static void CPE_Reset(void) { cpe_serverExtensionsCount = 0; cpe_pingTicks = 0; CPEExtensions_Reset(); @@ -1568,6 +1597,7 @@ static void CPE_Reset(void) { Net_Set(OPCODE_SPAWN_EFFECT, CPE_SpawnEffect, 26); Net_Set(OPCODE_PLUGIN_MESSAGE, CPE_PluginMessage, 66); Net_Set(OPCODE_ENTITY_TELEPORT_EXT, CPE_ExtEntityTeleport, 11); + Net_Set(OPCODE_LIGHTING_MODE, CPE_LightingMode, 3); } static cc_uint8* CPE_Tick(cc_uint8* data) { @@ -1584,13 +1614,12 @@ static cc_uint8* CPE_Tick(cc_uint8* data) { *------------------------------------------------------Custom models------------------------------------------------------* *#########################################################################################################################*/ static void CPE_DefineModel(cc_uint8* data) { - cc_uint8 id = data[0]; - struct CustomModel* cm = &custom_models[id]; + struct CustomModel* cm = CustomModel_Get(data[0]); cc_string name; cc_uint8 flags; cc_uint8 numParts; - if (id >= MAX_CUSTOM_MODELS) return; + if (!cm) return; CustomModel_Undefine(cm); Model_Init(&cm->model); @@ -1635,13 +1664,13 @@ static void CPE_DefineModel(cc_uint8* data) { } static void CPE_DefineModelPart(cc_uint8* data) { - cc_uint8 id = data[0]; - struct CustomModel* m = &custom_models[id]; + struct CustomModel* m; struct CustomModelPart* part; struct CustomModelPartDef p; int i; - if (id >= MAX_CUSTOM_MODELS || !m->defined || m->curPartIndex >= m->numParts) return; + m = CustomModel_Get(data[0]); + if (!m || !m->defined || m->curPartIndex >= m->numParts) return; part = &m->parts[m->curPartIndex]; p.min.x = GetFloat(data + 1); @@ -1652,7 +1681,8 @@ static void CPE_DefineModelPart(cc_uint8* data) { p.max.z = GetFloat(data + 21); /* read u, v coords for our 6 faces */ - for (i = 0; i < 6; i++) { + for (i = 0; i < 6; i++) + { p.u1[i] = Stream_GetU16_BE(data + 25 + (i*8 + 0)); p.v1[i] = Stream_GetU16_BE(data + 25 + (i*8 + 2)); p.u2[i] = Stream_GetU16_BE(data + 25 + (i*8 + 4)); @@ -1674,7 +1704,8 @@ static void CPE_DefineModelPart(cc_uint8* data) { p.flags = data[165]; data += 97; - for (i = 0; i < MAX_CUSTOM_MODEL_ANIMS; i++) { + for (i = 0; i < MAX_CUSTOM_MODEL_ANIMS; i++) + { cc_uint8 tmp = *data++; part->anims[i].type = tmp & 0x3F; part->anims[i].axis = tmp >> 6; @@ -1695,10 +1726,9 @@ static void CPE_DefineModelPart(cc_uint8* data) { if (m->curPartIndex == m->numParts) CustomModel_Register(m); } -/* unregisters and frees the custom model */ static void CPE_UndefineModel(cc_uint8* data) { - cc_uint8 id = data[0]; - if (id < MAX_CUSTOM_MODELS) CustomModel_Undefine(&custom_models[id]); + struct CustomModel* cm = CustomModel_Get(data[0]); + if (cm) CustomModel_Undefine(cm); } static void CustomModels_Reset(void) { @@ -1716,10 +1746,17 @@ static void CustomModels_Reset(void) { } /*########################################################################################################################* *------------------------------------------------------Custom blocks------------------------------------------------------* *#########################################################################################################################*/ -static void BlockDefs_OnBlockUpdated(BlockID block, cc_bool didBlockLight) { +static void BlockDefs_OnBlocksLightPropertyUpdated(BlockID block, cc_bool oldProp) { if (!World.Loaded) return; /* Need to refresh lighting when a block's light blocking state changes */ - if (Blocks.BlocksLight[block] != didBlockLight) Lighting.Refresh(); + if (Blocks.BlocksLight[block] != oldProp) Lighting.Refresh(); +} + +static void BlockDefs_OnBrightnessPropertyUpdated(BlockID block, cc_uint8 oldProp) { + if (!World.Loaded) return; + if (Lighting_Mode == LIGHTING_MODE_CLASSIC) return; + /* Need to refresh fancy lighting when a block's brightness changes */ + if (Blocks.Brightness[block] != oldProp) Lighting.Refresh(); } static TextureLoc BlockDefs_Tex(cc_uint8** ptr) { @@ -1738,13 +1775,15 @@ static TextureLoc BlockDefs_Tex(cc_uint8** ptr) { static BlockID BlockDefs_DefineBlockCommonStart(cc_uint8** ptr, cc_bool uniqueSideTexs) { cc_string name; BlockID block; - cc_bool didBlockLight; + cc_bool oldBlocksLight; + cc_uint8 oldBrightness; float speedLog2; cc_uint8 sound; cc_uint8* data = *ptr; ReadBlock(data, block); - didBlockLight = Blocks.BlocksLight[block]; + oldBlocksLight = Blocks.BlocksLight[block]; + oldBrightness = Blocks.Brightness[block]; Block_ResetProps(block); name = UNSAFE_GetString(data); data += STRING_SIZE; @@ -1766,14 +1805,15 @@ static BlockID BlockDefs_DefineBlockCommonStart(cc_uint8** ptr, cc_bool uniqueSi Block_Tex(block, FACE_YMIN) = BlockDefs_Tex(&data); Blocks.BlocksLight[block] = *data++ == 0; - BlockDefs_OnBlockUpdated(block, didBlockLight); + BlockDefs_OnBlocksLightPropertyUpdated(block, oldBlocksLight); sound = *data++; Blocks.StepSounds[block] = sound; Blocks.DigSounds[block] = sound; if (sound == SOUND_GLASS) Blocks.StepSounds[block] = SOUND_STONE; - Blocks.FullBright[block] = *data++ != 0; + Blocks.Brightness[block] = Block_ReadBrightness(*data++); + BlockDefs_OnBrightnessPropertyUpdated(block, oldBrightness); *ptr = data; return block; } @@ -1810,7 +1850,7 @@ static void BlockDefs_UndefineBlock(cc_uint8* data) { didBlockLight = Blocks.BlocksLight[block]; Block_UndefineCustom(block); - BlockDefs_OnBlockUpdated(block, didBlockLight); + BlockDefs_OnBlocksLightPropertyUpdated(block, didBlockLight); } static void BlockDefs_DefineBlockExt(cc_uint8* data) { diff --git a/src/Protocol.h b/src/Protocol.h index a27fe80..4141fb6 100644 --- a/src/Protocol.h +++ b/src/Protocol.h @@ -37,6 +37,7 @@ enum OPCODE_ { OPCODE_DEFINE_EFFECT, OPCODE_SPAWN_EFFECT, OPCODE_DEFINE_MODEL, OPCODE_DEFINE_MODEL_PART, OPCODE_UNDEFINE_MODEL, OPCODE_PLUGIN_MESSAGE, OPCODE_ENTITY_TELEPORT_EXT, + OPCODE_LIGHTING_MODE, OPCODE_COUNT }; diff --git a/src/Queue.c b/src/Queue.c new file mode 100644 index 0000000..a363faf --- /dev/null +++ b/src/Queue.c @@ -0,0 +1,72 @@ +#include "Core.h" +#include "Constants.h" +#include "Chat.h" +#include "Platform.h" +#include "Queue.h" + +void Queue_Init(struct Queue* queue, cc_uint32 structSize) { + queue->entries = NULL; + queue->structSize = structSize; + queue->capacity = 0; + queue->mask = 0; + queue->count = 0; + queue->head = 0; + queue->tail = 0; +} + +void Queue_Clear(struct Queue* queue) { + if (!queue->entries) return; + Mem_Free(queue->entries); + Queue_Init(queue, queue->structSize); +} + +static void Queue_Resize(struct Queue* queue) { + cc_uint8* entries; + int capacity, headToEndSize, byteOffsetToHead; + + if (queue->capacity >= (Int32_MaxValue / 4)) { + Chat_AddRaw("&cToo many generic queue entries, clearing"); + Queue_Clear(queue); + return; + } + capacity = queue->capacity * 2; + if (capacity < 32) capacity = 32; + entries = (cc_uint8*)Mem_Alloc(capacity, queue->structSize, "Generic queue"); + + /* Elements must be readjusted to avoid index wrapping issues */ + headToEndSize = (queue->capacity - queue->head) * queue->structSize; + byteOffsetToHead = queue->head * queue->structSize; + /* Copy from head to end */ + Mem_Copy(entries, queue->entries + byteOffsetToHead, headToEndSize); + if (queue->head != 0) { + /* If there's any leftover before the head, copy that bit too */ + Mem_Copy(entries + headToEndSize, queue->entries, byteOffsetToHead); + } + + Mem_Free(queue->entries); + + queue->entries = entries; + queue->capacity = capacity; + queue->mask = capacity - 1; /* capacity is power of two */ + queue->head = 0; + queue->tail = queue->count; +} + +/* Appends an entry to the end of the queue, resizing if necessary. */ +void Queue_Enqueue(struct Queue* queue, void* item) { + if (queue->count == queue->capacity) + Queue_Resize(queue); + + //queue->entries[queue->tail] = item; + Mem_Copy(queue->entries + queue->tail * queue->structSize, item, queue->structSize); + queue->tail = (queue->tail + 1) & queue->mask; + queue->count++; +} + +/* Retrieves the entry from the front of the queue. */ +void* Queue_Dequeue(struct Queue* queue) { + void* result = queue->entries + queue->head * queue->structSize; + queue->head = (queue->head + 1) & queue->mask; + queue->count--; + return result; +} \ No newline at end of file diff --git a/src/Queue.h b/src/Queue.h new file mode 100644 index 0000000..f62c941 --- /dev/null +++ b/src/Queue.h @@ -0,0 +1,22 @@ +#include "Core.h" + +#ifndef CC_QUEUE_H +#define CC_QUEUE_H + +struct Queue { + cc_uint8* entries; /* Buffer holding the bytes of the queue */ + int structSize; /* Size in bytes of the type of structure this queue holds */ + int capacity; /* Max number of elements in the buffer */ + int mask; /* capacity - 1, as capacity is always a power of two */ + int count; /* Number of used elements */ + int head; /* Head index into the buffer */ + int tail; /* Tail index into the buffer */ +}; +void Queue_Init(struct Queue* queue, cc_uint32 structSize); +/* Appends an entry to the end of the queue, resizing if necessary. */ +void Queue_Enqueue(struct Queue* queue, void* item); +/* Retrieves the entry from the front of the queue. */ +void* Queue_Dequeue(struct Queue* queue); +/* Frees the memory of the queue and resets the members to 0. */ +void Queue_Clear(struct Queue* queue); +#endif \ No newline at end of file diff --git a/src/SSL.c b/src/SSL.c index cb6d641..be43f5f 100644 --- a/src/SSL.c +++ b/src/SSL.c @@ -194,7 +194,7 @@ static SECURITY_STATUS SSL_Negotiate(struct SSLContext* ctx) { /* SChannel didn't process the entirety of the input buffer */ /* So move the leftover data back to the front of the input buffer */ leftover_len = in_buffers[1].cbBuffer; - memmove(ctx->incoming, ctx->incoming + (ctx->bufferLen - leftover_len), leftover_len); + Mem_Move(ctx->incoming, ctx->incoming + (ctx->bufferLen - leftover_len), leftover_len); ctx->bufferLen = leftover_len; } else if (sec != SEC_E_INCOMPLETE_MESSAGE) { /* SChannel processed entirely of input buffer */ @@ -279,7 +279,7 @@ static cc_result SSL_ReadDecrypted(struct SSLContext* ctx, cc_uint8* data, cc_ui /* incoming buffer stores decrypted data and then any leftover ciphertext */ /* So move the leftover ciphertext back to the start of the input buffer */ /* TODO: Share function with handshake function */ - memmove(ctx->incoming, ctx->incoming + (ctx->bufferLen - ctx->leftover), ctx->leftover); + Mem_Move(ctx->incoming, ctx->incoming + (ctx->bufferLen - ctx->leftover), ctx->leftover); ctx->bufferLen = ctx->leftover; ctx->leftover = 0; diff --git a/src/Screens.c b/src/Screens.c index af7a715..2e12b05 100644 --- a/src/Screens.c +++ b/src/Screens.c @@ -258,7 +258,7 @@ static void HUDScreen_InputUp(void* screen, int key) { static int HUDscreen_PointerDown(void* screen, int id, int x, int y) { struct HUDScreen* s = (struct HUDScreen*)screen; - if (Gui.TouchUI || Gui.InputGrab) { + if (Gui_TouchUI || Gui.InputGrab) { return Elem_HandlesPointerDown(&s->hotbar, id, x, y); } return false; @@ -266,13 +266,13 @@ static int HUDscreen_PointerDown(void* screen, int id, int x, int y) { static void HUDScreen_PointerUp(void *screen, int id, int x, int y) { struct HUDScreen* s = (struct HUDScreen*)screen; - if(!Gui.TouchUI) return; + if (!Gui_TouchUI) return; Elem_OnPointerUp(&s->hotbar, id, x, y); } static int HUDScreen_PointerMove(void *screen, int id, int x, int y) { struct HUDScreen* s = (struct HUDScreen*)screen; - if(!Gui.TouchUI) return false; + if (!Gui_TouchUI) return false; return Elem_HandlesPointerMove(&s->hotbar, id, x, y); } @@ -753,7 +753,7 @@ static int TabListOverlay_PointerDown(void* screen, int id, int x, int y) { static void TabListOverlay_KeyUp(void* screen, int key) { struct TabListOverlay* s = (struct TabListOverlay*)screen; - if (!KeyBind_Claims(KEYBIND_TABLIST, key) || s->staysOpen) return; + if (!InputBind_Claims(BIND_TABLIST, key) || s->staysOpen) return; Gui_Remove((struct Screen*)s); } @@ -1313,10 +1313,10 @@ static int ChatScreen_TextChanged(void* screen, const cc_string* str) { static int ChatScreen_KeyDown(void* screen, int key) { static const cc_string slash = String_FromConst("/"); struct ChatScreen* s = (struct ChatScreen*)screen; - int playerListKey = KeyBinds_Normal[KEYBIND_TABLIST]; + int playerListKey = KeyBind_Mappings[BIND_TABLIST].button1; cc_bool handlesList = playerListKey != CCKEY_TAB || !Gui.TabAutocomplete || !s->grabsInput; - if (KeyBind_Claims(KEYBIND_TABLIST, key) && handlesList) { + if (InputBind_Claims(BIND_TABLIST, key) && handlesList) { if (!tablist_active && !Server.IsSinglePlayer) { TabListOverlay_Show(false); } @@ -1328,27 +1328,31 @@ static int ChatScreen_KeyDown(void* screen, int key) { if (s->grabsInput) { #ifdef CC_BUILD_WEB /* See reason for this in HandleInputUp */ - if (KeyBind_Claims(KEYBIND_SEND_CHAT, key) || key == CCKEY_KP_ENTER) { + if (InputBind_Claims(BIND_SEND_CHAT, key) || key == CCKEY_KP_ENTER) { ChatScreen_EnterChatInput(s, false); #else - if (KeyBind_Claims(KEYBIND_SEND_CHAT, key) || key == CCKEY_KP_ENTER || Input_IsEscapeButton(key)) { + if (InputBind_Claims(BIND_SEND_CHAT, key) || key == CCKEY_KP_ENTER || Input_IsEscapeButton(key)) { ChatScreen_EnterChatInput(s, Input_IsEscapeButton(key)); #endif } else if (key == CCKEY_PAGEUP) { ChatScreen_ScrollChatBy(s, -Gui.Chatlines); } else if (key == CCKEY_PAGEDOWN) { ChatScreen_ScrollChatBy(s, +Gui.Chatlines); + } else if (key == CCWHEEL_UP) { + ChatScreen_ScrollChatBy(s, -1); + } else if (key == CCWHEEL_DOWN) { + ChatScreen_ScrollChatBy(s, +1); } else { Elem_HandlesKeyDown(&s->input.base, key); } return key < CCKEY_F1 || key > CCKEY_F24; } - if (KeyBind_Claims(KEYBIND_CHAT, key)) { + if (InputBind_Claims(BIND_CHAT, key)) { ChatScreen_OpenInput(&String_Empty); } else if (key == CCKEY_SLASH) { ChatScreen_OpenInput(&slash); - } else if (KeyBind_Claims(KEYBIND_INVENTORY, key)) { + } else if (InputBind_Claims(BIND_INVENTORY, key)) { InventoryScreen_Show(); } else { return false; @@ -1370,7 +1374,7 @@ static void ChatScreen_KeyUp(void* screen, int key) { if (key == CCKEY_ESCAPE) ChatScreen_EnterChatInput(s, true); #endif - if (Server.SupportsFullCP437 && KeyBind_Claims(KEYBIND_EXT_INPUT, key)) { + if (Server.SupportsFullCP437 && InputBind_Claims(BIND_EXT_INPUT, key)) { if (!Window_Main.Focused) return; ChatScreen_ToggleAltInput(s); } @@ -1378,12 +1382,7 @@ static void ChatScreen_KeyUp(void* screen, int key) { static int ChatScreen_MouseScroll(void* screen, float delta) { struct ChatScreen* s = (struct ChatScreen*)screen; - int steps; - if (!s->grabsInput) return false; - - steps = Utils_AccumulateWheelDelta(&s->chatAcc, delta); - ChatScreen_ScrollChatBy(s, -steps); - return true; + return s->grabsInput; } static int ChatScreen_PointerDown(void* screen, int id, int x, int y) { @@ -1393,7 +1392,7 @@ static int ChatScreen_PointerDown(void* screen, int id, int x, int y) { if (Game_HideGui) return false; if (!s->grabsInput) { - if (!Gui.TouchUI) return false; + if (!Gui_TouchUI) return false; String_InitArray(text, textBuffer); /* Should be able to click on links with touch */ @@ -1719,7 +1718,7 @@ static int InventoryScreen_KeyDown(void* screen, int key) { struct TableWidget* table = &s->table; /* Accuracy: Original classic doesn't close inventory menu when B is pressed */ - if (KeyBind_Claims(KEYBIND_INVENTORY, key) && s->releasedInv && !Game_ClassicMode) { + if (InputBind_Claims(BIND_INVENTORY, key) && s->releasedInv && !Game_ClassicMode) { Gui_Remove((struct Screen*)s); } else if (Input_IsEnterButton(key) && table->selectedIndex != -1) { Inventory_SetSelectedBlock(table->blocks[table->selectedIndex]); @@ -1739,7 +1738,7 @@ static cc_bool InventoryScreen_IsHotbarActive(void) { static void InventoryScreen_KeyUp(void* screen, int key) { struct InventoryScreen* s = (struct InventoryScreen*)screen; - if (KeyBind_Claims(KEYBIND_INVENTORY, key)) s->releasedInv = true; + if (InputBind_Claims(BIND_INVENTORY, key)) s->releasedInv = true; } static int InventoryScreen_PointerDown(void* screen, int id, int x, int y) { diff --git a/src/Server.c b/src/Server.c index 1a898eb..27a8383 100644 --- a/src/Server.c +++ b/src/Server.c @@ -119,6 +119,7 @@ cc_string SP_AutoloadMap = String_FromArray(autoloadBuffer); static void SPConnection_BeginConnect(void) { static const cc_string logName = String_FromConst("Singleplayer"); RNGState rnd; + int horSize, verSize; Chat_SetLogName(&logName); Game_UseCPEBlocks = Game_Version.HasCPE; @@ -130,13 +131,17 @@ static void SPConnection_BeginConnect(void) { Random_SeedFromCurrentTime(&rnd); World_NewMap(); -#if defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN - World_SetDimensions(16, 16, 16); +#if defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN || defined CC_BUILD_MACCLASSIC + horSize = 16; + verSize = 16; #elif defined CC_BUILD_LOWMEM - World_SetDimensions(64, 64, 64); + horSize = 64; + verSize = 64; #else - World_SetDimensions(128, 64, 128); + horSize = Game_ClassicMode ? 256 : 128; + verSize = 64; #endif + World_SetDimensions(horSize, verSize, horSize); #if defined CC_BUILD_N64 || defined CC_BUILD_NDS || defined CC_BUILD_PS1 || defined CC_BUILD_SATURN Gen_Active = &FlatgrassGen; diff --git a/src/SystemFonts.c b/src/SystemFonts.c index 8df4df3..2add903 100644 --- a/src/SystemFonts.c +++ b/src/SystemFonts.c @@ -258,6 +258,120 @@ void FallbackFont_DrawText(struct DrawTextArgs* args, struct Bitmap* bmp, int x, #include "freetype/ftmodapi.h" #include "freetype/ftglyph.h" +int cc_strncmp(const char* strA, const char* strB, size_t maxCount) { + const unsigned char* a = (const unsigned char*)strA; + const unsigned char* b = (const unsigned char*)strB; + int i; + + for (i = 0; a[i] && i < maxCount; i++) + { + if (a[i] != b[i]) return a[i] - b[i]; + } + return 0; +} + +int cc_strcmp(const char* strA, const char* strB) { + const unsigned char* a = (const unsigned char*)strA; + const unsigned char* b = (const unsigned char*)strB; + int i; + + for (i = 0; a[i]; i++) + { + if (a[i] != b[i]) return a[i] - b[i]; + } + return 0; +} + +size_t cc_strlen(const char* a) { + int i = 0; + while (*a++) i++; + return i; +} + +char* cc_strstr(const char* str, const char* substr) { + if (!substr[0]) return (char*)str; + + for (; *str; str++) + { + /* Definitely not a match */ + if (*str != substr[0]) continue; + + /* It's a possible match */ + if (cc_strcmp(str, substr) == 0) return (char*)str; + } + return NULL; +} + +int cc_memcmp(const void* ptrA, const void* ptrB, size_t num) { + const unsigned char* a = (const unsigned char*)ptrA; + const unsigned char* b = (const unsigned char*)ptrB; + + for (; num > 0; num--, a++, b++) + { + if (*a != *b) return *a - *b; + } + return 0; +} + +void* cc_memchr(const void* ptr, int ch, size_t num) { + const char* a = (const char*)ptr; + + for (; num > 0; num--, a++) + { + if (*a == ch) return (void*)a; + } + return NULL; +} + +static void swap(void* v1, void* v2, int size) { + char buffer[1024]; + + Mem_Copy(buffer, v1, size); + Mem_Copy(v1, v2, size); + Mem_Copy(v2, buffer, size); +} + +// https://www.geeksforgeeks.org/generic-implementation-of-quicksort-algorithm-in-c/ +static void _qsort(void* v, int size, int left, int right, + int (*comp)(const void*, const void*)) { + void* ptrL; + void* ptrM; + void* ptrI; + void* ptrE; + int i, last, mid; + + if (left >= right) return; + mid = (left + right) / 2; + + ptrL = (char*)v + (left * size); + ptrM = (char*)v + (mid * size); + swap(ptrL, ptrM, size); + last = left; + + for (i = left + 1; i <= right; i++) + { + ptrI = (char*)v + (i * size); + if ((*comp)(ptrL, ptrI) > 0) { + last++; + ptrE = (char*)v + (last * size); + swap(ptrI, ptrE, size); + } + } + + ptrE = (char*)v + (last * size); + swap(ptrL, ptrE, size); + _qsort(v, size, left, last - 1, comp); + _qsort(v, size, last + 1, right, comp); +} + +void cc_qsort(void* v, size_t count, size_t size, + int (*comp)(const void*, const void*)) { + if (!count) return; + _qsort(v, 0, count - 1, size, comp); +} + + + static FT_Library ft_lib; static struct FT_MemoryRec_ ft_mem; static struct StringsBuffer font_list; @@ -271,7 +385,7 @@ struct SysFont { FT_StreamRec stream; cc_uint8 buffer[8192]; /* small buffer to minimise disk I/O */ cc_uint16 widths[256]; /* cached width of each character glyph */ - FT_BitmapGlyph glyphs[256]; /* cached glyphs */ + FT_BitmapGlyph glyphs[256]; /* cached glyphs */ FT_BitmapGlyph shadow_glyphs[256]; /* cached glyphs (for back layer shadow) */ #ifdef CC_BUILD_DARWIN char filename[FILENAME_SIZE + 1]; @@ -367,8 +481,8 @@ static void* FT_ReallocWrapper(FT_Memory memory, long cur_size, long new_size, v #define FONT_CACHE_FILE "fontscache.txt" static cc_string font_candidates[] = { - String_FromConst(""), /* replaced with font_default */ - String_FromConst("Arial"), /* preferred font on all platforms */ + String_FromConst(""), /* replaced with font_default */ + String_FromConst("Arial"), /* preferred font on all platforms */ String_FromConst("Liberation Sans"), /* Nice looking fallbacks for linux */ String_FromConst("Nimbus Sans"), String_FromConst("Bitstream Charter"), @@ -810,7 +924,7 @@ void SysFont_DrawText(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int int ul_thick = FT_MulFix(face->underline_thickness, face->size->metrics.y_scale); int ulHeight = TEXT_CEIL(ul_thick); - int ulY = height + TEXT_CEIL(ul_pos); + int ulY = height + TEXT_CEIL(ul_pos); Drawer2D_Fill(bmp, begX, ulY + y, x - begX, ulHeight, color); } @@ -930,31 +1044,31 @@ cc_result SysFonts_Register(const cc_string* path, SysFont_RegisterCallback call } const cc_string* SysFonts_UNSAFE_GetDefault(void) { - return &String_Empty; + return &String_Empty; } void SysFonts_GetNames(struct StringsBuffer* buffer) { - interop_GetFontNames(buffer); + interop_GetFontNames(buffer); } cc_result SysFont_Make(struct FontDesc* desc, const cc_string* fontName, int size, int flags) { - return interop_SysFontMake(desc, fontName, size, flags); + return interop_SysFontMake(desc, fontName, size, flags); } void SysFont_MakeDefault(struct FontDesc* desc, int size, int flags) { - interop_SysMakeDefault(desc, size, flags); + interop_SysMakeDefault(desc, size, flags); } void SysFont_Free(struct FontDesc* desc) { - interop_SysFontFree(desc->handle); + interop_SysFontFree(desc->handle); } int SysFont_TextWidth(struct DrawTextArgs* args) { - return interop_SysTextWidth(args); + return interop_SysTextWidth(args); } void SysFont_DrawText(struct DrawTextArgs* args, struct Bitmap* bmp, int x, int y, cc_bool shadow) { - interop_SysTextDraw(args, bmp, x, y, shadow); + interop_SysTextDraw(args, bmp, x, y, shadow); } #else void SysFonts_SaveCache(void) { } diff --git a/src/TouchUI.c b/src/TouchUI.c index a6ae410..3dab6ab 100644 --- a/src/TouchUI.c +++ b/src/TouchUI.c @@ -553,7 +553,7 @@ static void TouchScreen_BindClick(void* screen, void* widget) { struct ButtonWidget* btn = (struct ButtonWidget*)widget; int i = btn->meta.val; - Input_Set(KeyBinds_Normal[s->descs[i].bind], true); + Input_Set(KeyBind_Mappings[s->descs[i].bind].button1, true); } static const struct TouchButtonDesc onscreenDescs[ONSCREEN_MAX_BTNS] = { @@ -572,11 +572,11 @@ static const struct TouchButtonDesc onscreenDescs[ONSCREEN_MAX_BTNS] = { { "Hotbar", 0,0,0, TouchScreen_SwitchClick } }; static const struct TouchButtonDesc normDescs[1] = { - { "\x1E", KEYBIND_JUMP, 50, 10, TouchScreen_BindClick } + { "\x1E", BIND_JUMP, 50, 10, TouchScreen_BindClick } }; static const struct TouchButtonDesc hackDescs[2] = { - { "\x1E", KEYBIND_FLY_UP, 50, 70, TouchScreen_BindClick }, - { "\x1F", KEYBIND_FLY_DOWN, 50, 10, TouchScreen_BindClick } + { "\x1E", BIND_FLY_UP, 50, 70, TouchScreen_BindClick }, + { "\x1F", BIND_FLY_DOWN, 50, 10, TouchScreen_BindClick } }; #define TOUCHSCREEN_BTN_COLOR PackedCol_Make(255, 255, 255, 200) @@ -693,8 +693,8 @@ static void TouchScreen_PointerUp(void* screen, int id, int x, int y) { { if (!(s->btns[i].active & id)) continue; - if (s->descs[i].bind < KEYBIND_COUNT) { - Input_Set(KeyBinds_Normal[s->descs[i].bind], false); + if (s->descs[i].bind < BIND_COUNT) { + Input_Set(KeyBind_Mappings[s->descs[i].bind].button1, false); } s->btns[i].active &= ~id; return; @@ -757,7 +757,6 @@ static void TouchScreen_GetMovement(struct LocalPlayer* p, float* xMoving, float ThumbstickWidget_GetMovement(&TouchScreen.thumbstick, xMoving, zMoving); } static struct LocalPlayerInput touchInput = { TouchScreen_GetMovement }; -static cc_bool touchHooked; static void TouchScreen_Init(void* screen) { struct TouchScreen* s = (struct TouchScreen*)screen; @@ -772,15 +771,14 @@ static void TouchScreen_Init(void* screen) { ButtonWidget_Init(&s->more, 40, TouchScreen_MoreClick); s->more.color = TOUCHSCREEN_BTN_COLOR; ThumbstickWidget_Init(&s->thumbstick); - - if (touchHooked) return; - touchHooked = true; + LocalPlayerInput_Add(&touchInput); } static void TouchScreen_Free(void* s) { Event_Unregister_(&UserEvents.HacksStateChanged, s, TouchScreen_HacksChanged); Event_Unregister_(&UserEvents.HackPermsChanged, s, TouchScreen_HacksChanged); + LocalPlayerInput_Remove(&touchInput); } static const struct ScreenVTABLE TouchScreen_VTABLE = { diff --git a/src/Vectors.c b/src/Vectors.c index 6ff297a..7bee5f2 100644 --- a/src/Vectors.c +++ b/src/Vectors.c @@ -37,26 +37,26 @@ void Vec3_TransformY(Vec3* result, float y, const struct Matrix* mat) { } Vec3 Vec3_RotateX(Vec3 v, float angle) { - float cosA = (float)Math_Cos(angle); - float sinA = (float)Math_Sin(angle); + float cosA = Math_CosF(angle); + float sinA = Math_SinF(angle); return Vec3_Create3(v.x, cosA * v.y + sinA * v.z, -sinA * v.y + cosA * v.z); } Vec3 Vec3_RotateY(Vec3 v, float angle) { - float cosA = (float)Math_Cos(angle); - float sinA = (float)Math_Sin(angle); + float cosA = Math_CosF(angle); + float sinA = Math_SinF(angle); return Vec3_Create3(cosA * v.x - sinA * v.z, v.y, sinA * v.x + cosA * v.z); } Vec3 Vec3_RotateY3(float x, float y, float z, float angle) { - float cosA = (float)Math_Cos(angle); - float sinA = (float)Math_Sin(angle); + float cosA = Math_CosF(angle); + float sinA = Math_SinF(angle); return Vec3_Create3(cosA * x - sinA * z, y, sinA * x + cosA * z); } Vec3 Vec3_RotateZ(Vec3 v, float angle) { - float cosA = (float)Math_Cos(angle); - float sinA = (float)Math_Sin(angle); + float cosA = Math_CosF(angle); + float sinA = Math_SinF(angle); return Vec3_Create3(cosA * v.x + sinA * v.y, -sinA * v.x + cosA * v.y, v.z); } @@ -96,8 +96,8 @@ const struct Matrix Matrix_Identity = Matrix_IdentityValue; /* Transposed, source https://open.gl/transformations */ void Matrix_RotateX(struct Matrix* result, float angle) { - float cosA = (float)Math_Cos(angle); - float sinA = (float)Math_Sin(angle); + float cosA = Math_CosF(angle); + float sinA = Math_SinF(angle); *result = Matrix_Identity; result->row2.y = cosA; result->row2.z = sinA; @@ -105,8 +105,8 @@ void Matrix_RotateX(struct Matrix* result, float angle) { } void Matrix_RotateY(struct Matrix* result, float angle) { - float cosA = (float)Math_Cos(angle); - float sinA = (float)Math_Sin(angle); + float cosA = Math_CosF(angle); + float sinA = Math_SinF(angle); *result = Matrix_Identity; result->row1.x = cosA; result->row1.z = -sinA; @@ -114,8 +114,8 @@ void Matrix_RotateY(struct Matrix* result, float angle) { } void Matrix_RotateZ(struct Matrix* result, float angle) { - float cosA = (float)Math_Cos(angle); - float sinA = (float)Math_Sin(angle); + float cosA = Math_CosF(angle); + float sinA = Math_SinF(angle); *result = Matrix_Identity; result->row1.x = cosA; result->row1.y = sinA; @@ -210,52 +210,51 @@ cc_bool FrustumCulling_SphereInFrustum(float x, float y, float z, float radius) } void FrustumCulling_CalcFrustumEquations(struct Matrix* projection, struct Matrix* modelView) { - struct Matrix clipMatrix; - float* clip = (float*)&clipMatrix; - Matrix_Mul(&clipMatrix, modelView, projection); - - /* Extract the numbers for the RIGHT plane */ - frustum00 = clip[3] - clip[0]; - frustum01 = clip[7] - clip[4]; - frustum02 = clip[11] - clip[8]; - frustum03 = clip[15] - clip[12]; + struct Matrix clip; + Matrix_Mul(&clip, modelView, projection); + + /* Extract the RIGHT plane */ + frustum00 = clip.row1.w - clip.row1.x; + frustum01 = clip.row2.w - clip.row2.x; + frustum02 = clip.row3.w - clip.row3.x; + frustum03 = clip.row4.w - clip.row4.x; FrustumCulling_Normalise(&frustum00, &frustum01, &frustum02, &frustum03); - /* Extract the numbers for the LEFT plane */ - frustum10 = clip[3] + clip[0]; - frustum11 = clip[7] + clip[4]; - frustum12 = clip[11] + clip[8]; - frustum13 = clip[15] + clip[12]; + /* Extract the LEFT plane */ + frustum10 = clip.row1.w + clip.row1.x; + frustum11 = clip.row2.w + clip.row2.x; + frustum12 = clip.row3.w + clip.row3.x; + frustum13 = clip.row4.w + clip.row4.x; FrustumCulling_Normalise(&frustum10, &frustum11, &frustum12, &frustum13); /* Extract the BOTTOM plane */ - frustum20 = clip[3] + clip[1]; - frustum21 = clip[7] + clip[5]; - frustum22 = clip[11] + clip[9]; - frustum23 = clip[15] + clip[13]; + frustum20 = clip.row1.w + clip.row1.y; + frustum21 = clip.row2.w + clip.row2.y; + frustum22 = clip.row3.w + clip.row3.y; + frustum23 = clip.row4.w + clip.row4.y; FrustumCulling_Normalise(&frustum20, &frustum21, &frustum22, &frustum23); /* Extract the TOP plane */ - frustum30 = clip[3] - clip[1]; - frustum31 = clip[7] - clip[5]; - frustum32 = clip[11] - clip[9]; - frustum33 = clip[15] - clip[13]; + frustum30 = clip.row1.w - clip.row1.y; + frustum31 = clip.row2.w - clip.row2.y; + frustum32 = clip.row3.w - clip.row3.y; + frustum33 = clip.row4.w - clip.row4.y; FrustumCulling_Normalise(&frustum30, &frustum31, &frustum32, &frustum33); /* Extract the FAR plane (Different for each graphics backend) */ -#if defined CC_BUILD_D3D9 || defined CC_BUILD_D3D11 +#if (CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9) || (CC_GFX_BACKEND == CC_GFX_BACKEND_D3D11) /* OpenGL and Direct3D require slightly different behaviour for NEAR clipping planes */ /* https://www.gamedevs.org/uploads/fast-extraction-viewing-frustum-planes-from-world-view-projection-matrix.pdf */ /* (and because reverse Z is used, 'NEAR' plane is actually the 'FAR' clipping plane) */ - frustum40 = clip[2]; - frustum41 = clip[6]; - frustum42 = clip[10]; - frustum43 = clip[14]; + frustum40 = clip.row1.z; + frustum41 = clip.row2.z; + frustum42 = clip.row3.z; + frustum43 = clip.row4.z; #else - frustum40 = clip[3] - clip[2]; - frustum41 = clip[7] - clip[6]; - frustum42 = clip[11] - clip[10]; - frustum43 = clip[15] - clip[14]; + frustum40 = clip.row1.w - clip.row1.z; + frustum41 = clip.row2.w - clip.row2.z; + frustum42 = clip.row3.w - clip.row3.z; + frustum43 = clip.row4.w - clip.row4.z; #endif FrustumCulling_Normalise(&frustum40, &frustum41, &frustum42, &frustum43); } diff --git a/src/VirtualKeyboard.h b/src/VirtualKeyboard.h index 2c6047c..93012a3 100644 --- a/src/VirtualKeyboard.h +++ b/src/VirtualKeyboard.h @@ -206,7 +206,11 @@ static void VirtualKeyboard_ProcessDown(void* obj, int key, cc_bool was) { } else if (key == CCPAD_X) { VirtualKeyboard_Backspace(); } else if (key == CCPAD_Y) { + VirtualKeyboard_AppendChar('@'); + } else if (key == CCPAD_L) { VirtualKeyboard_AppendChar(' '); + } else if (key == CCPAD_R) { + VirtualKeyboard_AppendChar('/'); } } @@ -330,7 +334,7 @@ static void VirtualKeyboard_Open(struct OpenKeyboardArgs* args, cc_bool launcher kb_shift = false; kb_str.length = 0; - if (args) String_AppendConst(&kb_str, args->placeholder); + String_AppendString(&kb_str, args->text); if (launcher) { KB_MarkDirty = VirtualKeyboard_MarkDirty2D; diff --git a/src/Vorbis.c b/src/Vorbis.c index b0a2e74..aa99bec 100644 --- a/src/Vorbis.c +++ b/src/Vorbis.c @@ -1079,15 +1079,15 @@ void imdct_init(struct imdct_state* state, int n) { /* setup twiddle factors */ for (k = 0, k2 = 0; k < n4; k++, k2 += 2) { - A[k2] = (float)Math_Cos((4*k * PI) / n); - A[k2+1] = -(float)Math_Sin((4*k * PI) / n); - B[k2] = (float)Math_Cos(((k2+1) * PI) / (2*n)); - B[k2+1] = (float)Math_Sin(((k2+1) * PI) / (2*n)); + A[k2] = Math_CosF((4*k * PI) / n); + A[k2+1] = -Math_SinF((4*k * PI) / n); + B[k2] = Math_CosF(((k2+1) * PI) / (2*n)); + B[k2+1] = Math_SinF(((k2+1) * PI) / (2*n)); } for (k = 0, k2 = 0; k < n8; k++, k2 += 2) { - C[k2] = (float)Math_Cos(((k2+1) * (2*PI)) / n); - C[k2+1] = -(float)Math_Sin(((k2+1) * (2*PI)) / n); + C[k2] = Math_CosF(((k2+1) * (2*PI)) / n); + C[k2+1] = -Math_SinF(((k2+1) * (2*PI)) / n); } for (k = 0; k < n8; k++) @@ -1219,13 +1219,13 @@ static void Vorbis_CalcWindow(struct VorbisWindow* window, int blockSize) { for (i = 0; i < n; i++) { - inner = Math_Sin((i + 0.5) / n * (PI/2)); - cur_window[i] = Math_Sin((PI/2) * inner * inner); + inner = Math_SinF((i + 0.5f) / n * (PI/2)); + cur_window[i] = Math_SinF((PI/2) * inner * inner); } for (i = 0; i < n; i++) { - inner = Math_Sin((i + 0.5) / n * (PI/2) + (PI/2)); - prev_window[i] = Math_Sin((PI/2) * inner * inner); + inner = Math_SinF((i + 0.5f) / n * (PI/2) + (PI/2)); + prev_window[i] = Math_SinF((PI/2) * inner * inner); } } diff --git a/src/Widgets.c b/src/Widgets.c index 85e66be..e386c37 100644 --- a/src/Widgets.c +++ b/src/Widgets.c @@ -399,7 +399,7 @@ void ScrollbarWidget_Create(struct ScrollbarWidget* w, int width) { /* It's easy to accidentally touch a bit to the right of the */ /* scrollbar with your finger, so just add some padding */ - if (!Gui.TouchUI) return; + if (!Gui_TouchUI) return; w->padding = Display_ScaleX(15); } @@ -429,9 +429,8 @@ static void HotbarWidget_BuildEntriesMesh(struct HotbarWidget* w, struct VertexT x = HotbarWidget_TileX(w, i); y = w->y + (w->height / 2); -#ifdef CC_BUILD_TOUCH - if (i == HOTBAR_MAX_INDEX && Gui.TouchUI) continue; -#endif + if (i == HOTBAR_MAX_INDEX && Gui_TouchUI) continue; + IsometricDrawer_AddBatch(Inventory_Get(i), scale, x, y); } w->verticesCount = IsometricDrawer_EndBatch(); @@ -467,13 +466,11 @@ static int HotbarWidget_Render2(void* widget, int offset) { HotbarWidget_RenderOutline(w, offset ); HotbarWidget_RenderEntries(w, offset + 8); -#ifdef CC_BUILD_TOUCH - if (Gui.TouchUI) { + if (Gui_TouchUI) { w->ellipsisTex.x = HotbarWidget_TileX(w, HOTBAR_MAX_INDEX) - w->ellipsisTex.width / 2; w->ellipsisTex.y = w->y + (w->height / 2) - w->ellipsisTex.height / 2; Texture_Render(&w->ellipsisTex); } -#endif Gfx_3DS_SetRenderScreen(TOP_SCREEN); return HOTBAR_MAX_VERTICES; @@ -482,9 +479,8 @@ static int HotbarWidget_Render2(void* widget, int offset) { static int HotbarWidget_MaxVertices(void* w) { return HOTBAR_MAX_VERTICES; } void HotbarWidget_Update(struct HotbarWidget* w, float delta) { -#ifdef CC_BUILD_TOUCH int i; - if (!Gui.TouchUI) return; + if (!Gui_TouchUI) return; for (i = 0; i < HOTBAR_MAX_INDEX; i++) { @@ -497,7 +493,6 @@ void HotbarWidget_Update(struct HotbarWidget* w, float delta) { w->touchTime[i] = 0; Inventory_Set(i, 0); } -#endif } static int HotbarWidget_ScrolledIndex(struct HotbarWidget* w, float delta, int index, int dir) { @@ -540,7 +535,7 @@ static int HotbarWidget_MapKey(int key) { int i; for (i = 0; i < INVENTORY_BLOCKS_PER_HOTBAR; i++) { - if (KeyBind_Claims(KEYBIND_HOTBAR_1 + i, key)) return i; + if (InputBind_Claims(BIND_HOTBAR_1 + i, key)) return i; } return -1; } @@ -560,14 +555,14 @@ static int HotbarWidget_KeyDown(void* widget, int key) { int index = HotbarWidget_MapKey(key); if (index == -1) { - if (KeyBind_Claims(KEYBIND_HOTBAR_LEFT, key)) + if (InputBind_Claims(BIND_HOTBAR_LEFT, key)) return HotbarWidget_CycleIndex(-1); - if (KeyBind_Claims(KEYBIND_HOTBAR_RIGHT, key)) + if (InputBind_Claims(BIND_HOTBAR_RIGHT, key)) return HotbarWidget_CycleIndex(+1); return false; } - if (KeyBind_IsPressed(KEYBIND_HOTBAR_SWITCH)) { + if (InputBind_IsPressed(BIND_HOTBAR_SWITCH)) { /* Pick from first to ninth row */ Inventory_SetHotbarIndex(index); w->altHandled = true; @@ -583,7 +578,7 @@ static void HotbarWidget_InputUp(void* widget, int key) { a) user presses alt then number b) user presses alt We only do case b) if case a) did not happen */ - if (!KeyBind_Claims(KEYBIND_HOTBAR_SWITCH, key)) return; + if (!InputBind_Claims(BIND_HOTBAR_SWITCH, key)) return; if (w->altHandled) { w->altHandled = false; return; } /* handled already */ /* Don't switch hotbar when alt+tabbing to another window */ @@ -604,16 +599,15 @@ static int HotbarWidget_PointerDown(void* widget, int id, int x, int y) { cellY = w->y; if (!Gui_Contains(cellX, cellY, width, height, x, y)) continue; -#ifdef CC_BUILD_TOUCH - if(Gui.TouchUI) { + if (Gui_TouchUI) { if (i == HOTBAR_MAX_INDEX) { InventoryScreen_Show(); return TOUCH_TYPE_GUI; } else { - w->touchId[i] = id; + w->touchId[i] = id; w->touchTime[i] = 0; } } -#endif + Inventory_SetSelectedIndex(i); return TOUCH_TYPE_GUI; } @@ -627,7 +621,7 @@ static void HotbarWidget_PointerUp(void* widget, int id, int x, int y) { for (i = 0; i < HOTBAR_MAX_INDEX; i++) { if (w->touchId[i] == id) { - w->touchId[i] = -1; + w->touchId[i] = -1; w->touchTime[i] = 0; } } @@ -639,13 +633,12 @@ static int HotbarWidget_PointerMove(void* widget, int id, int x, int y) { struct HotbarWidget* w = (struct HotbarWidget*)widget; int i; - for (i = 0; i < HOTBAR_MAX_INDEX; i++) { - if (w->touchId[i] == id) { - if (!Widget_Contains(w, x, y)) { - w->touchId[i] = -1; - w->touchTime[i] = 0; - return true; - } + for (i = 0; i < HOTBAR_MAX_INDEX; i++) + { + if (w->touchId[i] == id && !Widget_Contains(w, x, y)) { + w->touchId[i] = -1; + w->touchTime[i] = 0; + return true; } } #endif @@ -656,7 +649,7 @@ static int HotbarWidget_MouseScroll(void* widget, float delta) { struct HotbarWidget* w = (struct HotbarWidget*)widget; int index; - if (KeyBind_IsPressed(KEYBIND_HOTBAR_SWITCH)) { + if (InputBind_IsPressed(BIND_HOTBAR_SWITCH)) { index = Inventory.Offset / INVENTORY_BLOCKS_PER_HOTBAR; index = HotbarWidget_ScrolledIndex(w, delta, index, 1); Inventory_SetHotbarIndex(index); @@ -669,12 +662,10 @@ static int HotbarWidget_MouseScroll(void* widget, float delta) { } static void HotbarWidget_Free(void* widget) { -#ifdef CC_BUILD_TOUCH struct HotbarWidget* w = (struct HotbarWidget*)widget; - if (!Gui.TouchUI) return; + if (!Gui_TouchUI) return; Gfx_DeleteTexture(&w->ellipsisTex.ID); -#endif } static const struct WidgetVTABLE HotbarWidget_VTABLE = { @@ -700,14 +691,12 @@ void HotbarWidget_Create(struct HotbarWidget* w) { } void HotbarWidget_SetFont(struct HotbarWidget* w, struct FontDesc* font) { -#ifdef CC_BUILD_TOUCH static const cc_string dots = String_FromConst("..."); struct DrawTextArgs args; - if (!Gui.TouchUI) return; + if (!Gui_TouchUI) return; DrawTextArgs_Make(&args, &dots, font, true); Drawer2D_MakeTextTexture(&w->ellipsisTex, &args); -#endif } @@ -1717,7 +1706,7 @@ void TextInputWidget_Create(struct TextInputWidget* w, int width, const cc_strin w->base.convertPercents = false; w->base.padding = 3; - w->base.showCaret = !Gui.TouchUI; + w->base.showCaret = !Gui_TouchUI; w->base.flags = WIDGET_FLAG_SELECTABLE; w->base.GetMaxLines = TextInputWidget_GetMaxLines; @@ -2771,7 +2760,7 @@ static void ThumbstickWidget_BuildMesh(void* widget, struct VertexTextured** ver static int ThumbstickWidget_CalcDirs(struct ThumbstickWidget* w) { int i, dx, dy, dirs = 0; - double angle; + float angle; for (i = 0; i < INPUT_MAX_POINTERS; i++) { if (!(w->active & (1 << i))) continue; diff --git a/src/Widgets.h b/src/Widgets.h index 85a9f5c..db22bb4 100644 --- a/src/Widgets.h +++ b/src/Widgets.h @@ -77,10 +77,8 @@ struct HotbarWidget { struct Texture ellipsisTex; int state[HOTBAR_CORE_VERTICES / 4]; int verticesCount; -#ifdef CC_BUILD_TOUCH int touchId[HOTBAR_MAX_INDEX]; float touchTime[HOTBAR_MAX_INDEX]; -#endif }; #define HOTBAR_MAX_VERTICES (4 + 4 + HOTBAR_CORE_VERTICES) diff --git a/src/Window.h b/src/Window.h index 1fb30ac..ef4b3f7 100644 --- a/src/Window.h +++ b/src/Window.h @@ -94,6 +94,8 @@ CC_VAR extern struct _WindowData WindowInfo; /* Named WindowInfo for backwards c /* Data for alternate game window (e.g. 3DS) */ extern struct _WindowData Window_Alt; +/* Initialises necessary state before initing platform and loading options */ +void Window_PreInit(void); /* Initialises state for window, input, and display. */ void Window_Init(void); /* Potentially frees/resets state for window, input, and display. */ @@ -214,7 +216,7 @@ void Window_UpdateRawMouse(void); void Window_DisableRawMouse(void); /* OpenGL contexts are heavily tied to the window, so for simplicitly are also provided here */ -#ifdef CC_BUILD_GL +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) #define GLCONTEXT_DEFAULT_DEPTH 24 /* Creates an OpenGL context, then makes it the active context. */ /* NOTE: You MUST have created the window beforehand, as the GL context is attached to the window. */ diff --git a/src/Window_3DS.c b/src/Window_3DS.c index a17147b..f46de65 100644 --- a/src/Window_3DS.c +++ b/src/Window_3DS.c @@ -23,13 +23,15 @@ struct _WindowData WindowInfo; struct _WindowData Window_Alt; cc_bool launcherTop; +void Window_PreInit(void) { + gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, false); +} + // Note from https://github.com/devkitPro/libctru/blob/master/libctru/include/3ds/gfx.h // * Please note that the 3DS uses *portrait* screens rotated 90 degrees counterclockwise. // * Width/height refer to the physical dimensions of the screen; that is, the top screen // * is 240 pixels wide and 400 pixels tall; while the bottom screen is 240x320. void Window_Init(void) { - gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, false); - // deliberately swapped gfxGetFramebuffer(GFX_TOP, GFX_LEFT, &top_height, &top_width); gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, &btm_height, &btm_width); diff --git a/src/Window_Android.c b/src/Window_Android.c index f9b5e06..81e49af 100644 --- a/src/Window_Android.c +++ b/src/Window_Android.c @@ -1,5 +1,5 @@ #include "Core.h" -#if defined CC_BUILD_ANDROID && !defined CC_BUILD_SDL +#if CC_WIN_BACKEND == CC_WIN_BACKEND_ANDROID #include "_WindowBase.h" #include "String.h" #include "Funcs.h" @@ -146,6 +146,14 @@ static void JNICALL java_processPointerMove(JNIEnv* env, jobject o, jint id, jin Input_UpdateTouch(id, x, y); } +static void JNICALL java_processJoystickL(JNIEnv* env, jobject o, jint x, jint y) { + Gamepad_SetAxis(0, PAD_AXIS_LEFT, x / 4096.0f, y / 4096.0f, 1.0f / 60); +} + +static void JNICALL java_processJoystickR(JNIEnv* env, jobject o, jint x, jint y) { + Gamepad_SetAxis(0, PAD_AXIS_RIGHT, x / 4096.0f, y / 4096.0f, 1.0f / 60); +} + static void JNICALL java_processSurfaceCreated(JNIEnv* env, jobject o, jobject surface) { Platform_LogConst("WIN - CREATED"); win_handle = ANativeWindow_fromSurface(env, surface); @@ -234,6 +242,9 @@ static const JNINativeMethod methods[] = { { "processPointerUp", "(IIII)V", java_processPointerUp }, { "processPointerMove", "(IIII)V", java_processPointerMove }, + { "processJoystickL", "(II)V", java_processJoystickL }, + { "processJoystickR", "(II)V", java_processJoystickR }, + { "processSurfaceCreated", "(Landroid/view/Surface;)V", java_processSurfaceCreated }, { "processSurfaceDestroyed", "()V", java_processSurfaceDestroyed }, { "processSurfaceResized", "(Landroid/view/Surface;)V", java_processSurfaceResized }, @@ -273,6 +284,7 @@ static void CacheMethodRefs(JNIEnv* env) { JAVA_saveFileDialog = JavaGetIMethod(env, "saveFileDialog", "(Ljava/lang/String;Ljava/lang/String;)I"); } +void Window_PreInit(void) { } // TODO move to bottom of file? void Window_Init(void) { JNIEnv* env; diff --git a/src/Window_BeOS.cpp b/src/Window_BeOS.cpp new file mode 100644 index 0000000..81e4aae --- /dev/null +++ b/src/Window_BeOS.cpp @@ -0,0 +1,742 @@ +#include "Core.h" +#if CC_WIN_BACKEND == CC_WIN_BACKEND_BEOS + +extern "C" { +#include "_WindowBase.h" +#include "Graphics.h" +#include "String.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "Errors.h" +#include "Utils.h" +} +// Other +#include +// AppKit +#include +#include +#include +// GLKit +#include +#include +// InterfaceKit +#include +#include +#include +// StorageKit +#include +#include + +static BApplication* app_handle; +static BWindow* win_handle; +static BView* view_handle; +static BGLView* view_3D; + +// Event management +enum CCEventType { + CC_NONE, + CC_MOUSE_SCROLL, CC_MOUSE_DOWN, CC_MOUSE_UP, CC_MOUSE_MOVE, + CC_KEY_DOWN, CC_KEY_UP, CC_KEY_INPUT, + CC_WIN_RESIZED, CC_WIN_FOCUS, CC_WIN_REDRAW, CC_WIN_QUIT, + CC_RAW_MOUSE +}; +union CCEventValue { float f32; int i32; void* ptr; }; +struct CCEvent { + int type; + CCEventValue v1, v2; +}; + +#define EVENTS_DEFAULT_MAX 30 +static void* events_mutex; +static int events_count, events_capacity; +static CCEvent* events_list, events_default[EVENTS_DEFAULT_MAX]; + +static void Events_Init(void) { + events_mutex = Mutex_Create("BeOS events"); + events_capacity = EVENTS_DEFAULT_MAX; + events_list = events_default; +} + +static void Events_Push(const CCEvent* event) { + Mutex_Lock(events_mutex); + { + if (events_count >= events_capacity) { + Utils_Resize((void**)&events_list, &events_capacity, + sizeof(CCEvent), EVENTS_DEFAULT_MAX, 20); + } + events_list[events_count++] = *event; + } + Mutex_Unlock(events_mutex); +} + +static cc_bool Events_Pull(CCEvent* event) { + cc_bool found = false; + + Mutex_Lock(events_mutex); + { + if (events_count) { + *event = events_list[0]; + for (int i = 1; i < events_count; i++) { + events_list[i - 1] = events_list[i]; + } + events_count--; + found = true; + } + } + Mutex_Unlock(events_mutex); + return found; +} + +// BApplication implementation +class CC_BApp : public BApplication +{ +public: + CC_BApp() : BApplication("application/x-ClassiCube") { } + void DispatchMessage(BMessage* msg, BHandler* handler); +}; + +static void CallOpenFileCallback(const char* path); +void CC_BApp::DispatchMessage(BMessage* msg, BHandler* handler) { + CCEvent event = { 0 }; + const char* filename; + entry_ref fileRef; + + switch (msg->what) + { + case B_QUIT_REQUESTED: + Platform_LogConst("APP QUIT"); + event.type = CC_WIN_QUIT; + break; + case B_REFS_RECEIVED: + // TODO do we need to support more than 1 ref? + if (msg->FindRef("refs", 0, &fileRef) == B_OK) { + BPath path(&fileRef); + CallOpenFileCallback(path.Path()); + } + break; + case B_SAVE_REQUESTED: + // TODO do we need to support more than 1 ref? + if (msg->FindRef("directory", 0, &fileRef) == B_OK && + msg->FindString("name", &filename) == B_OK) { + BDirectory folder(&fileRef); + BPath path(&folder, filename); + // TODO add default file extension + CallOpenFileCallback(path.Path()); + } + break; + default: + //Platform_LogConst("UNHANDLED APP MESSAGE:"); + //msg->PrintToStream(); + break; + } + if (event.type) Events_Push(&event); + BApplication::DispatchMessage(msg, handler); +} + +// BWindow implementation +class CC_BWindow : public BWindow +{ + public: + CC_BWindow(BRect frame) : BWindow(frame, "", B_TITLED_WINDOW, 0) { } + void DispatchMessage(BMessage* msg, BHandler* handler); + + virtual ~CC_BWindow() { + if (!view_3D) return; + + // Fixes OpenGL related crashes on exit since Mesa 21 + // Calling RemoveChild seems to fix the crash as per https://dev.haiku-os.org/ticket/16840 + // "Some OpenGL applications like GLInfo crash on exit under Mesa 21" + this->Lock(); + this->RemoveChild(view_3D); + this->Unlock(); + } +}; + +static void ProcessKeyInput(BMessage* msg) { + CCEvent event; + const char* value; + cc_codepoint cp; + + if (msg->FindString("bytes", &value) != B_OK) return; + if (!Convert_Utf8ToCodepoint(&cp, (const cc_uint8*)value, String_Length(value))) return; + + event.type = CC_KEY_INPUT; + event.v1.i32 = cp; + Events_Push(&event); +} + +static int last_buttons; +static int mouse_raw_delta, mouse_is_tablet; + +static void UpdateMouseButton(int btn, int pressed) { + CCEvent event; + event.type = pressed ? CC_MOUSE_DOWN : CC_MOUSE_UP; + event.v1.i32 = btn; + Events_Push(&event); +} + +static void UpdateMouseButtons(int buttons) { + // BeOS API is really odd in that it only provides you with a bitmask + // of 'current mouse buttons pressed' + int changed = buttons ^ last_buttons; + + // TODO move logic to UpdateMouseButton instead? + if (changed & B_PRIMARY_MOUSE_BUTTON) + UpdateMouseButton(CCMOUSE_L, buttons & B_PRIMARY_MOUSE_BUTTON); + if (changed & B_SECONDARY_MOUSE_BUTTON) + UpdateMouseButton(CCMOUSE_R, buttons & B_SECONDARY_MOUSE_BUTTON); + if (changed & B_TERTIARY_MOUSE_BUTTON) + UpdateMouseButton(CCMOUSE_M, buttons & B_TERTIARY_MOUSE_BUTTON); + if (changed & B_MOUSE_BUTTON(4)) + UpdateMouseButton(CCMOUSE_X1, buttons & B_MOUSE_BUTTON(4)); + if (changed & B_MOUSE_BUTTON(5)) + UpdateMouseButton(CCMOUSE_X2, buttons & B_MOUSE_BUTTON(5)); + + last_buttons = buttons; +} + +static void HandleMouseMovement(BMessage* msg) { + int dx, dy; + float prs; + + if (msg->FindInt32("be:delta_x", &dx) == B_OK && + msg->FindInt32("be:delta_y", &dy) == B_OK) { + + CCEvent event = { 0 }; + event.type = CC_RAW_MOUSE; + event.v1.i32 = dx; + event.v2.i32 = -dy; + Events_Push(&event); + + mouse_raw_delta = true; + } else if (msg->FindFloat("be:tablet_pressure", &prs) == B_OK) { + mouse_is_tablet = true; + } +} + +void CC_BWindow::DispatchMessage(BMessage* msg, BHandler* handler) { + CCEvent event = { 0 }; + BPoint where; + float delta; + int32 value, width, height; + bool active; + + switch (msg->what) + { + case B_KEY_DOWN: + case B_UNMAPPED_KEY_DOWN: + if (msg->FindInt32("key", &value) == B_OK) { + event.type = CC_KEY_DOWN; + event.v1.i32 = value; + } + break; + case B_KEY_UP: + case B_UNMAPPED_KEY_UP: + if (msg->FindInt32("key", &value) == B_OK) { + event.type = CC_KEY_UP; + event.v1.i32 = value; + } + break; + case B_MOUSE_DOWN: + case B_MOUSE_UP: + if (msg->FindInt32("buttons", &value) == B_OK) { + UpdateMouseButtons(value); + HandleMouseMovement(msg); + } + break; + case B_MOUSE_MOVED: + if (msg->FindPoint("where", &where) == B_OK) { + event.type = CC_MOUSE_MOVE; + event.v1.i32 = where.x; + event.v2.i32 = where.y; + HandleMouseMovement(msg); + } + break; + case B_MOUSE_WHEEL_CHANGED: + if (msg->FindFloat("be:wheel_delta_y", &delta) == B_OK) { + event.type = CC_MOUSE_SCROLL; + event.v1.f32 = -delta; // negate to match other platforms + } + if (msg->FindFloat("be:wheel_delta_x", &delta) == B_OK) { + event.type = CC_MOUSE_SCROLL; + event.v2.f32 = -delta; // negate to match other platforms + } + break; + + case B_WINDOW_ACTIVATED: + if (msg->FindBool("active", &active) == B_OK) { + event.type = CC_WIN_FOCUS; + event.v1.i32 = active; + } + break; + case B_WINDOW_MOVED: + break; // avoid unhandled message spam + case B_WINDOW_RESIZED: + if (msg->FindInt32("width", &width) == B_OK && + msg->FindInt32("height", &height) == B_OK) { + event.type = CC_WIN_RESIZED; + // width/height is 1 less than actual width/height + event.v1.i32 = width + 1; + event.v2.i32 = height + 1; + } + break; + case B_QUIT_REQUESTED: + event.type = CC_WIN_QUIT; + Platform_LogConst("WINQUIT"); + break; + case _UPDATE_: + event.type = CC_WIN_REDRAW; + break; + default: + //Platform_LogConst("UNHANDLED WIN MESSAGE:"); + //msg->PrintToStream(); + break; + } + + if (event.type) Events_Push(&event); + if (msg->what == B_KEY_DOWN) ProcessKeyInput(msg); + BWindow::DispatchMessage(msg, handler); +} + + +static void AppThread(void) { + app_handle = new CC_BApp(); + // runs forever + app_handle->Run(); + // because there are multiple other threads relying + // on BApp connection, trying to delete the reference + // tends to break them and crash the game at exit + //delete app_handle; +} + +static void RunApp(void) { + void* thread; + Thread_Run(&thread, AppThread, 128 * 1024, "App thread"); + Thread_Detach(thread); + + // wait for BApplication to be started in other thread + do { + Thread_Sleep(10); + } while (!app_handle || app_handle->IsLaunching()); + + Platform_LogConst("App initialised"); +} + +void Window_PreInit(void) { } +void Window_Init(void) { + Events_Init(); + RunApp(); + Input.Sources = INPUT_SOURCE_NORMAL; + + BScreen screen(B_MAIN_SCREEN_ID); + BRect frame = screen.Frame(); + + // e.g. frame = (l:0.0, t:0.0, r:1023.0, b:767.0) + // so have to add 1 here for actual width/height + DisplayInfo.Width = frame.IntegerWidth() + 1; + DisplayInfo.Height = frame.IntegerHeight() + 1; + DisplayInfo.ScaleX = 1; + DisplayInfo.ScaleY = 1; +} + +void Window_Free(void) { } + +static void DoCreateWindow(int width, int height) { + // https://www.haiku-os.org/docs/api/classBRect.html#details + // right/bottom coordinates are inclusive of the coordinates, + // so need to subtract 1 to end up with correct width/height + int x = Display_CentreX(width), y = Display_CentreY(height); + BRect frame(x, y, x + width - 1, y + height - 1); + win_handle = new CC_BWindow(frame); + + Window_Main.Exists = true; + Window_Main.Handle = win_handle; + + frame = win_handle->Bounds(); + Window_Main.Width = frame.IntegerWidth() + 1; + Window_Main.Height = frame.IntegerHeight() + 1; +} + +void Window_Create2D(int width, int height) { + DoCreateWindow(width, height); + view_handle = new BView(win_handle->Bounds(), "CC_LAUNCHER", + B_FOLLOW_ALL, 0); + win_handle->AddChild(view_handle); +} + +void Window_Create3D(int width, int height) { + DoCreateWindow(width, height); + view_3D = new BGLView(win_handle->Bounds(), "CC_GAME", + B_FOLLOW_ALL, B_FRAME_EVENTS, + BGL_RGB | BGL_ALPHA | BGL_DOUBLE | BGL_DEPTH); + view_handle = view_3D; + win_handle->AddChild(view_handle); +} + +void Window_SetTitle(const cc_string* title) { + char raw[NATIVE_STR_LEN]; + String_EncodeUtf8(raw, title); + + win_handle->Lock(); // TODO even need to lock/unlock? + win_handle->SetTitle(raw); + win_handle->Unlock(); +} + +void Clipboard_GetText(cc_string* value) { + if (!be_clipboard->Lock()) return; + + BMessage* clip = be_clipboard->Data(); + char* str = NULL; + ssize_t str_len = 0; + + clip->FindData("text/plain", B_MIME_TYPE, (const void**)&str, &str_len); + if (str) String_AppendUtf8(value, str, str_len); + + be_clipboard->Unlock(); +} + +void Clipboard_SetText(const cc_string* value) { + char str[NATIVE_STR_LEN]; + int str_len = String_EncodeUtf8(str, value); + + if (!be_clipboard->Lock()) return; + be_clipboard->Clear(); + + BMessage* clip = be_clipboard->Data(); + clip->AddData("text/plain", B_MIME_TYPE, str, str_len); + be_clipboard->Commit(); + + be_clipboard->Unlock(); +} + +static BRect win_rect; +static cc_bool win_fullscreen; + +int Window_GetWindowState(void) { + return win_fullscreen ? WINDOW_STATE_FULLSCREEN : WINDOW_STATE_NORMAL; +} + +cc_result Window_EnterFullscreen(void) { + // TODO is there a better fullscreen API to use + win_fullscreen = true; + win_rect = win_handle->Frame(); + + BScreen screen(B_MAIN_SCREEN_ID); + BRect screen_frame = screen.Frame(); + + win_handle->Lock(); + win_handle->MoveTo(screen_frame.left, screen_frame.top); + win_handle->ResizeTo(screen_frame.Width(), screen_frame.Height()); + win_handle->SetFlags(win_handle->Flags() & ~(B_NOT_RESIZABLE | B_NOT_ZOOMABLE)); + //win_handle->SetLook(B_NO_BORDER_WINDOW_LOOK); // TODO unnecessary? + win_handle->Unlock(); + return 0; +} +cc_result Window_ExitFullscreen(void) { + win_fullscreen = false; + + win_handle->Lock(); + win_handle->MoveTo(win_rect.left, win_rect.top); + win_handle->ResizeTo(win_rect.Width(), win_rect.Height()); + win_handle->SetFlags(win_handle->Flags() | (B_NOT_RESIZABLE | B_NOT_ZOOMABLE)); + //win_handle->SetLook(B_TITLED_WINDOW_LOOK); + win_handle->Unlock(); + return 0; +} + +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { + win_handle->Lock(); // TODO even need to lock/unlock ? + win_handle->Show(); + win_handle->Unlock(); +} + +void Window_SetSize(int width, int height) { + // See reason for -1 in DoCreateWindow + win_handle->Lock(); // TODO even need to lock/unlock ? + win_handle->ResizeTo(width - 1, height - 1); + win_handle->Unlock(); +} + +void Window_RequestClose(void) { + BMessage* msg = new BMessage(B_QUIT_REQUESTED); + app_handle->PostMessage(msg); +} + +static const cc_uint8 key_map[] = { + /* 0x00 */ 0,CCKEY_ESCAPE,CCKEY_F1,CCKEY_F2, CCKEY_F3,CCKEY_F4,CCKEY_F5,CCKEY_F6, + /* 0x08 */ CCKEY_F7,CCKEY_F8,CCKEY_F9,CCKEY_F10, CCKEY_F11,CCKEY_F12,CCKEY_PRINTSCREEN,CCKEY_SCROLLLOCK, + /* 0x10 */ CCKEY_PAUSE,CCKEY_TILDE,'1','2', '3','4','5','6', + /* 0x18 */ '7','8','9','0', CCKEY_MINUS,CCKEY_EQUALS,CCKEY_BACKSPACE,CCKEY_INSERT, + /* 0x20 */ CCKEY_HOME,CCKEY_PAGEUP,CCKEY_NUMLOCK,CCKEY_KP_DIVIDE, CCKEY_KP_MULTIPLY,CCKEY_KP_MINUS,CCKEY_TAB,'Q', + /* 0x28 */ 'W','E','R','T', 'Y','U','I','O', + /* 0x30 */ 'P',CCKEY_LBRACKET,CCKEY_RBRACKET,CCKEY_BACKSLASH, CCKEY_DELETE,CCKEY_END,CCKEY_PAGEDOWN,CCKEY_KP7, + /* 0x38 */ CCKEY_KP8,CCKEY_KP9,CCKEY_KP_PLUS,CCKEY_CAPSLOCK, 'A','S','D','F', + /* 0x40 */ 'G','H','J','K', 'L',CCKEY_SEMICOLON,CCKEY_QUOTE,CCKEY_ENTER, + /* 0x48 */ CCKEY_KP4,CCKEY_KP5,CCKEY_KP6,CCKEY_LSHIFT, 'Z','X','C','V', + /* 0x50 */ 'B','N','M',CCKEY_COMMA, CCKEY_PERIOD,CCKEY_SLASH,CCKEY_RSHIFT,CCKEY_UP, + /* 0x58 */ CCKEY_KP1,CCKEY_KP2,CCKEY_KP3,CCKEY_KP_ENTER, CCKEY_LCTRL,CCKEY_LALT,CCKEY_SPACE,CCKEY_RALT, + /* 0x60 */ CCKEY_RCTRL,CCKEY_LEFT,CCKEY_DOWN,CCKEY_RIGHT, CCKEY_KP0,CCKEY_KP_DECIMAL,CCKEY_LWIN,0, + /* 0x68 */ CCKEY_RWIN,0,0,0, 0,0,0,0, +}; + +static int MapNativeKey(int raw) { + int key = raw >= 0 && raw < Array_Elems(key_map) ? key_map[raw] : 0; + if (!key) Platform_Log2("Unknown key: %i (%h)", &raw, &raw); + return key; +} + +void Window_ProcessEvents(float delta) { + CCEvent event; + int key; + + while (Events_Pull(&event)) + { + switch (event.type) + { + case CC_MOUSE_SCROLL: + Mouse_ScrollVWheel(event.v1.f32); + Mouse_ScrollHWheel(event.v2.f32); + break; + case CC_MOUSE_DOWN: + Input_SetPressed(event.v1.i32); + break; + case CC_MOUSE_UP: + Input_SetReleased(event.v1.i32); + break; + case CC_MOUSE_MOVE: + Pointer_SetPosition(0, event.v1.i32, event.v2.i32); + break; + case CC_KEY_DOWN: + key = MapNativeKey(event.v1.i32); + if (key) Input_SetPressed(key); + break; + case CC_KEY_UP: + key = MapNativeKey(event.v1.i32); + if (key) Input_SetReleased(key); + break; + case CC_KEY_INPUT: + Event_RaiseInt(&InputEvents.Press, event.v1.i32); + break; + case CC_WIN_RESIZED: + Window_Main.Width = event.v1.i32; + Window_Main.Height = event.v2.i32; + Event_RaiseVoid(&WindowEvents.Resized); + break; + case CC_WIN_FOCUS: + Window_Main.Focused = event.v1.i32; + Event_RaiseVoid(&WindowEvents.FocusChanged); + break; + case CC_WIN_REDRAW: + Event_RaiseVoid(&WindowEvents.RedrawNeeded); + break; + case CC_WIN_QUIT: + Window_Main.Exists = false; + Event_RaiseVoid(&WindowEvents.Closing); + break; + case CC_RAW_MOUSE: + if (Input.RawMode) Event_RaiseRawMove(&PointerEvents.RawMoved, event.v1.i32, event.v2.i32); + break; + } + } +} + +void Window_ProcessGamepads(float delta) { } + +static void Cursor_GetRawPos(int* x, int* y) { + BPoint where; + uint32 buttons; + + win_handle->Lock(); + view_handle->GetMouse(&where, &buttons, false); + win_handle->Unlock(); + + // TODO: Should checkQueue be true + *x = (int)where.x; + *y = (int)where.y; +} + +void Cursor_SetPosition(int x, int y) { + // https://discourse.libsdl.org/t/sdl-mouse-bug/597/11 + BRect frame = win_handle->Frame(); + set_mouse_position(frame.left + x, frame.top + y); +} + +static void Cursor_DoSetVisible(cc_bool visible) { + if (visible) { + app_handle->ShowCursor(); + } else { + app_handle->HideCursor(); + } +} + +static void ShowDialogCore(const char* title, const char* msg) { + BAlert* alert = new BAlert(title, msg, "OK"); + // doesn't show title by default + alert->SetLook(B_TITLED_WINDOW_LOOK); + alert->Go(); +} + +static BFilePanel* open_panel; +static BFilePanel* save_panel; +static FileDialogCallback file_callback; +static const char* const* file_filters; + +class CC_BRefFilter : public BRefFilter +{ +public: + CC_BRefFilter() : BRefFilter() { } + +#if defined CC_BUILD_BEOS + bool Filter(const entry_ref* ref, BNode* node, struct stat* st, const char* filetype) { +#else + bool Filter(const entry_ref* ref, BNode* node, stat_beos* st, const char* filetype) override { +#endif + BPath path(ref); + cc_string str; + int i; + + if (node->IsDirectory()) return true; + str = String_FromReadonly(path.Path()); + + for (i = 0; file_filters[i]; i++) + { + cc_string ext = String_FromReadonly(file_filters[i]); + if (String_CaselessEnds(&str, &ext)) return true; + } + return false; + } +}; + +static void CallOpenFileCallback(const char* rawPath) { + cc_string path; char pathBuffer[1024]; + String_InitArray(path, pathBuffer); + if (!file_callback) return; + + String_AppendUtf8(&path, rawPath, String_Length(rawPath)); + file_callback(&path); + file_callback = NULL; +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + if (!open_panel) { + open_panel = new BFilePanel(B_OPEN_PANEL); + open_panel->SetRefFilter(new CC_BRefFilter()); + // NOTE: the CC_BRefFilter is NOT owned by the BFilePanel, + // so this is technically a memory leak.. but meh + } + + file_callback = args->Callback; + file_filters = args->filters; + open_panel->Show(); + return 0; +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + if (!save_panel) { + save_panel = new BFilePanel(B_SAVE_PANEL); + save_panel->SetRefFilter(new CC_BRefFilter()); + // NOTE: the CC_BRefFilter is NOT owned by the BFilePanel, + // so this is technically a memory leak.. but meh + } + + file_callback = args->Callback; + file_filters = args->filters; + save_panel->Show(); + return 0; +} + +static BBitmap* win_framebuffer; +void Window_AllocFramebuffer(struct Bitmap* bmp) { + // right/bottom coordinates are inclusive of the coordinates, + // so need to subtract 1 to end up with correct width/height + BRect bounds(0, 0, bmp->width - 1, bmp->height - 1); + + win_framebuffer = new BBitmap(bounds, B_RGB32); + bmp->scan0 = (BitmapCol*)win_framebuffer->Bits(); +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + // TODO rect should maybe subtract -1 too ???? + BRect rect(r.x, r.y, r.x + r.width, r.y + r.height); + win_handle->Lock(); + view_handle->DrawBitmap(win_framebuffer, rect, rect); + win_handle->Unlock(); +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + delete win_framebuffer; + bmp->scan0 = NULL; +} + +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { } +void OnscreenKeyboard_SetText(const cc_string* text) { } +void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { } +void OnscreenKeyboard_Draw3D(void) { } +void OnscreenKeyboard_Close(void) { } + +void Window_EnableRawMouse(void) { + DefaultEnableRawMouse(); +} + +void Window_UpdateRawMouse(void) { + if (mouse_raw_delta) { // handled by events instead + CentreMousePosition(); + } else if (mouse_is_tablet) { + MoveRawUsingCursorDelta(); + Cursor_GetRawPos(&cursorPrevX, &cursorPrevY); + } else { + DefaultUpdateRawMouse(); + } +} + +void Window_DisableRawMouse(void) { + DefaultDisableRawMouse(); +} + + +/*########################################################################################################################* +*-----------------------------------------------------OpenGL context------------------------------------------------------* +*#########################################################################################################################*/ +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && !defined CC_BUILD_EGL +static cc_bool win_vsync; + +void GLContext_Create(void) { + view_3D->LockGL(); +} + +void GLContext_Update(void) { + // it's necessary to call UnlockGL then LockGL, otherwise resizing doesn't work + // (backbuffer rendering is performed to doesn't get resized) + // https://github.com/anholt/mesa/blob/01e511233b24872b08bff862ff692dfb5b22c1f4/src/gallium/targets/haiku-softpipe/SoftwareRenderer.cpp#L120..L127 + // might be fixed in newer MESA though? + view_3D->UnlockGL(); + view_3D->LockGL(); +} + +cc_bool GLContext_TryRestore(void) { return true; } +void GLContext_Free(void) { + view_3D->UnlockGL(); +} + +void* GLContext_GetAddress(const char* function) { +#if defined CC_BUILD_BEOS + return NULL; +#else + return view_3D->GetGLProcAddress(function); +#endif +} + +cc_bool GLContext_SwapBuffers(void) { + view_3D->SwapBuffers(win_vsync); + return true; +} + +void GLContext_SetFpsLimit(cc_bool vsync, float minFrameMs) { + win_vsync = vsync; +} +void GLContext_GetApiInfo(cc_string* info) { } +#endif // (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && !CC_BUILD_EGL + +#endif diff --git a/src/Window_Dreamcast.c b/src/Window_Dreamcast.c index f80b0fc..80d4d23 100644 --- a/src/Window_Dreamcast.c +++ b/src/Window_Dreamcast.c @@ -18,6 +18,12 @@ cc_bool window_inited; struct _DisplayData DisplayInfo; struct _WindowData WindowInfo; +void Window_PreInit(void) { + vid_set_mode(DEFAULT_VID_MODE, DEFAULT_PIXEL_MODE); + vid_flip(0); + // TODO: Why doesn't 32 bit work on real hardware for in-game? +} + void Window_Init(void) { DisplayInfo.Width = vid_mode->width; DisplayInfo.Height = vid_mode->height; @@ -33,10 +39,7 @@ void Window_Init(void) { DisplayInfo.ContentOffsetX = 10; DisplayInfo.ContentOffsetY = 20; Window_Main.SoftKeyboard = SOFT_KEYBOARD_VIRTUAL; - - vid_set_mode(DEFAULT_VID_MODE, DEFAULT_PIXEL_MODE); - vid_flip(0); - // TODO: Why doesn't 32 bit work on real hardware for in-game? + window_inited = true; } @@ -222,7 +225,9 @@ static void HandleButtons(int port, int mods) { Gamepad_SetButton(port, CCPAD_UP, mods & CONT_DPAD_UP); Gamepad_SetButton(port, CCPAD_DOWN, mods & CONT_DPAD_DOWN); - // Buttons not on standard controller (todo C) + // Buttons not on standard controller + Gamepad_SetButton(port, CCPAD_C, mods & CONT_C); + Gamepad_SetButton(port, CCPAD_D, mods & CONT_D); Gamepad_SetButton(port, CCPAD_Z, mods & CONT_Z); Gamepad_SetButton(port, CCPAD_CLEFT, mods & CONT_DPAD2_LEFT); Gamepad_SetButton(port, CCPAD_CRIGHT, mods & CONT_DPAD2_RIGHT); @@ -241,7 +246,7 @@ static void HandleJoystick(int port, int axis, int x, int y, float delta) { static void HandleController(int port, cont_state_t* state, float delta) { Gamepad_SetButton(port, CCPAD_L, state->ltrig > 10); Gamepad_SetButton(port, CCPAD_R, state->rtrig > 10); - // TODO CONT_Z, joysticks + // TODO second joystick // TODO: verify values are right HandleJoystick(port, PAD_AXIS_RIGHT, state->joyx, state->joyy, delta); } diff --git a/src/Window_GCWii.c b/src/Window_GCWii.c index 61bd5d0..74e417b 100644 --- a/src/Window_GCWii.c +++ b/src/Window_GCWii.c @@ -56,13 +56,15 @@ static void InitVideo(void) { VIDEO_WaitVSync(); } -void Window_Init(void) { +void Window_PreInit(void) { // TODO: SYS_SetResetCallback(reload); too? not sure how reset differs on GC/WII #if defined HW_RVL SYS_SetPowerCallback(OnPowerOff); #endif InitVideo(); - +} + +void Window_Init(void) { DisplayInfo.Width = rmode->fbWidth; DisplayInfo.Height = rmode->xfbHeight; DisplayInfo.ScaleX = 1; @@ -333,14 +335,14 @@ static void ProcessNunchuck_Game(int port, int mods, float delta) { Gamepad_SetButton(port, CCPAD_START, mods & WPAD_BUTTON_HOME); Gamepad_SetButton(port, CCPAD_SELECT, mods & WPAD_BUTTON_MINUS); - Input_SetNonRepeatable(KeyBinds_Normal[KEYBIND_FLY], mods & WPAD_BUTTON_LEFT); + Input_SetNonRepeatable(KeyBind_Mappings[BIND_FLY].button1, mods & WPAD_BUTTON_LEFT); if (mods & WPAD_BUTTON_RIGHT) { - Mouse_ScrollWheel(1.0*delta); + Mouse_ScrollVWheel(1.0*delta); } - Input_SetNonRepeatable(KeyBinds_Normal[KEYBIND_THIRD_PERSON], mods & WPAD_BUTTON_UP); - Input_SetNonRepeatable(KeyBinds_Normal[KEYBIND_FLY_DOWN], mods & WPAD_BUTTON_DOWN); + Input_SetNonRepeatable(KeyBind_Mappings[BIND_THIRD_PERSON].button1, mods & WPAD_BUTTON_UP); + Input_SetNonRepeatable(KeyBind_Mappings[BIND_FLY_DOWN].button1, mods & WPAD_BUTTON_DOWN); const float ANGLE_DELTA = 50; bool nunchuckUp = (analog.ang > -ANGLE_DELTA) && (analog.ang < ANGLE_DELTA) && (analog.mag > 0.5); diff --git a/src/Window_MacClassic.c b/src/Window_MacClassic.c new file mode 100644 index 0000000..27e6fb7 --- /dev/null +++ b/src/Window_MacClassic.c @@ -0,0 +1,469 @@ +#include "Core.h" +#if defined CC_BUILD_MACCLASSIC + +#include "_WindowBase.h" +#include "String.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "Options.h" +#include "Errors.h" + +#undef true +#undef false +#include +#include +#include +#include +#ifndef M68K_INLINE +#include +#include +#endif +#include +static WindowPtr win; +static cc_bool hasColorQD, useGWorld; + + +/*########################################################################################################################* +*---------------------------------------------------Imported headers------------------------------------------------------* +*#########################################################################################################################*/ +// On 68k these are implemented using direct 68k opcodes +// On PPC these are implemented using function calls +#if TARGET_CPU_68K + #define MAC_SYSAPI(_type) static _type + #define MAC_ONEWORDINLINE(w1) = w1 + #define MAC_TWOWORDINLINE(w1,w2) = {w1, w2} + #define MAC_THREEWORDINLINE(w1,w2,w3) = {w1, w2, w3} + #define MAC_FOURWORDINLINE(w1,w2,w3,w4) = {w1, w2, w3, w4} +#else + #define MAC_SYSAPI(_type) extern pascal _type + #define MAC_ONEWORDINLINE(w1) + #define MAC_TWOWORDINLINE(w1,w2) + #define MAC_THREEWORDINLINE(w1,w2,w3) + #define MAC_FOURWORDINLINE(w1,w2,w3,w4) +#endif +typedef unsigned long MAC_FourCharCode; +typedef SInt16 MAC_WindowPartCode; + +/*########################################################################################################################* +*--------------------------------------------------Public implementation--------------------------------------------------* +*#########################################################################################################################*/ +static const cc_uint8 key_map[8 * 16] = { +/* 0x00 */ 'A', 'S', 'D', 'F', 'H', 'G', 'Z', 'X', +/* 0x08 */ 'C', 'V', 0, 'B', 'Q', 'W', 'E', 'R', +/* 0x10 */ 'Y', 'T', '1', '2', '3', '4', '6', '5', +/* 0x18 */ CCKEY_EQUALS, '9', '7', CCKEY_MINUS, '8', '0', CCKEY_RBRACKET, 'O', +/* 0x20 */ 'U', CCKEY_LBRACKET, 'I', 'P', CCKEY_ENTER, 'L', 'J', CCKEY_QUOTE, +/* 0x28 */ 'K', CCKEY_SEMICOLON, CCKEY_BACKSLASH, CCKEY_COMMA, CCKEY_SLASH, 'N', 'M', CCKEY_PERIOD, +/* 0x30 */ CCKEY_TAB, CCKEY_SPACE, CCKEY_TILDE, CCKEY_BACKSPACE, 0, CCKEY_ESCAPE, 0, CCKEY_LWIN, +/* 0x38 */ CCKEY_LSHIFT, CCKEY_CAPSLOCK, CCKEY_LALT, CCKEY_LCTRL, 0, 0, 0, 0, +/* 0x40 */ 0, CCKEY_KP_DECIMAL, 0, CCKEY_KP_MULTIPLY, 0, CCKEY_KP_PLUS, 0, CCKEY_NUMLOCK, +/* 0x48 */ CCKEY_VOLUME_UP, CCKEY_VOLUME_DOWN, CCKEY_VOLUME_MUTE, CCKEY_KP_DIVIDE, CCKEY_KP_ENTER, 0, CCKEY_KP_MINUS, 0, +/* 0x50 */ 0, CCKEY_KP_ENTER, CCKEY_KP0, CCKEY_KP1, CCKEY_KP2, CCKEY_KP3, CCKEY_KP4, CCKEY_KP5, +/* 0x58 */ CCKEY_KP6, CCKEY_KP7, 0, CCKEY_KP8, CCKEY_KP9, 'N', 'M', CCKEY_PERIOD, +/* 0x60 */ CCKEY_F5, CCKEY_F6, CCKEY_F7, CCKEY_F3, CCKEY_F8, CCKEY_F9, 0, CCKEY_F11, +/* 0x68 */ 0, CCKEY_F13, 0, CCKEY_F14, 0, CCKEY_F10, 0, CCKEY_F12, +/* 0x70 */ 'U', CCKEY_F15, CCKEY_INSERT, CCKEY_HOME, CCKEY_PAGEUP, CCKEY_DELETE, CCKEY_F4, CCKEY_END, +/* 0x78 */ CCKEY_F2, CCKEY_PAGEDOWN, CCKEY_F1, CCKEY_LEFT, CCKEY_RIGHT, CCKEY_DOWN, CCKEY_UP, 0, +}; +static int MapNativeKey(UInt32 key) { return key < Array_Elems(key_map) ? key_map[key] : 0; } + +void Window_PreInit(void) { + InitGraf(&qd.thePort); + InitFonts(); + InitWindows(); + InitMenus(); + InitDialogs(NULL); + InitCursor(); + + EventRecord event; + for (int i = 0; i < 5; i++) + EventAvail(everyEvent, &event); + FlushEvents(everyEvent, 0); + + long tmpLong = 0; + Gestalt(gestaltQuickdrawVersion, &tmpLong); + hasColorQD = tmpLong >= gestalt32BitQD; +} + +void Window_Init(void) { + Rect r = qd.screenBits.bounds; + DisplayInfo.x = r.left; + DisplayInfo.y = r.top; + DisplayInfo.Width = r.right - r.left; + DisplayInfo.Height = r.bottom - r.top; + + DisplayInfo.ScaleX = 1.0f; + DisplayInfo.ScaleY = 1.0f; +} + +void Window_Free(void) { } + +static void DoCreateWindow(int width, int height) { + if (Window_Main.Exists) return; + + Rect r = qd.screenBits.bounds; + r.top += 40; + InsetRect(&r, 100, 100); + + if (hasColorQD) { + win = NewCWindow(NULL, &r, "\pClassiCube", true, documentProc, (WindowPtr)-1, true, 0); + } else { + win = NewWindow( NULL, &r, "\pClassiCube", true, documentProc, (WindowPtr)-1, true, 0); + } + + if (hasColorQD) { + Platform_LogConst("BLITTING IN FAST MODE"); + } else { + Platform_LogConst("BLITTING IN SLOW MODE"); + } + + useGWorld = hasColorQD; + SetPort(win); + r = win->portRect; + + Window_Main.Width = r.right - r.left; + Window_Main.Height = r.bottom - r.top; + Window_Main.Focused = true; + Window_Main.Exists = true; +} + +void Window_Create2D(int width, int height) { DoCreateWindow(width, height); } +void Window_Create3D(int width, int height) { DoCreateWindow(width, height); } + +void Window_SetTitle(const cc_string* title) { + // TODO +} + +void Clipboard_GetText(cc_string* value) { + Handle tmp = NewHandle(0); + HLock(tmp); + int dataSize = GetScrap(tmp, 'TEXT', 0); + HUnlock(tmp); + + String_AppendAll(value, (char*)tmp, dataSize); + DisposeHandle(tmp); + // TODO +} + +void Clipboard_SetText(const cc_string* value) { + PutScrap(value->length, 'TEXT', value->buffer); + // TODO +} + +int Window_GetWindowState(void) { + return WINDOW_STATE_NORMAL; + // TODO +} + +cc_result Window_EnterFullscreen(void) { + // TODO + return 0; +} + +cc_result Window_ExitFullscreen(void) { + // TODO + return 0; +} + +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { + // TODO +} + +void Window_SetSize(int width, int height) { + // TODO +} + +void Window_RequestClose(void) { + Event_RaiseVoid(&WindowEvents.Closing); +} + + +static void HandleMouseDown(EventRecord* event) { + MAC_WindowPartCode part; + WindowPtr window; + Point localPoint; + + int x, y; + + part = FindWindow(event->where, &window); + switch (part) + { + case inMenuBar: + HiliteMenu(0); + break; + case inSysWindow: + SystemClick(event, window); + break; + case inContent: + SetPt(&localPoint, event->where.h, event->where.v); + GlobalToLocal(&localPoint); + + x = localPoint.h; + y = localPoint.v; + Pointer_SetPosition(0, x, y); + Input_SetPressed(CCMOUSE_L); + break; + case inDrag: + DragWindow(window, event->where, &qd.screenBits.bounds); + break; + case inGoAway: + if (TrackGoAway(window, event->where)) { + Window_RequestClose(); + Window_Main.Exists = false; + } + } +} + + +static void HandleMouseUp(EventRecord* event) { + Input_SetReleased(CCMOUSE_L); +} + +static void HandleKeyDown(EventRecord* event) { + if ((event->modifiers & cmdKey)) + HiliteMenu(0); + + int ch = event->message & 0xFF; + int key = (event->message >> 8) & 0xFF; + + if (ch >= 32 && ch <= 127) + Event_RaiseInt(&InputEvents.Press, (cc_unichar)ch); + + key = MapNativeKey(key); + if (key) Input_SetPressed(key); +} + +static void HandleKeyUp(EventRecord* event) { + int key = (event->message >> 8) & 0xFF; + + key = MapNativeKey(key); + if (key) Input_SetReleased(key); +} + +void Window_ProcessEvents(float delta) { + EventRecord event; + SystemTask(); + + while (GetNextEvent(everyEvent, &event)) { + switch (event.what) + { + case mouseDown: + HandleMouseDown(&event); + break; + case mouseUp: + HandleMouseUp(&event); + break; + case keyDown: + case autoKey: + HandleKeyDown(&event); + break; + case keyUp: + HandleKeyUp(&event); + break; + case updateEvt: + BeginUpdate((WindowPtr)event.message); + EndUpdate( (WindowPtr)event.message); + Event_RaiseVoid(&WindowEvents.RedrawNeeded); + break; + case diskEvt: + if ((event.message & 0xFFFF0000) != noErr) + { + Point pt = { 100, 100 }; + DILoad(); + DIBadMount(pt, event.message); + DIUnload(); + } + break; + case kHighLevelEvent: + AEProcessAppleEvent(&event); + break; + default: + break; + } + } +} + +void Window_ProcessGamepads(float delta) { +} + +static void Cursor_GetRawPos(int* x, int* y) { + Point point; + GetMouse(&point); + + *x = point.h; + *y = point.v; +} + +void Cursor_SetPosition(int x, int y) { + // TODO +} + +static void Cursor_DoSetVisible(cc_bool visible) { + if (visible) { + ShowCursor(); + } else { + HideCursor(); + } +} + +static void ShowDialogCore(const char* title, const char* msg) { + // TODO + for (int i = 0; i < 20; i++) + { + Platform_LogConst(title); + Platform_LogConst(msg); + } +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + // TODO + return ERR_NOT_SUPPORTED; +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + // TODO + return ERR_NOT_SUPPORTED; +} + +static GWorldPtr fb_world; +static PixMapHandle fb_pixmap; +static int fb_stride; +static char* fb_bits; + +void Window_AllocFramebuffer(struct Bitmap* bmp) { + bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels"); + if (!useGWorld) return; + + // TODO bmp->scan0 should be the fb_world + QDErr err = NewGWorld(&fb_world, 32, &win->portRect, 0, 0, 0); + if (err != noErr) Logger_Abort2(err, "Failed to allocate GWorld"); + + fb_pixmap = GetGWorldPixMap(fb_world); + if (!fb_pixmap) Logger_Abort("Failed to allocate pixmap"); + + LockPixels(fb_pixmap); + fb_stride = (*fb_pixmap)->rowBytes & 0x3FFF; + fb_bits = (char*)GetPixBaseAddr(fb_pixmap); +} + +static void DrawFramebufferBulk(Rect2D r, struct Bitmap* bmp) { + GrafPtr thePort = (GrafPtr)win; + BitMap* memBits; + BitMap* winBits; + + for (int y = r.y; y < r.y + r.height; y++) + { + BitmapCol* src = Bitmap_GetRow(bmp, y); + uint32_t* dst = (uint32_t*)(fb_bits + fb_stride * y); + + for (int x = r.x; x < r.x + r.width; x++) + { + dst[x] = src[x]; + } + } + + memBits = &((GrafPtr)fb_world)->portBits; + winBits = &thePort->portBits; + + Rect update; + update.left = r.x; + update.right = r.x + r.width; + update.top = r.y; + update.bottom = r.y + r.height; + + CopyBits(memBits, winBits, &update, &update, srcCopy, nil); +} + +static void DrawFramebufferSlow(Rect2D r, struct Bitmap* bmp) { + for (int y = r.y; y < r.y + r.height; ++y) + { + BitmapCol* row = Bitmap_GetRow(bmp, y); + for (int x = r.x; x < r.x + r.width; ++x) + { + // TODO optimise + BitmapCol col = row[x]; + cc_uint8 R = BitmapCol_R(col); + cc_uint8 G = BitmapCol_G(col); + cc_uint8 B = BitmapCol_B(col); + + RGBColor pixelColor; + pixelColor.red = R << 8; + pixelColor.green = G << 8; + pixelColor.blue = B << 8; + + RGBForeColor(&pixelColor); + MoveTo(x, y); + Line(0, 0); + //SetCPixel(x, y, &pixelColor); + } + } +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + SetPort(win); + + if (useGWorld) { + DrawFramebufferBulk(r, bmp); + } else { + DrawFramebufferSlow(r, bmp); + } +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + Mem_Free(bmp->scan0); + if (!useGWorld) return; + + UnlockPixels(fb_pixmap); + DisposeGWorld(fb_world); +} + +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { } +void OnscreenKeyboard_SetText(const cc_string* text) { } +void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { } +void OnscreenKeyboard_Draw3D(void) { } +void OnscreenKeyboard_Close(void) { } + +void Window_EnableRawMouse(void) { + DefaultEnableRawMouse(); +} + +void Window_UpdateRawMouse(void) { + DefaultUpdateRawMouse(); +} + +void Window_DisableRawMouse(void) { + DefaultDisableRawMouse(); +} + + +/*########################################################################################################################* +*-------------------------------------------------------WGL OpenGL--------------------------------------------------------* +*#########################################################################################################################*/ +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && !defined CC_BUILD_EGL +void GLContext_Create(void) { + // TODO +} + +void GLContext_Update(void) { } +cc_bool GLContext_TryRestore(void) { return true; } +void GLContext_Free(void) { + // TODO +} + +void* GLContext_GetAddress(const char* function) { + return NULL; +} + +cc_bool GLContext_SwapBuffers(void) { + // TODO + return true; +} + +void GLContext_SetFpsLimit(cc_bool vsync, float minFrameMs) { + // TODO +} +void GLContext_GetApiInfo(cc_string* info) { } +#endif +#endif diff --git a/src/Window_N64.c b/src/Window_N64.c index d42f41d..f65379d 100644 --- a/src/Window_N64.c +++ b/src/Window_N64.c @@ -17,10 +17,12 @@ static cc_bool launcherMode; struct _DisplayData DisplayInfo; struct _WindowData WindowInfo; -void Window_Init(void) { +void Window_PreInit(void) { display_init(RESOLUTION_320x240, DEPTH_32_BPP, 2, GAMMA_NONE, FILTERS_DISABLED); - //display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, ANTIALIAS_RESAMPLE_FETCH_ALWAYS); - + //display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, ANTIALIAS_RESAMPLE_FETCH_ALWAYS); +} + +void Window_Init(void) { DisplayInfo.Width = display_get_width(); DisplayInfo.Height = display_get_height(); DisplayInfo.ScaleX = 0.5f; @@ -37,22 +39,22 @@ void Window_Init(void) { joypad_init(); // change defaults to make more sense for N64 - cc_uint8* binds = (cc_uint8*)KeyBind_GamepadDefaults; - binds[KEYBIND_JUMP] = CCPAD_A; - binds[KEYBIND_INVENTORY] = CCPAD_B; - binds[KEYBIND_PLACE_BLOCK] = CCPAD_Z; - binds[KEYBIND_HOTBAR_RIGHT] = CCPAD_L; - binds[KEYBIND_DELETE_BLOCK] = CCPAD_R; - - binds[KEYBIND_FORWARD] = CCPAD_CUP; - binds[KEYBIND_BACK] = CCPAD_CDOWN; - binds[KEYBIND_LEFT] = CCPAD_CLEFT; - binds[KEYBIND_RIGHT] = CCPAD_CRIGHT; - - binds[KEYBIND_FLY_UP] = CCPAD_UP; - binds[KEYBIND_FLY_DOWN] = CCPAD_DOWN; - binds[KEYBIND_SPEED] = CCPAD_LEFT; - binds[KEYBIND_FLY] = CCPAD_RIGHT; + BindMapping* binds = (BindMapping*)PadBind_Defaults; + BindMapping_Set(&binds[BIND_JUMP], CCPAD_A, 0); + BindMapping_Set(&binds[BIND_INVENTORY], CCPAD_B, 0); + BindMapping_Set(&binds[BIND_PLACE_BLOCK], CCPAD_Z, 0); + BindMapping_Set(&binds[BIND_HOTBAR_RIGHT], CCPAD_L, 0); + BindMapping_Set(&binds[BIND_DELETE_BLOCK], CCPAD_R, 0); + + BindMapping_Set(&binds[BIND_FORWARD], CCPAD_CUP, 0); + BindMapping_Set(&binds[BIND_BACK], CCPAD_CDOWN, 0); + BindMapping_Set(&binds[BIND_LEFT], CCPAD_CLEFT, 0); + BindMapping_Set(&binds[BIND_RIGHT], CCPAD_CRIGHT, 0); + + BindMapping_Set(&binds[BIND_FLY_UP], CCPAD_UP, 0); + BindMapping_Set(&binds[BIND_FLY_DOWN], CCPAD_DOWN, 0); + BindMapping_Set(&binds[BIND_SPEED], CCPAD_LEFT, 0); + BindMapping_Set(&binds[BIND_FLY], CCPAD_RIGHT, 0); } void Window_Free(void) { } diff --git a/src/Window_NDS.c b/src/Window_NDS.c index 87516b5..4eef854 100644 --- a/src/Window_NDS.c +++ b/src/Window_NDS.c @@ -133,6 +133,14 @@ static u16* bg_ptr; struct _DisplayData DisplayInfo; struct _WindowData WindowInfo; +void Window_PreInit(void) { + videoSetModeSub(MODE_0_2D); + vramSetBankH(VRAM_H_SUB_BG); + vramSetBankI(VRAM_I_SUB_BG_0x06208000); + setBrightness(2, 0); + consoleInit(); +} + void Window_Init(void) { DisplayInfo.Width = SCREEN_WIDTH; DisplayInfo.Height = SCREEN_HEIGHT; @@ -147,19 +155,6 @@ void Window_Init(void) { Window_Main.SoftKeyboard = SOFT_KEYBOARD_RESIZE; Input_SetTouchMode(true); Input.Sources = INPUT_SOURCE_GAMEPAD; - - videoSetModeSub(MODE_0_2D); - vramSetBankH(VRAM_H_SUB_BG); - vramSetBankI(VRAM_I_SUB_BG_0x06208000); - setBrightness(2, 0); - consoleInit(); - - cc_bool dsiMode = isDSiMode(); - Platform_Log1("Running in %c mode", dsiMode ? "DSi" : "DS"); - - char* dir = fatGetDefaultCwd(); - if (dir) Platform_Log1("CWD: %c", dir); - Mem_Free(dir); } void Window_Free(void) { } diff --git a/src/Window_PS1.c b/src/Window_PS1.c index 7fe7759..2bcc7c4 100644 --- a/src/Window_PS1.c +++ b/src/Window_PS1.c @@ -29,6 +29,7 @@ static char pad_buff[2][34]; struct _DisplayData DisplayInfo; struct _WindowData WindowInfo; +void Window_PreInit(void) { } void Window_Init(void) { DisplayInfo.Width = SCREEN_XRES; DisplayInfo.Height = SCREEN_YRES; diff --git a/src/Window_PS2.c b/src/Window_PS2.c index 7442818..a51a209 100644 --- a/src/Window_PS2.c +++ b/src/Window_PS2.c @@ -28,6 +28,7 @@ static char padBuf[256] __attribute__((aligned(64))); struct _DisplayData DisplayInfo; struct _WindowData WindowInfo; +void Window_PreInit(void) { } void Window_Init(void) { DisplayInfo.Width = 640; DisplayInfo.Height = graph_get_region() == GRAPH_MODE_PAL ? 512 : 448; diff --git a/src/Window_PS3.c b/src/Window_PS3.c index 445e271..24cc1b1 100644 --- a/src/Window_PS3.c +++ b/src/Window_PS3.c @@ -36,9 +36,11 @@ static void sysutil_callback(u64 status, u64 param, void* usrdata) { } } -void Window_Init(void) { +void Window_PreInit(void) { sysUtilRegisterCallback(0, sysutil_callback, NULL); - +} + +void Window_Init(void) { videoState state; videoResolution resolution; diff --git a/src/Window_PSP.c b/src/Window_PSP.c index 9fd59bf..31e294e 100644 --- a/src/Window_PSP.c +++ b/src/Window_PSP.c @@ -24,6 +24,11 @@ static cc_bool launcherMode; struct _DisplayData DisplayInfo; struct _WindowData WindowInfo; +void Window_PreInit(void) { + sceCtrlSetSamplingCycle(0); + sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); +} + void Window_Init(void) { DisplayInfo.Width = SCREEN_WIDTH; DisplayInfo.Height = SCREEN_HEIGHT; @@ -36,9 +41,6 @@ void Window_Init(void) { Window_Main.Exists = true; Input.Sources = INPUT_SOURCE_GAMEPAD; - sceCtrlSetSamplingCycle(0); - sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG); - sceDisplaySetMode(0, SCREEN_WIDTH, SCREEN_HEIGHT); } diff --git a/src/Window_PSVita.c b/src/Window_PSVita.c index 2f9c733..71f5eda 100644 --- a/src/Window_PSVita.c +++ b/src/Window_PSVita.c @@ -30,6 +30,12 @@ extern void Gfx_UpdateCommonDialogBuffers(void); extern void (*DQ_OnNextFrame)(void* fb); static void DQ_OnNextFrame2D(void* fb); +void Window_PreInit(void) { + sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG); + sceTouchSetSamplingState(SCE_TOUCH_PORT_FRONT, SCE_TOUCH_SAMPLING_STATE_START); + sceTouchSetSamplingState(SCE_TOUCH_PORT_BACK, SCE_TOUCH_SAMPLING_STATE_START); +} + void Window_Init(void) { DisplayInfo.Width = DISPLAY_WIDTH; DisplayInfo.Height = DISPLAY_HEIGHT; @@ -44,13 +50,8 @@ void Window_Init(void) { Window_Main.SoftKeyboard = SOFT_KEYBOARD_RESIZE; Input_SetTouchMode(true); Input.Sources = INPUT_SOURCE_GAMEPAD; - - sceCtrlSetSamplingMode(SCE_CTRL_MODE_ANALOG); - sceTouchSetSamplingState(SCE_TOUCH_PORT_FRONT, SCE_TOUCH_SAMPLING_STATE_START); - sceTouchSetSamplingState(SCE_TOUCH_PORT_BACK, SCE_TOUCH_SAMPLING_STATE_START); sceTouchGetPanelInfo(SCE_TOUCH_PORT_FRONT, &frontPanel); - Gfx_InitGXM(); Gfx_AllocFramebuffers(); } diff --git a/src/Window_SDL.c b/src/Window_SDL.c index 5eb653f..9d27cd8 100644 --- a/src/Window_SDL.c +++ b/src/Window_SDL.c @@ -1,5 +1,5 @@ #include "Core.h" -#if defined CC_BUILD_SDL2 +#if CC_WIN_BACKEND == CC_WIN_BACKEND_SDL2 #include "_WindowBase.h" #include "Graphics.h" #include "String.h" @@ -52,9 +52,12 @@ static void Window_SDLFail(const char* place) { Logger_Abort(str.buffer); } +void Window_PreInit(void) { + SDL_Init(SDL_INIT_VIDEO); +} + void Window_Init(void) { SDL_DisplayMode mode = { 0 }; - SDL_Init(SDL_INIT_VIDEO); SDL_GetDesktopDisplayMode(0, &mode); Input.Sources = INPUT_SOURCE_NORMAL; @@ -67,6 +70,20 @@ void Window_Init(void) { void Window_Free(void) { } + +#ifdef CC_BUILD_ICON +/* See misc/sdl/sdl_icon_gen.cs for how to generate this file */ +#include "../misc/sdl/CCIcon_SDL.h" + +static void ApplyIcon(void) { + SDL_Surface* surface = SDL_CreateRGBSurfaceFrom(CCIcon_Data, CCIcon_Width, CCIcon_Height, 32, CCIcon_Pitch, + 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); + SDL_SetWindowIcon(win_handle, surface); +} +#else +static void ApplyIcon(void) { } +#endif + static void DoCreateWindow(int width, int height, int flags) { win_handle = SDL_CreateWindow(NULL, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, flags | SDL_WINDOW_RESIZABLE); @@ -75,10 +92,12 @@ static void DoCreateWindow(int width, int height, int flags) { RefreshWindowBounds(); Window_Main.Exists = true; Window_Main.Handle = win_handle; + ApplyIcon(); /* TODO grab using SDL_SetWindowGrab? seems to be unnecessary on Linux at least */ } + void Window_Create2D(int width, int height) { DoCreateWindow(width, height, 0); } -#if !defined CC_BUILD_SOFTGPU +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) void Window_Create3D(int width, int height) { DoCreateWindow(width, height, SDL_WINDOW_OPENGL); } #else void Window_Create3D(int width, int height) { DoCreateWindow(width, height, 0); } @@ -189,6 +208,15 @@ static int MapNativeKey(SDL_Keycode k) { case SDLK_RSHIFT: return CCKEY_RSHIFT; case SDLK_RALT: return CCKEY_RALT; case SDLK_RGUI: return CCKEY_RWIN; + + case SDLK_AUDIONEXT: return CCKEY_MEDIA_NEXT; + case SDLK_AUDIOPREV: return CCKEY_MEDIA_PREV; + case SDLK_AUDIOPLAY: return CCKEY_MEDIA_PLAY; + case SDLK_AUDIOSTOP: return CCKEY_MEDIA_STOP; + + case SDLK_AUDIOMUTE: return CCKEY_VOLUME_MUTE; + case SDLK_VOLUMEDOWN: return CCKEY_VOLUME_DOWN; + case SDLK_VOLUMEUP: return CCKEY_VOLUME_UP; } return INPUT_NONE; } @@ -270,7 +298,8 @@ void Window_ProcessEvents(float delta) { case SDL_MOUSEBUTTONUP: OnMouseEvent(&e); break; case SDL_MOUSEWHEEL: - Mouse_ScrollWheel(e.wheel.y); + Mouse_ScrollHWheel(e.wheel.x); + Mouse_ScrollVWheel(e.wheel.y); break; case SDL_MOUSEMOTION: Pointer_SetPosition(0, e.motion.x, e.motion.y); @@ -430,7 +459,7 @@ void Window_DisableRawMouse(void) { /*########################################################################################################################* *-----------------------------------------------------OpenGL context------------------------------------------------------* *#########################################################################################################################*/ -#if defined CC_BUILD_GL && !defined CC_BUILD_EGL +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && !defined CC_BUILD_EGL static SDL_GLContext win_ctx; void GLContext_Create(void) { diff --git a/src/Window_SDL3.c b/src/Window_SDL3.c index b2d7d33..cbb2a5b 100644 --- a/src/Window_SDL3.c +++ b/src/Window_SDL3.c @@ -1,5 +1,5 @@ #include "Core.h" -#if defined CC_BUILD_SDL3 +#if CC_WIN_BACKEND == CC_WIN_BACKEND_SDL3 #include "_WindowBase.h" #include "Graphics.h" #include "String.h" @@ -24,11 +24,14 @@ static void Window_SDLFail(const char* place) { Logger_Abort(str.buffer); } -void Window_Init(void) { +void Window_PreInit(void) { SDL_Init(SDL_INIT_VIDEO); #ifdef CC_BUILD_FLATPAK SDL_SetHint(SDL_HINT_APP_ID, "net.classicube.flatpak.client"); #endif +} + +void Window_Init(void) { int displayID = SDL_GetPrimaryDisplay(); Input.Sources = INPUT_SOURCE_NORMAL; @@ -44,6 +47,19 @@ void Window_Init(void) { void Window_Free(void) { } +#ifdef CC_BUILD_ICON +/* See misc/sdl/sdl_icon_gen.cs for how to generate this file */ +#include "../misc/sdl/CCIcon_SDL.h" + +static void ApplyIcon(void) { + SDL_Surface* surface = SDL_CreateSurfaceFrom(CCIcon_Data, CCIcon_Width, CCIcon_Height, + CCIcon_Pitch, SDL_PIXELFORMAT_BGRA8888); + SDL_SetWindowIcon(win_handle, surface); +} +#else +static void ApplyIcon(void) { } +#endif + static void DoCreateWindow(int width, int height, int flags) { SDL_PropertiesID props = SDL_CreateProperties(); SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, SDL_WINDOWPOS_CENTERED); @@ -59,10 +75,16 @@ static void DoCreateWindow(int width, int height, int flags) { RefreshWindowBounds(); Window_Main.Exists = true; Window_Main.Handle = win_handle; + ApplyIcon(); /* TODO grab using SDL_SetWindowGrab? seems to be unnecessary on Linux at least */ } + void Window_Create2D(int width, int height) { DoCreateWindow(width, height, 0); } +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) void Window_Create3D(int width, int height) { DoCreateWindow(width, height, SDL_WINDOW_OPENGL); } +#else +void Window_Create3D(int width, int height) { DoCreateWindow(width, height, 0); } +#endif void Window_SetTitle(const cc_string* title) { char str[NATIVE_STR_LEN]; @@ -133,7 +155,7 @@ static int MapNativeKey(SDL_Keycode k) { case SDLK_BACKSPACE: return CCKEY_BACKSPACE; case SDLK_TAB: return CCKEY_TAB; case SDLK_SPACE: return CCKEY_SPACE; - case SDLK_QUOTE: return CCKEY_QUOTE; + case SDLK_APOSTROPHE: return CCKEY_QUOTE; case SDLK_EQUALS: return CCKEY_EQUALS; case SDLK_COMMA: return CCKEY_COMMA; case SDLK_MINUS: return CCKEY_MINUS; @@ -143,7 +165,7 @@ static int MapNativeKey(SDL_Keycode k) { case SDLK_LEFTBRACKET: return CCKEY_LBRACKET; case SDLK_BACKSLASH: return CCKEY_BACKSLASH; case SDLK_RIGHTBRACKET: return CCKEY_RBRACKET; - case SDLK_BACKQUOTE: return CCKEY_TILDE; + case SDLK_GRAVE: return CCKEY_TILDE; case SDLK_CAPSLOCK: return CCKEY_CAPSLOCK; case SDLK_PRINTSCREEN: return CCKEY_PRINTSCREEN; case SDLK_SCROLLLOCK: return CCKEY_SCROLLLOCK; @@ -176,6 +198,15 @@ static int MapNativeKey(SDL_Keycode k) { case SDLK_RSHIFT: return CCKEY_RSHIFT; case SDLK_RALT: return CCKEY_RALT; case SDLK_RGUI: return CCKEY_RWIN; + + case SDLK_AUDIONEXT: return CCKEY_MEDIA_NEXT; + case SDLK_AUDIOPREV: return CCKEY_MEDIA_PREV; + case SDLK_AUDIOPLAY: return CCKEY_MEDIA_PLAY; + case SDLK_AUDIOSTOP: return CCKEY_MEDIA_STOP; + + case SDLK_AUDIOMUTE: return CCKEY_VOLUME_MUTE; + case SDLK_VOLUMEDOWN: return CCKEY_VOLUME_DOWN; + case SDLK_VOLUMEUP: return CCKEY_VOLUME_UP; } return INPUT_NONE; } @@ -230,7 +261,8 @@ void Window_ProcessEvents(float delta) { case SDL_EVENT_MOUSE_BUTTON_UP: OnMouseEvent(&e); break; case SDL_EVENT_MOUSE_WHEEL: - Mouse_ScrollWheel(e.wheel.y); + Mouse_ScrollHWheel(e.wheel.x); + Mouse_ScrollVWheel(e.wheel.y); break; case SDL_EVENT_MOUSE_MOTION: Pointer_SetPosition(0, e.motion.x, e.motion.y); @@ -460,7 +492,7 @@ void Window_DisableRawMouse(void) { /*########################################################################################################################* *-----------------------------------------------------OpenGL context------------------------------------------------------* *#########################################################################################################################*/ -#if defined CC_BUILD_GL && !defined CC_BUILD_EGL +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && !defined CC_BUILD_EGL static SDL_GLContext win_ctx; void GLContext_Create(void) { diff --git a/src/Window_Saturn.c b/src/Window_Saturn.c index df8677c..5c9eb0e 100644 --- a/src/Window_Saturn.c +++ b/src/Window_Saturn.c @@ -20,7 +20,6 @@ #define SCREEN_HEIGHT 224 static cc_bool launcherMode; -static smpc_peripheral_digital_t state; struct _DisplayData DisplayInfo; struct _WindowData WindowInfo; @@ -29,6 +28,7 @@ static void OnVblank(void* work) { smpc_peripheral_intback_issue(); } +void Window_PreInit(void) { } void Window_Init(void) { DisplayInfo.Width = SCREEN_WIDTH; DisplayInfo.Height = SCREEN_HEIGHT; @@ -96,6 +96,9 @@ static void ProcessButtons(int port, int mods) { Gamepad_SetButton(port, CCPAD_A, mods & PERIPHERAL_DIGITAL_A); Gamepad_SetButton(port, CCPAD_B, mods & PERIPHERAL_DIGITAL_B); Gamepad_SetButton(port, CCPAD_X, mods & PERIPHERAL_DIGITAL_C); + + Gamepad_SetButton(port, CCPAD_Y, mods & PERIPHERAL_DIGITAL_X); + Gamepad_SetButton(port, CCPAD_Z, mods & PERIPHERAL_DIGITAL_Y); Gamepad_SetButton(port, CCPAD_L, mods & PERIPHERAL_DIGITAL_L); Gamepad_SetButton(port, CCPAD_R, mods & PERIPHERAL_DIGITAL_R); @@ -109,15 +112,58 @@ static void ProcessButtons(int port, int mods) { Gamepad_SetButton(port, CCPAD_DOWN, mods & PERIPHERAL_DIGITAL_DOWN); } +static smpc_peripheral_digital_t dig_state; +static smpc_peripheral_analog_t ana_state; + void Window_ProcessGamepads(float delta) { - smpc_peripheral_digital_port(1, &state); - ProcessButtons(0, state.pressed.raw | state.held.raw); + smpc_peripheral_digital_port(1, &dig_state); + ProcessButtons(0, dig_state.pressed.raw | dig_state.held.raw); + + smpc_peripheral_analog_port(1, &ana_state); } /*########################################################################################################################* *------------------------------------------------------Framebuffer--------------------------------------------------------* *#########################################################################################################################*/ +static const vdp2_vram_cycp_t vram_cycp = { + .pt[0].t0 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[0].t1 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[0].t2 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[0].t3 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[0].t4 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[0].t5 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[0].t6 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[0].t7 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + + .pt[1].t0 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[1].t1 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[1].t2 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[1].t3 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[1].t4 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[1].t5 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[1].t6 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[1].t7 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + + .pt[2].t0 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[2].t1 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[2].t2 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[2].t3 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[2].t4 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[2].t5 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[2].t6 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[2].t7 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + + .pt[3].t0 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[3].t1 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[3].t2 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[3].t3 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[3].t4 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[3].t5 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[3].t6 = VDP2_VRAM_CYCP_CHPNDR_NBG0, + .pt[3].t7 = VDP2_VRAM_CYCP_CHPNDR_NBG0 +}; + void Window_Create2D(int width, int height) { launcherMode = true; @@ -130,48 +176,10 @@ void Window_Create2D(int width, int height) { }; vdp2_scrn_bitmap_format_set(&format); - vdp2_scrn_priority_set(VDP2_SCRN_NBG0, 7); + vdp2_scrn_priority_set(VDP2_SCRN_NBG0, 5); vdp2_scrn_display_set(VDP2_SCRN_DISP_NBG0); - - const vdp2_vram_cycp_t vram_cycp = { - .pt[0].t0 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[0].t1 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[0].t2 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[0].t3 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[0].t4 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[0].t5 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[0].t6 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[0].t7 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - - .pt[1].t0 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[1].t1 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[1].t2 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[1].t3 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[1].t4 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[1].t5 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[1].t6 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[1].t7 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - - .pt[2].t0 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[2].t1 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[2].t2 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[2].t3 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[2].t4 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[2].t5 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[2].t6 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[2].t7 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - - .pt[3].t0 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[3].t1 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[3].t2 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[3].t3 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[3].t4 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[3].t5 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[3].t6 = VDP2_VRAM_CYCP_CHPNDR_NBG0, - .pt[3].t7 = VDP2_VRAM_CYCP_CHPNDR_NBG0 - }; - - vdp2_vram_cycp_set(&vram_cycp); + + vdp2_vram_cycp_set(&vram_cycp); } void Window_AllocFramebuffer(struct Bitmap* bmp) { @@ -192,10 +200,10 @@ void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { { // TODO optimise BitmapCol col = row[x]; - cc_uint8 r = BitmapCol_R(col); - cc_uint8 g = BitmapCol_G(col); - cc_uint8 b = BitmapCol_B(col); - vram[x + (y * 512)] = RGB1555(0, r >> 3, g >> 3, b >> 3); + cc_uint8 R = BitmapCol_R(col); + cc_uint8 G = BitmapCol_G(col); + cc_uint8 B = BitmapCol_B(col); + vram[x + (y * 512)] = RGB1555(0, R >> 3, G >> 3, B >> 3); } } diff --git a/src/Window_Switch.c b/src/Window_Switch.c index 94b695a..51c2032 100644 --- a/src/Window_Switch.c +++ b/src/Window_Switch.c @@ -51,13 +51,17 @@ static void Applet_Event(AppletHookType type, void* param) { } } -void Window_Init(void) { +void Window_PreInit(void) { // Configure our supported input layout: a single player with standard controller styles padConfigureInput(1, HidNpadStyleSet_NpadStandard); hidInitializeTouchScreen(); // Initialize the default gamepad (which reads handheld mode inputs as well as the first connected controller) padInitializeDefault(&pad); + + appletHook(&cookie, Applet_Event, NULL); +} +void Window_Init(void) { DisplayInfo.Depth = 4; // 32 bit TODO wrong, this is actually 4 bit DisplayInfo.ScaleX = 1; DisplayInfo.ScaleY = 1; @@ -72,8 +76,6 @@ void Window_Init(void) { Input.Sources = INPUT_SOURCE_GAMEPAD; nwindowSetDimensions(Window_Main.Handle, 1920, 1080); - - appletHook(&cookie, Applet_Event, NULL); SetResolution(); } diff --git a/src/Window_Terminal.c b/src/Window_Terminal.c new file mode 100644 index 0000000..0f776dc --- /dev/null +++ b/src/Window_Terminal.c @@ -0,0 +1,528 @@ +#include "Core.h" +#if CC_WIN_BACKEND == CC_WIN_BACKEND_TERMINAL +#include "_WindowBase.h" +#include "String.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "Options.h" +#include "Errors.h" +#include "Utils.h" +#include +#include +#include +#include + +#ifdef CC_BUILD_WIN +#include +#else +#include +#include +#include +#include +#endif + +#ifdef CC_BUILD_LINUX +#include +#include +#endif + +static cc_bool pendingResize, pendingClose; +#define CSI "\x1B[" + +#define ERASE_CMD(cmd) CSI cmd "J" +#define DEC_PM_SET(cmd) CSI "?" cmd "h" +#define DEC_PM_RESET(cmd) CSI "?" cmd "1" + +#ifdef CC_BUILD_WIN +static HANDLE hStdin, hStdout; +static DWORD inOldMode, outOldMode; + +static void UpdateDimensions(void) { + CONSOLE_SCREEN_BUFFER_INFO csbi = { 0 }; + int cols, rows; + + GetConsoleScreenBufferInfo(hStdout, &csbi); + cols = csbi.srWindow.Right - csbi.srWindow.Left + 1; + rows = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; + Platform_Log2("RESIZE: %i, %i", &cols, &rows); + + DisplayInfo.Width = cols; + DisplayInfo.Height = rows * 2; + Window_Main.Width = DisplayInfo.Width; + Window_Main.Height = DisplayInfo.Height; +} + +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif + +static void HookTerminal(void) { + hStdin = GetStdHandle(STD_INPUT_HANDLE); + hStdout = GetStdHandle(STD_OUTPUT_HANDLE); + + GetConsoleMode(hStdin, &inOldMode); + GetConsoleMode(hStdout, &outOldMode); + SetConsoleOutputCP(CP_UTF8); + + SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT); + SetConsoleMode(hStdout, ENABLE_VIRTUAL_TERMINAL_PROCESSING | ENABLE_PROCESSED_OUTPUT); +} + +static void UnhookTerminal(void) { + SetConsoleMode(hStdin, inOldMode); + SetConsoleMode(hStdout, outOldMode); +} + +static BOOL WINAPI consoleHandler(DWORD signal) { + if (signal == CTRL_C_EVENT) pendingClose = true; + return true; +} + +static void sigterm_handler(int sig) { pendingClose = true; UnhookTerminal(); } + +static void HookSignals(void) { + SetConsoleCtrlHandler(consoleHandler, TRUE); + + signal(SIGTERM, sigterm_handler); + signal(SIGINT, sigterm_handler); +} +#else +// Inspired from https://github.com/Cubified/tuibox/blob/main/tuibox.h#L606 +// Uses 'â–„' to double the vertical resolution +// (this trick was inspired from https://github.com/ichinaski/pxl/blob/master/main.go#L30) +static struct termios tio; +static struct winsize ws; +#ifdef CC_BUILD_LINUX +static int orig_KB = K_XLATE; +#endif + +static void UpdateDimensions(void) { + ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws); + + DisplayInfo.Width = ws.ws_col; + DisplayInfo.Height = ws.ws_row * 2; + Window_Main.Width = DisplayInfo.Width; + Window_Main.Height = DisplayInfo.Height; +} + +static void HookTerminal(void) { + struct termios raw; + + tcgetattr(STDIN_FILENO, &tio); + raw = tio; + raw.c_lflag &= ~(ECHO | ICANON); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw); + + // https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Normal-tracking-mode + printf(DEC_PM_SET("1049")); // Use Normal Screen Buffer and restore cursor as in DECRC, xterm. + printf(CSI "0m"); + printf(ERASE_CMD("2")); // Ps = 2 ⇒ Erase All. + printf(DEC_PM_SET("1003")); // Ps = 1 0 0 3 ⇒ Use All Motion Mouse Tracking, xterm. See + printf(DEC_PM_SET("1015")); // Ps = 1 0 1 5 ⇒ Enable urxvt Mouse Mode. + printf(DEC_PM_SET("1006")); // Ps = 1 0 0 6 ⇒ Enable SGR Mouse Mode, xterm. + printf(DEC_PM_RESET("25")); // Ps = 2 5 ⇒ Show cursor (DECTCEM), VT220. +} + +static void UnhookTerminal(void) { + //ioctl(STDIN_FILENO, KDSKBMODE, orig_KB); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); + + printf(DEC_PM_RESET("1049")); + printf(CSI "0m"); + printf(ERASE_CMD("2")); // Ps = 2 ⇒ Erase All. + printf(DEC_PM_RESET("1003")); + printf(DEC_PM_RESET("1015")); + printf(DEC_PM_RESET("1006")); + printf(DEC_PM_SET("25")); +} + +static void sigwinch_handler(int sig) { pendingResize = true; } +static void sigterm_handler(int sig) { pendingClose = true; UnhookTerminal(); } + +static void HookSignals(void) { + signal(SIGWINCH, sigwinch_handler); + signal(SIGTERM, sigterm_handler); + signal(SIGINT, sigterm_handler); +} +#endif + +void Window_PreInit(void) { } +void Window_Init(void) { + Input.Sources = INPUT_SOURCE_NORMAL; + DisplayInfo.Depth = 4; + DisplayInfo.ScaleX = 0.5f; + DisplayInfo.ScaleY = 0.5f; + + //ioctl(STDIN_FILENO , KDGKBMODE, &orig_KB); + //ioctl(STDIN_FILENO, KDSKBMODE, K_MEDIUMRAW); + HookTerminal(); + UpdateDimensions(); + HookSignals(); +} + +void Window_Free(void) { + UnhookTerminal(); +} + +static void DoCreateWindow(int width, int height) { + Window_Main.Exists = true; + Window_Main.Handle = (void*)1; + Window_Main.Focused = true; +} +void Window_Create2D(int width, int height) { DoCreateWindow(width, height); } +void Window_Create3D(int width, int height) { DoCreateWindow(width, height); } + +void Window_SetTitle(const cc_string* title) { + // TODO +} + +void Clipboard_GetText(cc_string* value) { + // TODO +} + +void Clipboard_SetText(const cc_string* value) { + // TODO +} + +int Window_GetWindowState(void) { + return WINDOW_STATE_NORMAL; +} + +cc_result Window_EnterFullscreen(void) { + return 0; +} +cc_result Window_ExitFullscreen(void) { + return 0; +} + +int Window_IsObscured(void) { return 0; } + +void Window_Show(void) { } + +void Window_SetSize(int width, int height) { + // TODO +} + +void Window_RequestClose(void) { + // TODO +} + +#ifdef CC_BUILD_WIN +static void KeyEventProc(KEY_EVENT_RECORD ker) +{ + if(ker.bKeyDown) + Platform_LogConst("key pressed"); + else + Platform_LogConst("key released"); +} + +static VOID MouseEventProc(MOUSE_EVENT_RECORD mer) { + switch(mer.dwEventFlags) + { + case 0: + if(mer.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) + { + Platform_LogConst("left button press"); + } + else if(mer.dwButtonState == RIGHTMOST_BUTTON_PRESSED) + { + Platform_LogConst("right button press"); + } + else + { + Platform_LogConst("button press"); + } + break; + case DOUBLE_CLICK: + Platform_LogConst("double click"); + break; + case MOUSE_MOVED: + Platform_LogConst("mouse moved"); + break; + case MOUSE_WHEELED: + Platform_LogConst("vertical mouse wheel"); + break; + default: + Platform_LogConst("unknown"); + break; + } +} + +static void ProcessConsoleEvents(float delta) { + DWORD events = 0; + GetNumberOfConsoleInputEvents(hStdin, &events); + if (!events) return; + + INPUT_RECORD buffer[128]; + if (!ReadConsoleInput(hStdin, buffer, 128, &events)) return; + + for (int i = 0; i < events; i++) + { + switch (buffer[i].EventType) + { + case KEY_EVENT: + KeyEventProc(buffer[i].Event.KeyEvent); + break; + case MOUSE_EVENT: + MouseEventProc(buffer[i].Event.MouseEvent); + break; + case WINDOW_BUFFER_SIZE_EVENT: + pendingResize = true; + break; + } + } +} + +#else +static int MapNativeMouse(int button) { + if (button == 1) return CCMOUSE_L; + if (button == 2) return CCMOUSE_M; + if (button == 3) return CCMOUSE_R; + + if (button == 8) return CCMOUSE_X1; + if (button == 9) return CCMOUSE_X2; + + /* Mouse horizontal and vertical scroll */ + if (button >= 4 && button <= 7) return 0; + Platform_Log1("Unknown mouse button: %i", &button); + return 0; +} + +static int stdin_available(void) { + struct pollfd pfd; + pfd.fd = STDIN_FILENO; + pfd.events = POLLIN; + + if (poll(&pfd, 1, 0)) { + if (pfd.revents & POLLIN) return 1; + } + return 0; +} + +#define ExtractXY() \ + tok = strtok(NULL, ";"); \ + x = atoi(tok); \ + tok = strtok(NULL, ";"); \ + y = atoi(tok) * 2; + +static void ProcessMouse(char* buf, int n) { + char cpy[256 + 2]; + strncpy(cpy, buf, n); + char* tok = strtok(cpy + 3, ";"); + int x, y, mouse; + if (!tok) return; + + switch (tok[0]){ + case '0': + mouse = strchr(buf, 'm') == NULL; + ExtractXY(); + Pointer_SetPosition(0, x, y); + Input_SetNonRepeatable(CCMOUSE_L, mouse); + break; + case '3': + mouse = (strcmp(tok, "32") == 0); + ExtractXY(); + Pointer_SetPosition(0, x, y); + break; + } +} + +static int MapKey(int key) { + if (key == ' ') return CCKEY_SPACE; + + if (key >= 'a' && key <= 'z') key -= 32; + if (key >= 'A' && key <= 'Z') return key; + + Platform_Log1("Unknown key: %i", &key); + return 0; +} + +static float event_time; +static float press_start[256]; +static void ProcessKey(int raw) { + int key = MapKey(raw); + if (key) { + Input_SetPressed(key); + press_start[raw] = event_time; + } + + if (raw >= 32 && raw < 127) { + Event_RaiseInt(&InputEvents.Press, raw); + } +} + +static void ProcessConsoleInput(void) { + char buf[256]; + + int n = read(STDIN_FILENO, buf, sizeof(buf)); + int A = buf[0]; + //Platform_Log2("IN: %i, %i", &n, &A); + + if (n >= 4 && buf[0] == '\x1b' && buf[1] == '[' && buf[2] == '<') { + ProcessMouse(buf, n); + } else if (buf[0] >= 32 && buf[0] < 127) { + ProcessKey(buf[0]); + } +} + +static void ProcessConsoleEvents(float delta) { + if (stdin_available()) ProcessConsoleInput(); + + event_time += delta; + // Auto release keys after a while + for (int i = 0; i < 256; i++) + { + if (press_start[i] && (event_time - press_start[i]) > 1.0f) { + Input_SetReleased(MapKey(i)); + press_start[i] = 0.0f; + } + } +} +#endif + +void Window_ProcessEvents(float delta) { + if (pendingResize) { + pendingResize = false; + UpdateDimensions(); + Event_RaiseVoid(&WindowEvents.Resized); + } + + if (pendingClose) { + pendingClose = false; + Window_Main.Exists = false; + Event_RaiseVoid(&WindowEvents.Closing); + return; + } + + ProcessConsoleEvents(delta); +} + +void Window_ProcessGamepads(float delta) { } + +static void Cursor_GetRawPos(int* x, int* y) { + *x = 0; + *y = 0; + // TODO +} + +void Cursor_SetPosition(int x, int y) { + // TODO +} + +static void Cursor_DoSetVisible(cc_bool visible) { + // TODO +} + + +static void ShowDialogCore(const char* title, const char* msg) { + Platform_LogConst(title); + Platform_LogConst(msg); +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + return ERR_NOT_SUPPORTED; +} + + +void Window_AllocFramebuffer(struct Bitmap* bmp) { + bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels"); +} + +#ifdef CC_BUILD_WIN + #define OutputConsole(buf, len) WriteConsole(hStdout, buf, len, NULL, NULL) + #define BOX_CHAR "\xE2\x96\x84" +#else + #define OutputConsole(buf, len) write(STDOUT_FILENO, buf, len) + #define BOX_CHAR "\xE2\x96\x84" +#endif + +// TODO doesn't work +static void AppendByteFast(cc_string* str, int value) { + if (value >= 100) { String_Append(str, '0' + (value / 100)); value %= 100; } + if (value >= 10) { String_Append(str, '0' + (value / 10)); value %= 10; } + String_Append(str, '0' + value); +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + char buf[256]; + cc_string str; + int len; + String_InitArray(str, buf); + + for (int y = r.y & ~0x01; y < r.y + r.height; y += 2) + { + //len = sprintf(buf, CSI "%i;%iH", y / 2, r.x); // move cursor to start + //OutputConsole(buf, len); + str.length = 0; + String_AppendConst(&str, CSI); + String_AppendInt( &str, y / 2); + String_Append( &str, ';'); + String_AppendInt( &str, r.x); + String_Append( &str, 'H'); + String_Append( &str, '\0'); + OutputConsole(buf, str.length); + + for (int x = r.x; x < r.x + r.width; x++) + { + BitmapCol top = Bitmap_GetPixel(bmp, x, y + 0); + BitmapCol bot = Bitmap_GetPixel(bmp, x, y + 1); + + // Use 'â–„' so each cell can use a background and foreground colour + // This essentially doubles the vertical resolution of the displayed image + //printf(CSI "48;2;%i;%i;%im", BitmapCol_R(top), BitmapCol_G(top), BitmapCol_B(top)); + //printf(CSI "38;2;%i;%i;%im", BitmapCol_R(bot), BitmapCol_G(bot), BitmapCol_B(bot)); + //printf("\xE2\x96\x84"); + //len = sprintf(buf, CSI "48;2;%i;%i;%im" CSI "38;2;%i;%i;%im" BOX_CHAR, + // BitmapCol_R(top), BitmapCol_G(top), BitmapCol_B(top), + // BitmapCol_R(bot), BitmapCol_G(bot), BitmapCol_B(bot)); + + str.length = 0; + String_AppendConst(&str, CSI "48;2;"); + String_AppendInt( &str, BitmapCol_R(top)); + String_Append( &str, ';'); + String_AppendInt( &str, BitmapCol_G(top)); + String_Append( &str, ';'); + String_AppendInt( &str, BitmapCol_B(top)); + String_Append( &str, 'm'); + + String_AppendConst(&str, CSI "38;2;"); + String_AppendInt( &str, BitmapCol_R(bot)); + String_Append( &str, ';'); + String_AppendInt( &str, BitmapCol_G(bot)); + String_Append( &str, ';'); + String_AppendInt( &str, BitmapCol_B(bot)); + String_Append( &str, 'm'); + + String_AppendConst(&str, BOX_CHAR); + String_Append( &str, '\0'); + OutputConsole(buf, str.length); + } + } +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + Mem_Free(bmp->scan0); +} + +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { } +void OnscreenKeyboard_SetText(const cc_string* text) { } +void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { } +void OnscreenKeyboard_Draw3D(void) { } +void OnscreenKeyboard_Close(void) { } + +void Window_EnableRawMouse(void) { + DefaultEnableRawMouse(); +} + +void Window_UpdateRawMouse(void) { + CentreMousePosition(); +} + +void Window_DisableRawMouse(void) { + DefaultDisableRawMouse(); +} +#endif diff --git a/src/Window_Web.c b/src/Window_Web.c index a259140..9301f5a 100644 --- a/src/Window_Web.c +++ b/src/Window_Web.c @@ -49,7 +49,8 @@ static void DeferredEnableRawMouse(void) { static EM_BOOL OnMouseWheel(int type, const EmscriptenWheelEvent* ev, void* data) { /* TODO: The scale factor isn't standardised.. is there a better way though? */ - Mouse_ScrollWheel(-Math_Sign(ev->deltaY)); + Mouse_ScrollHWheel(-Math_Sign(ev->deltaX)); + Mouse_ScrollVWheel(-Math_Sign(ev->deltaY)); DeferredEnableRawMouse(); return true; } @@ -247,12 +248,26 @@ static int MapNativeKey(int k, int l) { case DOM_VK_BACK_SLASH: return CCKEY_BACKSLASH; case DOM_VK_CLOSE_BRACKET: return CCKEY_RBRACKET; case DOM_VK_QUOTE: return CCKEY_QUOTE; - - /* chrome */ + + case DOM_VK_VOLUME_MUTE: return CCKEY_VOLUME_MUTE; + case DOM_VK_VOLUME_DOWN: return CCKEY_VOLUME_DOWN; + case DOM_VK_VOLUME_UP: return CCKEY_VOLUME_UP; + + /* Chrome specific keys */ + /*case 173: return CCKEY_VOLUME_MUTE; same as DOM_VK_HYPHEN_MINUS */ + case 174: return CCKEY_VOLUME_DOWN; + case 175: return CCKEY_VOLUME_UP; + case 176: return CCKEY_MEDIA_NEXT; + case 177: return CCKEY_MEDIA_PREV; + case 178: return CCKEY_MEDIA_STOP; + case 179: return CCKEY_MEDIA_PLAY; + case 186: return CCKEY_SEMICOLON; case 187: return CCKEY_EQUALS; case 189: return CCKEY_MINUS; } + + Platform_Log1("Unknown key: %i", &k); return INPUT_NONE; } @@ -368,10 +383,12 @@ extern void interop_AddClipboardListeners(void); extern void interop_ForceTouchPageLayout(void); extern void Game_DoFrame(void); -void Window_Init(void) { - int is_ios, droid; +void Window_PreInit(void) { emscripten_set_main_loop(Game_DoFrame, 0, false); +} +void Window_Init(void) { + int is_ios, droid; DisplayInfo.Width = GetScreenWidth(); DisplayInfo.Height = GetScreenHeight(); DisplayInfo.Depth = 24; @@ -728,7 +745,7 @@ void Window_DisableRawMouse(void) { /*########################################################################################################################* *------------------------------------------------Emscripten WebGL context-------------------------------------------------* *#########################################################################################################################*/ -#ifdef CC_BUILD_GL +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) #include "Graphics.h" static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx_handle; diff --git a/src/Window_WiiU.cpp b/src/Window_WiiU.cpp index b046ea4..dc9f089 100644 --- a/src/Window_WiiU.cpp +++ b/src/Window_WiiU.cpp @@ -76,6 +76,14 @@ static uint32_t OnReleased(void* context) { return 0; } +void Window_PreInit(void) { + KPADInit(); + VPADInit(); + + ProcUIRegisterCallback(PROCUI_CALLBACK_ACQUIRE, OnAcquired, NULL, 100); + ProcUIRegisterCallback(PROCUI_CALLBACK_RELEASE, OnReleased, NULL, 100); +} + void Window_Init(void) { LoadTVDimensions(); DisplayInfo.ScaleX = 1; @@ -95,12 +103,6 @@ void Window_Init(void) { Window_Alt.Width = 854; Window_Alt.Height = 480; - - KPADInit(); - VPADInit(); - - ProcUIRegisterCallback(PROCUI_CALLBACK_ACQUIRE, OnAcquired, NULL, 100); - ProcUIRegisterCallback(PROCUI_CALLBACK_RELEASE, OnReleased, NULL, 100); WHBGfxInit(); } diff --git a/src/Window_Win.c b/src/Window_Win.c index 3e8ac81..a0da93e 100644 --- a/src/Window_Win.c +++ b/src/Window_Win.c @@ -1,5 +1,5 @@ #include "Core.h" -#if defined CC_BUILD_WINGUI && !defined CC_BUILD_SDL +#if CC_WIN_BACKEND == CC_WIN_BACKEND_WIN32 #include "_WindowBase.h" #include "String.h" #include "Funcs.h" @@ -39,6 +39,10 @@ /* Missing when compiling with some older winapi SDKs */ #define WM_INPUT 0x00FF #endif +#ifndef WM_MOUSEHWHEEL +/* Missing when compiling with some older winapi SDKs */ +#define WM_MOUSEHWHEEL 0x020E +#endif static BOOL (WINAPI *_RegisterRawInputDevices)(PCRAWINPUTDEVICE devices, UINT numDevices, UINT size); static UINT (WINAPI *_GetRawInputData)(HRAWINPUT hRawInput, UINT cmd, void* data, UINT* size, UINT headerSize); @@ -52,25 +56,44 @@ static int win_totalWidth, win_totalHeight; /* Size of window including titlebar static cc_bool is_ansiWindow, grabCursor; static int windowX, windowY; -static const cc_uint8 key_map[14 * 16] = { - 0, 0, 0, 0, 0, 0, 0, 0, CCKEY_BACKSPACE, CCKEY_TAB, 0, 0, CCKEY_F5, CCKEY_ENTER, 0, 0, - 0, 0, 0, CCKEY_PAUSE, CCKEY_CAPSLOCK, 0, 0, 0, 0, 0, 0, CCKEY_ESCAPE, 0, 0, 0, 0, - CCKEY_SPACE, CCKEY_PAGEUP, CCKEY_PAGEDOWN, CCKEY_END, CCKEY_HOME, CCKEY_LEFT, CCKEY_UP, CCKEY_RIGHT, CCKEY_DOWN, 0, CCKEY_PRINTSCREEN, 0, CCKEY_PRINTSCREEN, CCKEY_INSERT, CCKEY_DELETE, 0, - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 0, 0, 0, 0, 0, 0, - 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', CCKEY_LWIN, CCKEY_RWIN, CCKEY_MENU, 0, 0, - CCKEY_KP0, CCKEY_KP1, CCKEY_KP2, CCKEY_KP3, CCKEY_KP4, CCKEY_KP5, CCKEY_KP6, CCKEY_KP7, CCKEY_KP8, CCKEY_KP9, CCKEY_KP_MULTIPLY, CCKEY_KP_PLUS, 0, CCKEY_KP_MINUS, CCKEY_KP_DECIMAL, CCKEY_KP_DIVIDE, - CCKEY_F1, CCKEY_F2, CCKEY_F3, CCKEY_F4, CCKEY_F5, CCKEY_F6, CCKEY_F7, CCKEY_F8, CCKEY_F9, CCKEY_F10, CCKEY_F11, CCKEY_F12, CCKEY_F13, CCKEY_F14, CCKEY_F15, CCKEY_F16, - CCKEY_F17, CCKEY_F18, CCKEY_F19, CCKEY_F20, CCKEY_F21, CCKEY_F22, CCKEY_F23, CCKEY_F24, 0, 0, 0, 0, 0, 0, 0, 0, - CCKEY_NUMLOCK, CCKEY_SCROLLLOCK, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - CCKEY_LSHIFT, CCKEY_RSHIFT, CCKEY_LCTRL, CCKEY_RCTRL, CCKEY_LALT, CCKEY_RALT, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CCKEY_SEMICOLON, CCKEY_EQUALS, CCKEY_COMMA, CCKEY_MINUS, CCKEY_PERIOD, CCKEY_SLASH, - CCKEY_TILDE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, CCKEY_LBRACKET, CCKEY_BACKSLASH, CCKEY_RBRACKET, CCKEY_QUOTE, 0, +static const cc_uint8 key_map[] = { +/* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 08 */ CCKEY_BACKSPACE, CCKEY_TAB, 0, 0, CCKEY_F5, CCKEY_ENTER, 0, 0, +/* 10 */ 0, 0, 0, CCKEY_PAUSE, CCKEY_CAPSLOCK, 0, 0, 0, +/* 18 */ 0, 0, 0, CCKEY_ESCAPE, 0, 0, 0, 0, +/* 20 */ CCKEY_SPACE, CCKEY_PAGEUP, CCKEY_PAGEDOWN, CCKEY_END, CCKEY_HOME, CCKEY_LEFT, CCKEY_UP, CCKEY_RIGHT, +/* 28 */ CCKEY_DOWN, 0, CCKEY_PRINTSCREEN, 0, CCKEY_PRINTSCREEN, CCKEY_INSERT, CCKEY_DELETE, 0, +/* 30 */ '0', '1', '2', '3', '4', '5', '6', '7', +/* 38 */ '8', '9', 0, 0, 0, 0, 0, 0, +/* 40 */ 0, 'A', 'B', 'C', 'D', 'E', 'F', 'G', +/* 48 */ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', +/* 50 */ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', +/* 58 */ 'X', 'Y', 'Z', CCKEY_LWIN, CCKEY_RWIN, CCKEY_MENU, 0, CCKEY_SLEEP, +/* 60 */ CCKEY_KP0, CCKEY_KP1, CCKEY_KP2, CCKEY_KP3, CCKEY_KP4, CCKEY_KP5, CCKEY_KP6, CCKEY_KP7, +/* 68 */ CCKEY_KP8, CCKEY_KP9, CCKEY_KP_MULTIPLY, CCKEY_KP_PLUS, 0, CCKEY_KP_MINUS, CCKEY_KP_DECIMAL, CCKEY_KP_DIVIDE, +/* 70 */ CCKEY_F1, CCKEY_F2, CCKEY_F3, CCKEY_F4, CCKEY_F5, CCKEY_F6, CCKEY_F7, CCKEY_F8, +/* 78 */ CCKEY_F9, CCKEY_F10, CCKEY_F11, CCKEY_F12, CCKEY_F13, CCKEY_F14, CCKEY_F15, CCKEY_F16, +/* 80 */ CCKEY_F17, CCKEY_F18, CCKEY_F19, CCKEY_F20, CCKEY_F21, CCKEY_F22, CCKEY_F23, CCKEY_F24, +/* 88 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 90 */ CCKEY_NUMLOCK, CCKEY_SCROLLLOCK, 0, 0, 0, 0, 0, 0, +/* 98 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* A0 */ CCKEY_LSHIFT, CCKEY_RSHIFT, CCKEY_LCTRL, CCKEY_RCTRL, CCKEY_LALT, CCKEY_RALT, CCKEY_BROWSER_PREV, CCKEY_BROWSER_NEXT, +/* A8 */ CCKEY_BROWSER_REFRESH, CCKEY_BROWSER_STOP, CCKEY_BROWSER_SEARCH, CCKEY_BROWSER_FAVORITES, CCKEY_BROWSER_HOME, CCKEY_VOLUME_MUTE, CCKEY_VOLUME_DOWN, CCKEY_VOLUME_UP, +/* B0 */ CCKEY_MEDIA_NEXT, CCKEY_MEDIA_PREV, CCKEY_MEDIA_STOP, CCKEY_MEDIA_PLAY, CCKEY_LAUNCH_MAIL, CCKEY_LAUNCH_MEDIA, CCKEY_LAUNCH_APP1, CCKEY_LAUNCH_CALC, +/* B8 */ 0, 0, CCKEY_SEMICOLON, CCKEY_EQUALS, CCKEY_COMMA, CCKEY_MINUS, CCKEY_PERIOD, CCKEY_SLASH, +/* C0 */ CCKEY_TILDE, 0, 0, 0, 0, 0, 0, 0, +/* C8 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* D0 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* D8 */ 0, 0, 0, CCKEY_LBRACKET, CCKEY_BACKSLASH, CCKEY_RBRACKET, CCKEY_QUOTE, 0, }; -static int MapNativeKey(WPARAM key, LPARAM meta) { - LPARAM ext = meta & (1UL << 24); - switch (key) + +static int MapNativeKey(WPARAM vk_key, LPARAM meta) { + LPARAM ext = meta & (1UL << 24); + LPARAM scancode = (meta >> 16) & 0xFF; + int key; + if (ext) scancode |= 0xE000; + + switch (vk_key) { case VK_CONTROL: return ext ? CCKEY_RCTRL : CCKEY_LCTRL; @@ -78,9 +101,11 @@ static int MapNativeKey(WPARAM key, LPARAM meta) { return ext ? CCKEY_RALT : CCKEY_LALT; case VK_RETURN: return ext ? CCKEY_KP_ENTER : CCKEY_ENTER; - default: - return key < Array_Elems(key_map) ? key_map[key] : 0; } + + key = vk_key < Array_Elems(key_map) ? key_map[vk_key] : 0; + if (!key) Platform_Log2("Unknown key: %x, %x", &vk_key, &scancode); + return key; } static void RefreshWindowBounds(void) { @@ -157,7 +182,11 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara case WM_MOUSEWHEEL: wheelDelta = ((short)HIWORD(wParam)) / (float)WHEEL_DELTA; - Mouse_ScrollWheel(wheelDelta); + Mouse_ScrollVWheel(wheelDelta); + return 0; + case WM_MOUSEHWHEEL: + wheelDelta = ((short)HIWORD(wParam)) / (float)WHEEL_DELTA; + Mouse_ScrollHWheel(wheelDelta); return 0; case WM_LBUTTONDOWN: @@ -241,7 +270,6 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara } else { key = MapNativeKey(wParam, lParam); if (key) Input_Set(key, pressed); - else Platform_Log1("Unknown key: %x", &wParam); } return 0; } break; @@ -275,6 +303,7 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara /*########################################################################################################################* *--------------------------------------------------Public implementation--------------------------------------------------* *#########################################################################################################################*/ +void Window_PreInit(void) { } void Window_Init(void) { static const struct DynamicLibSym funcs[] = { DynamicLib_Sym(RegisterRawInputDevices), @@ -580,7 +609,7 @@ static cc_result OpenSaveFileDialog(const cc_string* filters, FileDialogCallback /* OPENFILENAME increased after Windows 9x/NT4 with the addition of pvReserved and later fields */ /* (and Windows 9x/NT4 return an error if a lStructSize > OPENFILENAME_SIZE_VERSION_400 is used) */ ofn.wide.lStructSize = OPENFILENAME_SIZE_VERSION_400; - /* also note that this only works when you *don't* have OFN_HOOK in Flags - if you do, then */ + /* also note that this only works when OFN_HOOK is *not* included in Flags - if it is, then */ /* on modern Windows versions the dialogs are altered to show an old Win 9x style appearance */ /* (see https://github.com/geany/geany/issues/578 for example of this problem) */ @@ -745,7 +774,7 @@ void Window_DisableRawMouse(void) { /*########################################################################################################################* *-------------------------------------------------------WGL OpenGL--------------------------------------------------------* *#########################################################################################################################*/ -#if defined CC_BUILD_GL && !defined CC_BUILD_EGL +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && !defined CC_BUILD_EGL static HGLRC ctx_handle; static HDC ctx_DC; typedef BOOL (WINAPI *FP_SWAPINTERVAL)(int interval); diff --git a/src/Window_X11.c b/src/Window_X11.c index 0c55e07..fb3a6b3 100644 --- a/src/Window_X11.c +++ b/src/Window_X11.c @@ -1,5 +1,5 @@ #include "Core.h" -#if defined CC_BUILD_X11 && !defined CC_BUILD_SDL2 && !defined CC_BUILD_SDL3 +#if CC_WIN_BACKEND == CC_WIN_BACKEND_X11 #include "_WindowBase.h" #include "String.h" #include "Funcs.h" @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef CC_BUILD_XINPUT2 #include #endif @@ -67,6 +68,31 @@ static int MapNativeKey(KeySym key, unsigned int state) { if (key == XK_KP_Down) return CCKEY_DOWN; if (key == XK_KP_Page_Down) return CCKEY_PAGEDOWN; } + + switch (key) { + case XF86XK_AudioLowerVolume: return CCKEY_VOLUME_DOWN; + case XF86XK_AudioMute: return CCKEY_VOLUME_MUTE; + case XF86XK_AudioRaiseVolume: return CCKEY_VOLUME_UP; + + case XF86XK_AudioPlay: return CCKEY_MEDIA_PLAY; + case XF86XK_AudioStop: return CCKEY_MEDIA_STOP; + case XF86XK_AudioPrev: return CCKEY_MEDIA_PREV; + case XF86XK_AudioNext: return CCKEY_MEDIA_NEXT; + + case XF86XK_HomePage: return CCKEY_BROWSER_HOME; + case XF86XK_Mail: return CCKEY_LAUNCH_MAIL; + case XF86XK_Search: return CCKEY_BROWSER_SEARCH; + case XF86XK_Calculator: return CCKEY_LAUNCH_CALC; + + case XF86XK_Back: return CCKEY_BROWSER_PREV; + case XF86XK_Forward: return CCKEY_BROWSER_NEXT; + case XF86XK_Stop: return CCKEY_BROWSER_STOP; + case XF86XK_Refresh: return CCKEY_BROWSER_REFRESH; + case XF86XK_Sleep: return CCKEY_SLEEP; + case XF86XK_Favorites: return CCKEY_BROWSER_FAVORITES; + case XF86XK_AudioMedia: return CCKEY_LAUNCH_MEDIA; + case XF86XK_MyComputer: return CCKEY_LAUNCH_APP1; + } /* A chromebook user reported issues with pressing some keys: */ /* tilde - "Unknown key press: (8000060, 800007E) */ @@ -157,21 +183,31 @@ static int MapNativeKey(KeySym key, unsigned int state) { case XK_KP_Page_Up: return CCKEY_KP9; case XK_KP_Delete: return CCKEY_KP_DECIMAL; case XK_KP_Enter: return CCKEY_KP_ENTER; + + case XK_ISO_Level3_Shift: return CCKEY_RALT; /* AltGr mode switch on some European keyboard layouts */ } return INPUT_NONE; } /* NOTE: This may not be entirely accurate, because user can configure keycode mappings */ static const cc_uint8 keycodeMap[136] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, CCKEY_ESCAPE, '1', '2', '3', '4', '5', '6', - '7', '8', '9', '0', CCKEY_MINUS, CCKEY_EQUALS, CCKEY_BACKSPACE, CCKEY_TAB, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', - 'O', 'P', CCKEY_LBRACKET, CCKEY_RBRACKET, CCKEY_ENTER, CCKEY_LCTRL, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', CCKEY_SEMICOLON, - CCKEY_QUOTE, CCKEY_TILDE, CCKEY_LSHIFT, CCKEY_BACKSLASH, 'Z', 'X', 'C', 'V', 'B', 'N', 'M', CCKEY_PERIOD, CCKEY_COMMA, CCKEY_SLASH, CCKEY_RSHIFT, CCKEY_KP_MULTIPLY, - CCKEY_LALT, CCKEY_SPACE, CCKEY_CAPSLOCK, CCKEY_F1, CCKEY_F2, CCKEY_F3, CCKEY_F4, CCKEY_F5, CCKEY_F6, CCKEY_F7, CCKEY_F8, CCKEY_F9, CCKEY_F10, CCKEY_NUMLOCK, CCKEY_SCROLLLOCK, CCKEY_KP7, - CCKEY_KP8, CCKEY_KP9, CCKEY_KP_MINUS, CCKEY_KP4, CCKEY_KP5, CCKEY_KP6, CCKEY_KP_PLUS, CCKEY_KP1, CCKEY_KP2, CCKEY_KP3, CCKEY_KP0, CCKEY_KP_DECIMAL, 0, 0, 0, CCKEY_F11, - CCKEY_F12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - CCKEY_RALT, CCKEY_RCTRL, CCKEY_HOME, CCKEY_UP, CCKEY_PAGEUP, CCKEY_LEFT, CCKEY_RIGHT, CCKEY_END, CCKEY_DOWN, CCKEY_PAGEDOWN, CCKEY_INSERT, CCKEY_DELETE, 0, 0, 0, 0, - 0, 0, 0, CCKEY_PAUSE, 0, 0, 0, 0, 0, CCKEY_LWIN, 0, CCKEY_RWIN +/* 00 */ 0, 0, 0, 0, 0, 0, 0, 0, +/* 08 */ 0, CCKEY_ESCAPE, '1', '2', '3', '4', '5', '6', +/* 10 */ '7', '8', '9', '0', CCKEY_MINUS, CCKEY_EQUALS, CCKEY_BACKSPACE, CCKEY_TAB, +/* 18 */ 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', +/* 20 */ 'O', 'P', CCKEY_LBRACKET, CCKEY_RBRACKET, CCKEY_ENTER, CCKEY_LCTRL, 'A', 'S', +/* 28 */ 'D', 'F', 'G', 'H', 'J', 'K', 'L', CCKEY_SEMICOLON, +/* 30 */ CCKEY_QUOTE, CCKEY_TILDE, CCKEY_LSHIFT, CCKEY_BACKSLASH, 'Z', 'X', 'C', 'V', +/* 38 */ 'B', 'N', 'M', CCKEY_PERIOD, CCKEY_COMMA, CCKEY_SLASH, CCKEY_RSHIFT, CCKEY_KP_MULTIPLY, +/* 40 */ CCKEY_LALT, CCKEY_SPACE, CCKEY_CAPSLOCK, CCKEY_F1, CCKEY_F2, CCKEY_F3, CCKEY_F4, CCKEY_F5, +/* 48 */ CCKEY_F6, CCKEY_F7, CCKEY_F8, CCKEY_F9, CCKEY_F10, CCKEY_NUMLOCK, CCKEY_SCROLLLOCK, CCKEY_KP7, +/* 50 */ CCKEY_KP8, CCKEY_KP9, CCKEY_KP_MINUS, CCKEY_KP4, CCKEY_KP5, CCKEY_KP6, CCKEY_KP_PLUS, CCKEY_KP1, +/* 58 */ CCKEY_KP2, CCKEY_KP3, CCKEY_KP0, CCKEY_KP_DECIMAL, 0, 0, 0, CCKEY_F11, +/* 60 */ CCKEY_F12, 0, 0, 0, 0, 0, 0, 0, +/* 68 */ 0, 0, 0, 0, CCKEY_RALT, CCKEY_RCTRL, CCKEY_HOME, CCKEY_UP, +/* 70 */ CCKEY_PAGEUP, CCKEY_LEFT, CCKEY_RIGHT, CCKEY_END, CCKEY_DOWN, CCKEY_PAGEDOWN, CCKEY_INSERT, CCKEY_DELETE, +/* 78 */ 0, 0, 0, 0, 0, 0, 0, CCKEY_PAUSE, +/* 80 */ 0, 0, 0, 0, 0, CCKEY_LWIN, 0, CCKEY_RWIN }; static int MapNativeKeycode(unsigned int keycode) { @@ -234,14 +270,14 @@ static void HookXErrors(void) { /*########################################################################################################################* *--------------------------------------------------Public implementation--------------------------------------------------* *#########################################################################################################################*/ -#ifdef CC_BUILD_EGL +#if defined CC_BUILD_EGL || !(CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) static XVisualInfo GLContext_SelectVisual(void) { XVisualInfo info; cc_result res; int screen = DefaultScreen(win_display); res = XMatchVisualInfo(win_display, screen, 24, TrueColor, &info) || - XMatchVisualInfo(win_display, screen, 32, TrueColor, &info); + XMatchVisualInfo(win_display, screen, 32, TrueColor, &info); if (!res) Logger_Abort("Selecting visual"); return info; @@ -250,6 +286,7 @@ static XVisualInfo GLContext_SelectVisual(void) { static XVisualInfo GLContext_SelectVisual(void); #endif +void Window_PreInit(void) { } void Window_Init(void) { Display* display = XOpenDisplay(NULL); int screen; @@ -273,8 +310,8 @@ void Window_Init(void) { void Window_Free(void) { } #ifdef CC_BUILD_ICON -/* See misc/linux_icon_gen.cs for how to generate this file */ -#include "_CCIcon_X11.h" +/* See misc/linux/linux_icon_gen.cs for how to generate this file */ +#include "../misc/linux/CCIcon_X11.h" static void ApplyIcon(void) { Atom net_wm_icon = XInternAtom(win_display, "_NET_WM_ICON", false); @@ -465,7 +502,7 @@ void Window_RequestClose(void) { ev.xclient.display = win_display; ev.xclient.window = win_handle; ev.xclient.data.l[0] = wm_destroy; - + XSendEvent(win_display, win_handle, false, 0, &ev); XFlush(win_display); } @@ -474,8 +511,17 @@ static int MapNativeMouse(int button) { if (button == 1) return CCMOUSE_L; if (button == 2) return CCMOUSE_M; if (button == 3) return CCMOUSE_R; - if (button == 8) return CCMOUSE_X1; - if (button == 9) return CCMOUSE_X2; + + if (button == 8) return CCMOUSE_X1; + if (button == 9) return CCMOUSE_X2; + if (button == 10) return CCMOUSE_X3; + if (button == 11) return CCMOUSE_X4; + if (button == 12) return CCMOUSE_X5; + if (button == 13) return CCMOUSE_X6; + + /* Mouse horizontal and vertical scroll */ + if (button >= 4 && button <= 7) return 0; + Platform_Log1("Unknown mouse button: %i", &button); return 0; } @@ -610,8 +656,10 @@ void Window_ProcessEvents(float delta) { case ButtonPress: btn = MapNativeMouse(e.xbutton.button); if (btn) Input_SetPressed(btn); - else if (e.xbutton.button == 4) Mouse_ScrollWheel(+1); - else if (e.xbutton.button == 5) Mouse_ScrollWheel(-1); + else if (e.xbutton.button == 4) Mouse_ScrollVWheel( +1); + else if (e.xbutton.button == 5) Mouse_ScrollVWheel( -1); + else if (e.xbutton.button == 6) Mouse_ScrollHWheel(+1); + else if (e.xbutton.button == 7) Mouse_ScrollHWheel(-1); break; case ButtonRelease: @@ -1261,7 +1309,7 @@ void Window_DisableRawMouse(void) { /*########################################################################################################################* *-------------------------------------------------------glX OpenGL--------------------------------------------------------* *#########################################################################################################################*/ -#if defined CC_BUILD_GL && !defined CC_BUILD_EGL +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && !defined CC_BUILD_EGL #include static GLXContext ctx_handle; typedef int (*FP_SWAPINTERVAL)(int interval); diff --git a/src/Window_Xbox.c b/src/Window_Xbox.c index 43f3c0b..f07182c 100644 --- a/src/Window_Xbox.c +++ b/src/Window_Xbox.c @@ -40,6 +40,7 @@ static void OnDataReceived(UTR_T* utr) { } static void OnDeviceChanged(xid_dev_t *xid_dev__, int status__) { + Platform_LogConst("Getting devices"); xid_dev_t* xid_dev = usbh_xid_get_device_list(); Platform_LogConst("Devices check"); @@ -57,8 +58,11 @@ static void OnDeviceChanged(xid_dev_t *xid_dev__, int status__) { xid_ctrl = NULL; } -void Window_Init(void) { +void Window_PreInit(void) { XVideoSetMode(640, 480, 32, REFRESH_DEFAULT); // TODO not call +} + +void Window_Init(void) { VIDEO_MODE mode = XVideoGetMode(); DisplayInfo.Width = mode.width; @@ -75,11 +79,13 @@ void Window_Init(void) { DisplayInfo.ContentOffsetX = 10; DisplayInfo.ContentOffsetY = 10; +#ifndef CC_BUILD_CXBX usbh_core_init(); usbh_xid_init(); usbh_install_xid_conn_callback(OnDeviceChanged, OnDeviceChanged); OnDeviceChanged(NULL, 0); // TODO useless call? +#endif } void Window_Free(void) { usbh_core_deinit(); } @@ -108,7 +114,9 @@ void Window_RequestClose(void) { *----------------------------------------------------Input processing-----------------------------------------------------* *#########################################################################################################################*/ void Window_ProcessEvents(float delta) { +#ifndef CC_BUILD_CXBX usbh_pooling_hubs(); +#endif } void Cursor_SetPosition(int x, int y) { } // Makes no sense for Xbox diff --git a/src/Window_Xbox360.c b/src/Window_Xbox360.c index 5da252e..ef4d7bc 100644 --- a/src/Window_Xbox360.c +++ b/src/Window_Xbox360.c @@ -26,6 +26,7 @@ static uint32_t reg_read32(int reg) return read32n(0xec800000 + reg); } +void Window_PreInit(void) { } void Window_Init(void) { DisplayInfo.Width = reg_read32(D1GRPH_X_END); DisplayInfo.Height = reg_read32(D1GRPH_Y_END); @@ -96,8 +97,10 @@ struct controller_data_s */ static void HandleButtons(int port, struct controller_data_s* pad) { - Gamepad_SetButton(port, CCPAD_L, pad->lb); - Gamepad_SetButton(port, CCPAD_R, pad->rb); + Gamepad_SetButton(port, CCPAD_L, pad->lb); + Gamepad_SetButton(port, CCPAD_R, pad->rb); + Gamepad_SetButton(port, CCPAD_LSTICK, pad->lt > 100); + Gamepad_SetButton(port, CCPAD_RSTICK, pad->rt > 100); Gamepad_SetButton(port, CCPAD_A, pad->a); Gamepad_SetButton(port, CCPAD_B, pad->b); @@ -113,12 +116,22 @@ static void HandleButtons(int port, struct controller_data_s* pad) { Gamepad_SetButton(port, CCPAD_DOWN, pad->down); } +#define AXIS_SCALE 8192.0f +static void HandleJoystick(int port, int axis, int x, int y, float delta) { + if (Math_AbsI(x) <= 4096) x = 0; + if (Math_AbsI(y) <= 4096) y = 0; + + Gamepad_SetAxis(port, axis, x / AXIS_SCALE, -y / AXIS_SCALE, delta); +} + void Window_ProcessGamepads(float delta) { struct controller_data_s pad; int res = get_controller_data(&pad, 0); if (res == 0) return; HandleButtons(0, &pad); + HandleJoystick(0, PAD_AXIS_LEFT, pad.s1_x, pad.s1_y, delta); + HandleJoystick(0, PAD_AXIS_RIGHT, pad.s2_x, pad.s2_y, delta); } diff --git a/src/Window_cocoa.m b/src/Window_cocoa.m new file mode 100644 index 0000000..6eb9b68 --- /dev/null +++ b/src/Window_cocoa.m @@ -0,0 +1,955 @@ +// Silence deprecation warnings on modern macOS +#define GL_SILENCE_DEPRECATION + +#include "Core.h" +#if CC_WIN_BACKEND == CC_WIN_BACKEND_COCOA +#include "_WindowBase.h" +#include "ExtMath.h" +#include "Funcs.h" +#include "Bitmap.h" +#include "String.h" +#include "Options.h" +#import +#import +#include + +static int windowX, windowY; +static NSApplication* appHandle; +static NSWindow* winHandle; +static NSView* viewHandle; +static cc_bool canCheckOcclusion; +static cc_bool legacy_fullscreen; +static cc_bool scroll_debugging; + +#if defined MAC_OS_X_VERSION_10_12 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12 + #define WIN_MASK (NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable | NSWindowStyleMaskMiniaturizable) + #define ANY_EVENT_MASK NSEventMaskAny + #define DIALOG_OK NSModalResponseOK + + #define PASTEBOARD_STRING_TYPE NSPasteboardTypeString +#else + #define WIN_MASK (NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask) + #define ANY_EVENT_MASK NSAnyEventMask + #define DIALOG_OK NSOKButton + + #define PASTEBOARD_STRING_TYPE NSStringPboardType +#endif + +extern size_t CGDisplayBitsPerPixel(CGDirectDisplayID display); +// TODO: Try replacing with NSBitsPerPixelFromDepth([NSScreen mainScreen].depth) instead + +// Sourced from https://www.meandmark.com/keycodes.html +static const cc_uint8 key_map[8 * 16] = { +/* 0x00 */ 'A', 'S', 'D', 'F', 'H', 'G', 'Z', 'X', +/* 0x08 */ 'C', 'V', 0, 'B', 'Q', 'W', 'E', 'R', +/* 0x10 */ 'Y', 'T', '1', '2', '3', '4', '6', '5', +/* 0x18 */ CCKEY_EQUALS, '9', '7', CCKEY_MINUS, '8', '0', CCKEY_RBRACKET, 'O', +/* 0x20 */ 'U', CCKEY_LBRACKET, 'I', 'P', CCKEY_ENTER, 'L', 'J', CCKEY_QUOTE, +/* 0x28 */ 'K', CCKEY_SEMICOLON, CCKEY_BACKSLASH, CCKEY_COMMA, CCKEY_SLASH, 'N', 'M', CCKEY_PERIOD, +/* 0x30 */ CCKEY_TAB, CCKEY_SPACE, CCKEY_TILDE, CCKEY_BACKSPACE, 0, CCKEY_ESCAPE, 0, 0, +/* 0x38 */ 0, CCKEY_CAPSLOCK, 0, 0, 0, 0, 0, 0, +/* 0x40 */ 0, CCKEY_KP_DECIMAL, 0, CCKEY_KP_MULTIPLY, 0, CCKEY_KP_PLUS, 0, CCKEY_NUMLOCK, +/* 0x48 */ CCKEY_VOLUME_UP, CCKEY_VOLUME_DOWN, CCKEY_VOLUME_MUTE, CCKEY_KP_DIVIDE, CCKEY_KP_ENTER, 0, CCKEY_KP_MINUS, 0, +/* 0x50 */ 0, CCKEY_KP_ENTER, CCKEY_KP0, CCKEY_KP1, CCKEY_KP2, CCKEY_KP3, CCKEY_KP4, CCKEY_KP5, +/* 0x58 */ CCKEY_KP6, CCKEY_KP7, 0, CCKEY_KP8, CCKEY_KP9, 'N', 'M', CCKEY_PERIOD, +/* 0x60 */ CCKEY_F5, CCKEY_F6, CCKEY_F7, CCKEY_F3, CCKEY_F8, CCKEY_F9, 0, CCKEY_F11, +/* 0x68 */ 0, CCKEY_F13, 0, CCKEY_F14, 0, CCKEY_F10, 0, CCKEY_F12, +/* 0x70 */ 'U', CCKEY_F15, CCKEY_INSERT, CCKEY_HOME, CCKEY_PAGEUP, CCKEY_DELETE, CCKEY_F4, CCKEY_END, +/* 0x78 */ CCKEY_F2, CCKEY_PAGEDOWN, CCKEY_F1, CCKEY_LEFT, CCKEY_RIGHT, CCKEY_DOWN, CCKEY_UP, 0, +}; +static int MapNativeKey(UInt32 key) { return key < Array_Elems(key_map) ? key_map[key] : 0; } +// TODO: Check these.. +// case 0x37: return CCKEY_LWIN; +// case 0x38: return CCKEY_LSHIFT; +// case 0x3A: return CCKEY_LALT; +// case 0x3B: return Key_ControlLeft; + +// TODO: Verify these differences from OpenTK +//Backspace = 51, (0x33, CCKEY_DELETE according to that link) +//Return = 52, (0x34, ??? according to that link) +//Menu = 110, (0x6E, ??? according to that link) + + +/*########################################################################################################################* + *---------------------------------------------------------Cursor---------------------------------------------------------* + *#########################################################################################################################*/ +static cc_bool warping; +static int warpDX, warpDY; + +static cc_bool GetMouseCoords(int* x, int* y) { + NSPoint loc = [NSEvent mouseLocation]; + *x = (int)loc.x - windowX; + *y = (DisplayInfo.Height - (int)loc.y) - windowY; + // TODO: this seems to be off by 1 + return *x >= 0 && *y >= 0 && *x < Window_Main.Width && *y < Window_Main.Height; +} + +static void ProcessRawMouseMovement(NSEvent* ev) { + float dx = [ev deltaX]; + float dy = [ev deltaY]; + + if (warping) { dx -= warpDX; dy -= warpDY; } + Event_RaiseRawMove(&PointerEvents.RawMoved, dx, dy); +} + + +void Cursor_SetPosition(int x, int y) { + int curX, curY; + GetMouseCoords(&curX, &curY); + + CGPoint point; + point.x = x + windowX; + point.y = y + windowY; + CGDisplayMoveCursorToPoint(CGMainDisplayID(), point); + + // Next mouse movement event will include the delta from + // this warp - so need to adjust processing to remove the delta + warping = true; + warpDX = x - curX; + warpDY = y - curY; +} + +static void Cursor_DoSetVisible(cc_bool visible) { + if (visible) { + CGDisplayShowCursor(CGMainDisplayID()); + } else { + CGDisplayHideCursor(CGMainDisplayID()); + } +} + +void Window_EnableRawMouse(void) { + CGAssociateMouseAndMouseCursorPosition(NO); + DefaultEnableRawMouse(); +} + +void Window_UpdateRawMouse(void) { } +void Cursor_GetRawPos(int* x, int* y) { *x = 0; *y = 0; } + +void Window_DisableRawMouse(void) { + DefaultDisableRawMouse(); + CGAssociateMouseAndMouseCursorPosition(YES); +} + + +/*########################################################################################################################* +*---------------------------------------------------------General---------------------------------------------------------* +*#########################################################################################################################*/ +void Clipboard_GetText(cc_string* value) { + NSPasteboard* pasteboard; + const char* src; + NSString* str; + int len; + + pasteboard = [NSPasteboard generalPasteboard]; + str = [pasteboard stringForType:PASTEBOARD_STRING_TYPE]; + + if (!str) return; + src = [str UTF8String]; + len = String_Length(src); + String_AppendUtf8(value, src, len); +} + +void Clipboard_SetText(const cc_string* value) { + NSPasteboard* pasteboard; + char raw[NATIVE_STR_LEN]; + NSString* str; + + String_EncodeUtf8(raw, value); + str = [NSString stringWithUTF8String:raw]; + pasteboard = [NSPasteboard generalPasteboard]; + + [pasteboard declareTypes:[NSArray arrayWithObject:PASTEBOARD_STRING_TYPE] owner:nil]; + [pasteboard setString:str forType:PASTEBOARD_STRING_TYPE]; +} + + +static void LogUnhandled(NSString* str) { + if (!str) return; + const char* src = [str UTF8String]; + if (!src) return; + + cc_string msg = String_FromReadonly(src); + Platform_Log(msg.buffer, msg.length); + Logger_Log(&msg); +} + +// TODO: Should really be handled elsewhere, in Logger or ErrorHandler +static void LogUnhandledNSErrors(NSException* ex) { + // last chance to log exception details before process dies + LogUnhandled(@"About to die from unhandled NSException.."); + LogUnhandled([ex name]); + LogUnhandled([ex reason]); +} + +void Window_PreInit(void) { + NSSetUncaughtExceptionHandler(LogUnhandledNSErrors); +} + +static NSAutoreleasePool* pool; +void Window_Init(void) { + Input.Sources = INPUT_SOURCE_NORMAL; + + // https://www.cocoawithlove.com/2009/01/demystifying-nsapplication-by.html + pool = [[NSAutoreleasePool alloc] init]; + appHandle = [NSApplication sharedApplication]; + [appHandle activateIgnoringOtherApps:YES]; + + CGDirectDisplayID display = CGMainDisplayID(); + CGRect bounds = CGDisplayBounds(display); + + DisplayInfo.x = (int)bounds.origin.x; + DisplayInfo.y = (int)bounds.origin.y; + DisplayInfo.Width = (int)bounds.size.width; + DisplayInfo.Height = (int)bounds.size.height; + DisplayInfo.Depth = CGDisplayBitsPerPixel(display); + DisplayInfo.ScaleX = 1; + DisplayInfo.ScaleY = 1; + + // NSApplication sometimes replaces the uncaught exception handler, so set it again + NSSetUncaughtExceptionHandler(LogUnhandledNSErrors); +} + +void Window_Free(void) { } + + +/*########################################################################################################################* +*-----------------------------------------------------------Window--------------------------------------------------------* +*#########################################################################################################################*/ +#if !defined MAC_OS_X_VERSION_10_4 +// Doesn't exist in < 10.4 SDK. No issue since < 10.4 is only Big Endian PowerPC anyways +#define kCGBitmapByteOrder32Host 0 +#endif + +static void RefreshWindowBounds(void) { + if (legacy_fullscreen) { + CGRect rect = CGDisplayBounds(CGMainDisplayID()); + windowX = (int)rect.origin.x; // usually 0 + windowY = (int)rect.origin.y; // usually 0 + // TODO is it correct to use display bounds and not just 0? + + Window_Main.Width = (int)rect.size.width; + Window_Main.Height = (int)rect.size.height; + return; + } + + NSRect win = [winHandle frame]; + NSRect view = [viewHandle frame]; + int viewY; + + // For cocoa, the 0,0 origin is the bottom left corner of windows/views/screen. + // To get window's real Y screen position, first need to find Y of top. (win.y + win.height) + // Then just subtract from screen height to make relative to top instead of bottom of the screen. + // Of course this is only half the story, since we're really after Y position of the content. + // To work out top Y of view relative to window, it's just win.height - (view.y + view.height) + viewY = (int)win.size.height - ((int)view.origin.y + (int)view.size.height); + windowX = (int)win.origin.x + (int)view.origin.x; + windowY = DisplayInfo.Height - ((int)win.origin.y + (int)win.size.height) + viewY; + + Window_Main.Width = (int)view.size.width; + Window_Main.Height = (int)view.size.height; +} + +@interface CCWindow : NSWindow { } +@end +@implementation CCWindow +// If this isn't overriden, an annoying beep sound plays anytime a key is pressed +- (void)keyDown:(NSEvent *)event { } +@end + +@interface CCWindowDelegate : NSObject { } +@end +@implementation CCWindowDelegate +- (void)windowDidResize:(NSNotification *)notification { + RefreshWindowBounds(); + Event_RaiseVoid(&WindowEvents.Resized); +} + +- (void)windowDidMove:(NSNotification *)notification { + RefreshWindowBounds(); +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) + GLContext_Update(); +#endif +} + +- (void)windowDidBecomeKey:(NSNotification *)notification { + Window_Main.Focused = true; + Event_RaiseVoid(&WindowEvents.FocusChanged); +} + +- (void)windowDidResignKey:(NSNotification *)notification { + Window_Main.Focused = false; + Event_RaiseVoid(&WindowEvents.FocusChanged); +} + +- (void)windowDidMiniaturize:(NSNotification *)notification { + Event_RaiseVoid(&WindowEvents.StateChanged); +} + +- (void)windowDidDeminiaturize:(NSNotification *)notification { + Event_RaiseVoid(&WindowEvents.StateChanged); +} + +- (void)windowWillClose:(NSNotification *)notification { + Window_Main.Exists = false; + Event_RaiseVoid(&WindowEvents.Closing); +} +@end + + +static void DoDrawFramebuffer(NSRect dirty); +@interface CCView : NSView { } +@end +@implementation CCView + +- (void)drawRect:(NSRect)dirty { DoDrawFramebuffer(dirty); } + +- (void)viewDidEndLiveResize { + // When the user users left mouse to drag reisze window, this enters 'live resize' mode + // Although the game receives a left mouse down event, it does NOT receive a left mouse up + // This causes the game to get stuck with left mouse down after user finishes resizing + // So work arond that by always releasing left mouse when a live resize is finished + Input_SetReleased(CCMOUSE_L); +} +@end + +static void MakeContentView(void) { + NSRect rect; + NSView* view; + + view = [winHandle contentView]; + rect = [view frame]; + + viewHandle = [CCView alloc]; + [viewHandle initWithFrame:rect]; + [winHandle setContentView:viewHandle]; +} + +#ifdef CC_BUILD_ICON +// See misc/macOS/mac_icon_gen.cs for how to generate this file +#include "../misc/macOS/CCIcon_mac.h" + +static void ApplyIcon(void) { + NSImage* img; + const unsigned int* pixels = CCIcon_Data; + unsigned char** planes = (unsigned char**)&pixels; + + NSBitmapImageRep* rep = [NSBitmapImageRep alloc]; + rep = [rep initWithBitmapDataPlanes:planes + pixelsWide:CCIcon_Width pixelsHigh:CCIcon_Height + bitsPerSample:8 samplesPerPixel:4 + hasAlpha:YES isPlanar:NO + colorSpaceName:NSDeviceRGBColorSpace + bytesPerRow:CCIcon_Width * 4 + bitsPerPixel:32]; + + img = [NSImage alloc]; + img = [img initWithSize:NSMakeSize(CCIcon_Width, CCIcon_Height)]; + [img addRepresentation:rep]; + [appHandle setApplicationIconImage:img]; + //[img release]; +} +#else +static void ApplyIcon(void) { } +#endif + +static pascal OSErr HandleQuitMessage(const AppleEvent* ev, AppleEvent* reply, long handlerRefcon) { + Window_RequestClose(); + return 0; +} + +static void DoCreateWindow(int width, int height) { + CCWindowDelegate* del; + NSRect rect; + + // Technically the coordinates for the origin are at bottom left corner + // But since the window is in centre of the screen, don't need to care here + rect.origin.x = Display_CentreX(width); + rect.origin.y = Display_CentreY(height); + rect.size.width = width; + rect.size.height = height; + + winHandle = [CCWindow alloc]; + [winHandle initWithContentRect:rect styleMask:WIN_MASK backing:NSBackingStoreBuffered defer:false]; + [winHandle setAcceptsMouseMovedEvents:YES]; + + + scroll_debugging = Options_GetBool("scroll-debug", false); + // for quit buttons in dock and menubar + AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, + NewAEEventHandlerUPP(HandleQuitMessage), 0, false); + + Window_Main.Exists = true; + Window_Main.Handle = winHandle; + // CGAssociateMouseAndMouseCursorPosition implicitly grabs cursor + + del = [CCWindowDelegate alloc]; + [winHandle setDelegate:del]; + RefreshWindowBounds(); + MakeContentView(); + ApplyIcon(); + + canCheckOcclusion = [winHandle respondsToSelector:@selector(occlusionState)]; +} +void Window_Create2D(int width, int height) { DoCreateWindow(width, height); } +void Window_Create3D(int width, int height) { DoCreateWindow(width, height); } + +void Window_SetTitle(const cc_string* title) { + char raw[NATIVE_STR_LEN]; + NSString* str; + String_EncodeUtf8(raw, title); + + str = [NSString stringWithUTF8String:raw]; + [winHandle setTitle:str]; + [str release]; +} + +// NOTE: Only defined since macOS 10.7 SDK +#define _NSFullScreenWindowMask (1 << 14) +int Window_GetWindowState(void) { + int flags; + + // modern fullscreen using toggleFullScreen + flags = [winHandle styleMask]; + if (flags & _NSFullScreenWindowMask) return WINDOW_STATE_FULLSCREEN; + + // legacy fullscreen using CGLSetFullscreen + if (legacy_fullscreen) return WINDOW_STATE_FULLSCREEN; + + flags = [winHandle isMiniaturized]; + return flags ? WINDOW_STATE_MINIMISED : WINDOW_STATE_NORMAL; +} + +// NOTE: Only defined since macOS 10.9 SDK +#define _NSWindowOcclusionStateVisible (1 << 1) +int Window_IsObscured(void) { + if (!canCheckOcclusion) + return [winHandle isMiniaturized]; + + // covers both minimised and hidden behind another window + int flags = [winHandle occlusionState]; + return !(flags & _NSWindowOcclusionStateVisible); +} + +void Window_Show(void) { + [winHandle makeKeyAndOrderFront:appHandle]; + RefreshWindowBounds(); // TODO: even necessary? +} + +void Window_SetSize(int width, int height) { + // Can't use setContentSize:, because that resizes from the bottom left corner + NSRect rect = [winHandle frame]; + + rect.origin.y += Window_Main.Height - height; + rect.size.width += width - Window_Main.Width; + rect.size.height += height - Window_Main.Height; + [winHandle setFrame:rect display:YES]; +} + +void Window_RequestClose(void) { + [winHandle close]; +} + + +/*########################################################################################################################* +*-----------------------------------------------------Event processing----------------------------------------------------* +*#########################################################################################################################*/ +static int MapNativeMouse(long button) { + if (button == 0) return CCMOUSE_L; + if (button == 1) return CCMOUSE_R; + if (button == 2) return CCMOUSE_M; + + if (button == 3) return CCMOUSE_X1; + if (button == 4) return CCMOUSE_X2; + if (button == 5) return CCMOUSE_X3; + if (button == 6) return CCMOUSE_X4; + if (button == 7) return CCMOUSE_X5; + if (button == 8) return CCMOUSE_X6; + + Platform_Log1("Unknown mouse button: %i", &button); + return 0; +} + +static void ProcessKeyChars(id ev) { + const char* src; + cc_codepoint cp; + NSString* chars; + int i, len, flags; + + // Ignore text input while cmd is held down + // e.g. so Cmd + V to paste doesn't leave behind 'v' + flags = [ev modifierFlags]; + if (flags & 0x000008) return; + if (flags & 0x000010) return; + + chars = [ev characters]; + src = [chars UTF8String]; + len = String_Length(src); + + while (len > 0) { + i = Convert_Utf8ToCodepoint(&cp, src, len); + if (!i) break; + + Event_RaiseInt(&InputEvents.Press, cp); + src += i; len -= i; + } +} + +static int TryGetKey(NSEvent* ev) { + int code = [ev keyCode]; + int key = MapNativeKey(code); + if (key) return key; + + Platform_Log1("Unknown key %i", &code); + return 0; +} + +static void DebugScrollEvent(NSEvent* ev) { +#ifdef kCGScrollWheelEventDeltaAxis1 + float dy = [ev deltaY]; + int steps = dy > 0.0f ? Math_Ceil(dy) : Math_Floor(dy); + + CGEventRef ref = [ev CGEvent]; + if (!ref) return; + int raw = CGEventGetIntegerValueField(ref, kCGScrollWheelEventDeltaAxis1); + + Platform_Log3("SCROLL: %i.0 = (%i, %f3)", &steps, &raw, &dy); +#endif +} + +void Window_ProcessEvents(float delta) { + NSEvent* ev; + int key, type, steps, x, y; + float dx, dy; + + // https://wiki.freepascal.org/Cocoa_Internals/Application + [pool release]; + pool = [[NSAutoreleasePool alloc] init]; + + for (;;) { + ev = [appHandle nextEventMatchingMask:ANY_EVENT_MASK untilDate:Nil inMode:NSDefaultRunLoopMode dequeue:YES]; + if (!ev) break; + type = [ev type]; + + switch (type) { + case 1: // NSLeftMouseDown + case 3: // NSRightMouseDown + case 25: // NSOtherMouseDown + key = MapNativeMouse([ev buttonNumber]); + if (GetMouseCoords(&x, &y) && key) Input_SetPressed(key); + break; + + case 2: // NSLeftMouseUp + case 4: // NSRightMouseUp + case 26: // NSOtherMouseUp + key = MapNativeMouse([ev buttonNumber]); + if (key) Input_SetReleased(key); + break; + + case 10: // NSKeyDown + key = TryGetKey(ev); + if (key) Input_SetPressed(key); + // TODO: Test works properly with other languages + ProcessKeyChars(ev); + break; + + case 11: // NSKeyUp + key = TryGetKey(ev); + if (key) Input_SetReleased(key); + break; + + case 12: // NSFlagsChanged + key = [ev modifierFlags]; + // TODO: Figure out how to only get modifiers that changed + Input_Set(CCKEY_LCTRL, key & 0x000001); + Input_Set(CCKEY_LSHIFT, key & 0x000002); + Input_Set(CCKEY_RSHIFT, key & 0x000004); + Input_Set(CCKEY_LWIN, key & 0x000008); + Input_Set(CCKEY_RWIN, key & 0x000010); + Input_Set(CCKEY_LALT, key & 0x000020); + Input_Set(CCKEY_RALT, key & 0x000040); + Input_Set(CCKEY_RCTRL, key & 0x002000); + Input_Set(CCKEY_CAPSLOCK, key & 0x010000); + break; + + case 22: // NSScrollWheel + if (scroll_debugging) DebugScrollEvent(ev); + dx = [ev deltaX]; + dy = [ev deltaY]; + // https://bugs.eclipse.org/bugs/show_bug.cgi?id=220175 + // delta is in 'line height' units, but I don't know how to map that to actual units. + // All I know is that scrolling by '1 wheel notch' produces a delta of around 0.1, and that + // sometimes I'll see it go all the way up to 5-6 with a larger wheel scroll. + // So mulitplying by 10 doesn't really seem a good idea, instead I just round outwards. + // TODO: Figure out if there's a better way than this. */ + steps = dx > 0.0f ? Math_Ceil(dx) : Math_Floor(dx); + Mouse_ScrollHWheel(steps); + + steps = dy > 0.0f ? Math_Ceil(dy) : Math_Floor(dy); + Mouse_ScrollVWheel(steps); + break; + + case 5: // NSMouseMoved + case 6: // NSLeftMouseDragged + case 7: // NSRightMouseDragged + case 27: // NSOtherMouseDragged + if (GetMouseCoords(&x, &y)) Pointer_SetPosition(0, x, y); + + if (Input.RawMode) ProcessRawMouseMovement(ev); + warping = false; + break; + } + [appHandle sendEvent:ev]; + } +} + +void Window_ProcessGamepads(float delta) { } + + +/*########################################################################################################################* +*-----------------------------------------------------------Dialogs-------------------------------------------------------* +*#########################################################################################################################*/ +void ShowDialogCore(const char* title, const char* msg) { + CFStringRef titleCF, msgCF; + NSAlert* alert; + + titleCF = CFStringCreateWithCString(NULL, title, kCFStringEncodingASCII); + msgCF = CFStringCreateWithCString(NULL, msg, kCFStringEncodingASCII); + + alert = [NSAlert alloc]; + alert = [alert init]; + + [alert setMessageText: titleCF]; + [alert setInformativeText: msgCF]; + [alert addButtonWithTitle: @"OK"]; + + [alert runModal]; + CFRelease(titleCF); + CFRelease(msgCF); +} + +static NSMutableArray* GetOpenSaveFilters(const char* const* filters) { + NSMutableArray* types = [NSMutableArray array]; + int i; + + for (i = 0; filters[i]; i++) + { + NSString* filter = [NSString stringWithUTF8String:filters[i]]; + filter = [filter substringFromIndex:1]; + [types addObject:filter]; + } + return types; +} + +static void OpenSaveDoCallback(NSURL* url, FileDialogCallback callback) { + NSString* str; + const char* src; + int len; + + str = [url path]; + src = [str UTF8String]; + len = String_Length(src); + + cc_string path; char pathBuffer[NATIVE_STR_LEN]; + String_InitArray(path, pathBuffer); + String_AppendUtf8(&path, src, len); + callback(&path); +} + +cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { + NSSavePanel* dlg = [NSSavePanel savePanel]; + + // TODO: Use args->defaultName, but only macOS 10.6 + + NSMutableArray* types = GetOpenSaveFilters(args->filters); + [dlg setAllowedFileTypes:types]; + if ([dlg runModal] != DIALOG_OK) return 0; + + NSURL* file = [dlg URL]; + if (file) OpenSaveDoCallback(file, args->Callback); + return 0; +} + +cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { + NSOpenPanel* dlg = [NSOpenPanel openPanel]; + + NSMutableArray* types = GetOpenSaveFilters(args->filters); + [dlg setCanChooseFiles: YES]; + if ([dlg runModalForTypes:types] != DIALOG_OK) return 0; + // unfortunately below code doesn't work when linked against SDK < 10.6 + // https://developer.apple.com/documentation/appkit/nssavepanel/1534419-allowedfiletypes + // [dlg setAllowedFileTypes:types]; + // if ([dlg runModal] != DIALOG_OK) return 0; + + NSArray* files = [dlg URLs]; + if ([files count] < 1) return 0; + + NSURL* file = [files objectAtIndex:0]; + OpenSaveDoCallback(file, args->Callback); + return 0; +} + + +/*########################################################################################################################* +*--------------------------------------------------------Framebuffer------------------------------------------------------* +*#########################################################################################################################*/ +static struct Bitmap fb_bmp; +void Window_AllocFramebuffer(struct Bitmap* bmp) { + bmp->scan0 = (BitmapCol*)Mem_Alloc(bmp->width * bmp->height, 4, "window pixels"); + fb_bmp = *bmp; +} + +static void DoDrawFramebuffer(NSRect dirty) { + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + CGContextRef context = NULL; + CGDataProviderRef provider; + NSGraphicsContext* nsContext; + CGImageRef image; + CGRect rect; + + Event_RaiseVoid(&WindowEvents.Redrawing); + + // Unfortunately CGImageRef is immutable, so changing the + // underlying data doesn't change what shows when drawing. + // TODO: Find a better way of doing this in cocoa.. + if (!fb_bmp.scan0) return; + nsContext = [NSGraphicsContext currentContext]; + context = [nsContext graphicsPort]; + + // TODO: Only update changed bit.. + rect.origin.x = 0; rect.origin.y = 0; + rect.size.width = Window_Main.Width; + rect.size.height = Window_Main.Height; + + // TODO: REPLACE THIS AWFUL HACK + provider = CGDataProviderCreateWithData(NULL, fb_bmp.scan0, + Bitmap_DataSize(fb_bmp.width, fb_bmp.height), NULL); + image = CGImageCreate(fb_bmp.width, fb_bmp.height, 8, 32, fb_bmp.width * 4, colorSpace, + kCGBitmapByteOrder32Host | kCGImageAlphaNoneSkipFirst, provider, NULL, 0, 0); + + CGContextDrawImage(context, rect, image); + CGContextSynchronize(context); + + CGImageRelease(image); + CGDataProviderRelease(provider); + CGColorSpaceRelease(colorSpace); +} + +void Window_DrawFramebuffer(Rect2D r, struct Bitmap* bmp) { + NSRect rect; + rect.origin.x = r.x; + rect.origin.y = Window_Main.Height - r.y - r.height; + rect.size.width = r.width; + rect.size.height = r.height; + + [viewHandle setNeedsDisplayInRect:rect]; + [viewHandle displayIfNeeded]; +} + +void Window_FreeFramebuffer(struct Bitmap* bmp) { + Mem_Free(bmp->scan0); +} + +void OnscreenKeyboard_Open(struct OpenKeyboardArgs* args) { } +void OnscreenKeyboard_SetText(const cc_string* text) { } +void OnscreenKeyboard_Draw2D(Rect2D* r, struct Bitmap* bmp) { } +void OnscreenKeyboard_Draw3D(void) { } +void OnscreenKeyboard_Close(void) { } + + +/*########################################################################################################################* +*--------------------------------------------------------NSOpenGL---------------------------------------------------------* +*#########################################################################################################################*/ +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && !defined CC_BUILD_EGL +static NSOpenGLContext* ctxHandle; +#include + +// SDKs < macOS 10.7 do not have this defined +#ifndef kCGLRPVideoMemoryMegabytes +#define kCGLRPVideoMemoryMegabytes 131 +#endif + +static int SupportsModernFullscreen(void) { + return [winHandle respondsToSelector:@selector(toggleFullScreen:)]; +} + +static NSOpenGLPixelFormat* MakePixelFormat(cc_bool fullscreen) { + // TODO: Is there a penalty for fullscreen contexts in 10.7 and later? + // Need to test whether there is a performance penalty or not + if (SupportsModernFullscreen()) fullscreen = false; + + NSOpenGLPixelFormatAttribute attribs[] = { + NSOpenGLPFAColorSize, DisplayInfo.Depth, + NSOpenGLPFADepthSize, 24, + NSOpenGLPFADoubleBuffer, + fullscreen ? NSOpenGLPFAFullScreen : 0, + // TODO do we have to mask to main display? or can we just use -1 for all displays? + NSOpenGLPFAScreenMask, CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID()), + 0 + }; + return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; +} + +void GLContext_Create(void) { + NSOpenGLPixelFormat* fmt; + fmt = MakePixelFormat(true); + if (!fmt) { + Platform_LogConst("Failed to create full screen pixel format."); + Platform_LogConst("Trying again to create a non-fullscreen pixel format."); + fmt = MakePixelFormat(false); + } + if (!fmt) Logger_Abort("Choosing pixel format"); + + ctxHandle = [NSOpenGLContext alloc]; + ctxHandle = [ctxHandle initWithFormat:fmt shareContext:Nil]; + if (!ctxHandle) Logger_Abort("Failed to create OpenGL context"); + + [ctxHandle setView:viewHandle]; + [fmt release]; + [ctxHandle makeCurrentContext]; + [ctxHandle update]; +} + +void GLContext_Update(void) { + // TODO: Why does this crash on resizing + [ctxHandle update]; +} +cc_bool GLContext_TryRestore(void) { return true; } + +void GLContext_Free(void) { + [NSOpenGLContext clearCurrentContext]; + [ctxHandle clearDrawable]; + [ctxHandle release]; +} + +void* GLContext_GetAddress(const char* function) { + static const cc_string glPath = String_FromConst("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"); + static void* lib; + + if (!lib) lib = DynamicLib_Load2(&glPath); + return DynamicLib_Get2(lib, function); +} + +cc_bool GLContext_SwapBuffers(void) { + [ctxHandle flushBuffer]; + return true; +} + +void GLContext_SetFpsLimit(cc_bool vsync, float minFrameMs) { + int value = vsync ? 1 : 0; + [ctxHandle setValues:&value forParameter: NSOpenGLCPSwapInterval]; +} + +// kCGLCPCurrentRendererID is only available on macOS 10.4 and later +#if defined MAC_OS_X_VERSION_10_4 +static const char* GetAccelerationMode(CGLContextObj ctx) { + GLint fGPU, vGPU; + + // NOTE: only macOS 10.4 or later + if (CGLGetParameter(ctx, kCGLCPGPUFragmentProcessing, &fGPU)) return NULL; + if (CGLGetParameter(ctx, kCGLCPGPUVertexProcessing, &vGPU)) return NULL; + + if (fGPU && vGPU) return "Fully"; + if (fGPU || vGPU) return "Partially"; + return "Not"; +} + +void GLContext_GetApiInfo(cc_string* info) { + CGLContextObj ctx = [ctxHandle CGLContextObj]; + GLint rendererID; + CGLGetParameter(ctx, kCGLCPCurrentRendererID, &rendererID); + + GLint nRenders = 0; + CGLRendererInfoObj rend; + CGLQueryRendererInfo(-1, &rend, &nRenders); + + for (int i = 0; i < nRenders; i++) + { + GLint curID = -1; + CGLDescribeRenderer(rend, i, kCGLRPRendererID, &curID); + if (curID != rendererID) continue; + + GLint acc = 0; + CGLDescribeRenderer(rend, i, kCGLRPAccelerated, &acc); + const char* mode = GetAccelerationMode(ctx); + + GLint vram = 0; + if (!CGLDescribeRenderer(rend, i, kCGLRPVideoMemoryMegabytes, &vram)) { + // preferred path (macOS 10.7 or later) + } else if (!CGLDescribeRenderer(rend, i, kCGLRPVideoMemory, &vram)) { + vram /= (1024 * 1024); // TODO: use float instead? + } else { + vram = -1; // TODO show a better error? + } + + if (mode && acc) { + String_Format2(info, "VRAM: %i MB, %c HW accelerated\n", &vram, mode); + } else { + String_Format2(info, "VRAM: %i MB, %c\n", + &vram, acc ? "HW accelerated" : "no HW acceleration"); + } + break; + } + CGLDestroyRendererInfo(rend); +} +#else +// macOS 10.3 and earlier case +void GLContext_GetApiInfo(cc_string* info) { + // TODO: retrieve rendererID from a CGLPixelFormatObj, but this isn't all that important +} +#endif + +cc_result Window_EnterFullscreen(void) { + if (SupportsModernFullscreen()) { + [winHandle toggleFullScreen:appHandle]; + return 0; + } + + Platform_LogConst("Falling back to legacy fullscreen.."); + legacy_fullscreen = true; + [ctxHandle clearDrawable]; + CGDisplayCapture(CGMainDisplayID()); + + // setFullScreen doesn't return an error code, which is unfortunate + // because if setFullScreen fails, you're left with a blank window + // that's still rendering thousands of frames per second + //[ctxHandle setFullScreen]; + //return 0; + + // CGLSetFullScreenOnDisplay is the preferable API, because it + // works properly on macOS 10.7 and all later versions + // However, because this API was only introduced in 10.7, it + // is essentially useless for us - because the superior + // toggleFullScreen API is already used in macOS 10.7+ + //cc_result res = CGLSetFullScreenOnDisplay([ctxHandle CGLContextObj], CGDisplayIDToOpenGLDisplayMask(CGMainDisplayID())); + + // CGLSetFullsScreen has existed since macOS 10.1, however + // it was deprecated in 10.6 - and by deprecated, Apple + // REALLY means deprecated. If the SDK ClassiCube is compiled + // against is 10.6 or later, then CGLSetFullScreen will always + // fail to work (CGLSetFullScreenOnDisplay still works) though + // So make sure you compile ClassiCube with an older SDK version + cc_result res = CGLSetFullScreen([ctxHandle CGLContextObj]); + + if (res) Window_ExitFullscreen(); + RefreshWindowBounds(); + Event_RaiseVoid(&WindowEvents.Resized); + return res; +} + +cc_result Window_ExitFullscreen(void) { + if (SupportsModernFullscreen()) { + [winHandle toggleFullScreen:appHandle]; + return 0; + } + + legacy_fullscreen = false; + CGDisplayRelease(CGMainDisplayID()); + [ctxHandle clearDrawable]; + [ctxHandle setView:viewHandle]; + + RefreshWindowBounds(); + Event_RaiseVoid(&WindowEvents.Resized); + return 0; +} +#endif +#endif diff --git a/src/World.c b/src/World.c index 7168372..a96547a 100644 --- a/src/World.c +++ b/src/World.c @@ -183,10 +183,12 @@ void Env_Reset(void) { PackedCol_GetShaded(Env.SunCol, &Env.SunXSide, &Env.SunZSide, &Env.SunYMin); - Env.SkyCol = ENV_DEFAULT_SKY_COLOR; - Env.FogCol = ENV_DEFAULT_FOG_COLOR; - Env.CloudsCol = ENV_DEFAULT_CLOUDS_COLOR; - Env.SkyboxCol = ENV_DEFAULT_SKYBOX_COLOR; + Env.SkyCol = ENV_DEFAULT_SKY_COLOR; + Env.FogCol = ENV_DEFAULT_FOG_COLOR; + Env.CloudsCol = ENV_DEFAULT_CLOUDS_COLOR; + Env.SkyboxCol = ENV_DEFAULT_SKYBOX_COLOR; + Env.LavaLightCol = ENV_DEFAULT_LAVALIGHT_COLOR; + Env.LampLightCol = ENV_DEFAULT_LAMPLIGHT_COLOR; Env.Weather = WEATHER_SUNNY; Env.ExpFog = false; } @@ -247,7 +249,12 @@ void Env_SetCloudsCol(PackedCol color) { void Env_SetSkyboxCol(PackedCol color) { Env_Set(color, Env.SkyboxCol, ENV_VAR_SKYBOX_COLOR); } - +void Env_SetLavaLightCol(PackedCol color) { + Env_Set(color, Env.LavaLightCol, ENV_VAR_LAVALIGHT_COLOR); +} +void Env_SetLampLightCol(PackedCol color) { + Env_Set(color, Env.LampLightCol, ENV_VAR_LAMPLIGHT_COLOR); +} void Env_SetSunCol(PackedCol color) { PackedCol_GetShaded(color, &Env.SunXSide, &Env.SunZSide, &Env.SunYMin); Env_Set(color, Env.SunCol, ENV_VAR_SUN_COLOR); diff --git a/src/World.h b/src/World.h index 455cc47..1f98c14 100644 --- a/src/World.h +++ b/src/World.h @@ -118,7 +118,8 @@ enum EnvVar { ENV_VAR_CLOUDS_HEIGHT, ENV_VAR_CLOUDS_SPEED, ENV_VAR_WEATHER_SPEED, ENV_VAR_WEATHER_FADE, ENV_VAR_WEATHER, ENV_VAR_EXP_FOG, ENV_VAR_SKYBOX_HOR_SPEED, ENV_VAR_SKYBOX_VER_SPEED, ENV_VAR_SKY_COLOR, ENV_VAR_CLOUDS_COLOR, ENV_VAR_FOG_COLOR, - ENV_VAR_SUN_COLOR, ENV_VAR_SHADOW_COLOR, ENV_VAR_SKYBOX_COLOR + ENV_VAR_SUN_COLOR, ENV_VAR_SHADOW_COLOR, ENV_VAR_SKYBOX_COLOR, + ENV_VAR_LAVALIGHT_COLOR, ENV_VAR_LAMPLIGHT_COLOR }; CC_VAR extern struct _EnvData { @@ -134,18 +135,21 @@ CC_VAR extern struct _EnvData { PackedCol SkyCol, FogCol, CloudsCol, SkyboxCol; PackedCol SunCol, SunXSide, SunZSide, SunYMin; PackedCol ShadowCol, ShadowXSide, ShadowZSide, ShadowYMin; + PackedCol LavaLightCol, LampLightCol; } Env; #define Env_SidesHeight (Env.EdgeHeight + Env.SidesOffset) enum Weather_ { WEATHER_SUNNY, WEATHER_RAINY, WEATHER_SNOWY }; extern const char* const Weather_Names[3]; -#define ENV_DEFAULT_SKY_COLOR PackedCol_Make(0x99, 0xCC, 0xFF, 0xFF) -#define ENV_DEFAULT_FOG_COLOR PackedCol_Make(0xFF, 0xFF, 0xFF, 0xFF) -#define ENV_DEFAULT_CLOUDS_COLOR PackedCol_Make(0xFF, 0xFF, 0xFF, 0xFF) -#define ENV_DEFAULT_SKYBOX_COLOR PackedCol_Make(0xFF, 0xFF, 0xFF, 0xFF) -#define ENV_DEFAULT_SUN_COLOR PackedCol_Make(0xFF, 0xFF, 0xFF, 0xFF) -#define ENV_DEFAULT_SHADOW_COLOR PackedCol_Make(0x9B, 0x9B, 0x9B, 0xFF) +#define ENV_DEFAULT_SKY_COLOR PackedCol_Make(0x99, 0xCC, 0xFF, 0xFF) +#define ENV_DEFAULT_FOG_COLOR PackedCol_Make(0xFF, 0xFF, 0xFF, 0xFF) +#define ENV_DEFAULT_CLOUDS_COLOR PackedCol_Make(0xFF, 0xFF, 0xFF, 0xFF) +#define ENV_DEFAULT_SKYBOX_COLOR PackedCol_Make(0xFF, 0xFF, 0xFF, 0xFF) +#define ENV_DEFAULT_SUN_COLOR PackedCol_Make(0xFF, 0xFF, 0xFF, 0xFF) +#define ENV_DEFAULT_SHADOW_COLOR PackedCol_Make(0x9B, 0x9B, 0x9B, 0xFF) +#define ENV_DEFAULT_LAVALIGHT_COLOR PackedCol_Make(0xFF, 0xEB, 0xC6, 0xFF) +#define ENV_DEFAULT_LAMPLIGHT_COLOR PackedCol_Make(0xFF, 0xFF, 0xFF, 0xFF) /* Resets all environment settings to default. */ /* NOTE: Unlike Env_Set functions, DOES NOT raise EnvVarChanged event. */ @@ -197,6 +201,10 @@ CC_API void Env_SetSunCol(PackedCol color); /* Sets colour of shadow. (default #9B9B9B) */ /* This is the colour used for lighting when underground. */ CC_API void Env_SetShadowCol(PackedCol color); +/* Sets colour that bright natural blocks cast with fancy lighting. (default #FFEBC6) */ +CC_API void Env_SetLavaLightCol(PackedCol color); +/* Sets colour that bright artificial blocks cast with fancy lighting. (default #FFFFFF) */ +CC_API void Env_SetLampLightCol(PackedCol color); #define RESPAWN_NOT_FOUND -100000.0f /* Finds the highest Y coordinate of any solid block that intersects the given bounding box */ diff --git a/src/_D3D11Shaders.h b/src/_D3D11Shaders.h deleted file mode 100644 index 334bbf1..0000000 --- a/src/_D3D11Shaders.h +++ /dev/null @@ -1,449 +0,0 @@ -// Generated using misc/D3D11ShaderGen.c - -//######################################################################################################################## -//------------------------------------------------------Vertex shaders---------------------------------------------------- -//######################################################################################################################## -static const unsigned char vs_colored[804] = { - 0x44,0x58,0x42,0x43,0x1a,0x76,0x9d,0x56,0x98,0x2d,0x30,0x9a,0x2f,0x00,0xd8,0xb0,0x6d,0xda,0x7a,0x6b,0x01,0x00,0x00,0x00,0x24,0x03,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x50,0x01,0x00,0x00,0xa4,0x01,0x00,0x00,0xa8,0x02,0x00,0x00,0x52,0x44,0x45,0x46,0xc4,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xfe,0xff,0x00,0x09,0x00,0x00,0x94,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73, - 0x00,0xab,0xab,0xab,0x3c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x76,0x70,0x4d,0x61,0x74,0x72,0x69,0x78,0x00,0xab,0xab, - 0x03,0x00,0x03,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c, - 0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00, - 0x49,0x53,0x47,0x4e,0x48,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00, - 0x50,0x4f,0x53,0x49,0x54,0x49,0x4f,0x4e,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0xab,0x4f,0x53,0x47,0x4e,0x4c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53,0x49,0x54,0x49,0x4f, - 0x4e,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0xfc,0x00,0x00,0x00,0x40,0x00,0x01,0x00,0x3f,0x00,0x00,0x00,0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,0x72,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,0xf2,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03, - 0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x67,0x00,0x00,0x04,0xf2,0x20,0x10,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00, - 0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x01,0x00,0x00,0x00,0x38,0x00,0x00,0x08,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x56,0x15,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0a, - 0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xa6,0x1a,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xf2,0x20,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00, -}; -static const unsigned char vs_textured[912] = { - 0x44,0x58,0x42,0x43,0x05,0x38,0x0a,0xc5,0x5e,0x15,0x86,0xef,0xa6,0xbc,0xb1,0x6a,0x8b,0x6c,0xf4,0x1e,0x01,0x00,0x00,0x00,0x90,0x03,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x70,0x01,0x00,0x00,0xe4,0x01,0x00,0x00,0x14,0x03,0x00,0x00,0x52,0x44,0x45,0x46,0xc4,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xfe,0xff,0x00,0x09,0x00,0x00,0x94,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73, - 0x00,0xab,0xab,0xab,0x3c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x76,0x70,0x4d,0x61,0x74,0x72,0x69,0x78,0x00,0xab,0xab, - 0x03,0x00,0x03,0x00,0x04,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c, - 0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00, - 0x49,0x53,0x47,0x4e,0x68,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00, - 0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x50,0x4f,0x53,0x49,0x54,0x49,0x4f,0x4e, - 0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x00,0x4f,0x53,0x47,0x4e,0x6c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0c,0x00,0x00,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53,0x49,0x54,0x49, - 0x4f,0x4e,0x00,0xab,0x53,0x48,0x44,0x52,0x28,0x01,0x00,0x00,0x40,0x00,0x01,0x00,0x4a,0x00,0x00,0x00,0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,0x72,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,0xf2,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x5f,0x00,0x00,0x03, - 0x32,0x10,0x10,0x00,0x02,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0x32,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x01,0x00,0x00,0x00, - 0x67,0x00,0x00,0x04,0xf2,0x20,0x10,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0x32,0x20,0x10,0x00, - 0x00,0x00,0x00,0x00,0x46,0x10,0x10,0x00,0x02,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x01,0x00,0x00,0x00, - 0x38,0x00,0x00,0x08,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x56,0x15,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x10,0x00,0x00,0x00,0x00,0x00, - 0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0xa6,0x1a,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xf2,0x20,0x10,0x00,0x02,0x00,0x00,0x00,0x46,0x0e,0x10,0x00, - 0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x07,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char vs_textured_offset[976] = { - 0x44,0x58,0x42,0x43,0x5c,0x17,0x5e,0xed,0xce,0x9c,0xa2,0x40,0x5c,0x3e,0x7c,0x93,0xb5,0xed,0x14,0x40,0x01,0x00,0x00,0x00,0xd0,0x03,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x34,0x01,0x00,0x00,0xa4,0x01,0x00,0x00,0x18,0x02,0x00,0x00,0x54,0x03,0x00,0x00,0x52,0x44,0x45,0x46,0xf8,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xfe,0xff,0x00,0x09,0x00,0x00,0xc8,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73, - 0x00,0xab,0xab,0xab,0x3c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6d,0x76,0x70,0x4d,0x61,0x74,0x72,0x69,0x78,0x00,0xab,0xab,0x03,0x00,0x03,0x00,0x04,0x00,0x04,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x65,0x78,0x4f,0x66,0x66,0x73,0x65,0x74,0x00,0xab,0xab,0x01,0x00,0x03,0x00,0x01,0x00,0x02,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f, - 0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00,0x49,0x53,0x47,0x4e,0x68,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x59,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x50,0x4f,0x53,0x49,0x54,0x49,0x4f,0x4e,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x54,0x45,0x58,0x43,0x4f, - 0x4f,0x52,0x44,0x00,0x4f,0x53,0x47,0x4e,0x6c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x0c,0x00,0x00,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x00,0x00,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x54,0x45,0x58,0x43, - 0x4f,0x4f,0x52,0x44,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53,0x49,0x54,0x49,0x4f,0x4e,0x00,0xab,0x53,0x48,0x44,0x52,0x34,0x01,0x00,0x00, - 0x40,0x00,0x01,0x00,0x4d,0x00,0x00,0x00,0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,0x72,0x10,0x10,0x00, - 0x00,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,0xf2,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x5f,0x00,0x00,0x03,0x32,0x10,0x10,0x00,0x02,0x00,0x00,0x00,0x65,0x00,0x00,0x03, - 0x32,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x01,0x00,0x00,0x00,0x67,0x00,0x00,0x04,0xf2,0x20,0x10,0x00,0x02,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x32,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x10,0x10,0x00,0x02,0x00,0x00,0x00, - 0x46,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x01,0x00,0x00,0x00, - 0x38,0x00,0x00,0x08,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x56,0x15,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x10,0x10,0x00,0x00,0x00,0x00,0x00, - 0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0xa6,0x1a,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xf2,0x20,0x10,0x00,0x02,0x00,0x00,0x00,0x46,0x0e,0x10,0x00, - 0x00,0x00,0x00,0x00,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x07,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; - - -//######################################################################################################################## -//------------------------------------------------------Pixel shaders----------------------------------------------------- -//######################################################################################################################## -static const unsigned char ps_colored[424] = { - 0x44,0x58,0x42,0x43,0x16,0x20,0x1a,0xbf,0xc8,0x73,0x21,0xb1,0xcb,0xa1,0x3a,0x9c,0xc5,0xa5,0x36,0x55,0x01,0x00,0x00,0x00,0xa8,0x01,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0xec,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,0x52,0x44,0x45,0x46,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0x1c,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66, - 0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e, - 0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00,0x49,0x53,0x47,0x4e,0x28,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0xab,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, - 0x53,0x56,0x5f,0x54,0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0x38,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x62,0x10,0x00,0x03, - 0xf2,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00, - 0x46,0x1e,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_textured[632] = { - 0x44,0x58,0x42,0x43,0x6b,0x07,0x3a,0x46,0xe7,0x48,0xcd,0xc6,0x61,0xf4,0x31,0x00,0x4d,0xa2,0x88,0x52,0x01,0x00,0x00,0x00,0x78,0x02,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0xdc,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,0x60,0x01,0x00,0x00,0xfc,0x01,0x00,0x00,0x52,0x44,0x45,0x46,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0x6e,0x00,0x00,0x00,0x5c,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x05,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x74,0x65,0x78,0x53,0x74,0x61,0x74,0x65, - 0x00,0x74,0x65,0x78,0x56,0x61,0x6c,0x75,0x65,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61, - 0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00,0xab,0xab,0x49,0x53,0x47,0x4e, - 0x48,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0x00,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x54,0x45,0x58,0x43, - 0x4f,0x4f,0x52,0x44,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x53,0x56,0x5f,0x54,0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab, - 0x53,0x48,0x44,0x52,0x94,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x25,0x00,0x00,0x00,0x5a,0x00,0x00,0x03,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x58,0x18,0x00,0x04, - 0x00,0x70,0x10,0x00,0x00,0x00,0x00,0x00,0x55,0x55,0x00,0x00,0x62,0x10,0x00,0x03,0x32,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x00,0x03,0xf2,0x10,0x10,0x00, - 0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00,0x45,0x00,0x00,0x09,0xf2,0x00,0x10,0x00, - 0x00,0x00,0x00,0x00,0x46,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x7e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x07, - 0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x01,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54, - 0x74,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_colored_test[512] = { - 0x44,0x58,0x42,0x43,0x96,0x8a,0x87,0x09,0x0b,0x87,0x03,0xec,0x5f,0xc8,0x2e,0xe4,0x75,0xae,0x39,0xc8,0x01,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x88,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0xec,0x00,0x00,0x00,0x84,0x01,0x00,0x00,0x52,0x44,0x45,0x46,0x4c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0x1c,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66, - 0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e, - 0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00,0x49,0x53,0x47,0x4e,0x28,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0xab,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, - 0x53,0x56,0x5f,0x54,0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0x90,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x24,0x00,0x00,0x00,0x62,0x10,0x00,0x03, - 0xf2,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00,0x31,0x00,0x00,0x07, - 0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x00,0x3f,0x1f,0x00,0x04,0x03,0x0a,0x00,0x10,0x00, - 0x00,0x00,0x00,0x00,0x0d,0x00,0x04,0x03,0x01,0x40,0x00,0x00,0xff,0xff,0xff,0xff,0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00, - 0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x15,0x00,0x00,0x01,0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x00,0x00,0x00,0x00, - 0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_textured_test[732] = { - 0x44,0x58,0x42,0x43,0x79,0x06,0x95,0x54,0x09,0x72,0xe5,0xe5,0x96,0x93,0xa5,0x15,0x18,0x9d,0xd3,0x7e,0x01,0x00,0x00,0x00,0xdc,0x02,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0xdc,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,0x60,0x01,0x00,0x00,0x60,0x02,0x00,0x00,0x52,0x44,0x45,0x46,0xa0,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0x6e,0x00,0x00,0x00,0x5c,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x65,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x05,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x74,0x65,0x78,0x53,0x74,0x61,0x74,0x65, - 0x00,0x74,0x65,0x78,0x56,0x61,0x6c,0x75,0x65,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61, - 0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00,0xab,0xab,0x49,0x53,0x47,0x4e, - 0x48,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x03,0x00,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x54,0x45,0x58,0x43, - 0x4f,0x4f,0x52,0x44,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x53,0x56,0x5f,0x54,0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab, - 0x53,0x48,0x44,0x52,0xf8,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x5a,0x00,0x00,0x03,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x58,0x18,0x00,0x04, - 0x00,0x70,0x10,0x00,0x00,0x00,0x00,0x00,0x55,0x55,0x00,0x00,0x62,0x10,0x00,0x03,0x32,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x00,0x03,0xf2,0x10,0x10,0x00, - 0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x45,0x00,0x00,0x09,0xf2,0x00,0x10,0x00, - 0x00,0x00,0x00,0x00,0x46,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x7e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x07, - 0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x01,0x00,0x00,0x00,0x31,0x00,0x00,0x07,0x12,0x00,0x10,0x00, - 0x01,0x00,0x00,0x00,0x3a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x00,0x3f,0x1f,0x00,0x04,0x03,0x0a,0x00,0x10,0x00,0x01,0x00,0x00,0x00, - 0x0d,0x00,0x04,0x03,0x01,0x40,0x00,0x00,0xff,0xff,0xff,0xff,0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00, - 0x3e,0x00,0x00,0x01,0x15,0x00,0x00,0x01,0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01, - 0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_colored_linear[812] = { - 0x44,0x58,0x42,0x43,0x4d,0x07,0xb0,0xb7,0x92,0xe8,0xd5,0x3f,0x71,0x68,0x19,0x03,0x90,0x20,0xa6,0x6d,0x01,0x00,0x00,0x00,0x2c,0x03,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x30,0x01,0x00,0x00,0x84,0x01,0x00,0x00,0xb8,0x01,0x00,0x00,0xb0,0x02,0x00,0x00,0x52,0x44,0x45,0x46,0xf4,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0xc4,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73, - 0x00,0xab,0xab,0xab,0x3c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x45,0x6e,0x64,0x00,0xab,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x43,0x6f,0x6c,0x6f,0x72,0x00,0xab,0xab,0xab,0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c, - 0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00,0x49,0x53,0x47,0x4e,0x4c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x08,0x00,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53,0x49,0x54,0x49,0x4f, - 0x4e,0x00,0xab,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x53,0x56,0x5f,0x54,0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0xf0,0x00,0x00,0x00, - 0x40,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x62,0x10,0x00,0x03,0xf2,0x10,0x10,0x00, - 0x00,0x00,0x00,0x00,0x64,0x20,0x00,0x04,0x82,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00, - 0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x80,0x41,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x20,0x00,0x08,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09,0xe2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x19,0x10,0x00,0x00,0x00,0x00,0x00, - 0x56,0x8e,0x20,0x80,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0x72,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x10,0x00, - 0x00,0x00,0x00,0x00,0x96,0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x96,0x87,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0x82,0x20,0x10,0x00, - 0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_textured_linear[1036] = { - 0x44,0x58,0x42,0x43,0xea,0x4f,0xef,0xd5,0x7f,0x41,0x2e,0x1b,0xb7,0x39,0xd9,0x13,0x36,0xaf,0xbb,0x5a,0x01,0x00,0x00,0x00,0x0c,0x04,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xf4,0x01,0x00,0x00,0x28,0x02,0x00,0x00,0x90,0x03,0x00,0x00,0x52,0x44,0x45,0x46,0x44,0x01,0x00,0x00,0x01,0x00,0x00,0x00, - 0x98,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0x14,0x01,0x00,0x00,0x7c,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x05,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x65,0x78,0x53,0x74,0x61,0x74,0x65, - 0x00,0x74,0x65,0x78,0x56,0x61,0x6c,0x75,0x65,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x00,0xab,0x8e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xb0,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xe8,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x45, - 0x6e,0x64,0x00,0xab,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x43,0x6f,0x6c,0x6f,0x72,0x00,0xab,0xab,0xab, - 0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c, - 0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00, - 0x49,0x53,0x47,0x4e,0x6c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00, - 0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0f,0x08,0x00,0x00,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44, - 0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53,0x49,0x54,0x49,0x4f,0x4e,0x00,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x53,0x56,0x5f,0x54, - 0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0x60,0x01,0x00,0x00,0x40,0x00,0x00,0x00,0x58,0x00,0x00,0x00,0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00, - 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5a,0x00,0x00,0x03,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x58,0x18,0x00,0x04,0x00,0x70,0x10,0x00,0x00,0x00,0x00,0x00, - 0x55,0x55,0x00,0x00,0x62,0x10,0x00,0x03,0x32,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x00,0x03,0xf2,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x64,0x20,0x00,0x04, - 0x82,0x10,0x10,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x02,0x00,0x00,0x00, - 0x00,0x00,0x00,0x09,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x80,0x41,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x0e,0x20,0x00,0x08,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x45,0x00,0x00,0x09,0xf2,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x7e,0x10,0x00,0x00,0x00,0x00,0x00, - 0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0b,0xe2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x09,0x10,0x00,0x01,0x00,0x00,0x00,0x06,0x19,0x10,0x00, - 0x01,0x00,0x00,0x00,0x56,0x8e,0x20,0x80,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x07,0x12,0x00,0x10,0x00,0x01,0x00,0x00,0x00, - 0x3a,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0x82,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00, - 0x01,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0x72,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x96,0x07,0x10,0x00,0x00,0x00,0x00,0x00, - 0x96,0x87,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_colored_test_linear[892] = { - 0x44,0x58,0x42,0x43,0x8a,0xcb,0x96,0x93,0x3f,0x48,0x28,0x07,0x96,0x55,0xae,0xf3,0xd3,0x7b,0xa5,0x81,0x01,0x00,0x00,0x00,0x7c,0x03,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x30,0x01,0x00,0x00,0x84,0x01,0x00,0x00,0xb8,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x52,0x44,0x45,0x46,0xf4,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0xc4,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73, - 0x00,0xab,0xab,0xab,0x3c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x98,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa8,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0xb4,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x45,0x6e,0x64,0x00,0xab,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x43,0x6f,0x6c,0x6f,0x72,0x00,0xab,0xab,0xab,0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c, - 0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00,0x49,0x53,0x47,0x4e,0x4c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x00,0x00,0x00, - 0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x3e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x08,0x00,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53,0x49,0x54,0x49,0x4f, - 0x4e,0x00,0xab,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x53,0x56,0x5f,0x54,0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0x40,0x01,0x00,0x00, - 0x40,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x62,0x10,0x00,0x03,0xf2,0x10,0x10,0x00, - 0x00,0x00,0x00,0x00,0x64,0x20,0x00,0x04,0x82,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00, - 0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00,0x31,0x00,0x00,0x07,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00, - 0x00,0x00,0x00,0x3f,0x1f,0x00,0x04,0x03,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,0x04,0x03,0x01,0x40,0x00,0x00,0xff,0xff,0xff,0xff,0x36,0x00,0x00,0x05, - 0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x15,0x00,0x00,0x01,0x00,0x00,0x00,0x09,0x12,0x00,0x10,0x00, - 0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x80,0x41,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x20,0x00,0x08, - 0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x09, - 0xe2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x19,0x10,0x00,0x00,0x00,0x00,0x00,0x56,0x8e,0x20,0x80,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x32,0x00,0x00,0x0a,0x72,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x96,0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x96,0x87,0x20,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0x82,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01, - 0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_textured_test_linear[1116] = { - 0x44,0x58,0x42,0x43,0x1d,0x79,0x4f,0x31,0xfb,0x7d,0xd0,0xf9,0x3d,0xad,0x4f,0xc0,0xb9,0xbe,0x19,0x8b,0x01,0x00,0x00,0x00,0x5c,0x04,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xf4,0x01,0x00,0x00,0x28,0x02,0x00,0x00,0xe0,0x03,0x00,0x00,0x52,0x44,0x45,0x46,0x44,0x01,0x00,0x00,0x01,0x00,0x00,0x00, - 0x98,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0x14,0x01,0x00,0x00,0x7c,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x05,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x65,0x78,0x53,0x74,0x61,0x74,0x65, - 0x00,0x74,0x65,0x78,0x56,0x61,0x6c,0x75,0x65,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x00,0xab,0x8e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xb0,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xe8,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x45, - 0x6e,0x64,0x00,0xab,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x43,0x6f,0x6c,0x6f,0x72,0x00,0xab,0xab,0xab, - 0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c, - 0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00, - 0x49,0x53,0x47,0x4e,0x6c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00, - 0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0f,0x08,0x00,0x00,0x54,0x45,0x58,0x43,0x4f,0x4f,0x52,0x44, - 0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53,0x49,0x54,0x49,0x4f,0x4e,0x00,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x53,0x56,0x5f,0x54, - 0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0xb0,0x01,0x00,0x00,0x40,0x00,0x00,0x00,0x6c,0x00,0x00,0x00,0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00, - 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5a,0x00,0x00,0x03,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x58,0x18,0x00,0x04,0x00,0x70,0x10,0x00,0x00,0x00,0x00,0x00, - 0x55,0x55,0x00,0x00,0x62,0x10,0x00,0x03,0x32,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x00,0x03,0xf2,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x64,0x20,0x00,0x04, - 0x82,0x10,0x10,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x02,0x00,0x00,0x00, - 0x45,0x00,0x00,0x09,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x7e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x10,0x00, - 0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x07,0xf2,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x01,0x00,0x00,0x00, - 0x31,0x00,0x00,0x07,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x00,0x3f,0x1f,0x00,0x04,0x03, - 0x3a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,0x04,0x03,0x01,0x40,0x00,0x00,0xff,0xff,0xff,0xff,0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00, - 0x46,0x0e,0x10,0x00,0x01,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x15,0x00,0x00,0x01,0x00,0x00,0x00,0x09,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x80, - 0x41,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x20,0x00,0x08,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x3a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0b,0x72,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x46,0x02,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x12,0x10,0x00,0x01,0x00,0x00,0x00,0x96,0x87,0x20,0x80,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x32,0x00,0x00,0x0a,0x72,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0xf6,0x0f,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x02,0x10,0x00,0x00,0x00,0x00,0x00,0x96,0x87,0x20,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0x82,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x3e,0x00,0x00,0x01, - 0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_colored_density[856] = { - 0x44,0x58,0x42,0x43,0x9c,0xb3,0xe5,0x3c,0x3d,0x38,0xc9,0xc6,0x6e,0x98,0xfc,0xe6,0x28,0x0a,0xcd,0x79,0x01,0x00,0x00,0x00,0x58,0x03,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x34,0x01,0x00,0x00,0x88,0x01,0x00,0x00,0xbc,0x01,0x00,0x00,0xdc,0x02,0x00,0x00,0x52,0x44,0x45,0x46,0xf8,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0xc8,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73, - 0x00,0xab,0xab,0xab,0x3c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x44,0x65,0x6e,0x73,0x69,0x74,0x79,0x00,0xab,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x43,0x6f,0x6c,0x6f,0x72,0x00,0xab,0xab,0xab,0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f, - 0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00,0x49,0x53,0x47,0x4e,0x4c,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x3e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x08,0x00,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53, - 0x49,0x54,0x49,0x4f,0x4e,0x00,0xab,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x53,0x56,0x5f,0x54,0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab,0x53,0x48,0x44,0x52, - 0x18,0x01,0x00,0x00,0x40,0x00,0x00,0x00,0x46,0x00,0x00,0x00,0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x62,0x10,0x00,0x03, - 0xf2,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x64,0x20,0x00,0x04,0x82,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00, - 0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00,0x38,0x00,0x00,0x08,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x01,0x00,0x00,0x00, - 0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x07,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x01,0x40,0x00,0x00,0x3b,0xaa,0xb8,0x3f,0x19,0x00,0x00,0x05,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x07, - 0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x09,0xe2,0x00,0x10,0x00, - 0x00,0x00,0x00,0x00,0x06,0x19,0x10,0x00,0x00,0x00,0x00,0x00,0x56,0x8e,0x20,0x80,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0a, - 0x72,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x96,0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x96,0x87,0x20,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0x82,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54, - 0x74,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_textured_density[1080] = { - 0x44,0x58,0x42,0x43,0xc0,0x13,0x86,0xc6,0xba,0x6d,0x77,0x79,0x76,0x05,0x6f,0x20,0x79,0xb9,0x5d,0x48,0x01,0x00,0x00,0x00,0x38,0x04,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x84,0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x2c,0x02,0x00,0x00,0xbc,0x03,0x00,0x00,0x52,0x44,0x45,0x46,0x48,0x01,0x00,0x00,0x01,0x00,0x00,0x00, - 0x98,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0x18,0x01,0x00,0x00,0x7c,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x05,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x65,0x78,0x53,0x74,0x61,0x74,0x65, - 0x00,0x74,0x65,0x78,0x56,0x61,0x6c,0x75,0x65,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x00,0xab,0x8e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xb0,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xec,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x44, - 0x65,0x6e,0x73,0x69,0x74,0x79,0x00,0xab,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x43,0x6f,0x6c,0x6f,0x72, - 0x00,0xab,0xab,0xab,0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52, - 0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31, - 0x31,0x2e,0x30,0x00,0x49,0x53,0x47,0x4e,0x6c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x0f,0x00,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0f,0x08,0x00,0x00,0x54,0x45,0x58,0x43, - 0x4f,0x4f,0x52,0x44,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53,0x49,0x54,0x49,0x4f,0x4e,0x00,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, - 0x53,0x56,0x5f,0x54,0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0x88,0x01,0x00,0x00,0x40,0x00,0x00,0x00,0x62,0x00,0x00,0x00,0x59,0x00,0x00,0x04, - 0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5a,0x00,0x00,0x03,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x58,0x18,0x00,0x04,0x00,0x70,0x10,0x00, - 0x00,0x00,0x00,0x00,0x55,0x55,0x00,0x00,0x62,0x10,0x00,0x03,0x32,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x00,0x03,0xf2,0x10,0x10,0x00,0x01,0x00,0x00,0x00, - 0x64,0x20,0x00,0x04,0x82,0x10,0x10,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02, - 0x02,0x00,0x00,0x00,0x38,0x00,0x00,0x08,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x02,0x00,0x00,0x00,0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x07,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x3b,0xaa,0xb8,0x3f, - 0x19,0x00,0x00,0x05,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x07,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x80,0x3f,0x45,0x00,0x00,0x09,0xf2,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x10,0x10,0x00, - 0x00,0x00,0x00,0x00,0x46,0x7e,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0b,0xe2,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x06,0x09,0x10,0x00,0x01,0x00,0x00,0x00,0x06,0x19,0x10,0x00,0x01,0x00,0x00,0x00,0x56,0x8e,0x20,0x80,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x38,0x00,0x00,0x07,0x12,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x3a,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x36,0x00,0x00,0x05, - 0x82,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0x72,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x10,0x00, - 0x00,0x00,0x00,0x00,0x96,0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x96,0x87,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54, - 0x74,0x00,0x00,0x00,0x0a,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_colored_test_density[936] = { - 0x44,0x58,0x42,0x43,0x8b,0xbd,0x84,0x52,0xb8,0xfa,0xa4,0x23,0x37,0x6a,0xff,0xe0,0x97,0x76,0x5b,0xe3,0x01,0x00,0x00,0x00,0xa8,0x03,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x34,0x01,0x00,0x00,0x88,0x01,0x00,0x00,0xbc,0x01,0x00,0x00,0x2c,0x03,0x00,0x00,0x52,0x44,0x45,0x46,0xf8,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x48,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0xc8,0x00,0x00,0x00,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73, - 0x00,0xab,0xab,0xab,0x3c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x90,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x9c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x44,0x65,0x6e,0x73,0x69,0x74,0x79,0x00,0xab,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x43,0x6f,0x6c,0x6f,0x72,0x00,0xab,0xab,0xab,0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52,0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f, - 0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31,0x31,0x2e,0x30,0x00,0x49,0x53,0x47,0x4e,0x4c,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x08,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x0f,0x00,0x00,0x3e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0f,0x08,0x00,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53, - 0x49,0x54,0x49,0x4f,0x4e,0x00,0xab,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00,0x53,0x56,0x5f,0x54,0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab,0x53,0x48,0x44,0x52, - 0x68,0x01,0x00,0x00,0x40,0x00,0x00,0x00,0x5a,0x00,0x00,0x00,0x59,0x00,0x00,0x04,0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x62,0x10,0x00,0x03, - 0xf2,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x64,0x20,0x00,0x04,0x82,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00, - 0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02,0x01,0x00,0x00,0x00,0x31,0x00,0x00,0x07,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x00,0x00,0x00,0x00, - 0x01,0x40,0x00,0x00,0x00,0x00,0x00,0x3f,0x1f,0x00,0x04,0x03,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,0x04,0x03,0x01,0x40,0x00,0x00,0xff,0xff,0xff,0xff, - 0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x15,0x00,0x00,0x01,0x38,0x00,0x00,0x08, - 0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x10,0x10,0x00,0x01,0x00,0x00,0x00,0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x07, - 0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x3b,0xaa,0xb8,0x3f,0x19,0x00,0x00,0x05,0x12,0x00,0x10,0x00, - 0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x07,0x12,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x01,0x40,0x00,0x00,0x00,0x00,0x80,0x3f,0x00,0x00,0x00,0x09,0xe2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x19,0x10,0x00,0x00,0x00,0x00,0x00,0x56,0x8e,0x20,0x80, - 0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0x72,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x96,0x07,0x10,0x00,0x00,0x00,0x00,0x00,0x96,0x87,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0x82,0x20,0x10,0x00,0x00,0x00,0x00,0x00, - 0x3a,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x0e,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; -static const unsigned char ps_textured_test_density[1160] = { - 0x44,0x58,0x42,0x43,0xbd,0x21,0xa2,0x31,0xd8,0x5a,0x9a,0x36,0xba,0x5b,0x4d,0xde,0x22,0x7e,0xc8,0x19,0x01,0x00,0x00,0x00,0x88,0x04,0x00,0x00,0x05,0x00,0x00,0x00, - 0x34,0x00,0x00,0x00,0x84,0x01,0x00,0x00,0xf8,0x01,0x00,0x00,0x2c,0x02,0x00,0x00,0x0c,0x04,0x00,0x00,0x52,0x44,0x45,0x46,0x48,0x01,0x00,0x00,0x01,0x00,0x00,0x00, - 0x98,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x1c,0x00,0x00,0x00,0x00,0x04,0xff,0xff,0x00,0x09,0x00,0x00,0x18,0x01,0x00,0x00,0x7c,0x00,0x00,0x00,0x03,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x85,0x00,0x00,0x00,0x02,0x00,0x00,0x00, - 0x05,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x74,0x65,0x78,0x53,0x74,0x61,0x74,0x65, - 0x00,0x74,0x65,0x78,0x56,0x61,0x6c,0x75,0x65,0x00,0x24,0x47,0x6c,0x6f,0x62,0x61,0x6c,0x73,0x00,0xab,0x8e,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xb0,0x00,0x00,0x00, - 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xec,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0xfc,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x0c,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x08,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x44, - 0x65,0x6e,0x73,0x69,0x74,0x79,0x00,0xab,0x00,0x00,0x03,0x00,0x01,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x6f,0x67,0x43,0x6f,0x6c,0x6f,0x72, - 0x00,0xab,0xab,0xab,0x01,0x00,0x03,0x00,0x01,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4d,0x69,0x63,0x72,0x6f,0x73,0x6f,0x66,0x74,0x20,0x28,0x52, - 0x29,0x20,0x48,0x4c,0x53,0x4c,0x20,0x53,0x68,0x61,0x64,0x65,0x72,0x20,0x43,0x6f,0x6d,0x70,0x69,0x6c,0x65,0x72,0x20,0x31,0x30,0x2e,0x30,0x2e,0x31,0x30,0x30,0x31, - 0x31,0x2e,0x30,0x00,0x49,0x53,0x47,0x4e,0x6c,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x59,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x01,0x00,0x00,0x00, - 0x0f,0x0f,0x00,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x0f,0x08,0x00,0x00,0x54,0x45,0x58,0x43, - 0x4f,0x4f,0x52,0x44,0x00,0x43,0x4f,0x4c,0x4f,0x52,0x00,0x53,0x56,0x5f,0x50,0x4f,0x53,0x49,0x54,0x49,0x4f,0x4e,0x00,0xab,0x4f,0x53,0x47,0x4e,0x2c,0x00,0x00,0x00, - 0x01,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, - 0x53,0x56,0x5f,0x54,0x41,0x52,0x47,0x45,0x54,0x00,0xab,0xab,0x53,0x48,0x44,0x52,0xd8,0x01,0x00,0x00,0x40,0x00,0x00,0x00,0x76,0x00,0x00,0x00,0x59,0x00,0x00,0x04, - 0x46,0x8e,0x20,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x5a,0x00,0x00,0x03,0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x58,0x18,0x00,0x04,0x00,0x70,0x10,0x00, - 0x00,0x00,0x00,0x00,0x55,0x55,0x00,0x00,0x62,0x10,0x00,0x03,0x32,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x62,0x10,0x00,0x03,0xf2,0x10,0x10,0x00,0x01,0x00,0x00,0x00, - 0x64,0x20,0x00,0x04,0x82,0x10,0x10,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x65,0x00,0x00,0x03,0xf2,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0x68,0x00,0x00,0x02, - 0x02,0x00,0x00,0x00,0x45,0x00,0x00,0x09,0xf2,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x7e,0x10,0x00,0x00,0x00,0x00,0x00, - 0x00,0x60,0x10,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x07,0xf2,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x1e,0x10,0x00, - 0x01,0x00,0x00,0x00,0x31,0x00,0x00,0x07,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x00,0x3f, - 0x1f,0x00,0x04,0x03,0x3a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x0d,0x00,0x04,0x03,0x01,0x40,0x00,0x00,0xff,0xff,0xff,0xff,0x36,0x00,0x00,0x05,0xf2,0x20,0x10,0x00, - 0x00,0x00,0x00,0x00,0x46,0x0e,0x10,0x00,0x01,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x15,0x00,0x00,0x01,0x38,0x00,0x00,0x08,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x3a,0x10,0x10,0x00,0x02,0x00,0x00,0x00,0x0a,0x80,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x07,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x00, - 0x3a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x3b,0xaa,0xb8,0x3f,0x19,0x00,0x00,0x05,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x00,0x10,0x00, - 0x00,0x00,0x00,0x00,0x33,0x00,0x00,0x07,0x82,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3a,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x01,0x40,0x00,0x00,0x00,0x00,0x80,0x3f, - 0x32,0x00,0x00,0x0b,0x72,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x02,0x10,0x00,0x00,0x00,0x00,0x00,0x46,0x12,0x10,0x00,0x01,0x00,0x00,0x00,0x96,0x87,0x20,0x80, - 0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x0a,0x72,0x20,0x10,0x00,0x00,0x00,0x00,0x00,0xf6,0x0f,0x10,0x00,0x00,0x00,0x00,0x00, - 0x46,0x02,0x10,0x00,0x00,0x00,0x00,0x00,0x96,0x87,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x05,0x82,0x20,0x10,0x00,0x00,0x00,0x00,0x00, - 0x3a,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x3e,0x00,0x00,0x01,0x53,0x54,0x41,0x54,0x74,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x04,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, -}; diff --git a/src/_GL1Funcs.h b/src/_GL1Funcs.h new file mode 100644 index 0000000..e9ea877 --- /dev/null +++ b/src/_GL1Funcs.h @@ -0,0 +1,63 @@ +/* Raster state functions */ +GL_FUNC(void, glAlphaFunc)(GLenum func, GLfloat ref); +GL_FUNC(void, glBlendFunc)(GLenum sfactor, GLenum dfactor); +GL_FUNC(void, glClearColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_FUNC(void, glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GL_FUNC(void, glDepthFunc)(GLenum func); +GL_FUNC(void, glDepthMask)(GLboolean flag); +GL_FUNC(void, glDisable)(GLenum cap); +GL_FUNC(void, glDisableClientState)(GLenum array); +GL_FUNC(void, glEnable)(GLenum cap); +GL_FUNC(void, glEnableClientState)(GLenum array); + +/* Fog functions */ +GL_FUNC(void, glFogf)(GLenum pname, GLfloat param); +GL_FUNC(void, glFogfv)(GLenum pname, const GLfloat* params); +GL_FUNC(void, glFogi)(GLenum pname, GLint param); +GL_FUNC(void, glFogiv)(GLenum pname, const GLint* params); + +/* Transform functions */ +GL_FUNC(void, glLoadIdentity)(void); +GL_FUNC(void, glLoadMatrixf)(const GLfloat* m); +GL_FUNC(void, glMatrixMode)(GLenum mode); +GL_FUNC(void, glViewport)(GLint x, GLint y, GLsizei width, GLsizei height); + +/* Draw functions */ +GL_FUNC(void, glDrawArrays)(GLenum mode, GLint first, GLsizei count); +GL_FUNC(void, glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); +GL_FUNC(void, glColorPointer)(GLint size, GLenum type, GLsizei stride, GLpointer pointer); +GL_FUNC(void, glTexCoordPointer)(GLint size, GLenum type, GLsizei stride, GLpointer pointer); +GL_FUNC(void, glVertexPointer)(GLint size, GLenum type, GLsizei stride, GLpointer pointer); + +/* Misc functions */ +GL_FUNC(void, glClear)(GLuint mask); +GL_FUNC(void, glHint)(GLenum target, GLenum mode); +GL_FUNC(void, glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); + +/* Texture functions */ +GL_FUNC(void, glBindTexture)(GLenum target, GLuint texture); +GL_FUNC(void, glDeleteTextures)(GLsizei n, const GLuint* textures); +GL_FUNC(void, glGenTextures)(GLsizei n, GLuint* textures); +GL_FUNC(void, glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +GL_FUNC(void, glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); +GL_FUNC(void, glTexParameteri)(GLenum target, GLenum pname, GLint param); + +/* State get functions */ +GL_FUNC(GLenum, glGetError)(void); +GL_FUNC(void, glGetFloatv)(GLenum pname, GLfloat* params); +GL_FUNC(void, glGetIntegerv)(GLenum pname, GLint* params); +GL_FUNC(const GLubyte*, glGetString)(GLenum name); + +/* Legacy display list functions */ +GL_FUNC(void, glCallList)(GLuint list); +GL_FUNC(void, glDeleteLists)(GLuint list, GLsizei range); +GL_FUNC(GLuint, glGenLists)(GLsizei range); +GL_FUNC(void, glNewList)(GLuint list, GLenum mode); +GL_FUNC(void, glEndList)(void); + +/* Legacy vertex draw functions */ +GL_FUNC(void, glBegin)(GLenum mode); +GL_FUNC(void, glEnd)(void); +GL_FUNC(void, glColor4ub)(GLubyte r, GLubyte g, GLubyte b, GLubyte a); +GL_FUNC(void, glTexCoord2f)(float u, float v); +GL_FUNC(void, glVertex3f)(float x, float y, float z); \ No newline at end of file diff --git a/src/_GLShared.h b/src/_GLShared.h index bc0b470..cd27a04 100644 --- a/src/_GLShared.h +++ b/src/_GLShared.h @@ -18,17 +18,13 @@ #define TRANSFER_FORMAT GL_UNSIGNED_BYTE #endif +#define uint_to_ptr(raw) ((void*)((cc_uintptr)(raw))) +#define ptr_to_uint(raw) ((GLuint)((cc_uintptr)(raw))) + /*########################################################################################################################* *---------------------------------------------------------General---------------------------------------------------------* *#########################################################################################################################*/ -static void GLContext_GetAll(const struct DynamicLibSym* syms, int count) { - int i; - for (i = 0; i < count; i++) { - *syms[i].symAddr = GLContext_GetAddress(syms[i].name); - } -} - static void GL_UpdateVsync(void) { GLContext_SetFpsLimit(gfx_vsync, gfx_minFrameMs); } @@ -90,9 +86,9 @@ static void Gfx_DoMipmaps(int x, int y, struct Bitmap* bmp, int rowWidth, cc_boo GenMipmaps(width, height, cur, prev, rowWidth); if (partial) { - glTexSubImage2D(GL_TEXTURE_2D, lvl, x, y, width, height, PIXEL_FORMAT, TRANSFER_FORMAT, cur); + _glTexSubImage2D(GL_TEXTURE_2D, lvl, x, y, width, height, PIXEL_FORMAT, TRANSFER_FORMAT, cur); } else { - glTexImage2D(GL_TEXTURE_2D, lvl, GL_RGBA, width, height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, cur); + _glTexImage2D(GL_TEXTURE_2D, lvl, GL_RGBA, width, height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, cur); } if (prev != bmp->scan0) Mem_Free(prev); @@ -117,17 +113,17 @@ static CC_NOINLINE void UpdateTextureSlow(int x, int y, struct Bitmap* part, int CopyTextureData(ptr, part->width << 2, part, rowWidth << 2); if (full) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, part->width, part->height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, ptr); + _glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, part->width, part->height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, ptr); } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, part->width, part->height, PIXEL_FORMAT, TRANSFER_FORMAT, ptr); + _glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, part->width, part->height, PIXEL_FORMAT, TRANSFER_FORMAT, ptr); } if (count > UPDATE_FAST_SIZE) Mem_Free(ptr); } static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) { - GLuint texId; - glGenTextures(1, &texId); - glBindTexture(GL_TEXTURE_2D, texId); + GfxResourceID texId = NULL; + _glGenTextures(1, (GLuint*)&texId); + _glBindTexture(GL_TEXTURE_2D, ptr_to_uint(texId)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); if (mipmaps) { @@ -141,7 +137,7 @@ static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 } if (bmp->width == rowWidth) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmp->width, bmp->height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, bmp->scan0); + _glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmp->width, bmp->height, 0, PIXEL_FORMAT, TRANSFER_FORMAT, bmp->scan0); } else { UpdateTextureSlow(0, 0, bmp, rowWidth, true); } @@ -151,10 +147,10 @@ static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 } void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) { - glBindTexture(GL_TEXTURE_2D, (GLuint)texId); + _glBindTexture(GL_TEXTURE_2D, ptr_to_uint(texId)); if (part->width == rowWidth) { - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, part->width, part->height, PIXEL_FORMAT, TRANSFER_FORMAT, part->scan0); + _glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, part->width, part->height, PIXEL_FORMAT, TRANSFER_FORMAT, part->scan0); } else { UpdateTextureSlow(x, y, part, rowWidth, false); } @@ -163,8 +159,8 @@ void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, i } void Gfx_DeleteTexture(GfxResourceID* texId) { - GLuint id = (GLuint)(*texId); - if (id) glDeleteTextures(1, &id); + GLuint id = ptr_to_uint(*texId); + if (id) _glDeleteTextures(1, &id); *texId = 0; } @@ -177,7 +173,7 @@ void Gfx_DisableMipmaps(void) { } *#########################################################################################################################*/ static PackedCol gfx_clearColor; void Gfx_SetFaceCulling(cc_bool enabled) { gl_Toggle(GL_CULL_FACE); } -void Gfx_SetAlphaBlending(cc_bool enabled) { gl_Toggle(GL_BLEND); } +static void SetAlphaBlend(cc_bool enabled) { gl_Toggle(GL_BLEND); } void Gfx_SetAlphaArgBlend(cc_bool enabled) { } static void GL_ClearColor(PackedCol color) { @@ -282,7 +278,7 @@ void Gfx_GetApiInfo(cc_string* info) { int pointerSize = sizeof(void*) * 8; glGetIntegerv(GL_DEPTH_BITS, &depthBits); -#ifdef CC_BUILD_GLMODERN +#if CC_GFX_BACKEND == CC_GFX_BACKEND_GL2 String_Format1(info, "-- Using OpenGL Modern (%i bit) --\n", &pointerSize); #else String_Format1(info, "-- Using OpenGL (%i bit) --\n", &pointerSize); @@ -312,13 +308,14 @@ void Gfx_ClearBuffers(GfxBuffers buffers) { } void Gfx_EndFrame(void) { -#ifndef CC_BUILD_GLMODERN +#if CC_GFX_BACKEND == CC_GFX_BACKEND_GL1 if (Window_IsObscured()) { TickReducedPerformance(); } else { EndReducedPerformance(); } #endif + /* TODO always run ?? */ if (!GLContext_SwapBuffers()) Gfx_LoseContext("GLContext lost"); if (gfx_minFrameMs) LimitFPS(); diff --git a/src/_GraphicsBase.h b/src/_GraphicsBase.h index b61cedb..d4f8410 100644 --- a/src/_GraphicsBase.h +++ b/src/_GraphicsBase.h @@ -24,6 +24,7 @@ static int gfx_stride, gfx_format = -1; static cc_bool gfx_vsync, gfx_fogEnabled; static float gfx_minFrameMs; +static cc_bool gfx_rendering2D; /*########################################################################################################################* @@ -31,6 +32,23 @@ static float gfx_minFrameMs; *#########################################################################################################################*/ static cc_bool gfx_colorMask[4] = { true, true, true, true }; cc_bool Gfx_GetFog(void) { return gfx_fogEnabled; } +static cc_bool gfx_alphaTest, gfx_alphaBlend; + +static void SetAlphaTest(cc_bool enabled); +void Gfx_SetAlphaTest(cc_bool enabled) { + if (gfx_alphaTest == enabled) return; + + gfx_alphaTest = enabled; + SetAlphaTest(enabled); +} + +static void SetAlphaBlend(cc_bool enabled); +void Gfx_SetAlphaBlending(cc_bool enabled) { + if (gfx_alphaBlend == enabled) return; + + gfx_alphaBlend = enabled; + SetAlphaBlend(enabled); +} /* Initialises/Restores render state */ CC_NOINLINE static void Gfx_RestoreState(void); @@ -242,7 +260,7 @@ void Gfx_Make2DQuad(const struct Texture* tex, PackedCol color, struct VertexTex float y1 = (float)tex->y, y2 = (float)(tex->y + tex->height); struct VertexTextured* v = *vertices; -#ifdef CC_BUILD_D3D9 +#if CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9 /* NOTE: see "https://msdn.microsoft.com/en-us/library/windows/desktop/bb219690(v=vs.85).aspx", */ /* i.e. the msdn article called "Directly Mapping Texels to Pixels (Direct3D 9)" for why we have to do this. */ x1 -= 0.5f; x2 -= 0.5f; @@ -256,6 +274,7 @@ void Gfx_Make2DQuad(const struct Texture* tex, PackedCol color, struct VertexTex *vertices = v; } +#ifndef CC_BUILD_PS1 static cc_bool gfx_hadFog; void Gfx_Begin2D(int width, int height) { struct Matrix ortho; @@ -265,16 +284,23 @@ void Gfx_Begin2D(int width, int height) { Gfx_LoadIdentityMatrix(MATRIX_VIEW); Gfx_SetDepthTest(false); + Gfx_SetDepthWrite(false); Gfx_SetAlphaBlending(true); + gfx_hadFog = Gfx_GetFog(); if (gfx_hadFog) Gfx_SetFog(false); + gfx_rendering2D = true; } void Gfx_End2D(void) { Gfx_SetDepthTest(true); + Gfx_SetDepthWrite(true); Gfx_SetAlphaBlending(false); + if (gfx_hadFog) Gfx_SetFog(true); + gfx_rendering2D = false; } +#endif /*########################################################################################################################* @@ -498,7 +524,7 @@ GfxResourceID Gfx_CreateDynamicVb(VertexFormat fmt, int maxVertices) { } } -#if defined CC_BUILD_GL || defined CC_BUILD_D3D9 +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) || (CC_GFX_BACKEND == CC_GFX_BACKEND_D3D9) /* Slightly more efficient implementations are defined in the backends */ #else void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) { diff --git a/src/_HttpBase.h b/src/_HttpBase.h index d0b0c4b..4073f1a 100644 --- a/src/_HttpBase.h +++ b/src/_HttpBase.h @@ -294,7 +294,11 @@ void Http_LogError(const char* action, const struct HttpRequest* item) { *-----------------------------------------------------Http component------------------------------------------------------* *#########################################################################################################################*/ static void Http_InitCommon(void) { +#if defined CC_BUILD_NDS + httpOnly = Options_GetBool(OPT_HTTP_ONLY, true); +#else httpOnly = Options_GetBool(OPT_HTTP_ONLY, false); +#endif httpsVerify = Options_GetBool(OPT_HTTPS_VERIFY, true); Options_Get(OPT_SKIN_SERVER, &skinServer, SKINS_SERVER); diff --git a/src/_PlatformBase.h b/src/_PlatformBase.h index d2b9e0b..da1939b 100644 --- a/src/_PlatformBase.h +++ b/src/_PlatformBase.h @@ -90,6 +90,13 @@ int Stopwatch_ElapsedMS(cc_uint64 beg, cc_uint64 end) { return (int)raw / 1000; } +static CC_INLINE void SocketAddr_Set(cc_sockaddr* addr, const void* src, unsigned srcLen) { + if (srcLen > CC_SOCKETADDR_MAXSIZE) Logger_Abort("Attempted to copy too large socket"); + + Mem_Copy(addr->data, src, srcLen); + addr->size = srcLen; +} + cc_result Socket_WriteAll(cc_socket socket, const cc_uint8* data, cc_uint32 count) { cc_uint32 sent; cc_result res; diff --git a/src/_PlatformConsole.h b/src/_PlatformConsole.h index 8a03f41..53e9000 100644 --- a/src/_PlatformConsole.h +++ b/src/_PlatformConsole.h @@ -4,8 +4,9 @@ cc_bool Platform_SingleProcess = true; /*########################################################################################################################* *---------------------------------------------------------Memory----------------------------------------------------------* *#########################################################################################################################*/ -void Mem_Set(void* dst, cc_uint8 value, cc_uint32 numBytes) { memset(dst, value, numBytes); } -void Mem_Copy(void* dst, const void* src, cc_uint32 numBytes) { memcpy(dst, src, numBytes); } +void* Mem_Set(void* dst, cc_uint8 value, unsigned numBytes) { return memset( dst, value, numBytes); } +void* Mem_Copy(void* dst, const void* src, unsigned numBytes) { return memcpy( dst, src, numBytes); } +void* Mem_Move(void* dst, const void* src, unsigned numBytes) { return memmove(dst, src, numBytes); } void* Mem_TryAlloc(cc_uint32 numElems, cc_uint32 elemsSize) { cc_uint32 size = CalcMemSize(numElems, elemsSize); diff --git a/src/_WindowBase.h b/src/_WindowBase.h index 02fcec3..b5dd9ad 100644 --- a/src/_WindowBase.h +++ b/src/_WindowBase.h @@ -74,7 +74,7 @@ void Window_ShowDialog(const char* title, const char* msg) { struct GraphicsMode { int R, G, B, A; }; /* Creates a GraphicsMode compatible with the default display device */ -static void InitGraphicsMode(struct GraphicsMode* m) { +static CC_INLINE void InitGraphicsMode(struct GraphicsMode* m) { int bpp = DisplayInfo.Depth; m->A = 0; @@ -100,7 +100,7 @@ static void InitGraphicsMode(struct GraphicsMode* m) { } /* EGL is window system agnostic, other OpenGL context backends are tied to one windowing system */ -#if defined CC_BUILD_GL && defined CC_BUILD_EGL +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) && defined CC_BUILD_EGL /*########################################################################################################################* *-------------------------------------------------------EGL OpenGL--------------------------------------------------------* *#########################################################################################################################*/ @@ -132,7 +132,7 @@ static void GLContext_FreeSurface(void) { } void GLContext_Create(void) { -#ifdef CC_BUILD_GLMODERN +#if CC_GFX_BACKEND == CC_GFX_BACKEND_GL2 static EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; #else static EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE }; @@ -145,7 +145,7 @@ void GLContext_Create(void) { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, -#if defined CC_BUILD_GLES && defined CC_BUILD_GLMODERN +#if defined CC_BUILD_GLES && (CC_GFX_BACKEND == CC_GFX_BACKEND_GL2) EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, #elif defined CC_BUILD_GLES EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, diff --git a/src/interop_cocoa.m b/src/interop_cocoa.m index 647445d..7df9606 100644 --- a/src/interop_cocoa.m +++ b/src/interop_cocoa.m @@ -6,23 +6,7 @@ #include "String.h" #include "Options.h" #import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import +#import #include static int windowX, windowY; diff --git a/src/interop_ios.m b/src/interop_ios.m index 0ae0c0d..473af70 100644 --- a/src/interop_ios.m +++ b/src/interop_ios.m @@ -1,4 +1,6 @@ +// Silence deprecation warnings on modern iOS #define GLES_SILENCE_DEPRECATION + #include "_WindowBase.h" #include "Bitmap.h" #include "Input.h" @@ -17,8 +19,6 @@ #include #include #include -#include -#include #include #ifdef TARGET_OS_TV @@ -76,7 +76,7 @@ static UIInterfaceOrientationMask SupportedOrientations(void) { static cc_bool fullscreen = true; static void UpdateStatusBar(void) { - if (@available(iOS 10.7, *)) { + if ([cc_controller respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) { // setNeedsStatusBarAppearanceUpdate - iOS 7.0 [cc_controller setNeedsStatusBarAppearanceUpdate]; } else { @@ -436,6 +436,7 @@ void Window_SetTitle(const cc_string* title) { // TODO: Implement this somehow } +void Window_PreInit(void) { } void Window_Init(void) { //Window_Main.SoftKeyboard = SOFT_KEYBOARD_RESIZE; // keyboard now shifts up @@ -509,16 +510,16 @@ void ShowDialogCore(const char* title, const char* msg) { NSString* _msg = [NSString stringWithCString:msg encoding:NSASCIIStringEncoding]; alert_completed = false; - if (@available(iOS 10.8, *)) { - UIAlertController* alert = [UIAlertController alertControllerWithTitle:_title message:_msg preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction* okBtn = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* act) { alert_completed = true; }]; - [alert addAction:okBtn]; - [cc_controller presentViewController:alert animated:YES completion: Nil]; - } else { - UIAlertView* alert = [UIAlertView alloc]; - alert = [alert initWithTitle:_title message:_msg delegate:cc_controller cancelButtonTitle:@"OK" otherButtonTitles:nil]; - [alert show]; - } +#ifdef TARGET_OS_TV + UIAlertController* alert = [UIAlertController alertControllerWithTitle:_title message:_msg preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction* okBtn = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* act) { alert_completed = true; }]; + [alert addAction:okBtn]; + [cc_controller presentViewController:alert animated:YES completion: Nil]; +#else + UIAlertView* alert = [UIAlertView alloc]; + alert = [alert initWithTitle:_title message:_msg delegate:cc_controller cancelButtonTitle:@"OK" otherButtonTitles:nil]; + [alert show]; +#endif // TODO clicking outside message box crashes launcher // loop until alert is closed TODO avoid sleeping @@ -651,18 +652,15 @@ cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) { if (utType) [types addObject:utType]; } - if (@available(iOS 10.8, *)) { - UIDocumentPickerViewController* dlg; - dlg = [UIDocumentPickerViewController alloc]; - dlg = [dlg initWithDocumentTypes:types inMode:UIDocumentPickerModeOpen]; - //dlg = [dlg initWithDocumentTypes:types inMode:UIDocumentPickerModeImport]; - - open_dlg_callback = args->Callback; - dlg.delegate = cc_controller; - [cc_controller presentViewController:dlg animated:YES completion: Nil]; - return 0; // TODO still unfinished - } - return ERR_NOT_SUPPORTED; + UIDocumentPickerViewController* dlg; + dlg = [UIDocumentPickerViewController alloc]; + dlg = [dlg initWithDocumentTypes:types inMode:UIDocumentPickerModeOpen]; + //dlg = [dlg initWithDocumentTypes:types inMode:UIDocumentPickerModeImport]; + + open_dlg_callback = args->Callback; + dlg.delegate = cc_controller; + [cc_controller presentViewController:dlg animated:YES completion: Nil]; + return 0; // TODO still unfinished } cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { @@ -680,22 +678,23 @@ cc_result Window_SaveFileDialog(const struct SaveFileDialogArgs* args) { NSString* str = ToNSString(&save_path); NSURL* url = [NSURL fileURLWithPath:str isDirectory:NO]; - if (@available(iOS 10.8, *)) { - UIDocumentPickerViewController* dlg; - dlg = [UIDocumentPickerViewController alloc]; - dlg = [dlg initWithURL:url inMode:UIDocumentPickerModeExportToService]; - - dlg.delegate = cc_controller; - [cc_controller presentViewController:dlg animated:YES completion: Nil]; - return 0; // TODO still unfinished - } - return ERR_NOT_SUPPORTED; + UIDocumentPickerViewController* dlg; + dlg = [UIDocumentPickerViewController alloc]; + dlg = [dlg initWithURL:url inMode:UIDocumentPickerModeExportToService]; + + dlg.delegate = cc_controller; + [cc_controller presentViewController:dlg animated:YES completion: Nil]; + return 0; } /*#########################################################################################################################* - *--------------------------------------------------------2D window--------------------------------------------------------* + *-----------------------------------------------------Window creation-----------------------------------------------------* *#########################################################################################################################*/ +@interface CC3DView : UIView +@end +static void Init3DLayer(void); + void Window_Create2D(int width, int height) { launcherMode = true; CGRect bounds = DoCreateWindow(); @@ -705,49 +704,25 @@ void Window_Create2D(int width, int height) { cc_controller.view = view_handle; } - -/*#########################################################################################################################* - *--------------------------------------------------------3D window--------------------------------------------------------* - *#########################################################################################################################*/ -static void GLContext_OnLayout(void); - -@interface CCGLView : UIView -@end - -@implementation CCGLView - -+ (Class)layerClass { - return [CAEAGLLayer class]; -} - -- (void)layoutSubviews { - [super layoutSubviews]; - GLContext_OnLayout(); -} -@end - void Window_Create3D(int width, int height) { launcherMode = false; CGRect bounds = DoCreateWindow(); - // CAEAGLLayer - iOS 2.0 - view_handle = [[CCGLView alloc] initWithFrame:bounds]; + view_handle = [[CC3DView alloc] initWithFrame:bounds]; view_handle.multipleTouchEnabled = true; cc_controller.view = view_handle; - - CAEAGLLayer* layer = (CAEAGLLayer*)view_handle.layer; - layer.opaque = YES; - layer.drawableProperties = - @{ - kEAGLDrawablePropertyRetainedBacking : [NSNumber numberWithBool:NO], - kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8 - }; + + Init3DLayer(); } /*########################################################################################################################* *--------------------------------------------------------GLContext--------------------------------------------------------* *#########################################################################################################################*/ +#if (CC_GFX_BACKEND & CC_GFX_BACKEND_GL_MASK) +#include +#include + static EAGLContext* ctx_handle; static GLuint framebuffer; static GLuint color_renderbuffer, depth_renderbuffer; @@ -841,14 +816,40 @@ cc_bool GLContext_SwapBuffers(void) { } void GLContext_SetFpsLimit(cc_bool vsync, float minFrameMs) { } void GLContext_GetApiInfo(cc_string* info) { } -const struct UpdaterInfo Updater_Info = { "&eCompile latest source code to update", 0 }; + + +@implementation CC3DView + ++ (Class)layerClass { + return [CAEAGLLayer class]; +} + +- (void)layoutSubviews { + [super layoutSubviews]; + GLContext_OnLayout(); +} +@end + +static void Init3DLayer(void) { + // CAEAGLLayer - iOS 2.0 + CAEAGLLayer* layer = (CAEAGLLayer*)view_handle.layer; + + layer.opaque = YES; + layer.drawableProperties = + @{ + kEAGLDrawablePropertyRetainedBacking : [NSNumber numberWithBool:NO], + kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8 + }; +} +#endif /*########################################################################################################################* *--------------------------------------------------------Updater----------------------------------------------------------* *#########################################################################################################################*/ -const char* const Updater_OGL = NULL; -const char* const Updater_D3D9 = NULL; +const struct UpdaterInfo Updater_Info = { + "&eRedownload and reinstall to update", 0 +}; cc_bool Updater_Clean(void) { return true; } cc_result Updater_GetBuildTime(cc_uint64* t) { @@ -877,6 +878,7 @@ cc_result Process_StartOpen(const cc_string* args) { // openURL - iOS 2.0 (deprecated) NSString* str = ToNSString(args); NSURL* url = [[NSURL alloc] initWithString:str]; + [UIApplication.sharedApplication openURL:url]; return 0; } @@ -1841,4 +1843,4 @@ void LBackend_CloseScreen(struct LScreen* s) { { [view removeFromSuperview]; } -} +} \ No newline at end of file diff --git a/src/interop_web.js b/src/interop_web.js index 4d34ade..a6bd7c2 100644 --- a/src/interop_web.js +++ b/src/interop_web.js @@ -350,8 +350,8 @@ mergeInto(LibraryManager.library, { // previously you were required to add interop_LoadIndexedDB to Module.preRun array // to load the indexedDB asynchronously *before* starting ClassiCube, because it // could not load indexedDB asynchronously - // however, as ClassiCube now loads IndexedDB asynchronously itself, this is no longer - // necessary, but is kept arounf foe backwards compatibility + // however, as ClassiCube now loads IndexedDB asynchronously itself, this is + // no longer necessary, but is kept around for backwards compatibility }, interop_SaveNode__deps: ['IDBFS_getDB', 'IDBFS_storeRemoteEntry'], interop_SaveNode: function(path) { @@ -441,7 +441,7 @@ mergeInto(LibraryManager.library, { req.onsuccess = function() { db = req.result; window.IDBFS_db = db; - // browser will sometimes close connection behind the scenes + // browser will sometimes close IndexedDB connection behind the scenes db.onclose = function(ev) { console.log('IndexedDB connection closed unexpectedly!'); window.IDBFS_db = null; diff --git a/src/main.c b/src/main.c index 104c9bf..f0179e2 100644 --- a/src/main.c +++ b/src/main.c @@ -56,9 +56,10 @@ static void SetupProgram(int argc, char** argv) { static char ipBuffer[STRING_SIZE]; cc_result res; Logger_Hook(); + Window_PreInit(); Platform_Init(); + res = Platform_SetDefaultCurrentDirectory(argc, argv); - Options_Load(); Window_Init(); @@ -164,7 +165,12 @@ int main(int argc, char** argv) { cc_result res; SetupProgram(argc, argv); - res = RunProgram(argc, argv); + /* If single process mode, then the loop is launcher -> game -> launcher etc */ + do { + res = RunProgram(argc, argv); + } while (Platform_SingleProcess && Window_Main.Exists); + + Window_Free(); Process_Exit(res); return res; }