forked from kmck/karaoke
-
Notifications
You must be signed in to change notification settings - Fork 0
/
spec.txt
395 lines (298 loc) · 15.4 KB
/
spec.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
CD+G Revealed: Playing back Karaoke tracks in Software
Version 1.0
1/9/95
Jim Bumgardner
Introduction
A CD+G is a special Audio Compact disc that contains graphics data in addition to the audio data on the disc. The disc can be played on a regular Audio CD player, but when played on a special CD+G player, can output a graphics signal (typically, the CD+G player is hooked up to a television set).
This file describes how CD+G information is stored on the disc, and provides information to help programmers implement CD+G playback on personal computers equipped with CD+G compatible CD-ROM drives. This document assumes a familiarity with computer programming, and especially the C programming language.
Ever since I released a utility for the Macintosh that allows owners of Apple's
CD300 to play CD+G discs (CDG Player), I have received numerous requests asking
for the CD+G specification. Unfortunately, this information has not been made
available to the general public (as far as I know) and is hard to find.
Hopefully, this informal description will help.
It has been a while since I read the CD+G specification. I am describing this
system from memory, and will often deviate from the nomenclature used in the
actual CD Audio and CD+G specification.
How CD+G information is stored on the disc
==========================================
A Compact Disc contains two kinds of data: Content data, which is used to store
Audio and Computer software and the like, and Subchannel data, which is normally
used by the CD player to help control the disc.
Assuming the disc is being read at normal speed (approx 150 kps) for audio
playback, the data is read at 75 sectors per second. In each sector there are
2352 bytes of Content data and 96 bytes of Subchannel data.
On the disc, the Subchannel data is interspersed with the audio data. But when
the disc is played back, the two streams of data are separated. On a typical
CD-ROM player you can't access the Subchannel information - it is never sent to
the computer. In fact, until recently on most CD-ROM players, you couldn't read
the Content data on an audio track either. You could only read the Content data a
data track which is used specifically for storing computer information.
Presumeably, this was done to prevent people from easily pirating Audio CDs.
More recently however, manufacturers have started producing drives that allow the
computer to access not only the Content data on an audio track, but also the
Subchannel data. As we shall see, it is this Subchannel capability which is
needed for a computer to be able to play a CD+G disc.
The 96 bytes of Subchannel information in each sector contain 4 packets of 24
bytes apiece.
The structure of the packet is as follows:
typedef struct {
char command;
char instruction;
char parityQ[2];
char data[16];
char parityP[4];
} SubCode;
Each byte in the 16 byte SubCode.data[] field can be thought of as being divided
into 8-bits. Each of these bits corresponds to a separate stream of information.
These streams are called "channels", and are labeled starting with the letter P,
like so:
Channel# P Q R S T U V W
Bit# 7 6 5 4 3 2 1 0
---------------
Byte # 0 0 0 0 0 0 0 0 0
Byte # 1 0 0 0 0 0 0 0 0
Byte # 2 0 0 0 0 0 0 0 0
.
. (etc.)
.
Byte # 15 0 0 0 0 0 0 0 0
Both the P and Q channels, on a regular Audio CD are used for timing information.
They are used to assist the CD Player in tracking the current location on the
disc, and to provide the timing information for the time display on the CD
Player.
On a regular Audio CD, channels R through W are unused.
The CD+G format takes advantage of the unused channels R thru W. These unused
six bits are used to store graphics information. Note that this is an extremely
thin stream of information. 6 bits per byte * 16 bytes per packet * 4
packets per sector * 75 sectors per second = 28800 bits per second, or 3.6 K per
second. By comparison, a typical 160 x 120 QuickTime movie uses 90K per second.
CD+G Graphics Instructions
==========================
The CD+G standard is published by Philips and Sony as an extension of the Red
Book. It defines a specific system for decoding the subchannels R thru W. Note:
if you gain sufficient control of the CD mastering process, you could define your
own Audio-compatible format which is potentially more interesting than CD+G.
For example, you could use the Subchannel to store control information for an
animatronics robot, MIDI information, etc. There already is a CD+G+MIDI extension
of the CD+G standard, but I won't describe it here.
Also, there is an "Extended" CD+G standard which allows for more colors and
effects in a backward compatible manner, but I have yet to see any discs
published in this format, so I will only describe the basic format.
In the CD+G system, 16 color graphics are displayed on a raster field which is
300 x 216 pixels in size. The middle 294 x 204 area is within the TV's
"safe area", and that is where the graphics are displayed. The outer border is
set to a solid color. The colors are stored in a 16 entry color lookup table.
Each color in the table is drawn from an RGB space of 4096 (4 bits each for
R,G and B) colors.
Since we are using a 16 color table, each pixel can be stored in 4 bits,
resulting in a total pixelmap size of 4 * 300 * 216 = 259200 bits = a little less
than 32K.
The SubCode.command and SubCode.instruction fields in each SubCode packet are
used to determine how the data is to be interpreted. I will enumerate these
commands below. When reading the command and instruction fields, you should only
pay attention to the lower 6 bits of each of these bytes (e.g. by ANDing
the byte with the hex value 3Fh). The upper 2 bits are used for the P and Q
channels which you should ignore.
If the lower 6 bits of the command field are equal to 9, then the SubCode packet
contains CD+G information, otherwise it should be ignored.
If the packet contains CD+G information, then you use the instruction field
(again, the lower six bits), to determine how to interpret the data.
An example will be shown below.
Instruction List (Brief)
================
A more detailed description of each instruction appears later in this document.
Number Name/Description
====== ================
1 Memory Preset
Set the screen to a particular color.
2 Border Preset
Set the border of the screen to a particular color.
6 Tile Block (Normal)
Load a 12 x 6, 2 color tile and display it normally.
20 Scroll Preset
Scroll the image, filling in the new area with a color.
24 Scroll Copy
Scroll the image, rotating the bits back around.
28 Define Transparent Color
Define a specific color as being transparent.
30 Load Color Table (entries 0-7)
Load in the lower 8 entries of the color table.
31 Load Color Table (entries 8-15)
Load in the upper 8 entries of the color table.
38 Tile Block (XOR)
Load a 12 x 6, 2 color tile and display it using the XOR method.
Code Example
===========
This code example shows how you might implement the graphics display dispatcher
for a CD+G player in C.
#define SC_MASK 0x3F
#define SC_CDG_COMMAND 0x09
#define CDG_MEMORYPRESET 1
#define CDG_BORDERPRESET 2
// etc... - define each instruction listed above
ReadSubCodePacket(&subCode);
if ((subCode.command & SC_MASK) == SC_CDG_COMMAND) { // CD+G?
switch (subCode.instruction & SC_MASK) {
case CDG_MEMORYPRESET: MemoryPreset(subCode.data); break;
case CDG_BORDERPRESET: BorderPreset(subCode.data); break;
// etc... - implemement each instruction listed above
}
}
How to read SubCode packets on a Computer equipped with a CD-ROM drive
======================================================================
This is the (possibly) hard part. If your CD-ROM drive doesn't support this
feature, you are shit-out-of-luck. If the *Driver* software that is used to
control your CD-ROM drive doesn't support this feature, you are also
shit-out-of-luck, although less so, since you might be able to write a new
driver, or obtain a new one. Good luck.
As far as I know, the only way this step can be easily solved (today), it to use
an Apple Macintosh equipped with an Apple CD300 drive or better. Both this
drive, and the driver that is included with it support SubCode access. Apple
publishes a document called "CD-ROM Driver Calls" which is available from
ftp.apple.com. It describes the newer driver calls that allow you to retrieve
SubCode packets on the Apple CD300 drive. These calls often do not work on 3rd
party drives. I used the information in this document to code a function based on
the Mac Toolbox call PBControl, which will retrieve SubCode packets.
CD+G Instructions (detailed)
=================
Here I describe the CD+G instructions in detail, hopefully providing enough
information for a programmer to implement CD+G playback.
Note that in all these instructions, only the lower 6 bits of each data byte are
used. So, for example, If I refer to subCode.data[0], I actually mean
(subCode.data[0] & 0x3F).
****
Memory Preset (subCode.instruction==1)
****
In this instruction, the 16 byte data field is interepreted as follows.
typedef struct {
char color; // Only lower 4 bits are used, mask with 0x0F
char repeat; // Only lower 4 bits are used, mask with 0x0F
char filler[14];
} CDG_MemPreset;
Color refers to a color to clear the screen to. The entire screen should be
cleared to this color.
When these commands appear in bunches (to insure that the screen gets cleared),
the repeat count is used to number them. If this is true, and you have a
reliable data stream, you can ignore the command if repeat != 0.
***
Border Preset (subCode.instruction==2)
***
In this instruction, the 16 byte data field is interepreted as follows.
typedef struct {
char color; // Only lower 4 bits are used, mask with 0x0F
char filler[15];
} CDG_BorderPreset;
Color refers to a color to clear the screen to. The border area of the screen
should be cleared to this color. The border area is the area contained with a
rectangle defined by (0,0,300,216) minus the interior pixels which are contained
within a rectangle defined by (6,12,294,204).
***
Tile Block Normal (subCode.instruction==6)
Tile Block XOR (subCode.instruction==38)
***
These commands load a 12 x 6 tile of pixels from the subCode.data area. I recall
that in the original CD+G spec, the tile is refered to as a "font", but I think
the word tile is more appropriate, because the tile can (and does) contain any
graphical image, not just text. Larger images are built by using multiple tiles.
The XOR variant is a special case of the same command, the difference is
described below.
The tile is stored using 1-bit graphics. The structure contains two colors which
are to be used when rendering the tile. The tile is extracted from 16 bytes of
subCode.data[] in the following manner:
typedef struct {
char color0; // Only lower 4 bits are used, mask with 0x0F
char color1; // Only lower 4 bits are used, mask with 0x0F
char row; // Only lower 5 bits are used, mask with 0x1F
char column; // Only lower 6 bits are used, mask with 0x3F
char tilePixels[12]; // Only lower 6 bits of each byte are used
} CDG_Tile;
color0, color1 describe the two colors (from the color table) which are to be
used when rendering the tile. Color0 is used for 0 bits, Color1 is used for 1
bits.
Row and Column describe the position of the tile in tile coordinate space. To
convert to pixels, multiply row by 12, and column by 6.
tilePixels[] contains the actual bit values for the tile, six pixels per byte.
The uppermost valid bit of each byte (0x20) contains the left-most pixel of each
scanline of the tile.
In the normal instruction, the corresponding colors from the color table are
simply copied to the screen.
In the XOR variant, the color values are combined with the color values that are
already onscreen using the XOR operator. Since CD+G only allows a maximum of 16
colors, we are XORing the pixel values (0-15) themselves, which correspond to
indexes into a color lookup table. We are not XORing the actual R,G,B values.
***
Scroll Preset (subCode.instruction==20)
Scroll Copy (subCode.instruction==24)
***
In these instruction, the 16 byte data field is interepreted as follows.
typedef struct {
char color; // Only lower 4 bits are used, mask with 0x0F
char hScroll; // Only lower 6 bits are used, mask with 0x3F
char vScroll; // Only lower 6 bits are used, mask with 0x3F
} CDG_Scroll;
This command is used to scroll all the pixels on the screen horizontally and/or
vertically.
The color refers to a fill color to use for the new area uncovered by the
scrolling action. It is only used in the Scroll Preset command. In the Scroll
Copy command the screen is "rotated" around. For example, in scrolling to the
left, pixels uncovered on the right are filled in by the pixels being scrolled
off the screen on the left.
The hScroll field is a compound field. It can be divided into two fields like so:
SCmd = (hScroll & 0x30) >> 4;
HOffset = (hScroll & 0x07);
SCmd is a scrolliing instruction, which is either 0, 1 or 2.
0 means don't scroll
1 means scroll 6 pixels to the right,
2 means scroll 6 pixels to the left.
HOffset is a horizontal offset which is used for offsetting the graphic
display by amounts less than 6 pixels. It can assume values from 0 to 5.
Similarly, the vScroll field is a compound field. It can be divided into two
fields like so:
SCmd = (vScroll & 0x30) >> 4;
VOffset = (vScroll & 0x0F);
SCmd is a scrolliing instruction, which is either 0, 1 or 2.
0 means don't scroll
1 means scroll 12 pixels down,
2 means scroll 12 pixels up.
VOffset is a vertical offset which is used for offsetting the graphic
display by amounts less than 12 pixels. It can assume values from 0 to 11.
Smooth horizontal and vertical scrolling in all directions can be done by
combining scroll commands. For example, here is a smooth horizontal scroll to
the left:
SCmd HScroll
=== =======
0 1
0 2
0 3
0 4
0 5
0 6
2 0
(repeat)
You can create the effect of an infinite panorama by continually loading in new
tiles into the border area and scrolling them into view.
***
Define Transparent Color (subCode.instruction==28)
***
This command is used to define a CLUT color as being transparent, for example so
that the the graphics can be overlayed on top of a live video signal.
***
Load Color Table Lo [colors 0 thru 7] (subCode.instruction==30)
Load Color Table High [colors 8 thru 15] (subCode.instruction==31)
***
These commands are used to load in the colors for the color table. The colors
are specified using 4 bits each for R, G and B, resulting in 4096 possible
colors. The only different between the two instructions is whether the low
part or the high part of the color table is loaded.
In these instruction, the 16 byte data field is interpreted as follows.
typedef struct {
short colorSpec[8]; // AND with 0x3F3F to clear P and Q channel
} CDG_LoadCLUT;
Each colorSpec value can be converted to RGB using the following diagram:
[---high byte---] [---low byte----]
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
X X r r r r g g X X g g b b b b
Note that P and Q channel bits need to be masked off (they are marked
here with Xs.
The Load CLUT commands are often used in CD+G to provide the illusion of
animation through the use of color cyling.