System Error Alert Table

From Computers Wiki
Revision as of 00:45, 25 September 2025 by Huntertur (talk | contribs) (→‎Reading it: Display default)
Jump to navigationJump to search

The System Error Alert Table (resource type DSAT, allegedly short for Deep Shit Alert Table) describes startup text and fatal error dialogs for the classic Mac OS.

Specification

See Inside Macintosh: Operating System Utilities, Chapter 2 - System Error Handler, The System Error Alert Table Resource.

Reading it

ResEdit doesn't support DSAT and only shows a hex editor despite having a custom icon for the resource type.

Here is an extremely rough Python script for dumping the alerts, their IDs, and their error messages. Despite DSAT definitions being polymorphic, there is no type information, so it determines what is an alert by process of elimination (correct size, text pointers are valid, pointed-to text is ASCII). Copy-paste the hex editor output from ResEdit into a text file, then pass its filename to this script:

dsat.py contents

from argparse import ArgumentParser
from pathlib import Path
import struct
from typing import NamedTuple

parser = ArgumentParser()
parser.add_argument('hexfilepath')
buffer = bytes.fromhex(Path(parser.parse_args().hexfilepath).read_text())
offset = 0

def read_short():
    global offset
    number = int.from_bytes(buffer[offset:offset + 2])
    offset += 2
    return number

definition_count = read_short()
definitions: dict[int, 'Definition']

class Alert(NamedTuple):
    text1_id: int
    text2_id: int
    icon_id: int
    proc_id: int
    button_layout_id: int

    @property
    def text1(self):
        return definitions[self.text1_id].as_text().replace('/', '\n') if self.text1_id else None

    @property
    def text2(self):
        return definitions[self.text2_id].as_text().replace('/', '\n') if self.text2_id else None

    @property
    def text(self):
        if not self.text1:
            return None

        if self.text2:
            return self.text1 + '\n' + self.text2

        return self.text1

class Definition(NamedTuple):
    id: int
    data: bytes

    def as_alert(self):
        return Alert(*struct.unpack('>HHHHH', self.data))

    def as_text(self):
        return self.data[4:-1].decode('ascii')

def read_definition():
    global offset
    id = read_short()
    length = read_short()
    data = buffer[offset:offset + length]
    offset += length
    return Definition(id, data)

default_alert = read_definition().as_alert()
definitions = {(definition := read_definition()).id: definition
               for _ in range(definition_count)}

for error_id, definition in definitions.items():
    if len(definition.data) == 10:
        alert = definition.as_alert()
        try:
            print(error_id, '-', alert.text)
        except (KeyError, UnicodeDecodeError):
            pass

print('Default - ', default_alert.text)

Contents in different system versions

TODO: make that utility first