Skip to content

Commit 40284c0

Browse files
committed
BeyondDarkCastleTuneup: Add magtapes to BDC Prefs
Patch the new-saved-game code to route newly added 'MagT' resources into BDC Prefs, which is user-modifiable, instead of BDC Data B, which isn't.
1 parent f1c978b commit 40284c0

2 files changed

Lines changed: 138 additions & 6 deletions

File tree

mac/hacks/BeyondDarkCastleTuneup/BeyondDarkCastleTuneup.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
#define IDENTIFYING_RESTYPE 'GDSK'
1818

19+
#define SAVEGAME_CODE_RESID 12
20+
1921
#define ENVCHECK_CODE_RESID 4
2022
#define SPINLOOP_CODE_RESID 3
2123

mac/hacks/CastleTuneup-template/CastleTuneup.cc.hh

Lines changed: 136 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,48 @@
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.
@@ -56,9 +97,90 @@
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;
59109
static 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+
62184
static inline
63185
void 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

159294
int main()
160295
{
161-
enum
162-
{
163-
_TEInit = 0xA9CC,
164-
};
165-
166296
Handle self = GetResource( 'INIT', 0 );
167297

168298
DetachResource( self );

0 commit comments

Comments
 (0)