From a6a030052c9f06d08631228ef964769c68e3192c Mon Sep 17 00:00:00 2001 From: Celtic Minstrel Date: Sat, 12 Apr 2014 01:09:37 -0400 Subject: [PATCH] Implement loading of .meg files using the Resource manager - I extract pixel data from the resource without using QuickDraw - Both resource-fork and data-fork .meg files work Related changes: - The custom graphics textures are now wrapped in a custom class - bmp images are loaded if a meg is not found Incidental changes: - Various TODO notes - Fix cScenario::spec_strs skipping several strings and potentially fetching out-of-bound entries - oopsError now uses string streams instead of sprintf --- osx/BoE.xcodeproj/project.pbxproj | 96 ++-- .../xcschemes/Blades of Exile.xcscheme | 2 +- osx/boe.fileio.cpp | 2 +- osx/boe.graphics.cpp | 5 +- osx/boe.graphutil.cpp | 38 +- osx/boe.newgraph.cpp | 14 +- osx/boe.party.cpp | 1 + osx/boe.text.cpp | 9 +- osx/boe.town.cpp | 12 +- osx/classes/monster.cpp | 1 + osx/classes/scenario.cpp | 7 +- osx/dialogxml/dlogutil.cpp | 11 +- osx/dialogxml/pict.cpp | 109 ++--- osx/tools/fileio.cpp | 71 +-- osx/tools/graphtool.cpp | 16 +- osx/tools/graphtool.h | 23 +- osx/tools/qdpict.cpp | 427 ++++++++++++++++++ 17 files changed, 658 insertions(+), 186 deletions(-) create mode 100644 osx/tools/qdpict.cpp diff --git a/osx/BoE.xcodeproj/project.pbxproj b/osx/BoE.xcodeproj/project.pbxproj index d9165fa1..88bccbc9 100644 --- a/osx/BoE.xcodeproj/project.pbxproj +++ b/osx/BoE.xcodeproj/project.pbxproj @@ -296,21 +296,6 @@ 914B2AA618E7E50D007B6799 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA218E7E500007B6799 /* OpenGL.framework */; }; 914B2AA718E7E50E007B6799 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA218E7E500007B6799 /* OpenGL.framework */; }; 914B2AA818E7E50E007B6799 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA218E7E500007B6799 /* OpenGL.framework */; }; - 914B2AB018E7E52F007B6799 /* sfml-audio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA918E7E529007B6799 /* sfml-audio.framework */; }; - 914B2AB118E7E530007B6799 /* sfml-audio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA918E7E529007B6799 /* sfml-audio.framework */; }; - 914B2AB218E7E531007B6799 /* sfml-audio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AA918E7E529007B6799 /* sfml-audio.framework */; }; - 914B2AB318E7E535007B6799 /* sfml-graphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAA18E7E529007B6799 /* sfml-graphics.framework */; }; - 914B2AB418E7E536007B6799 /* sfml-graphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAA18E7E529007B6799 /* sfml-graphics.framework */; }; - 914B2AB518E7E536007B6799 /* sfml-graphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAA18E7E529007B6799 /* sfml-graphics.framework */; }; - 914B2AB618E7E539007B6799 /* sfml-system.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAB18E7E529007B6799 /* sfml-system.framework */; }; - 914B2AB718E7E539007B6799 /* sfml-system.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAB18E7E529007B6799 /* sfml-system.framework */; }; - 914B2AB818E7E53A007B6799 /* sfml-system.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAB18E7E529007B6799 /* sfml-system.framework */; }; - 914B2AB918E7E53C007B6799 /* sfml-window.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAC18E7E529007B6799 /* sfml-window.framework */; }; - 914B2ABA18E7E53D007B6799 /* sfml-window.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAC18E7E529007B6799 /* sfml-window.framework */; }; - 914B2ABB18E7E53D007B6799 /* sfml-window.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAC18E7E529007B6799 /* sfml-window.framework */; }; - 914B2ABC18E7E540007B6799 /* SFML.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAD18E7E529007B6799 /* SFML.framework */; }; - 914B2ABD18E7E540007B6799 /* SFML.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAD18E7E529007B6799 /* SFML.framework */; }; - 914B2ABE18E7E541007B6799 /* SFML.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAD18E7E529007B6799 /* SFML.framework */; }; 914B2ABF18E7E543007B6799 /* sndfile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAE18E7E529007B6799 /* sndfile.framework */; }; 914B2AC018E7E544007B6799 /* sndfile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAE18E7E529007B6799 /* sndfile.framework */; }; 914B2AC118E7E544007B6799 /* sndfile.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 914B2AAE18E7E529007B6799 /* sndfile.framework */; }; @@ -512,6 +497,27 @@ 91E5C7B80F9F619D00C21460 /* talking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E5C7B70F9F619D00C21460 /* talking.cpp */; }; 91E5C7B90F9F619D00C21460 /* talking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E5C7B70F9F619D00C21460 /* talking.cpp */; }; 91E5C7BA0F9F619D00C21460 /* talking.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91E5C7B70F9F619D00C21460 /* talking.cpp */; }; + 91F6F8E318F87F3700E3EA15 /* sfml-audio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DD18F87F3700E3EA15 /* sfml-audio.framework */; }; + 91F6F8E418F87F3700E3EA15 /* sfml-audio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DD18F87F3700E3EA15 /* sfml-audio.framework */; }; + 91F6F8E518F87F3700E3EA15 /* sfml-audio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DD18F87F3700E3EA15 /* sfml-audio.framework */; }; + 91F6F8E618F87F3700E3EA15 /* sfml-graphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DE18F87F3700E3EA15 /* sfml-graphics.framework */; }; + 91F6F8E718F87F3700E3EA15 /* sfml-graphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DE18F87F3700E3EA15 /* sfml-graphics.framework */; }; + 91F6F8E818F87F3700E3EA15 /* sfml-graphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DE18F87F3700E3EA15 /* sfml-graphics.framework */; }; + 91F6F8E918F87F3700E3EA15 /* sfml-network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DF18F87F3700E3EA15 /* sfml-network.framework */; }; + 91F6F8EA18F87F3700E3EA15 /* sfml-network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DF18F87F3700E3EA15 /* sfml-network.framework */; }; + 91F6F8EB18F87F3700E3EA15 /* sfml-network.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8DF18F87F3700E3EA15 /* sfml-network.framework */; }; + 91F6F8EC18F87F3700E3EA15 /* sfml-system.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E018F87F3700E3EA15 /* sfml-system.framework */; }; + 91F6F8ED18F87F3700E3EA15 /* sfml-system.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E018F87F3700E3EA15 /* sfml-system.framework */; }; + 91F6F8EE18F87F3700E3EA15 /* sfml-system.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E018F87F3700E3EA15 /* sfml-system.framework */; }; + 91F6F8EF18F87F3700E3EA15 /* sfml-window.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E118F87F3700E3EA15 /* sfml-window.framework */; }; + 91F6F8F018F87F3700E3EA15 /* sfml-window.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E118F87F3700E3EA15 /* sfml-window.framework */; }; + 91F6F8F118F87F3700E3EA15 /* sfml-window.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E118F87F3700E3EA15 /* sfml-window.framework */; }; + 91F6F8F218F87F3700E3EA15 /* SFML.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E218F87F3700E3EA15 /* SFML.framework */; }; + 91F6F8F318F87F3700E3EA15 /* SFML.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E218F87F3700E3EA15 /* SFML.framework */; }; + 91F6F8F418F87F3700E3EA15 /* SFML.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F6F8E218F87F3700E3EA15 /* SFML.framework */; }; + 91F6F8F618F8DE6300E3EA15 /* qdpict.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91F6F8F518F8DE6300E3EA15 /* qdpict.cpp */; }; + 91F6F8F718F8DE6300E3EA15 /* qdpict.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91F6F8F518F8DE6300E3EA15 /* qdpict.cpp */; }; + 91F6F8F818F8DE6300E3EA15 /* qdpict.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 91F6F8F518F8DE6300E3EA15 /* qdpict.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1275,11 +1281,6 @@ 914701A918F64A85008A6DC9 /* dialog.xsd */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = dialog.xsd; path = dialogs/dialog.xsd; sourceTree = ""; }; 914B2AA118E7E500007B6799 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = ../../../../../../System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 914B2AA218E7E500007B6799 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = ../../../../../../System/Library/Frameworks/OpenGL.framework; sourceTree = ""; }; - 914B2AA918E7E529007B6799 /* sfml-audio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-audio.framework"; path = "../../../../../../Library/Frameworks/sfml-audio.framework"; sourceTree = ""; }; - 914B2AAA18E7E529007B6799 /* sfml-graphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-graphics.framework"; path = "../../../../../../Library/Frameworks/sfml-graphics.framework"; sourceTree = ""; }; - 914B2AAB18E7E529007B6799 /* sfml-system.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-system.framework"; path = "../../../../../../Library/Frameworks/sfml-system.framework"; sourceTree = ""; }; - 914B2AAC18E7E529007B6799 /* sfml-window.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-window.framework"; path = "../../../../../../Library/Frameworks/sfml-window.framework"; sourceTree = ""; }; - 914B2AAD18E7E529007B6799 /* SFML.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SFML.framework; path = ../../../../../../Library/Frameworks/SFML.framework; sourceTree = ""; }; 914B2AAE18E7E529007B6799 /* sndfile.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = sndfile.framework; path = ../../../../../../Library/Frameworks/sndfile.framework; sourceTree = ""; }; 914B2ACC18E7FFEF007B6799 /* SND1.WAV */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = SND1.WAV; sourceTree = ""; }; 914B2ACD18E7FFEF007B6799 /* SND10.WAV */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; path = SND10.WAV; sourceTree = ""; }; @@ -1480,6 +1481,13 @@ 91E5C7A60F9F615400C21460 /* fileio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fileio.cpp; sourceTree = ""; }; 91E5C7B60F9F619D00C21460 /* talking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = talking.h; sourceTree = ""; }; 91E5C7B70F9F619D00C21460 /* talking.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = talking.cpp; sourceTree = ""; }; + 91F6F8DD18F87F3700E3EA15 /* sfml-audio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-audio.framework"; path = "../../../../../../Library/Frameworks/sfml-audio.framework"; sourceTree = ""; }; + 91F6F8DE18F87F3700E3EA15 /* sfml-graphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-graphics.framework"; path = "../../../../../../Library/Frameworks/sfml-graphics.framework"; sourceTree = ""; }; + 91F6F8DF18F87F3700E3EA15 /* sfml-network.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-network.framework"; path = "../../../../../../Library/Frameworks/sfml-network.framework"; sourceTree = ""; }; + 91F6F8E018F87F3700E3EA15 /* sfml-system.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-system.framework"; path = "../../../../../../Library/Frameworks/sfml-system.framework"; sourceTree = ""; }; + 91F6F8E118F87F3700E3EA15 /* sfml-window.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = "sfml-window.framework"; path = "../../../../../../Library/Frameworks/sfml-window.framework"; sourceTree = ""; }; + 91F6F8E218F87F3700E3EA15 /* SFML.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SFML.framework; path = ../../../../../../Library/Frameworks/SFML.framework; sourceTree = ""; }; + 91F6F8F518F8DE6300E3EA15 /* qdpict.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = qdpict.cpp; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1489,12 +1497,13 @@ files = ( 914B2AA318E7E507007B6799 /* Cocoa.framework in Frameworks */, 914B2AA618E7E50D007B6799 /* OpenGL.framework in Frameworks */, - 914B2AB218E7E531007B6799 /* sfml-audio.framework in Frameworks */, - 914B2AB318E7E535007B6799 /* sfml-graphics.framework in Frameworks */, - 914B2AB618E7E539007B6799 /* sfml-system.framework in Frameworks */, - 914B2AB918E7E53C007B6799 /* sfml-window.framework in Frameworks */, - 914B2ABC18E7E540007B6799 /* SFML.framework in Frameworks */, 914B2ABF18E7E543007B6799 /* sndfile.framework in Frameworks */, + 91F6F8E318F87F3700E3EA15 /* sfml-audio.framework in Frameworks */, + 91F6F8E618F87F3700E3EA15 /* sfml-graphics.framework in Frameworks */, + 91F6F8E918F87F3700E3EA15 /* sfml-network.framework in Frameworks */, + 91F6F8EC18F87F3700E3EA15 /* sfml-system.framework in Frameworks */, + 91F6F8EF18F87F3700E3EA15 /* sfml-window.framework in Frameworks */, + 91F6F8F218F87F3700E3EA15 /* SFML.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1504,12 +1513,13 @@ files = ( 914B2AA418E7E509007B6799 /* Cocoa.framework in Frameworks */, 914B2AA718E7E50E007B6799 /* OpenGL.framework in Frameworks */, - 914B2AB018E7E52F007B6799 /* sfml-audio.framework in Frameworks */, - 914B2AB418E7E536007B6799 /* sfml-graphics.framework in Frameworks */, - 914B2AB718E7E539007B6799 /* sfml-system.framework in Frameworks */, - 914B2ABA18E7E53D007B6799 /* sfml-window.framework in Frameworks */, - 914B2ABD18E7E540007B6799 /* SFML.framework in Frameworks */, 914B2AC018E7E544007B6799 /* sndfile.framework in Frameworks */, + 91F6F8E418F87F3700E3EA15 /* sfml-audio.framework in Frameworks */, + 91F6F8E718F87F3700E3EA15 /* sfml-graphics.framework in Frameworks */, + 91F6F8EA18F87F3700E3EA15 /* sfml-network.framework in Frameworks */, + 91F6F8ED18F87F3700E3EA15 /* sfml-system.framework in Frameworks */, + 91F6F8F018F87F3700E3EA15 /* sfml-window.framework in Frameworks */, + 91F6F8F318F87F3700E3EA15 /* SFML.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1519,12 +1529,13 @@ files = ( 914B2AA518E7E50A007B6799 /* Cocoa.framework in Frameworks */, 914B2AA818E7E50E007B6799 /* OpenGL.framework in Frameworks */, - 914B2AB118E7E530007B6799 /* sfml-audio.framework in Frameworks */, - 914B2AB518E7E536007B6799 /* sfml-graphics.framework in Frameworks */, - 914B2AB818E7E53A007B6799 /* sfml-system.framework in Frameworks */, - 914B2ABB18E7E53D007B6799 /* sfml-window.framework in Frameworks */, - 914B2ABE18E7E541007B6799 /* SFML.framework in Frameworks */, 914B2AC118E7E544007B6799 /* sndfile.framework in Frameworks */, + 91F6F8E518F87F3700E3EA15 /* sfml-audio.framework in Frameworks */, + 91F6F8E818F87F3700E3EA15 /* sfml-graphics.framework in Frameworks */, + 91F6F8EB18F87F3700E3EA15 /* sfml-network.framework in Frameworks */, + 91F6F8EE18F87F3700E3EA15 /* sfml-system.framework in Frameworks */, + 91F6F8F118F87F3700E3EA15 /* sfml-window.framework in Frameworks */, + 91F6F8F418F87F3700E3EA15 /* SFML.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1918,6 +1929,7 @@ 91C688E70FD702B9000F6D01 /* cursors.m */, 912283C80FD0E16C00B21642 /* undo.cpp */, 919145FF18E63B70005CF3A4 /* winutil.mac.mm */, + 91F6F8F518F8DE6300E3EA15 /* qdpict.cpp */, ); name = src; sourceTree = ""; @@ -1949,11 +1961,12 @@ 914B2AA018E7E4A3007B6799 /* Linked Frameworks */ = { isa = PBXGroup; children = ( - 914B2AA918E7E529007B6799 /* sfml-audio.framework */, - 914B2AAA18E7E529007B6799 /* sfml-graphics.framework */, - 914B2AAB18E7E529007B6799 /* sfml-system.framework */, - 914B2AAC18E7E529007B6799 /* sfml-window.framework */, - 914B2AAD18E7E529007B6799 /* SFML.framework */, + 91F6F8DD18F87F3700E3EA15 /* sfml-audio.framework */, + 91F6F8DE18F87F3700E3EA15 /* sfml-graphics.framework */, + 91F6F8DF18F87F3700E3EA15 /* sfml-network.framework */, + 91F6F8E018F87F3700E3EA15 /* sfml-system.framework */, + 91F6F8E118F87F3700E3EA15 /* sfml-window.framework */, + 91F6F8E218F87F3700E3EA15 /* SFML.framework */, 914B2AAE18E7E529007B6799 /* sndfile.framework */, 914B2AA118E7E500007B6799 /* Cocoa.framework */, 914B2AA218E7E500007B6799 /* OpenGL.framework */, @@ -2563,6 +2576,7 @@ 919145FC18E3AB1B005CF3A4 /* boe.appleevents.mm in Sources */, 914B2AC618E7E6EB007B6799 /* winutil.mac.mm in Sources */, 9107074C18F1D18400F7BD7F /* scrollbar.cpp in Sources */, + 91F6F8F618F8DE6300E3EA15 /* qdpict.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2610,6 +2624,7 @@ 91A32D1E0FDE04A000C4E957 /* tinyxmlerror.cpp in Sources */, 91A32D1F0FDE04A100C4E957 /* tinyxmlparser.cpp in Sources */, 9107074D18F1D18400F7BD7F /* scrollbar.cpp in Sources */, + 91F6F8F718F8DE6300E3EA15 /* qdpict.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2662,6 +2677,7 @@ 91A32D230FDE04A600C4E957 /* tinyxmlerror.cpp in Sources */, 91A32D240FDE04A600C4E957 /* tinyxmlparser.cpp in Sources */, 9107074E18F1D18500F7BD7F /* scrollbar.cpp in Sources */, + 91F6F8F818F8DE6300E3EA15 /* qdpict.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/osx/BoE.xcodeproj/xcshareddata/xcschemes/Blades of Exile.xcscheme b/osx/BoE.xcodeproj/xcshareddata/xcschemes/Blades of Exile.xcscheme index 9f13338f..f320f8b7 100644 --- a/osx/BoE.xcodeproj/xcshareddata/xcschemes/Blades of Exile.xcscheme +++ b/osx/BoE.xcodeproj/xcshareddata/xcschemes/Blades of Exile.xcscheme @@ -64,7 +64,7 @@ shouldUseLaunchSchemeArgsEnv = "YES" savedToolIdentifier = "" useCustomWorkingDirectory = "NO" - buildConfiguration = "Release" + buildConfiguration = "Debug" debugDocumentVersioning = "YES"> = 2000) { // custom - source_gworld = spec_scen_g; - source_rect = get_custom_rect(scenario.ter_types[terrain_to_draw].picture - 2000 + (anim_ticks % 4)); + graf_pos_ref(source_gworld, source_rect) = spec_scen_g.find_graphic(scenario.ter_types[terrain_to_draw].picture - 2000 + (anim_ticks % 4)); anim_type = 0; terrain_there[i][j] = -1; } else if (scenario.ter_types[terrain_to_draw].picture >= 1000) { // custom - source_gworld = spec_scen_g; - source_rect = get_custom_rect(scenario.ter_types[terrain_to_draw].picture - 1000); + graf_pos_ref(source_gworld, source_rect) = spec_scen_g.find_graphic(scenario.ter_types[terrain_to_draw].picture - 1000); terrain_there[i][j] = -1; } else if (scenario.ter_types[terrain_to_draw].picture >= 400) { // animated - source_gworld = anim_gworld; + source_gworld = &anim_gworld; terrain_to_draw = scenario.ter_types[terrain_to_draw].picture; source_rect = calc_rect(4 * ((terrain_to_draw - 400) / 5) + (anim_ticks % 4),(terrain_to_draw - 400) % 5); terrain_there[i][j] = -1; @@ -140,7 +138,7 @@ void draw_one_terrain_spot (short i,short j,short terrain_to_draw) //// if (terrain_there[i][j] == scenario.ter_types[terrain_to_draw].picture) return; terrain_there[i][j] = scenario.ter_types[terrain_to_draw].picture; terrain_to_draw = scenario.ter_types[terrain_to_draw].picture; - source_gworld = terrain_gworld[terrain_to_draw / 50]; + source_gworld = &terrain_gworld[terrain_to_draw / 50]; terrain_there[i][j] = terrain_to_draw; terrain_to_draw %= 50; source_rect = calc_rect(terrain_to_draw % 10, terrain_to_draw / 10); @@ -153,7 +151,7 @@ void draw_one_terrain_spot (short i,short j,short terrain_to_draw) //// anim_onscreen = true; } - rect_draw_some_item(source_gworld, source_rect, terrain_screen_gworld, where_draw); + rect_draw_some_item(*source_gworld, source_rect, terrain_screen_gworld, where_draw); } void draw_monsters() //// @@ -192,11 +190,12 @@ void draw_monsters() //// get_monst_dims(univ.party.out_c[i].what_monst.monst[j],&width,&height); if (picture_wanted >= 1000) { for (k = 0; k < width * height; k++) { - source_rect = get_custom_rect(picture_wanted % 1000 + + sf::Texture* src_gw; + graf_pos_ref(src_gw, source_rect) = spec_scen_g.find_graphic(picture_wanted % 1000 + ((univ.party.out_c[i].direction < 4) ? 0 : (width * height)) + k); to_rect = monst_rects[(width - 1) * 2 + height - 1][k]; to_rect.offset(13 + 28 * where_draw.x,13 + 36 * where_draw.y); - rect_draw_some_item(spec_scen_g, source_rect, terrain_screen_gworld,to_rect, sf::BlendAlpha); + rect_draw_some_item(*src_gw, source_rect, terrain_screen_gworld,to_rect, sf::BlendAlpha); } } if (picture_wanted < 1000) { @@ -228,7 +227,8 @@ void draw_monsters() //// store_loc.y += k / width; // customize? if (univ.town.monst[i].picture_num >= 1000) { - source_rect = get_custom_rect((univ.town.monst[i].picture_num % 1000) + + sf::Texture* src_gw; + graf_pos_ref(src_gw, source_rect) = spec_scen_g.find_graphic((univ.town.monst[i].picture_num % 1000) + k + ((univ.town.monst[i].direction < 4) ? 0 : width * height) + ((combat_posing_monster == i + 100) ? (2 * width * height) : 0)); ter = univ.town->terrain(univ.town.monst[i].cur_loc.x,univ.town.monst[i].cur_loc.y); @@ -240,7 +240,7 @@ void draw_monsters() //// && ((univ.town.monst[i].active == 1) || (univ.town.monst[i].target == 6)) && (width == 1) && (height == 1)) //// draw_one_terrain_spot((short) where_draw.x,(short) where_draw.y,10000 + scenario.ter_types[ter].flag1.u); - else Draw_Some_Item(spec_scen_g, source_rect, terrain_screen_gworld, store_loc, 1, 0); + else Draw_Some_Item(*src_gw, source_rect, terrain_screen_gworld, store_loc, 1, 0); } if (univ.town.monst[i].picture_num < 1000) { pic_num_t this_monst = univ.town.monst[i].picture_num; @@ -274,7 +274,8 @@ void draw_monsters() //// store_loc.y += k / width; // customize? if (univ.town.monst[i].picture_num >= 1000) { - source_rect = get_custom_rect((univ.town.monst[i].picture_num % 1000) + + sf::Texture* src_gw; + graf_pos_ref(src_gw, source_rect) = spec_scen_g.find_graphic((univ.town.monst[i].picture_num % 1000) + k + ((univ.town.monst[i].direction < 4) ? 0 : width * height) + ((combat_posing_monster == i + 100) ? (2 * width * height) : 0)); ter = univ.town->terrain(univ.town.monst[i].cur_loc.x,univ.town.monst[i].cur_loc.y); @@ -285,7 +286,7 @@ void draw_monsters() //// && ((univ.town.monst[i].active == 1) || (univ.town.monst[i].target == 6)) && (width == 1) && (height == 1)) draw_one_terrain_spot((short) where_draw.x,(short) where_draw.y,10000 + scenario.ter_types[ter].flag1.u); //// - else Draw_Some_Item(spec_scen_g, source_rect, terrain_screen_gworld, store_loc, 1, 0); + else Draw_Some_Item(*src_gw, source_rect, terrain_screen_gworld, store_loc, 1, 0); } if (univ.town.monst[i].picture_num < 1000) { pic_num_t this_monst = univ.town.monst[i].picture_num; @@ -406,10 +407,11 @@ void draw_items(location where){ if(univ.town.items[i].contained) continue; if(party_can_see(where) >= 6) continue; if(univ.town.items[i].graphic_num >= 1000){ - from_rect = get_custom_rect(univ.town.items[i].graphic_num - 1000); + sf::Texture* src_gw; + graf_pos_ref(src_gw, from_rect) = spec_scen_g.find_graphic(univ.town.items[i].graphic_num - 1000); to_rect = coord_to_rect(where.x,where.y); terrain_there[where_draw.x][where_draw.y] = -1; - rect_draw_some_item(spec_scen_g,from_rect,terrain_screen_gworld,to_rect,sf::BlendAlpha); + rect_draw_some_item(*src_gw,from_rect,terrain_screen_gworld,to_rect,sf::BlendAlpha); }else{ from_rect = get_item_template_rect(univ.town.items[i].graphic_num); to_rect = coord_to_rect(where_draw.x,where_draw.y); diff --git a/osx/boe.newgraph.cpp b/osx/boe.newgraph.cpp index 5d9eae49..43fc9e6c 100644 --- a/osx/boe.newgraph.cpp +++ b/osx/boe.newgraph.cpp @@ -717,7 +717,7 @@ void click_shop_rect(RECT area_rect) } -std::pair calc_item_rect(int num,RECT& to_rect) { +graf_pos calc_item_rect(int num,RECT& to_rect) { RECT from_rect = {0,0,18,18}; sf::Texture *from_gw = &tiny_obj_gworld; if (num < 45) { @@ -843,14 +843,14 @@ void draw_shop_graphics(bool pressed,RECT clip_area_rect) case 0: case 1: case 2: case 3: case 4: base_item = get_stored_item(what_chosen); base_item.ident = true; - std::pair(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect); + graf_pos_ref(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect); rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha); strcpy(cur_name,base_item.full_name.c_str()); get_item_interesting_string(base_item,cur_info_str); break; case 5: base_item = store_alchemy(what_chosen - 500); - std::pair(from_gw, from_rect) = calc_item_rect(53,to_rect); + graf_pos_ref(from_gw, from_rect) = calc_item_rect(53,to_rect); rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha); strcpy(cur_name,base_item.full_name.c_str()); strcpy(cur_info_str,""); @@ -863,14 +863,14 @@ void draw_shop_graphics(bool pressed,RECT clip_area_rect) break; case 7: what_chosen -= 700; - std::pair(from_gw, from_rect) = calc_item_rect(99,to_rect); + graf_pos_ref(from_gw, from_rect) = calc_item_rect(99,to_rect); rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha); strcpy(cur_name,heal_types[what_chosen]); strcpy(cur_info_str,""); break; case 8: base_item = store_mage_spells(what_chosen - 800 - 30); - std::pair(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect); + graf_pos_ref(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect); rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha); strcpy(cur_name,base_item.full_name.c_str()); @@ -878,7 +878,7 @@ void draw_shop_graphics(bool pressed,RECT clip_area_rect) break; case 9: base_item = store_priest_spells(what_chosen - 900 - 30); - std::pair(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect); + graf_pos_ref(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect); rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha); strcpy(cur_name,base_item.full_name.c_str()); strcpy(cur_info_str,""); @@ -888,7 +888,7 @@ void draw_shop_graphics(bool pressed,RECT clip_area_rect) what_magic_shop_item = what_chosen % 1000; base_item = univ.party.magic_store_items[what_magic_shop][what_magic_shop_item]; base_item.ident = true; - std::pair(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect); + graf_pos_ref(from_gw, from_rect) = calc_item_rect(base_item.graphic_num,to_rect); rect_draw_some_item(*from_gw, from_rect, talk_gworld, to_rect, sf::BlendAlpha); strcpy(cur_name,base_item.full_name.c_str()); get_item_interesting_string(base_item,cur_info_str); diff --git a/osx/boe.party.cpp b/osx/boe.party.cpp index 4449787d..bf924178 100644 --- a/osx/boe.party.cpp +++ b/osx/boe.party.cpp @@ -389,6 +389,7 @@ void init_party_scen_data() // univ.party.special_notes_str[i][j] = 0; // for (i = 0; i < 120; i++) // univ.party.talk_save[i].personality = -1; + // TODO: The journal at least should persist across scenarios; the other two, maybe, maybe not univ.party.journal.clear(); univ.party.special_notes.clear(); univ.party.talk_save.clear(); diff --git a/osx/boe.text.cpp b/osx/boe.text.cpp index 0460b0f6..7958b6de 100644 --- a/osx/boe.text.cpp +++ b/osx/boe.text.cpp @@ -72,7 +72,8 @@ extern location dest_locs[40] ; //extern piles_of_stuff_dumping_type *data_store; extern cScenario scenario; -extern sf::Texture spec_scen_g,tiny_obj_gworld,invenbtn_gworld,status_gworld; +extern sf::Texture tiny_obj_gworld,invenbtn_gworld,status_gworld; +extern cCustomGraphics spec_scen_g; extern sf::Texture pc_gworld; extern sf::RenderTexture pc_stats_gworld, item_stats_gworld, text_area_gworld; extern short terrain_there[9][9]; @@ -484,8 +485,9 @@ void place_item_button(short which_button_to_put,short which_slot,short which_bu to_rect.offset(20,1); from_rect.inset(2,2); if (extra_val >= 150) { - from_rect = get_custom_rect(extra_val - 150); - rect_draw_some_item(spec_scen_g, from_rect, item_stats_gworld, to_rect,sf::BlendAlpha); + sf::Texture* src_gw; + graf_pos_ref(src_gw, from_rect) = spec_scen_g.find_graphic(extra_val - 150); + rect_draw_some_item(*src_gw, from_rect, item_stats_gworld, to_rect,sf::BlendAlpha); } else rect_draw_some_item(tiny_obj_gworld, from_rect, item_stats_gworld, to_rect, sf::BlendAlpha); return; @@ -1442,6 +1444,7 @@ RECT destrec = {0,0,36,28}; // SetPort(cur_port); //} +// TODO: This seems to duplicate logic found in graphtool to get a rect from a picture index RECT coord_to_rect(short i,short j) { RECT to_return; diff --git a/osx/boe.town.cpp b/osx/boe.town.cpp index 7e41c83c..894f2ab2 100644 --- a/osx/boe.town.cpp +++ b/osx/boe.town.cpp @@ -68,7 +68,8 @@ extern location golem_m_locs[16]; extern cScenario scenario; extern cUniverse univ; //extern piles_of_stuff_dumping_type *data_store; -extern sf::Texture spec_scen_g,bg_gworld; +extern sf::Texture bg_gworld; +extern cCustomGraphics spec_scen_g; bool need_map_full_refresh = true,forcing_map_button_redraw = false; extern sf::RenderTexture map_gworld,small_ter_gworld; // In the 0..65535 range, this colour was {65535,65535,52428} @@ -1352,8 +1353,6 @@ void clear_map() } -// TODO: Eliminate need for this OR put it in a better place -bool have_spec_scen_graphics = false; // TODO: Eliminate the flag, always do full redraw void draw_map (sf::RenderWindow& the_dialog, short the_item) //the_item; // Being sneaky - if this gets value of 5, this is not a full restore - @@ -1590,12 +1589,13 @@ void draw_map (sf::RenderWindow& the_dialog, short the_item) map_graphic_placed[where.x / 8][where.y] | (unsigned char)(s_pow(2,where.x % 8)); pic = scenario.ter_types[what_ter].picture; if (pic >= 1000) { - if (have_spec_scen_graphics) { + if (spec_scen_g) { //print_nums(0,99,pic); pic = pic % 1000; - custom_from = coord_to_rect(pic % 10, pic / 10); + sf::Texture* src_gw; + graf_pos_ref(src_gw, custom_from) = spec_scen_g.find_graphic(pic); custom_from.offset(-13,-13); - rect_draw_some_item(spec_scen_g,custom_from,map_gworld,draw_rect); + rect_draw_some_item(*src_gw,custom_from,map_gworld,draw_rect); } } else switch ((pic >= 400) ? anim_map_pats[pic - 400] : map_pats[pic]) { diff --git a/osx/classes/monster.cpp b/osx/classes/monster.cpp index e5b87b9c..b55351bb 100644 --- a/osx/classes/monster.cpp +++ b/osx/classes/monster.cpp @@ -27,6 +27,7 @@ cMonster& cMonster::operator = (legacy::monster_record_type& old){ armor = old.armor; skill = old.skill; for(i = 0; i < 3; i++) a[i] = old.a[i]; + // TODO: These two bits of data belong in a[] a1_type = old.a1_type; a23_type = old.a23_type; m_type = (eMonsterType) old.m_type; diff --git a/osx/classes/scenario.cpp b/osx/classes/scenario.cpp index c47e4449..491eb7b6 100644 --- a/osx/classes/scenario.cpp +++ b/osx/classes/scenario.cpp @@ -35,6 +35,7 @@ cScenario& cScenario::operator = (legacy::scenario_data_type& old){ difficulty = old.difficulty; intro_pic = old.intro_pic; default_ground = old.default_ground; + // TODO: One or both of these should probably be moved to cTown for(i = 0; i < 200; i++) town_size[i] = old.town_size[i]; for(i = 0; i < 200; i++) town_hidden[i] = old.town_hidden[i]; flag_a = old.flag_a; @@ -48,6 +49,7 @@ cScenario& cScenario::operator = (legacy::scenario_data_type& old){ out_start.y = old.out_start.y; which_town_start = old.which_town_start; flag_b = old.flag_b; + // TODO: Town data size doesn't even need to be stored at all; its only purpose is for locating the offset of a town within the old scenario format; same with out data size for(i = 0; i < 200; i++) for(j = 0; j < 5; j++) town_data_size[i][j] = old.town_data_size[i][j]; @@ -60,6 +62,7 @@ cScenario& cScenario::operator = (legacy::scenario_data_type& old){ out_data_size[i][0] = old.out_data_size[i][0]; out_data_size[i][1] = old.out_data_size[i][1]; } + // TODO: Combine store_item_rects and store_item_towns into a structure for(i = 0; i < 3; i++) { store_item_rects[i].top = old.store_item_rects[i].top; store_item_rects[i].left = old.store_item_rects[i].left; @@ -68,9 +71,11 @@ cScenario& cScenario::operator = (legacy::scenario_data_type& old){ } for(i = 0; i < 3; i++) store_item_towns[i] = old.store_item_towns[i]; flag_e = old.flag_e; + // TODO: Combine these two into a structure for(i = 0; i < 50; i++) special_items[i] = old.special_items[i]; for(i = 0; i < 50; i++) special_item_special[i] = old.special_item_special[i]; rating = old.rating; + // TODO: Is this used anywhere? uses_custom_graphics = old.uses_custom_graphics; flag_f = old.flag_f; for(i = 0; i < 256; i++) scen_monsters[i] = old.scen_monsters[i]; @@ -125,6 +130,6 @@ char(& cScenario::scen_strs(short i))[256]{ if(i % 2 == 0) return spec_item_names[(i - 60) / 2]; else return spec_item_strs[(i - 60) / 2]; } - if(i >= 160 && i < 260) return spec_strs[i - 100]; + if(i >= 160 && i < 260) return spec_strs[i - 160]; return journal_strs[6]; // random unused slot } diff --git a/osx/dialogxml/dlogutil.cpp b/osx/dialogxml/dlogutil.cpp index 846b6d04..e9402637 100644 --- a/osx/dialogxml/dlogutil.cpp +++ b/osx/dialogxml/dlogutil.cpp @@ -455,15 +455,16 @@ void giveError(std::string str1, std::string str2, cDialog* parent){ } void oopsError(short error, short code, short mode){ // mode is 0 for scened, 1 for game, 2 for pced - char error_str1[256], error_str2[256]; + std::ostringstream error_str1, error_str2; static const char* progname[3] = {"the scenario editor", "Blades of Exile", "the PC editor"}; static const char* filetname[3] = {"scenario", "game", "game"}; - sprintf(error_str1,"The program encountered an error while loading/saving/creating the %s. To prevent future problems, the program will now terminate. Trying again may solve the problem.", filetname[mode]); + error_str1 << "The program encountered an error while loading/saving/creating the " << filetname[mode] + << ". To prevent future problems, the program will now terminate. Trying again may solve the problem."; // TODO: Update this error message - giving more memory is no longer an option in OSX. - sprintf(error_str2,"Giving %s more memory might also help. Be sure to back your %s up often. Error number: %d.",progname[mode],filetname[mode],error); + error_str2 << "Giving " << progname[mode] << " more memory might also help. Be sure to back your " << filetname[mode] << " up often. Error number: " << error << "."; if(code != 0) - sprintf(error_str2,"%s Result code: %i.",error_str2,code); - giveError(error_str1,error_str2,0); + error_str2 << " Result code: " << code << "."; + giveError(error_str1.str(),error_str2.str(),NULL); exit(1); } diff --git a/osx/dialogxml/pict.cpp b/osx/dialogxml/pict.cpp index 43bba855..de518b61 100644 --- a/osx/dialogxml/pict.cpp +++ b/osx/dialogxml/pict.cpp @@ -16,6 +16,7 @@ #include "restypes.hpp" extern sf::Texture bg_gworld; +extern cCustomGraphics spec_scen_g; void cPict::init(){ drawPict()[PIC_TER] = &cPict::drawPresetTer; @@ -744,8 +745,8 @@ void cPict::drawCustomTer(short num, RECT to_rect){ to_rect.right = to_rect.left + 28; to_rect.bottom = to_rect.top + 32; RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect); } @@ -755,8 +756,8 @@ void cPict::drawCustomTerAnim(short num, RECT to_rect){ to_rect.bottom = to_rect.top + 32; num += animFrame; RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect); } @@ -769,8 +770,8 @@ void cPict::drawCustomMonstSm(short num, RECT to_rect){ fill_rect(*inWindow, to_rect, sf::Color::Black); RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect, sf::BlendAlpha); } @@ -783,13 +784,12 @@ void cPict::drawCustomMonstWide(short num, RECT to_rect){ fill_rect(*inWindow, to_rect, sf::Color::Black); RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); small_monst_rect.offset(to_rect.left,to_rect.top + 7); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); - n = get_custom_rect(num,from_rect); - from_gw = getSheet(SHEET_CUSTOM, n); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+1); small_monst_rect.offset(14,0); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); } @@ -803,13 +803,12 @@ void cPict::drawCustomMonstTall(short num, RECT to_rect){ fill_rect(*inWindow, to_rect, sf::Color::Black); RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); small_monst_rect.offset(to_rect.left + 7,to_rect.top); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); - n = get_custom_rect(num,from_rect); - from_gw = getSheet(SHEET_CUSTOM, n); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+1); small_monst_rect.offset(0,18); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); } @@ -823,39 +822,35 @@ void cPict::drawCustomMonstLg(short num, RECT to_rect){ fill_rect(*inWindow, to_rect, sf::Color::Black); RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); small_monst_rect.offset(to_rect.left,to_rect.top); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); - n = get_custom_rect(num,from_rect); - from_gw = getSheet(SHEET_CUSTOM, n); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+1); small_monst_rect.offset(14,0); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); - n = get_custom_rect(num,from_rect); - from_gw = getSheet(SHEET_CUSTOM, n); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+2); small_monst_rect.offset(-14,18); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); - n = get_custom_rect(num,from_rect); - from_gw = getSheet(SHEET_CUSTOM, n); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+3); small_monst_rect.offset(14,0); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); } void cPict::drawCustomDlog(short num, RECT to_rect){ RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); to_rect.right = to_rect.left + 18; to_rect.bottom = to_rect.top + 36; from_rect.right = from_rect.left + 18; from_rect.bottom = from_rect.top + 36; rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect); - n = get_custom_rect(num,from_rect); - from_gw = getSheet(SHEET_CUSTOM, n); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+1); to_rect.offset(18,0); from_rect.right = from_rect.left + 18; from_rect.bottom = from_rect.top + 36; @@ -874,16 +869,15 @@ void cPict::drawCustomDlogLg(short num, RECT to_rect){ void cPict::drawCustomTalk(short num, RECT to_rect){ RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); to_rect.right = to_rect.left + 16; to_rect.bottom = to_rect.top + 32; from_rect.right = from_rect.left + 16; from_rect.bottom = from_rect.top + 32; rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect); - n = get_custom_rect(num,from_rect); - from_gw = getSheet(SHEET_CUSTOM, n); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+1); to_rect.offset(16,0); from_rect.right = from_rect.left + 16; from_rect.bottom = from_rect.top + 32; @@ -895,8 +889,8 @@ void cPict::drawCustomItem(short num, RECT to_rect){ to_rect.right = to_rect.left + 28; to_rect.bottom = to_rect.top + 32; RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); fill_rect(*inWindow, to_rect, sf::Color::Black); rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect, sf::BlendAlpha); } @@ -904,8 +898,8 @@ void cPict::drawCustomItem(short num, RECT to_rect){ void cPict::drawCustomMissile(short num, RECT to_rect){ num += animFrame % 4; RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); from_rect.right = from_rect.left + 18; from_rect.bottom = from_rect.top + 18; if(animFrame >= 4) from_rect.offset(0, 18); @@ -916,8 +910,8 @@ void cPict::drawCustomMissile(short num, RECT to_rect){ void cPict::drawCustomTerMap(short num, RECT to_rect){ RECT from_rect; - short n = get_custom_rect(num,from_rect); - std::shared_ptr from_gw = getSheet(SHEET_CUSTOM, n); + sf::Texture* from_gw; + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num); from_rect.right = from_rect.left + 12; from_rect.bottom = from_rect.top + 12; num /= 1000; num--; @@ -931,8 +925,10 @@ void cPict::drawPartyMonstSm(short num, RECT to_rect){ printf("Drawing graphic %i as a custom space pic.\n",num); to_rect.right = to_rect.left + 28; to_rect.bottom = to_rect.top + 32; - std::shared_ptr from_gw = getSheet(SHEET_PARTY); - RECT from_rect = get_custom_rect(num); + sf::Texture* from_gw; + RECT from_rect; + + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num, true); fill_rect(*inWindow, to_rect, sf::Color::Black); rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect, sf::BlendAlpha); } @@ -942,13 +938,14 @@ void cPict::drawPartyMonstWide(short num, RECT to_rect){ to_rect.right = to_rect.left + 28; to_rect.bottom = to_rect.top + 36; fill_rect(*inWindow, to_rect, sf::Color::Black); - std::shared_ptr from_gw = getSheet(SHEET_PARTY); + sf::Texture* from_gw; + RECT from_rect; - RECT from_rect = get_custom_rect(num); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num, true); small_monst_rect.offset(to_rect.left,to_rect.top + 7); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); - from_rect = get_custom_rect(num+1); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+1, true); small_monst_rect.offset(14,0); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); } @@ -958,14 +955,15 @@ void cPict::drawPartyMonstTall(short num, RECT to_rect){ to_rect.right = to_rect.left + 28; to_rect.bottom = to_rect.top + 36; fill_rect(*inWindow, to_rect, sf::Color::Black); - std::shared_ptr from_gw = getSheet(SHEET_PARTY); + sf::Texture* from_gw; + RECT from_rect; - RECT from_rect = get_custom_rect(num); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num, true); small_monst_rect.offset(to_rect.left + 7,to_rect.top); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); small_monst_rect.offset(0,18); - from_rect = get_custom_rect(num+1); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+1, true); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); } @@ -974,22 +972,23 @@ void cPict::drawPartyMonstLg(short num, RECT to_rect){ to_rect.right = to_rect.left + 28; to_rect.bottom = to_rect.top + 36; fill_rect(*inWindow, to_rect, sf::Color::Black); - std::shared_ptr from_gw = getSheet(SHEET_PARTY); + sf::Texture* from_gw; + RECT from_rect; - RECT from_rect = get_custom_rect(num); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num, true); small_monst_rect.offset(to_rect.left,to_rect.top); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); small_monst_rect.offset(14,0); - from_rect = get_custom_rect(num+1); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+1, true); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); small_monst_rect.offset(-14,18); - from_rect = get_custom_rect(num+2); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+2, true); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); small_monst_rect.offset(14,0); - from_rect = get_custom_rect(num+3); + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num+3, true); rect_draw_some_item(*from_gw, from_rect, *inWindow, small_monst_rect, sf::BlendAlpha); } @@ -1006,8 +1005,10 @@ void cPict::drawPartyItem(short num, RECT to_rect){ printf("Drawing graphic %i as a custom space pic.\n",num); to_rect.right = to_rect.left + 28; to_rect.bottom = to_rect.top + 32; - std::shared_ptr from_gw = getSheet(SHEET_PARTY); - RECT from_rect = get_custom_rect(num); + sf::Texture* from_gw; + RECT from_rect; + + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num, true); fill_rect(*inWindow, to_rect, sf::Color::Black); rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect, sf::BlendAlpha); } @@ -1016,8 +1017,10 @@ void cPict::drawPartyPc(short num, RECT to_rect){ printf("Drawing graphic %i as a custom space pic.\n",num); to_rect.right = to_rect.left + 28; to_rect.bottom = to_rect.top + 32; - std::shared_ptr from_gw = getSheet(SHEET_PARTY); - RECT from_rect = get_custom_rect(num); + sf::Texture* from_gw; + RECT from_rect; + + graf_pos_ref(from_gw, from_rect) = spec_scen_g.find_graphic(num, true); fill_rect(*inWindow, to_rect, sf::Color::Black); rect_draw_some_item(*from_gw, from_rect, *inWindow, to_rect, sf::BlendAlpha); } diff --git a/osx/tools/fileio.cpp b/osx/tools/fileio.cpp index 7aa652e6..563a8f8a 100644 --- a/osx/tools/fileio.cpp +++ b/osx/tools/fileio.cpp @@ -28,9 +28,10 @@ extern bool cur_scen_is_mac, mac_is_intel; extern cScenario scenario; -extern sf::Texture spec_scen_g,items_gworld,tiny_obj_gworld,fields_gworld,roads_gworld,boom_gworld,missiles_gworld; +extern sf::Texture items_gworld,tiny_obj_gworld,fields_gworld,roads_gworld,boom_gworld,missiles_gworld; extern sf::Texture dlogpics_gworld,monst_gworld[],terrain_gworld[],anim_gworld,talkfaces_gworld,pc_gworld; extern sf::Texture status_gworld, vehicle_gworld, small_ter_gworld; +extern cCustomGraphics spec_scen_g; extern cUniverse univ; //extern unsigned char borders[4][50]; //extern cOutdoors current_terrain; @@ -154,6 +155,7 @@ bool load_scenario(fs::path file_to_load){ port_item_list(item_data); scenario = *temp_scenario; scenario.append(*item_data); + // TODO: Consider skipping the fread and assignment when len is 0 for (i = 0; i < 270; i++) { len = (long) (scenario.scen_str_len[i]); n = fread(&(scenario.scen_strs(i)), len, 1, file_id); @@ -701,48 +703,47 @@ bool load_outdoor_str(location which_out, short which_str, char* str){ return true; } +#ifdef __APPLE__ +bool tryLoadPictFromResourceFile(fs::path& gpath, sf::Image& graphics_store); +#endif + void load_spec_graphics() { + static const char*const noGraphics = "The game will still work without the custom graphics, but some things will not look right."; short i; fs::path path(scenario.scen_file); printf("Loading scenario graphics... (%s)\n",path.c_str()); - path.replace_extension("exr"); + // Tried path.replace_extension, but that only deleted the extension, so I have to do it manually + std::string filename = path.stem().string(); + path = path.parent_path(); + if(spec_scen_g) spec_scen_g.clear(); // TODO: Load new-style sheets - //if(err != noErr) { - // for (i = 0; i < 63; i++) - // file_name[i] = whatever[i]; - path.replace_extension("meg"); - // TODO: There's no way around it; I'll have to read resource files for this section. -#if 0 - err = FSPathMakeRef(path, &file, NULL); - err = FSOpenResourceFile(&file, 0, NULL, fsRdPerm /*fsRdWrPerm*/, &custRef); - //file_num = HOpen(file_to_load.vRefNum,file_to_load.parID,file_name,1); - //if (file_num < 0){ - if(err != noErr){ - //whatever = (char *) file_to_load.name; - printf("First attempt failed... (%s)\n",(char*)path); - for (i = 0; i < 250; i++) { - if (path[i] == '.') { - path[i + 1] = 'b'; - path[i + 2] = 'm'; - path[i + 3] = 'p'; - //path[i + 4] = 0; - break; - } - } - err = FSPathMakeRef(path, &file, NULL); - FSSpec spec; - FSGetCatalogInfo(&file, kFSCatInfoNone, NULL, NULL, &spec, NULL); - err = FSpOpenDF(&spec, fsRdPerm, &custRef); - //spec_scen_g = load_bmp_from_file(file_name); - spec_scen_g = importPictureFileToGWorld(&spec); - if(spec_scen_g == NULL)printf("Scenario graphics not found (%s).\n",file_name); - }else{ - spec_scen_g = load_pict(1); - CloseResFile(custRef); - } + static sf::Image graphics_store; + bool foundGraphics = false; +#ifdef __APPLE__ + fs::path gpath = path/(filename + ".meg"); + if(fs::exists(gpath)) + foundGraphics = tryLoadPictFromResourceFile(gpath, graphics_store); #endif + if(!foundGraphics) { + fs::path gpath = path/(filename + ".bmp"); + if(fs::exists(gpath)) { + if(graphics_store.loadFromFile(gpath.string())) + foundGraphics = true; + else giveError("An old-style .bmp graphics file was found, but there was an error reading from the file.",noGraphics); + } + } + if(foundGraphics) { + // If we're here, we found old-style graphics. + // This means they need an alpha channel + graphics_store.createMaskFromColor(sf::Color::White); + spec_scen_g.is_old = true; + spec_scen_g.sheets = new sf::Texture[1]; + spec_scen_g.sheets[0].loadFromImage(graphics_store); + } else { + // Check for new-style graphics + } }//else{} // Now load regular graphics diff --git a/osx/tools/graphtool.cpp b/osx/tools/graphtool.cpp index 0be387a4..f38511d3 100644 --- a/osx/tools/graphtool.cpp +++ b/osx/tools/graphtool.cpp @@ -573,20 +573,14 @@ RECT calc_rect(short i, short j){ return base_rect; } -RECT get_custom_rect (short which_rect){ - RECT store_rect = {0,0,36,28}; - - store_rect.offset(28 * (which_rect % 10),36 * (which_rect / 10)); - return store_rect; -} - -short get_custom_rect (short which_rect, RECT& store_rect){ // returns the number of the sheet to use +graf_pos cCustomGraphics::find_graphic(pic_num_t which_rect, bool party) { short sheet = which_rect / 100; - which_rect %= 100; - store_rect = {0,0,28,36}; + if(is_old) sheet = 0; + else which_rect %= 100; + RECT store_rect = {0,0,28,36}; store_rect.offset(28 * (which_rect % 10),36 * (which_rect / 10)); - return sheet; + return std::make_pair(party ? this->party : &sheets[sheet],store_rect); } // TODO: This doesn't belong in this file diff --git a/osx/tools/graphtool.h b/osx/tools/graphtool.h index dbb360f7..157344d1 100644 --- a/osx/tools/graphtool.h +++ b/osx/tools/graphtool.h @@ -72,6 +72,27 @@ public: }; typedef unsigned short pic_num_t; +using graf_pos = std::pair; +using graf_pos_ref = std::pair; + +struct cCustomGraphics { + sf::Texture* sheets = NULL; + sf::Texture* party = NULL; + bool is_old = false; + void clear() { + if(sheets != NULL) delete[] sheets; + } + ~cCustomGraphics() { + if(party != NULL) delete party; + } + explicit operator bool() { + return sheets; + } + graf_pos find_graphic(pic_num_t pic, bool party = false); +}; + + + void init_graph_tool(void (*redraw_callback)()); void clean_up_graphtool(); void set_cursor(cursor_type which_curs); @@ -84,8 +105,6 @@ short string_length(const char *str); //OSStatus flip_pict(OSType domain, OSType type, short id, void *ptr, UInt32 size, bool isNative, void *refcon); //void draw_terrain(); RECT calc_rect(short i, short j); -RECT get_custom_rect (short which_rect); -short get_custom_rect (short which_rect, RECT& store_rect); void setActiveRenderTarget(sf::RenderTarget& where); void tileImage(sf::RenderTarget& target, RECT area, sf::Texture& img, sf::BlendMode mode = sf::BlendNone); void tileImage(sf::RenderTarget& target, RECT area, sf::Texture& img, RECT srcRect, sf::BlendMode mode = sf::BlendNone); diff --git a/osx/tools/qdpict.cpp b/osx/tools/qdpict.cpp new file mode 100644 index 00000000..045300d1 --- /dev/null +++ b/osx/tools/qdpict.cpp @@ -0,0 +1,427 @@ +// +// qdpict.cpp +// BoE +// +// Created by Celtic Minstrel on 14-04-11. +// +// + +#ifndef __APPLE__ +#error qdpict.cpp uses Apple APIs at the moment; try omitting it from the build +#endif + +#include +#include +#include "porting.h" +#include "location.h" +#include "dlogutil.h" +// TODO: Don't use the resource manager +#include + +static int32_t extract_long(char* ptr) { + int32_t l = *(int32_t*) ptr; + flip_long(&l); + return l; +} + +static int16_t extract_word(char* ptr) { + int16_t s = *(int16_t*) ptr; + flip_short(&s); + return s; +} + +template +static typename std::make_unsigned::type to_unsigned(T val) { + return *reinterpret_cast::type*>(&val); +} + +template class ptr_guard { + T* the_ptr; + T*const guard; + void boundcheck() { + if(the_ptr > guard) oopsError(127, the_ptr - guard); + } +public: + ptr_guard(T* begin, T* end) : the_ptr(begin), guard(end) {} + ptr_guard& operator+=(ptrdiff_t amt) { + the_ptr += amt; + boundcheck(); + return *this; + } + ptr_guard operator++(int) { + ptr_guard tmp = *this; + the_ptr++; + boundcheck(); + return tmp; + } + void align(size_t alignment, size_t sz) { + size_t spaceLeft = guard - the_ptr; + void* ptr = the_ptr; + the_ptr = (char*)std::align(alignment, sz, ptr, spaceLeft); + boundcheck(); + } + T& operator[](size_t i) { + if(the_ptr + i > guard) oopsError(128, i - (guard - the_ptr)); + return the_ptr[i]; + } + template explicit operator T2*() {return (T2*)the_ptr;} + operator T*() {return the_ptr;} + T& operator*() {return *the_ptr;} + T* operator->() {return the_ptr;} +}; + +void loadColourTable(ptr_guard& picData, sf::Color(& clut)[256], int numColours) { + while(numColours >= 0) { + int i = extract_word(picData); + if(i > 256) oopsError(5); + picData += 2; + clut[i].r = to_unsigned(extract_word(picData)) / 256; + picData += 2; + clut[i].g = to_unsigned(extract_word(picData)) / 256; + picData += 2; + clut[i].b = to_unsigned(extract_word(picData)) / 256; + picData += 2; + clut[i].a = 0xff; + numColours--; + } +} + +void loadUnpackedPixels(ptr_guard& picData,ptr_guard& pixels,sf::Color(& clut)[256],legacy::Rect& bounds,int rowBytes) { + for(int i = 0; i < bounds.bottom - bounds.top; i++) { + for(int j = 0; j < bounds.right - bounds.left; j++) { + size_t pixel = i * rowBytes + j; + size_t iClr = to_unsigned(*picData++); + pixels[4 * pixel + 0] = clut[iClr].r; + pixels[4 * pixel + 1] = clut[iClr].g; + pixels[4 * pixel + 2] = clut[iClr].b; + pixels[4 * pixel + 3] = clut[iClr].a; + } + } +} + +void loadPackedPixels(ptr_guard& picData,ptr_guard& pixels,sf::Color(& clut)[256],legacy::Rect& bounds,int rowBytes) { + // Packed data + int countSize = rowBytes > 250 ? 2 : 1; + for(int i = 0; i < bounds.bottom - bounds.top; i++) { + int byteCount = countSize == 2 ? extract_word(picData) : *picData; + picData += countSize; + char* start = picData; + int j = 0; + while(picData - start + 1 < byteCount) { + int repCount = *picData++; + if(repCount == -128) continue; + int k = j; + if(repCount >= 0) { + repCount++; + while(j - k < repCount) { + size_t pixel = i * rowBytes + j; + size_t iClr = to_unsigned(*picData++); + pixels[4 * pixel + 0] = clut[iClr].r; + pixels[4 * pixel + 1] = clut[iClr].g; + pixels[4 * pixel + 2] = clut[iClr].b; + pixels[4 * pixel + 3] = clut[iClr].a; + j++; + } + } else { + repCount = 1 - repCount; + size_t val = to_unsigned(*picData++); + while(j - k < repCount) { + size_t pixel = i * rowBytes + j; + pixels[4 * pixel + 0] = clut[val].r; + pixels[4 * pixel + 1] = clut[val].g; + pixels[4 * pixel + 2] = clut[val].b; + pixels[4 * pixel + 3] = clut[val].a; + j++; + } + } + } + + } +} + +legacy::Rect loadPixMapData(ptr_guard& picData, ptr_guard& pixels, int pixMapType) { + int rowBytes = extract_word(picData) & 0x7fff; + picData += 2; // Skip rowBytes; assume we have a v2 (colour) bitmap + legacy::Rect bounds = *(legacy::Rect*)picData; + flip_rect(&bounds); + picData += sizeof(legacy::Rect); + picData += 2 + 2 + 4; // Skip version, packType, and packSize + picData += 4 + 4; // Skip hRes and vRes + picData += 2 + 2; // Skip pixelType and pixelSize + if(picData[-1] != 8) oopsError(3); + picData += 2 + 2; // Skip cmpCount and cmpSize + picData += 4 + 4 + 4; // Skip planeBytes, pbTable, pmReserved + picData += 4 + 2; // Skip ctSeed and ctFlags + int numColours = extract_word(picData); + if(numColours >= 256) oopsError(4); + picData += 2; + sf::Color clut[256]; + loadColourTable(picData, clut, numColours); + picData += 2 * sizeof(legacy::Rect); // Skip source and dest rect + picData += 2; // Skip mode + if(pixMapType == 0x91 || pixMapType == 0x99) { + // Same code as for Clip, above + // TODO: I'm skipping a byte here, but that might be part of the size + picData++; + // This size field includes the size field itself + picData += *picData - 1; + } + if(rowBytes < 8) + loadUnpackedPixels(picData, pixels, clut, bounds, rowBytes); + else loadPackedPixels(picData, pixels, clut, bounds, rowBytes); + return bounds; +} + +rectangle loadFromPictResource(Handle resHandle, unsigned char*& pixelStore) { + HLock(resHandle); + // TODO: Use picSize to ensure I don't go out of bounds + size_t picSize = GetHandleSize(resHandle); + ptr_guard picData(*resHandle, *resHandle + picSize); + picData += 2; // Skip picture size field + picData += sizeof(legacy::Rect); // Skip picture frame field (actual frame is stored later) + if(strncmp(picData, "\0\x11\x02\xff", 4) != 0) // QuickDraw version code (version 2) + oopsError(1); + picData += 4; // Skip version field + if(strncmp(picData, "\x0c\0", 2) != 0) // Header opcode + oopsError(2); + picData += 2 + 4; // Skip header opcode and picture size (which is -1) + rectangle picFrame; + // Next is the bounding rect with 4-byte components + // However, they are fixed-point, so the second 2 bytes are fractional + // We'll ignore that part. + picFrame.top = extract_word(picData); picData += 4; + picFrame.left = extract_word(picData); picData += 4; + picFrame.bottom = extract_word(picData); picData += 4; + picFrame.right = extract_word(picData); picData += 4; + // We're using this info solely to initialize the target data array. + // I'm not sure I have the components in the right order, but for this, it doesn't actually matter + size_t picDataSize = picFrame.height() * picFrame.width() * 4; // Four bytes per pixel + pixelStore = new unsigned char[picDataSize]; + ptr_guard pixels(pixelStore, pixelStore + picDataSize); + // Then 4 reserved bytes + picData += 4; + int pixMapType = 0; + legacy::Rect bounds; + // Now we need to skip any superfluous opcodes until we get to pixel data - opcode 90, 91, 98, or 99 + // We're assuming it's stored as pixel data, so any other opcodes will just be ignored + bool done = false; + while(!done) { + // All opcodes have a first byte of 0 (other than the header opcode) + picData++; + switch(*(unsigned char*)picData++) { + case 0x00: // Nop + case 0x1C: // HiliteMode + case 0x1E: // DefHilite + case 0x38: // FrameSameRect + case 0x39: // PaintSameRect + case 0x3A: // EraseSameRect + case 0x3B: // InvertSameRect + case 0x3C: // FillSameRect + case 0x48: // FrameSameRRect + case 0x49: // PaintSameRRect + case 0x4A: // EraseSameRRect + case 0x4B: // InvertSameRRect + case 0x4C: // FillSameRRect + case 0x58: // FrameSameOval + case 0x59: // PaintSameOval + case 0x5A: // EraseSameOval + case 0x5B: // InvertSameOval + case 0x5C: // FillSameOval + case 0x78: // FrameSameRect + case 0x79: // PaintSameRect + case 0x7A: // EraseSameRect + case 0x7B: // InvertSameRect + case 0x7C: // FillSameRect + case 0x88: // FrameRgn + case 0x89: // PaintRgn + case 0x8A: // EraseRgn + case 0x8B: // InvertRgn + case 0x8C: // FillRgn + case 0x3D: case 0x3E: case 0x3F: // Reserved + case 0x4D: case 0x4E: case 0x4F: // Reserved + case 0x5D: case 0x5E: case 0x5F: // Reserved + case 0x7D: case 0x7E: case 0x7F: // Reserved + case 0x8D: case 0x8E: case 0x8F: // Reserved + break; + case 0x04: // TxFace + case 0x11: // Version + picData++; + break; + case 0x03: // TxFont + case 0x05: // TxMode + case 0x08: // PnMode + case 0x0D: // TxSize + case 0x15: // PbLocHFrac + case 0x16: // ChExtra + case 0x23: // ShortLineFrom + case 0xA0: // ShortComment + picData += 2; + break; + case 0x06: // SpExtra + case 0x07: // PnSize + case 0x0B: // OvSize + case 0x0C: // Origin + case 0x0E: // FgColor + case 0x0F: // BkColor + case 0x21: // LineFrom + case 0x68: // FrameSameArc + case 0x69: // PaintSameArc + case 0x6A: // EraseSameArc + case 0x6B: // InvertSameArc + case 0x6C: // FillSameArc + case 0x6D: case 0x6E: case 0x6F: // Reserved + picData += 4; + break; + case 0x22: // ShortLine + picData += 6; + break; + case 0x02: // BkPat + case 0x09: // PnPat + case 0x0A: // FillPat + case 0x10: // TxRatio + case 0x20: // Line + case 0x30: // FrameRect + case 0x31: // PaintRect + case 0x32: // EraseRect + case 0x33: // InvertRect + case 0x34: // FillRect + case 0x40: // FrameRRect + case 0x41: // PaintRRect + case 0x42: // EraseRRect + case 0x43: // InvertRRect + case 0x44: // FillRRect + case 0x50: // FrameOval + case 0x51: // PaintOval + case 0x52: // EraseOval + case 0x53: // InvertOval + case 0x54: // FillOval + case 0x35: case 0x36: case 0x37: // Reserved + case 0x45: case 0x46: case 0x47: // Reserved + case 0x55: case 0x56: case 0x57: // Reserved + picData += 8; + break; + case 0x60: // FrameArc + case 0x61: // PaintArc + case 0x62: // EraseArc + case 0x63: // InvertArc + case 0x64: // FillArc + case 0x65: case 0x66: case 0x67: // Reserved + picData += 12; + break; + case 0x01: // Clip + case 0x80: // FrameRgn + case 0x81: // PaintRgn + case 0x82: // EraseRgn + case 0x83: // InvertRgn + case 0x84: // FillRgn + case 0x85: case 0x86: case 0x87: + // TODO: I'm skipping a byte here, but that might be part of the size + picData++; + // This size field includes the size field itself + picData += *picData - 1; + break; + case 0x28: // LongText + picData += 4; + picData += *picData + 1; + break; + case 0x29: // DHText + case 0x2A: // DVText + picData++; + picData += *picData + 1; + break; + case 0x2B: // DHDVText + case 0xA1: // LongComment + picData += 2; + picData += *picData + 1; + break; + // MARK: Main part of load function - the pixel data + case 0x90: // BitsRect + bounds = loadPixMapData(picData, pixels, 0x90); + break; + case 0x91: // BitsRgn + bounds = loadPixMapData(picData, pixels, 0x91); + break; + case 0x98: // PackBitsRect + bounds = loadPixMapData(picData, pixels, 0x98); + break; + case 0x99: // PackBitsRgn + bounds = loadPixMapData(picData, pixels, 0x99); + break; + case 0xFF: + done = true; + break; + case 0x12: // BkPixPat + case 0x13: // PnPixPat + case 0x14: // FillPixPat + // argument is a pixpat + case 0x1A: // RGBFgCol + case 0x1B: // RGBBkCol + case 0x1D: // HiliteColor + case 0x1F: // OpColor + // argument is an RGB colour + case 0x70: // FramePoly + case 0x71: // PaintPoly + case 0x72: // ErasePoly + case 0x73: // InvertPoly + case 0x74: // FillPoly + case 0x75: case 0x76: case 0x77: // Reserved + // argument is a polygon + default: + // These are mostly reserved opcodes whose first field is a two-byte length + // I don't want to deal with them, and it's highly unlikely they'll come up. + // Thus, just give an error if they do. + oopsError(9); + break; + } + // There may be a byte of padding to align it to word boundaries. + picData.align(sizeof(int16_t), sizeof(int16_t)); + } + HUnlock(resHandle); + return rectangle(bounds.top, bounds.left, bounds.bottom, bounds.right); +} + +bool tryLoadPictFromResourceFile(fs::path& gpath, sf::Image& graphics_store) { + static const char*const noGraphics = "The game will still work without the custom graphics, but some things will not look right."; + // TODO: There's no way around it; I'll have to read resource files for this section. + FSRef file; + ResFileRefNum custRef; + OSErr err = FSPathMakeRef((const UInt8*)gpath.c_str(), &file, NULL); + err = FSOpenResourceFile(&file, 0, NULL, fsRdPerm, &custRef); + if(err != noErr) { // TODO: Is the error that would be returned if the resources were stored in the resource fork? + HFSUniStr255 rsrc; + err = FSGetResourceForkName(&rsrc); + err = FSOpenResourceFile(&file, rsrc.length, rsrc.unicode, fsRdPerm, &custRef); + if(err != noErr) { + giveError("An old-style .meg graphics file was found, but neither data nor resource fork could not be read.",noGraphics); + return false; + } + } + int nPicts = Count1Resources('PICT'); + if(nPicts < 1) { + CloseResFile(custRef); + giveError("An old-style .meg graphics file was found, but it did not contain any PICT resources.",noGraphics); + return false; + } + Handle resHandle = Get1Resource('PICT', 1); + if(ResError() == resNotFound) { + CloseResFile(custRef); + giveError("An old-style .meg graphics file was found, but it did not contain a PICT resource of ID 1.",noGraphics); + return false; + } + if(resHandle == NULL) { + CloseResFile(custRef); + giveError("An old-style .meg graphics file was found, but an error occurred while loading it.",noGraphics); + return false; + } + unsigned char* data = NULL; + rectangle picFrame = loadFromPictResource(resHandle, data); + CloseResFile(custRef); + if(picFrame.width() <= 0 || picFrame.height() <= 0) { + if(data != NULL) delete[] data; + giveError("An old-style .meg graphics file was found, but an error occurred while reading it.",noGraphics); + return false; + } + graphics_store.create(picFrame.width(), picFrame.height(), data); + if(data != NULL) delete[] data; + return true; +}