Code Monkey home page Code Monkey logo

mediastation's Introduction

Disney's Animated Storybook: The Lion King Media Station

A Python-based asset extractor and very incomplete bytecode decompiler for Media Station, Inc. CD-ROM children's titles. I loved many of these when I was growing up - especially Dalmatians. The ultimate goal of this repo is to create an engine for ScummVM, but I've found investigation and reverse-engineering easier to do out-of-tree in Python. Please join me in preserving these top-quality children's titles for future generations!

The most important knowledge needed right now is documentation for the bytecode engine (scripts). If you have knowledge or code you can contribute, please let us know!

Installation

Get it on PyPI: pip3 install MediaStation

Usage

Installing the PyPI package also installs a MediaStation script that can be invoked from the command line as follows:

#             Input directory   Export directory
#            ................. ...................
MediaStation ~/DALMATIANS/DATA ~/DalmatiansExtract

Known Titles

See and contribute to the updated list on this projects's wiki.

Support My Reverse Engineering!

Buy Me A Coffee

If you like my reverse engineering, you can buy me a matcha latte to show your appreciation ๐Ÿต!

Technical Details

Please contribute if you have more details here!

File Formats

All the data files for known titles are stored in the data/ subdirectory on the CD-ROM. These seem to be the same across the Windows and Mac versions. Some titles have additional files than these (like Tonka Garage, which has some Direct3D models for the car design activity), but these are the known files and formats unique to the Media Station engine.

Media Station titles have these types of files:

  • Context files (*.CXT)
  • Title definition file (BOOT.STM)
  • Profile (PROFILE._ST) - ONLY non-OG titles.

Each context file generally contains all the assets (and, depending on the version, the scripts) necessary to render one screen of the game. Since the format seems to have been originally designed for Disney's Interactive Storybook, this makes sense.

Context Files

  • A context file contains one or more subfiles, which are each complete and (almost) standard RIFFs.
  • Each subfile inside a context file contains one or more (almost) standard RIFF _chunk_s.
    • igod: Indicates a chunk that contains metadata about asset(s) in metadata sections.
    • a000, where 000 is a string that represents a 3-digit hexadecimal number: Indicates a chunk that contains actual asset data (mainly sounds and bitmaps) with lower-level metadata in metadata sections.
  • Each chunk can contain the following:
    • One or more metadata sections.
    • Raw asset data (PCM audio or RLE-compressed bitmaps).
  • Each metadata section contains one or more _datum_s.
  • Each datum contains a "primitive" data type (integer, string, etc.)

Title Definition (System) File

Also known as the "system" file. Contains metadata sections with global title information like the following:

  • Title compiler version.
  • Declarations of each context file.
  • File offsets of all subfiles in all context files.
  • Declarations of cursors stored as resources in the executable.

Profile

When present, contains a human-readable enumeration of metadata like the following:

  • All the assets in the title, along with the IDs and chunk FourCC(s) for that asset.
  • Declarations of the variables, constants, cursors, and so forth used in the game.

This doesn't seem to be opened/read by the executables at all while the titles are running. But there is a ton of useful cross-checking info in here.

Motivation

I re-discovered these titles when I was finding Director titles for the ScummVM Director engine at GSoC 2020. Coincidentally, the main data file extension (*.CXT) used in Media Station titles is the same as that used for protected Director cast archives. I quickly discovered these weren't Director titles but something completely different - and so this project was born to preserve them.

Engine History

Coming soon! For now, the Disney's Animated Storybook article has great background on the early titles, sourced largely from Newton Lee's books.

Future Enhancements

  • The bytecode decompiler needs a ton of work.
  • Some script data seems to be stored in the executables. That should be extracted.
  • Write a wikipedia article about the defunct Michigan-based company Media Station, Inc.

References

mediastation's People

Contributors

bjnfne avatar npjg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

bjnfne

mediastation's Issues

Extracting Barbi CD-ROM

Hello.
I'm trying to figure out how to extract "Magic Fairy Tales: Barbie As Rapunzel" and the script files on unknown section type: 0x0041

Here is result of processing: boot.stm

---
 Title Compiler T3.5r5 built Oct 11 1996 14:18:33 - 3.5r5
 Barbie
 Title Source J:\barbie.eng\src\rapunzel.imt; built Mon Jan 13 17:30:50 1997

WARNING:root:Detected unknown section 0x000c
WARNING:root:Detected unknown section 0x0064
WARNING:root:Detected unknown section 0x006a
---

