Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resource Interchange File Format #230

Closed
KOLANICH opened this issue Sep 22, 2019 · 1 comment · Fixed by #229
Closed

Resource Interchange File Format #230

KOLANICH opened this issue Sep 22, 2019 · 1 comment · Fixed by #229

Comments

@KOLANICH
Copy link
Contributor

KOLANICH commented Sep 22, 2019

meta:
  id: riff
  title: Resource Interchange File Format (RIFF)
  license: CC0-1.0
  endian: le
  encoding: ASCII
  xref:
    justsolve: RIFF
    loc: fdd000025
    wikidata: Q1196805
doc: |
  The Resource Interchange File Format (RIFF) is a generic file container format
  for storing data in tagged chunks. It is primarily used to store multimedia
  such as sound and video, though it may also be used to store any arbitrary data.
  The Microsoft implementation is mostly known through container formats
  like AVI, ANI and WAV, which use RIFF as their basis.
doc-ref: https://www.johnloomis.org/cpe102/asgn/asgn1/riff.html
WiP: https://github.com/kaitai-io/kaitai_struct_formats/pull/229
issues:
  affect: [81, 458, 135, 196]
@generalmimon
Copy link
Member

I've figured out a way how to move basic building RIFF types into separate files and reuse them in all RIFF-compliant formats.

The basic building unit of every RIFF file is the chunk:

meta:
  id: chunk
  encoding: ASCII
  endian: le
params:
- id: expected_chunk_id
  doc: Optional parameter, pass empty string ('') if you don't want to specify
  type: str
seq:
  - id: chunk_id
    if: expected_chunk_id == ''
    type: str
    size: 4
    pad-right: 0x20
  - id: chunk_id_assert
    if: expected_chunk_id != ''
    type: str
    size: 4
    pad-right: 0x20
    valid: expected_chunk_id
  - id: chunk_size
    type: u4
  - id: chunk_data
    type: slot
    size: chunk_size
  - id: pad_byte
    size: chunk_size % 2
types:
  slot: {} # Keeps _io for later use of the same substream

The 'RIFF' and 'LIST' chunk data structure is defined as follows:

meta:
  id: parent_chunk_data
  encoding: ASCII
  endian: le
params:
  - id: expected_form_type
    doc: Optional parameter, pass empty string ('') if you don't want to specify
    type: str
seq:
  - id: form_type
    if: expected_form_type == ''
    type: str
    size: 4
    pad-right: 0x20
  - id: form_type_assert
    if: expected_form_type != ''
    type: str
    size: 4
    pad-right: 0x20
    valid: expected_form_type
  - id: subchunks
    type: slot
    size-eos: true
types:
  slot: {} # Keeps _io for later use of the same substream

Instead of parsing the chunk body immediately, I use an empty type named slot to keep reference to a substream and use it later. Sample usage:

  info_subchunk:
    seq:
      - id: chunk
        type: chunk('')
    instances:
      chunk_data:
        io: chunk.chunk_data._io
        pos: 0
        type: strz

I enclose a KSY spec for a sample RIFF form type 'GOBL', which is used in the original RIFF specification as an example of how an RIFF form should look like. I created a sample file to test it, so you can see the structure.
Both common RIFF structures use validation on optional fields, so you'll have to slightly edit the generated code to make it work (due to bug in current Kaitai Struct: kaitai-io/kaitai_struct#435 (comment)). It is enough just to move the validation code to the if clause.
gobl.zip

@generalmimon generalmimon linked a pull request Apr 7, 2020 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants