diff --git a/CMakeLists.txt b/CMakeLists.txt index c9791df..a7e8b66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -69,6 +69,7 @@ if (NOT(POMME_NO_GRAPHICS)) ${POMME_SRCDIR}/Graphics/Color.cpp ${POMME_SRCDIR}/Graphics/ColorManager.cpp ${POMME_SRCDIR}/Graphics/Graphics.cpp + ${POMME_SRCDIR}/Graphics/Icons.cpp ${POMME_SRCDIR}/Graphics/PICT.cpp ${POMME_SRCDIR}/Graphics/SysFont.h ${POMME_SRCDIR}/Graphics/SystemPalettes.cpp diff --git a/src/Files/Resources.cpp b/src/Files/Resources.cpp index 2616067..2cb23fd 100644 --- a/src/Files/Resources.cpp +++ b/src/Files/Resources.cpp @@ -1,6 +1,6 @@ #include "Pomme.h" #include "PommeFiles.h" -#include "Memory/BlockDescriptor.h" +#include "PommeMemory.h" #include "Utilities/bigendianstreams.h" #include diff --git a/src/Graphics/Graphics.cpp b/src/Graphics/Graphics.cpp index ee13875..7c9d77a 100644 --- a/src/Graphics/Graphics.cpp +++ b/src/Graphics/Graphics.cpp @@ -1,13 +1,13 @@ #include "Pomme.h" +#include "PommeFiles.h" #include "PommeGraphics.h" +#include "PommeMemory.h" #include "SysFont.h" #include "Utilities/memstream.h" #include #include -#include -#include -#include +#include using namespace Pomme; using namespace Pomme::Graphics; @@ -674,55 +674,3 @@ void DrawChar(char c) penX += glyph.width; } - -// ---------------------------------------------------------------------------- -// Icons - -void Pomme::Graphics::SetWindowIconFromIcl8Resource(SDL_Window* window, short icl8ID) -{ - Handle colorIcon = GetResource('icl8', icl8ID); - Handle bwIcon = GetResource('ICN#', icl8ID); - - if (1024 != GetHandleSize(colorIcon)) - { - DisposeHandle(colorIcon); - DisposeHandle(bwIcon); - throw std::invalid_argument("icl8 resource has incorrect size"); - } - - if (256 != GetHandleSize(bwIcon)) - { - DisposeHandle(colorIcon); - DisposeHandle(bwIcon); - throw std::invalid_argument("ICN# resource has incorrect size"); - } - - uint32_t* maskScanlines = (uint32_t*)(*bwIcon + 128); // mask starts 128 bytes into ICN# resource - ByteswapInts(4, 32, maskScanlines); - - const int width = 32; - const int height = 32; - - SDL_Surface* icon = SDL_CreateRGBSurface(0, width, height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000); - for (int y = 0; y < height; y++) - { - uint32_t* out = (uint32_t*) ((char*) icon->pixels + icon->pitch * y); - for (int x = 0; x < width; x++) - { - uint8_t paletteEntry = (*colorIcon)[y * width + x]; - uint32_t argb = Pomme::Graphics::clut8[paletteEntry]; - bool masked = maskScanlines[y] & (1 << (width - 1 - x)); - if (!masked) - { - argb &= 0x00FFFFFF; - } - *out++ = argb; - } - } - - SDL_SetWindowIcon(window, icon); - SDL_FreeSurface(icon); - - DisposeHandle(colorIcon); - DisposeHandle(bwIcon); -} diff --git a/src/Graphics/Icons.cpp b/src/Graphics/Icons.cpp new file mode 100644 index 0000000..37ae32b --- /dev/null +++ b/src/Graphics/Icons.cpp @@ -0,0 +1,154 @@ +#include "Pomme.h" +#include "PommeGraphics.h" +#include "PommeMemory.h" +#include "Utilities/structpack.h" + +#include +#include + +// ---------------------------------------------------------------------------- +// Icons + +static Handle Get4bitIconAsARGB(Handle colorIcon, Ptr bwMask, int width) +{ + int height = width; + + if (!colorIcon || !bwMask) + return nil; + + if (width*height/2 != GetHandleSize(colorIcon)) + return nil; + + Handle icon = NewHandle(width * height * 4); + + for (int y = 0; y < height; y++) + { + uint32_t* out = (uint32_t*) (*icon + y * width * 4); + + uint32_t scanlineMask = 0xFFFFFFFF; + if (!bwMask) + ; + else if (width == 32) + scanlineMask = Byteswap32(bwMask + y*4); + else if (width == 16) + scanlineMask = Byteswap16(bwMask + y*2); + + for (int x = 0; x < width; x++) + { + uint8_t paletteEntry = (*colorIcon)[y * (width>>1) + (x>>1)]; + if (!(x & 1)) + paletteEntry >>= 4; + paletteEntry &= 0x0F; + + uint32_t argb = Pomme::Graphics::clut4[paletteEntry]; + + bool masked = scanlineMask & (1 << (width - 1 - x)); + if (!masked) + argb &= 0x00FFFFFF; + + *out++ = argb; + } + } + + return icon; +} + +static Handle Get8bitIconAsARGB(Handle colorIcon, Ptr bwMask, int width) +{ + int height = width; + + if (!colorIcon || !bwMask) + return nil; + + if (width*height != GetHandleSize(colorIcon)) + return nil; + + Handle icon = NewHandle(width * height * 4); + + for (int y = 0; y < height; y++) + { + uint32_t* out = (uint32_t*) (*icon + y * width * 4); + + uint32_t scanlineMask = 0xFFFFFFFF; + if (!bwMask) + ; + else if (width == 32) + scanlineMask = Byteswap32(bwMask + y*4); + else if (width == 16) + scanlineMask = Byteswap16(bwMask + y*2); + + for (int x = 0; x < width; x++) + { + uint8_t paletteEntry = (*colorIcon)[y * width + x]; + uint32_t argb = Pomme::Graphics::clut8[paletteEntry]; + + bool masked = scanlineMask & (1 << (width - 1 -x)); + if (!masked) + argb &= 0x00FFFFFF; + + *out++ = argb; + } + } + + return icon; +} + +Handle Pomme::Graphics::GetIcl8AsARGB(short id) +{ + Handle colorIcon = GetResource('icl8', id); + Handle bwIcon = GetResource('ICN#', id); + + Pomme::Memory::DisposeHandleGuard autoDisposeColorIcon(colorIcon); + Pomme::Memory::DisposeHandleGuard autoDisposeBwIcon(bwIcon); + + Ptr mask = nil; + if (bwIcon && 256 == GetHandleSize(bwIcon)) + mask = *bwIcon + 128; // Mask data for icl8 starts 128 bytes into ICN# + + return Get8bitIconAsARGB(colorIcon, mask, 32); +} + +Handle Pomme::Graphics::GetIcs8AsARGB(short id) +{ + Handle colorIcon = GetResource('ics8', id); + Handle bwIcon = GetResource('ics#', id); + + Pomme::Memory::DisposeHandleGuard autoDisposeColorIcon(colorIcon); + Pomme::Memory::DisposeHandleGuard autoDisposeBwIcon(bwIcon); + + Ptr mask = nil; + if (bwIcon && 64 == GetHandleSize(bwIcon)) + mask = *bwIcon + 32; // Mask data for ics8 starts 32 bytes into ics# + + return Get8bitIconAsARGB(colorIcon, mask, 16); +} + +Handle Pomme::Graphics::GetIcl4AsARGB(short id) +{ + Handle colorIcon = GetResource('icl4', id); + Handle bwIcon = GetResource('ICN#', id); + + Pomme::Memory::DisposeHandleGuard autoDisposeColorIcon(colorIcon); + Pomme::Memory::DisposeHandleGuard autoDisposeBwIcon(bwIcon); + + Ptr mask = nil; + if (bwIcon && 256 == GetHandleSize(bwIcon)) + mask = *bwIcon + 128; // Mask data for icl8 starts 128 bytes into ICN# + + return Get4bitIconAsARGB(colorIcon, mask, 32); +} + +Handle Pomme::Graphics::GetIcs4AsARGB(short id) +{ + Handle colorIcon = GetResource('ics4', id); + Handle bwIcon = GetResource('ics#', id); + + Pomme::Memory::DisposeHandleGuard autoDisposeColorIcon(colorIcon); + Pomme::Memory::DisposeHandleGuard autoDisposeBwIcon(bwIcon); + + Ptr mask = nil; + if (bwIcon && 64 == GetHandleSize(bwIcon)) + mask = *bwIcon + 32; // Mask data for ics8 starts 32 bytes into ics# + + return Get4bitIconAsARGB(colorIcon, mask, 16); +} diff --git a/src/Memory/Memory.cpp b/src/Memory/Memory.cpp index 398ce99..d0c12c8 100644 --- a/src/Memory/Memory.cpp +++ b/src/Memory/Memory.cpp @@ -3,7 +3,7 @@ #include #include "Pomme.h" -#include "Memory/BlockDescriptor.h" +#include "PommeMemory.h" using namespace Pomme; using namespace Pomme::Memory; diff --git a/src/PommeGraphics.h b/src/PommeGraphics.h index 2e04fe2..c6ff5b8 100644 --- a/src/PommeGraphics.h +++ b/src/PommeGraphics.h @@ -3,7 +3,6 @@ #include "PommeTypes.h" #include #include -#include namespace Pomme::Graphics { @@ -54,7 +53,10 @@ namespace Pomme::Graphics CGrafPtr GetScreenPort(void); - void SetWindowIconFromIcl8Resource(SDL_Window* sdlWindow, short i); + Handle GetIcl8AsARGB(short i); + Handle GetIcs8AsARGB(short i); + Handle GetIcl4AsARGB(short i); + Handle GetIcs4AsARGB(short i); inline int Width(const Rect& r) { return r.right - r.left; } diff --git a/src/Memory/BlockDescriptor.h b/src/PommeMemory.h similarity index 63% rename from src/Memory/BlockDescriptor.h rename to src/PommeMemory.h index f9689b5..a4dc369 100644 --- a/src/Memory/BlockDescriptor.h +++ b/src/PommeMemory.h @@ -21,4 +21,21 @@ namespace Pomme::Memory static BlockDescriptor* HandleToBlock(Handle h); }; + + class DisposeHandleGuard + { + public: + DisposeHandleGuard(Handle theHandle) + : h(theHandle) + {} + + ~DisposeHandleGuard() + { + if (h) + DisposeHandle(h); + } + + private: + Handle h; + }; }