annotate _posts/2025-10-19-oms-part-1.html @ 118:503e22dd6cf5

blog: add (unfinished) series on OMS I'll update this as I do more research into the inner workings of OMS. It's much more interesting (and more convoluted) than ASIO is unfortunately, but it means the blog posts will probably be more interesting
author Paper <paper@tflc.us>
date Sun, 19 Oct 2025 23:15:02 -0400
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
118
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
1 ---
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
2 layout: post
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
3 author: Paper
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
4 title: 'The Open Music System, part 1 - initialization'
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
5 nowplaying: 'The Radio Dept. - Brobygatan'
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
6 ---
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
7 <span>
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
8 Applications wanting to interact with OMS must first call into
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
9 <code>Gestalt</code> with the first parameter being the magic
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
10 bytes <code>" OMS"</code> (<code>0x204F3D53</code>) and the
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
11 second parameter being a pointer to a 32-bit variable that
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
12 receives the magic pointer.
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
13 </span>
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
14 {% comment %}
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
15 is there was a way to do this with newlines? this is ugly
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
16 {% endcomment %}
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
17 <figure><pre class="code-block"><code>UniversalProcPtr OMS_GetGestaltPtr(void)
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
18 {
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
19 OSErr err;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
20 uint32_t x;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
21
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
22 err = Gestalt(0x204F3D53 /* " OMS" */, &x);
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
23 if (err != noErr)
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
24 return NULL;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
25
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
26 return (UniversalProcPtr)x;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
27 }</code></pre></figure>
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
28 <span>
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
29 From here, applications must retrieve an array of functions
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
30 through calling that magic pointer. Note that users cannot
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
31 simply call this pointer directly, unless they are specifically
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
32 only targeting 68k. You must use the <code>CallUniversalProc</code>
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
33 function to safely call into 68k code.
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
34 </span>
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
35 <figure><pre class="code-block"><code>UniversalProcPtr oms_table[0x5e];
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
36
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
37 #define OMS_GESTALT_PROC_TYPE \
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
38 (kThinkCStackBased \
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
39 | RESULT_SIZE(kFourByteCode) \
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
40 | STACK_ROUTINE_PARAMETER(1, kTwoByteCode) \
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
41 | STACK_ROUTINE_PARAMETER(2, kFourByteCode))
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
42
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
43 int32_t OMS_Init(void)
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
44 {
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
45 uint32_t functable;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
46 UniversalProcPtr omsptr;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
47
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
48 omsptr = OMS_GetGestaltPtr();
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
49 if (!omsptr)
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
50 return -1;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
51
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
52 functable = CallUniversalProc(omsptr, OMS_GESTALT_PROC_TYPE, 4, 0);
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
53 if (functable != (uint32_t)-1) {
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
54 memcpy(oms_table, (const void *)functable, sizeof(oms_table));
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
55 } else {
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
56 /* very old OMS */
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
57 uint32_t i;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
58
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
59 functable = CallUniversalProc(omsptr, OMS_GESTALT_PROC_TYPE, 1, 0);
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
60 if (!functable)
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
61 return -1;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
62
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
63 for (i = 0; i < ARRAY_SIZE(oms_table); i++, functable += 4)
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
64 oms_table[i] = (UniversalProcPtr)functable;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
65 }
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
66
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
67 return 0;
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
68 }</code></pre></figure>
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
69 <span>
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
70 At this point, you can now call into any of the pointers in
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
71 <code>oms_table</code>, provided that you know what the parameters
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
72 are. The easiest way I've found to find the parameters is to open an
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
73 OMS-capable program in a reverse-engineering tool, search for uses of
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
74 <code>CallUniversalProc</code> that look roughly like the initialization
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
75 code above, and mark the offset they are copied to as the OMS table with
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
76 the correct size and type. You can then find other uses of
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
77 <code>CallUniversalProc</code> that use the pointers in the OMS table,
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
78 and mark down the procedure type (the second parameter to
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
79 <code>CallUniversalProc</code>). To decode the procedure type, I've
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
80 written a simple utility to do the heavy lifting
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
81 <a class="prettylink" href="https://hg.tflc.us/codedump/file/tip/decode-mixed-mode.c">here</a>.
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
82 Do take note that it does not support register-based calling yet.
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
83 Feel free to send me any patches if you add support for it ;)
503e22dd6cf5 blog: add (unfinished) series on OMS
Paper <paper@tflc.us>
parents:
diff changeset
84 </span>