"""File format classes for the games Jill of the Jungle (DOS, 1992) and
Xargon (DOS, 1994)."""
from __future__ import annotations
from mrcrowbar import models as mrc
from mrcrowbar.lib.audio import base as aud
# source: Xargon source code release - https://www.classicdosgames.com/game/Xargon.html
PC_SPEAKER_NOTE_TABLE = [
64,
67,
71,
76,
80,
85,
90,
95,
101,
107,
114,
121,
0,
0,
0,
0,
128,
135,
143,
152,
161,
170,
181,
191,
203,
215,
228,
242,
0,
0,
0,
0,
256,
271,
287,
304,
322,
341,
362,
383,
406,
430,
456,
483,
0,
0,
0,
0,
512,
542,
574,
608,
645,
683,
724,
767,
812,
861,
912,
967,
0,
0,
0,
0,
1024,
1084,
1149,
1217,
1290,
1366,
1448,
1534,
1625,
1722,
1825,
1933,
0,
0,
0,
0,
2048,
2169,
2298,
2435,
2580,
2733,
2896,
3068,
3250,
3444,
3649,
3866,
0,
0,
0,
0,
4096,
4339,
4597,
4870,
5160,
5467,
5792,
6137,
6501,
6888,
7298,
7732,
0,
0,
0,
0,
8192,
8679,
9195,
9741,
10321,
10935,
11585,
12274,
13003,
13777,
14596,
15646,
0,
0,
0,
0,
16384,
17358,
18390,
19483,
20642,
21870,
23170,
24548,
26007,
27554,
29192,
30928,
0,
0,
0,
0,
]
[docs]class Sound( mrc.Block ):
SAMPLE_RATE = 6000
raw_data = mrc.Bytes( 0x00 )
def __init__( self, *args, **kwargs ):
super().__init__( *args, **kwargs )
self.wave = aud.Wave(
self,
mrc.Ref( "raw_data" ),
channels=1,
sample_rate=self.SAMPLE_RATE,
format_type=int,
field_size=1,
signedness="unsigned",
endian=None,
)
[docs]class Text( mrc.Block ):
data = mrc.Bytes( 0x00 )
[docs]class VCLFile( mrc.Block ):
sound_offsets = mrc.UInt32_LE( 0x00, count=50 )
sound_sizes = mrc.UInt16_LE( 0xc8, count=50 )
sound_freqs = mrc.UInt16_LE( 0x12c, count=50 )
text_offsets = mrc.UInt32_LE( 0x190, count=40 )
text_lengths = mrc.UInt16_LE( 0x230, count=40 )
raw_data = mrc.Bytes( 0x280 )
def __init__( self, *args, **kwargs ):
super().__init__( *args, **kwargs )
self.sounds = mrc.LinearStore(
self,
mrc.Ref( "raw_data" ),
Sound,
offsets=mrc.Ref( "sound_offsets" ),
sizes=mrc.Ref( "sound_sizes" ),
base_offset=-0x280,
)
# source: http://www.shikadi.net/moddingwiki/SHA_Format
[docs]class Tileset( mrc.Block ):
num_shapes = mrc.UInt8( 0x00 )
num_rots = mrc.UInt16_LE( 0x01 )
len_cga = mrc.UInt16_LE( 0x03 )
len_ega = mrc.UInt16_LE( 0x05 )
len_vga = mrc.UInt16_LE( 0x07 )
colour_depth = mrc.UInt8( 0x09 )
flags = mrc.UInt16_LE( 0x0a )
[docs]class SHAFile( mrc.Block ):
tileset_offsets = mrc.UInt32_LE( 0x0000, count=128 )
tileset_sizes = mrc.UInt16_LE( 0x0200, count=128 )
tileset_data = mrc.Bytes( 0x0300 )
tilesets = mrc.StoreRef(
Tileset,
mrc.Ref( "store" ),
mrc.Ref( "tileset_offsets" ),
mrc.Ref( "tileset_sizes" ),
count=128,
)
def __init__( self, *args, **kwargs ):
self.store = mrc.Store( self, mrc.Ref( "tileset_data" ) )
super().__init__( *args, **kwargs )
[docs]class JillLoader( mrc.Loader ):
"""Loader for the game Jill of the Jungle (DOS, 1992)."""
_SEP = mrc.Loader._SEP
_JILL_FILE_CLASS_MAP = {
_SEP + r"JN([1-3])(SAVE)\.([0-9])$": None,
_SEP + r"(JILL)([1-3])\.(VCL)$": VCLFile,
_SEP + r"(JILL)([1-3])\.(SHA)$": SHAFile,
_SEP + r"(JILL)\.(DMA)$": None,
_SEP + r"(.*)\.(DDT)$": None,
_SEP + r"(.*)\.JN([1-3])$": None,
}
def __init__( self ):
super().__init__( self._JILL_FILE_CLASS_MAP )
[docs]class XargonLoader( mrc.Loader ):
"""Loader for the game Xargon (DOS, 1994)."""
_SEP = mrc.Loader._SEP
_XARGON_FILE_CLASS_MAP = {
_SEP + "(AUDIO).XR([1-3])$": VCLFile,
_SEP + "(BOARD)_([0-9A-Z]+).XR([1-3])$": None,
_SEP + "(DEMO)([1-3]).XR([1-3])$": None,
_SEP + "(GRAPHICS).XR([1-3])$": SHAFile,
_SEP + "(INTRO).XR([1-3])$": None,
_SEP + "(MAP).XR([1-3])$": None,
_SEP + "(SONG)_([0-9]+).XR([1-3])$": None,
_SEP + "(STORY).XR([1-3])$": None,
_SEP + "(TILES).XR([1-3])$": None,
}
def __init__( self ):
super().__init__( self._XARGON_FILE_CLASS_MAP )