I'm not sure what information a can share to define the issue. May be the source of iso: Magic Fairy Tales: Barbie As Rapunzel

Problems with exporting items from Pooh Animated Storybook

C:\Users\jaker>C:\Users\jaker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\Scripts\MediaStation.exe "C:\Users\jaker\Downloads\Disney's Animated Storybook Winnie the Pooh and the Honey Tree\DATA" "C:\Users\jaker\Downloads\Disney's Animated Storybook Winnie the Pooh and the Honey Tree\Export"
Processing matched file C:\Users\jaker\Downloads\Disney's Animated Storybook Winnie the Pooh and the Honey Tree\DATA\BOOT.STM

WARNING:root:Detected unknown section 0x000c
WARNING:root:Detected unknown section 0x0064
WARNING:root:Detected unknown section 0x0066

Processing matched file C:\Users\jaker\Downloads\Disney's Animated Storybook Winnie the Pooh and the Honey Tree\DATA\100.CXT
Processing matched file C:\Users\jaker\Downloads\Disney's Animated Storybook Winnie the Pooh and the Honey Tree\DATA\104.CXT
Processing matched file C:\Users\jaker\Downloads\Disney's Animated Storybook Winnie the Pooh and the Honey Tree\DATA\120.CXT
Processing matched file C:\Users\jaker\Downloads\Disney's Animated Storybook Winnie the Pooh and the Honey Tree\DATA\126.CXT
Processing matched file C:\Users\jaker\Downloads\Disney's Animated Storybook Winnie the Pooh and the Honey Tree\DATA\158.CXT
Processing matched file C:\Users\jaker\Downloads\Disney's Animated Storybook Winnie the Pooh and the Honey Tree\DATA\159.CXT
Processing matched file C:\Users\jaker\Downloads\Disney's Animated Storybook Winnie the Pooh and the Honey Tree\DATA\161.CXT
Traceback (most recent call last):
File "", line 198, in _run_module_as_main
File "", line 88, in run_code
File "C:\Users\jaker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\Scripts\MediaStation.exe_main
.py", line 7, in
File "C:\Users\jaker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\MediaStation\Engine.py", line 138, in main
media_station_engine.process(command_line_arguments.input, file_detection_entries)
File "C:\Users\jaker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\asset_extraction_framework\Application.py", line 66, in process
self.process(sub_directory_path, [file_detection_entry])
File "C:\Users\jaker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\asset_extraction_framework\Application.py", line 75, in process
processed_file = file_detection_entry.file_processor(path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\jaker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\MediaStation\Context.py", line 204, in init
chunk = self.read_old_style_header_sections(subfile, chunk)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\jaker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\MediaStation\Context.py", line 271, in read_old_style_header_sections
chunk = subfile.get_next_chunk()
^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\jaker\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\MediaStation\Riff\SubFile.py", line 82, in get_next_chunk
raise BinaryParsingError(
asset_extraction_framework.Exceptions.BinaryParsingError: Attempted to read a new chunk past the end of the subfile whose data starts at 0x18 and ends at 0x47e.

Position: 0x047e
Context:
0000045e 69 67 6f 64 18 00 00 00 03 00 0d 00 03 00 13 00 |igod............|
0000046e 03 00 a1 00 03 00 10 00 03 00 a1 00 03 00 00 00 |................|
0000047e a1 00 10 00 00 00 6e 04 00 00 00 00 00 00 |......n.......|
0000048c

Errors when exporting from 101 Dalmatians game

The below errors were encountered when exporting from the Disney's Animated Storybook: 101 Dalmatians game. I mounted the ISO file as drive D: and ran this command: python cxt.py "D:\DATA" "G:\Media Station Rips\Dalmatians".

Traceback (most recent call last):
  File "cxt.py", line 1451, in parse
    cxt.parse(stream)
  File "cxt.py", line 1030, in parse
    if not self.get_header(stream, chunk): break
  File "cxt.py", line 1132, in get_header
    contents = [AssetHeader(stream)]
  File "cxt.py", line 577, in __init__
    raise TypeError("AssetHeader(): Unknown field delimiter in header: 0x{:0>4x}".format(type.d))
TypeError: AssetHeader(): Unknown field delimiter in header: 0x0773
Traceback (most recent call last):
  File "cxt.py", line 1467, in parse
    logging.debug(" >>> {} ".format(header))
  File "cxt.py", line 164, in __format__
    return self.__repr__()
  File "cxt.py", line 608, in __repr__
    self.filenum.d, self.type.d, self.id.d, self.id.d,
AttributeError: 'str' object has no attribute 'd'
Traceback (most recent call last):
  File "cxt.py", line 1472, in parse
    value_assert(stream.tell(), riff["offset"], "stream position")
  File "cxt.py", line 132, in value_assert
    assert ax == target, msg
AssertionError: Expected stream position 871728 (0xd4d30), received 1150402 (0x118dc2)
Traceback (most recent call last):
  File "cxt.py", line 1451, in parse
    cxt.parse(stream)
  File "cxt.py", line 1030, in parse
    if not self.get_header(stream, chunk): break
  File "cxt.py", line 1132, in get_header
    contents = [AssetHeader(stream)]
  File "cxt.py", line 600, in __init__
    self.children.append(AssetHeader(stream, stage=True))
  File "cxt.py", line 577, in __init__
    raise TypeError("AssetHeader(): Unknown field delimiter in header: 0x{:0>4x}".format(type.d))
TypeError: AssetHeader(): Unknown field delimiter in header: 0x06ac

I received these errors (or variations of them) many times during the export. I've listed the errors in order of first appearance.

And at the very end, this error occurs (which I think is harmless):

Traceback (most recent call last):
  File "cxt.py", line 1472, in parse
    value_assert(stream.tell(), riff["offset"], "stream position")
  File "cxt.py", line 132, in value_assert
    assert ax == target, msg
AssertionError: Expected stream position 19414016 (0x1283c00), received 16 (0x0010)

Also, many of the images are exported as blank/black PNGs, and it seems like only a small fraction of the assets are exported correctly. I've attached the exported 131 folder as an example: 131.zip.

The same (or very similar) errors occur when exporting from these other games:

Error when exporting from Lion King game

The below error was encountered when exporting from the Disney's Animated Storybook: The Lion King game. I mounted the ISO file as drive D: and ran this command: python cxt.py "D:\DATA" "G:\Media Station Rips\lionking-export".

Traceback (most recent call last):
  File "cxt.py", line 1451, in parse
    cxt.parse(stream)
  File "cxt.py", line 1043, in parse
    res = self.get_header(stream, chunk)
  File "cxt.py", line 1177, in get_header
    raise ValueError("Leftover end-of-chunk flags should not be present")
ValueError: Leftover end-of-chunk flags should not be present

This error occurred many times and it seems like the export failed entirely. I get only a system.json file without any subfolders or exported assets. system.zip

Error when exporting from Pocahontas Animated Storybook

When running MediaStation.exe on the directory (copied to my hard drive), I receive the following warnings and errors:

Processing matched file POCA_P6546\BOOT.STM
WARNING:root:Detected unknown section 0x000c
WARNING:root:Detected unknown section 0x0064
WARNING:root:Detected unknown section 0x006b
Processing matched file POCA_P6546\100.CXT
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "C:\Users\thevi\AppData\Local\Programs\Python\Python312\Scripts\MediaStation.exe\__main__.py", line 7, in <module>
  File "C:\Users\thevi\AppData\Local\Programs\Python\Python312\Lib\site-packages\MediaStation\Engine.py", line 70, in main
    media_station_engine.process(command_line_arguments.input, file_detection_entries)
  File "C:\Users\thevi\AppData\Local\Programs\Python\Python312\Lib\site-packages\asset_extraction_framework\Application.py", line 57, in process
    self.process(sub_directory_path, [file_detection_entry])
  File "C:\Users\thevi\AppData\Local\Programs\Python\Python312\Lib\site-packages\asset_extraction_framework\Application.py", line 66, in process
    processed_file = file_detection_entry.file_processor(path)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\thevi\AppData\Local\Programs\Python\Python312\Lib\site-packages\MediaStation\Context.py", line 198, in __init__
    Datum(self.stream)
  File "C:\Users\thevi\AppData\Local\Programs\Python\Python312\Lib\site-packages\MediaStation\Primitives\Datum.py", line 85, in __init__
    raise ValueError(f'Unknown datum type: 0x{self.t:04x}')
ValueError: Unknown datum type: 0x6769

No files are extracted. No JSON is saved.

OS: Windows 11 Pro 22H2
Python version: 3.12 64-bit
MediaStation version: latest release from PyPI (sorry, don't know which version number that would be)
CPU: AMD Ryzen 7 7700X

If you need any more info about my operating environment, let me know!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.