Thank you for making this release possible, everyone.
This has been something of a holy grail for me, and it was super neat to try it out. It really made me wonder what it would have been like if they had a few more months, but who knows, maybe if we're lucky some later builds may surface. It'd be fun to see how the Tim Curry looking character handled!
That aside, I enjoy reverse engineering stuff, so I wrote a script to dump the assets. It's super fascinating to see what they put together. For those curious here's some initial observations:
A lot of the game appears scriptable in plain text, including AI. Entities are also composed in a component style model in plain text, and adding new ones seems easy enough. Levels are entirely described in plain text, including entity placement and lighting data. Level geometry is in binary, however, and is referenced in these level scripts. In fact, everything seems to be oriented around the concept of a 'level', very much like how a scene works in Unity and such. Overall, it's a super modern impression that I got from this well over 20 year old prototype! Some examples
Item definitions:
Code:
ITEM_DEF
UNK_ECandle_tallstand_candle
tallstand_candle
NULL
NULL
1
0 0 0 0
NULL
ITEM_DEF
ECandle_s2_01_Lght_item_glow01
tallstand_candle_glow
NULL
tallstand_candle_glow
1
1 0 0 0
s2_01_Lght_item_01
Animation sets:
Code:
ANIMSET_DEF
E06_GhostCardinalAnimSet
5
E06_GhstCardinal_Death
E06_GhstCardinal_Get_Hit
E06_GhstCardinal_Move
E06_GhstCardinal_Shield
E06_GhstCardinal_Strike
ANIMSET_DEF
E02_GhostAnimSet
2
E02_Ghost_Die_Blue
E02_Ghost_Float_Blue
Entity placements:
Code:
ENTITY_DEF
RigidModel
s2_01
0
2
0
-2174.27
-2167.98
3.0305
0
0
0
ENTITY_DEF
Actor
Sonia
0
3
0
-3094
-1445.29
68
0
0
90
ENTITY_DEF
Emitter
Ghost_Cardinal_Dist500_Max1
0
4
1
-1692.35
-2385.17
21.646
0
0
-135
Note that the entity placements reference level geometry with the RigidModel tag.
AI script:
Code:
AI_DEF
Attack_FarRangeCorkscrew
TurnTowardTarget 0.0
FlyForwardUpLeft 50.0
FlyLeft 50.0
FlyForwardDownLeft 50.0
FlyDown 50.0
FlyForwardDownRight 50.0
FlyRight 50.0
FlyForwardUpRight 50.0
FlyUp 50.0
TurnTowardTarget 0.0
FlyTowardTarget 0.0
FlyForward 75.0
FlyUp 50.0
AI_ENDDEF
AI_DEF
Attack_FarRangeSawtooth
TurnTowardTarget 0.0
FlyForward 75.0
FlyUp 75.0
FlyForward 75.0
FlyDown 75.0
FlyForward 75.0
FlyUp 75.0
FlyForward 75.0
FlyDown 75.0
FlyForward 75.0
AI_ENDDEF
AI_DEF
Spawn_MedusaHeadRise
FlyUp 75.0
TurnTowardTarget 0.0
Death2 0.0
TurnTowardTarget 0.0
TurnRight 22.5
TurnLeft 45.0
TurnRight 45.0
TurnLeft 45.0
TurnRight 45.0
TurnLeft 45.0
TurnRight 45.0
TurnLeft 45.0
TurnRight 45.0
TurnLeft 22.5
Taunt 0.0
FlyDown 25.0
AI_ENDDEF
AI_DEF
Dying_DefaultRotInHell
Death1 0.0
Wait 5.0
AI_ENDDEF
The AI script reminded me the original Quake, where AI routines were built up on small, generic atomic actions, but in form it reminded me more of Half Life, which regimented the Quake style into a more data-oriented style.
See here for a comparison! It's not really surprising though, the game programmer world is pretty small. As an aside, if you've ever read DeLoura's book you've probably noticed the castlevania team really took it to heart!
Another fun curiosity is this script file for a font tool they were using, which was left on disk:
Code:
/* Font database. */
/* setdir: set the path for font textures for subsequent fonts */
DIRSYS #basepath, (#subpath1, #subpath2, ... ) - set path from dirpaths.txt */
/* DIRPATH #fullPath - set path directly; path must be a string (i.e. enclosed in double quotes, with '\' at end) */
/* type: 0 - fixed width, 1 - proportional */
fontname Heading_White
type 1
asciirange 32 126
texturesize 256
numtextures 1
celldimension 21 17
texturefiles heading_white.pvr
sp 8
. 5
0 12
1 10
2 12
3 12
4 13
5 13
6 12
7 12
8 12
9 12
A 16
B 15
C 15
D 15
E 13
F 12
G 16
H 14
I 5
J 12
K 15
L 13
M 17
N 14
O 16
P 13
Q 17
R 15
S 14
T 13
U 14
V 16
W 21
X 15
Y 14
Z 14
a 14
b 13
c 13
d 13
e 12
f 11
g 14
h 12
i 6
j 10
k 13
l 11
m 14
n 12
o 14
p 12
q 15
r 13
s 12
t 12
u 12
v 14
w 19
x 13
y 13
z 12
end
The actual file is quite a bit larger, but all follows this same format
It's likely that all these files would have been converted into some binary form for production, but imagine how cool it would have been if the game had shipped with this system intact? we could have a very modifiable castlevania!
Moving on, there are no major surprises on disk from what I can tell. The other character is not present in any form, and some of the creatures seen in other screenshots are not here either. No extra levels seem to be left on disk either. It's unfortunate, but then again, we're very fortunate to have just this release as is! There are some neat trivia about the assets though:
All textures are 16 bit, encoded in either ARGB1555, ARGB4444 or RGB565 format. Larger textures use the VQ encoding, while smaller ones are just morton coded. None use the bump map format, though there are two textures, 'b_brick_01_bump' and 'b_brick_01_bump' which appear to be meant to be, and may possibly be used, as bump maps. Sonia is a single 512x512 texture, as well as Medusa and the Evil Cleric characters. Lesser ones are 256x256. Environmental textures run the gamut. Animated effects like the candle flames have each frame of animation stored in separate images, which are then referenced in a binary file that appears to describe the animation. The script dumps these into png format, in case anyone is wondering, and I've attached a few for those interested in art appreciation.
Characters all use skeletal animation. The skeletal hierarchies are described in separate binary files from the meshes. I'm unsure of the exact number of vertex weights at the moment, but it's likely to be a limit of one per vertex. If I have time I'll get the script to dump the assets in gltf so people can play around with them in Unity or whatever. The script itself should be available soon for anyone else interested in diving into the guts of this.
That's about it for now. Thanks again to everyone involved in getting this released. It's been a lot of fun!