1111 This is a set of application hot patches for Dark Castle
1212 and Beyond Dark Castle. The two games share a great deal
1313 of code (with similar sets of compatibility issues with
14- Advanced Mac Substitute), but in different locations.
14+ Advanced Mac Substitute), though in different locations.
15+
16+ Beyond Dark Castle also introduces new logic that's not
17+ present in Dark Castle, to support its new features like
18+ saved games. This is the subject of our first patch.
19+
20+ Beyond Dark Castle shipped on two 800K disks. The second
21+ disk is required for all gameplay. In order to support
22+ single-drive systems, Beyond Dark Castle was designed to
23+ require only the second disk until gameplay ended. The
24+ BDC Data B file contains 'CODE' and other resources for
25+ this purpose, and the saved game resources (type 'MagT')
26+ are added to BDC Data B, not BDC Prefs (on disk one).
27+
28+ Advanced Mac Substitute maintains a distinction between
29+ application files and user files. The Castle Prefs INITs
30+ already address the problem of Castle Prefs (and BDC Prefs)
31+ being load-bearing game files (that must exist and aren't
32+ created by the game) by copying them to the Preferences
33+ folder if they don't already exist there. Clearly, saved
34+ games should also be stored in the user's BDC Prefs file.
35+
36+ Normally we'd patch the relevant 'CODE' resource in our
37+ startup patch (of _TEInit), but here, we can't do that --
38+ the code to be patched lives in BDC Data B, which isn't
39+ opened until gameplay starts. Instead, we'll patch one
40+ of the Toolbox routines, _CurResFile. The game-saving
41+ logic uses the usual Cur/Use/Add/Use pattern to add the
42+ resource to a specific resource file. Presumably, this
43+ was originally intended to be the prefs file but had to
44+ be changed to the Data B file to avoid requiring disk
45+ switches. In our _CurResFile patch, we try to load the
46+ 'CODE' id=12 resource. If we're post-game saving a high
47+ score, BDC Data B will be closed and the load will fail.
48+ But if we're in-game saving the game state, the load is
49+ guaranteed to succeed (because the very same resource is
50+ the one currently executing). All we need to do here is
51+ to substitute the BDC Prefs refnum for the Data B refnum.
52+
53+ Since we're patching _CurResFile in the application (and
54+ not at system startup time), we have to remove the patch
55+ as well, so we patch _ExitToShell and remove both there.
1556
1657 The subsequent comments refer to "Dark Castle", but apply
1758 equally to both Dark Castle and Beyond Dark Castle.
5697#include " mac_sys/trap_address.hh"
5798
5899
100+ enum
101+ {
102+ _CurResFile = 0xA994 ,
103+ _ExitToShell = 0xA9F4 ,
104+ _TEInit = 0xA9CC ,
105+ };
106+
107+ static UniversalProcPtr old_CurResFile;
108+ static UniversalProcPtr old_ExitToShell;
59109static UniversalProcPtr old_TEInit;
60110
61111
112+ static
113+ void CurResFile_handler ()
114+ {
115+ using mac::glue::GetHandleSize_raw;
116+
117+ enum
118+ {
119+ // These are offsets relative to the start of the 'CODE' resource.
120+
121+ offset_to_CurResFile = 0x02d0 ,
122+ offset_to_MOVE_pop = 0x02d2 , // MOVE.W (A7)+,D6
123+ offset_to_MOVE_push = 0x02d4 , // MOVE.W (-746,A5),-(A7)
124+ offset_to_A5_index = offset_to_MOVE_push + 2 ,
125+ offset_to_UseResFile = offset_to_A5_index + 2 ,
126+ minimum_handle_size = offset_to_UseResFile + 2 ,
127+ };
128+
129+ enum
130+ {
131+ A5_index_of_DataB_refnum = (UInt16) -746 ,
132+ A5_index_of_Prefs_refnum = (UInt16) -744 ,
133+ };
134+
135+ if ( Handle h = GetResource ( ' CODE' , SAVEGAME_CODE_RESID ) )
136+ {
137+ Size size = GetHandleSize_raw ( h );
138+
139+ if ( size >= minimum_handle_size )
140+ {
141+ UInt16* p = (UInt16*) (*h + offset_to_CurResFile);
142+
143+ if ( *p++ == _CurResFile &&
144+ *p++ == 0x3C1F &&
145+ *p++ == 0x3F2D &&
146+ *p == A5_index_of_DataB_refnum )
147+ {
148+ *p = A5_index_of_Prefs_refnum;
149+ }
150+ }
151+ }
152+ }
153+
154+ static
155+ asm
156+ pascal short CurResFile_patch ()
157+ {
158+ LINK A6 ,#0
159+ MOVEM .L D1 -D2 /A1 ,-(SP )
160+
161+ JSR CurResFile_handler
162+
163+ MOVEM .L (SP )+,D1 -D2 /A1
164+ UNLK A6
165+
166+ MOVEA .L old_CurResFile,A0
167+ JMP (A0 )
168+ }
169+
170+ static
171+ void ExitToShell_patch ()
172+ {
173+ using mac::sys::set_trap_address;
174+
175+ set_trap_address ( old_CurResFile, _CurResFile );
176+ set_trap_address ( old_ExitToShell, _ExitToShell );
177+
178+ asm
179+ {
180+ DC .W _ExitToShell | 0x400 // autoPop
181+ }
182+ }
183+
62184static inline
63185void install_envcheck_patch ( Handle h, Size handle_size )
64186{
@@ -129,10 +251,23 @@ void TEInit_handler()
129251{
130252 using mac::glue::GetHandleSize_raw;
131253
254+ using mac::sys::get_trap_address;
255+ using mac::sys::set_trap_address;
256+
132257 if ( Handle h = GetResource ( IDENTIFYING_RESTYPE , 0 ) )
133258 {
134259 ReleaseResource ( h );
135260
261+ #ifdef SAVEGAME_CODE_RESID
262+
263+ old_CurResFile = get_trap_address ( _CurResFile );
264+ old_ExitToShell = get_trap_address ( _ExitToShell );
265+
266+ set_trap_address ( (ProcPtr) CurResFile_patch, _CurResFile );
267+ set_trap_address ( (ProcPtr) ExitToShell_patch, _ExitToShell );
268+
269+ #endif
270+
136271 if ( (h = GetResource ( ' CODE' , ENVCHECK_CODE_RESID )) )
137272 {
138273 install_envcheck_patch ( h, GetHandleSize_raw ( h ) );
@@ -158,11 +293,6 @@ pascal asm void TEInit_patch()
158293
159294int main ()
160295{
161- enum
162- {
163- _TEInit = 0xA9CC ,
164- };
165-
166296 Handle self = GetResource ( ' INIT' , 0 );
167297
168298 DetachResource ( self );
0 commit comments