Difference between Data Type 2 (packed) and Type 3 (raw) writing?

All,

I just have a quick question. I’m looking at the MMC4 specs and am trying to differentiate the difference between data type 2 (packed) and type 3 (raw) when writing DAO/96. It appears that type 2 uses interleaved sub-channel data such as:

byte 0: P1 Q1 R1 S1 T1 U1 V1 W1
byte 1: P2 Q2 R2 S2 T2 U2 V2 W2

byte 95: …

but i’m not sure what the raw form of the subchannel data is or rather what the difference is.

Any help is greatly appreciated. Thanks!

Hi, welcome to the forum.

I too had this question in mind a while back, but a member named IpseDixit has enlighten me. Apparently, the packed mode is the CD+G subcode format, i.e. the info used for graphics and text, which can be played on certain CD+G compatible players.

Look at this thread: http://club.cdfreaks.com/showthread.php?t=81488

If u scroll down near to the bottom, a very helpful member (not forgetting the others) named taras_g has a code listed there, that does the conversion, i.e. it converts your raw form into the packed form.

What it does is that it applies the CD+G delays on them. U can see the CD+G delays are in a table named “offsets”.

But, I think, this may need attention: only the lower 6 bits of each byte is supposed to be delayed. The upper 2 bits are the normal P & Q bits - same as in raw form. So I think there’s supposed to be some sort of skew, between the P & Q with the lower 6 bits.

If I have time, I’ll try to test out his source code.

*Note: naturally, if subcodes RW (lower 6 bits) have no data, i.e. all zeroes, u won’t see any difference, I suppose you won’t even need to apply the process. It’s only a problem if you have CD+G data in those parts.

Truman,

Thanks for the reply and the info. That’s exactly what I needed to know. The MMC docs need to be a little more specific in referencing the data format. :slight_smile:

Not sure if I’m in the right direction here, but think of it this way. If you start with 4 bytes of RAW sub (P-W) and you pack them (R-W), you will have 3 bytes in the end… (you get rid of P and Q and then make ‘bytes’ out of what bits are left).

P1 Q1 R1 S1 T1 U1 V1 W1 byte1
P2 Q2 R2 S2 T2 U2 V2 W2 byte2
P3 Q3 R3 S3 T3 U3 V3 W3 byte3
P4 Q4 R4 S4 T4 U4 V4 W4 byte4

becomes (after stripping the P and Q and packing)

R1 S1 T1 U1 V1 W1 R2 S2 byte1
T2 U2 V2 W2 R3 S3 T3 U3 byte2
V3 W3 R4 S4 T4 U4 V4 W4 byte3

sfritzinger, is this what you were asking?

Truman, is this what you already tried to say/point to? If so…sorry. :doh:

No need to apologise, RichMan (I think you’re more of an expert than me :)). Not quite as above, sorry I wasn’t clear. For anyone interested, I hope I can explain…

A bit of info

Subcodes R through W are defined specially in CD+G format, which I’m applying here. First, RW are actually used in the usual subcode interleaved state as is:

P1 Q1 R1 S1 T1 U1 V1 W1 byte1
P2 Q2 R2 S2 T2 U2 V2 W2 byte2
P3 Q3 R3 S3 T3 U3 V3 W3 byte3
P4 Q4 R4 S4 T4 U4 V4 W4 byte4

It doesn’t stop there…

In CD+G, to protect the RW parts, they applied their own Reed-solomon error correction code & also an 8 times interleaving.

Note, P & Q subcodes are not affected.

Some units they defined in CD+G:

RW parts are 6 bits, which they call a symbol (1 RW = 1 symbol)
A group of 24 symbols forms 1 pack (24 x symbols = 1 pack)
4 packs forms 1 packet (4 packs = 1 packet).

Converting from raw sub to pack sub

As mentioned above, an 8 times interleaving was added. Note, that this is a second interleaving (causing some confusion), lets call this the CD+G interleaving to distinguish it between the usual subcode interleaving.

Fundamentally, you can probably see that the only difference is with this extra CD+G interleaving.

Naturally, because we wish to decode, the process is to apply the opposite to CD+G interleaving (i.e. de-interleave) to give u the pack sub.

Ok, before we begin, there’s one catch, in “8 times” interleaving. It means 8 x 24 symbols = 192 symbols.

Basically, on the CD+G, RW subcodes were delayed about 192 symbols. Here’s the delay table that delayed each 24 bytes of raw subcode of a sector:

//CD+G subcode interleave delays.
unsigned int cdg_interleave_delays[]=
{
    192, 258, 317, 383, 292, 242, 342, 367,
    200, 225, 250, 275, 300, 325, 350, 375,
    208, 233, 217, 283, 308, 333, 358, 267
};

Ok, maybe enough talk for now, I should show it practically…

Let’s take those raw subcodes of a single sector:

Assume it’s at sector 10:

P00 Q00 R00 S00 T00 U00 V00 W00 byte0
P01 Q01 R01 S01 T02 U01 V01 W01 byte1
P02 Q02 R02 S02 T03 U02 V02 W02 byte2
P03 Q03 R03 S03 T04 U03 V03 W03 byte3

P92 Q92 R92 S92 T92 U92 V92 W92 byte92
P93 Q93 R93 S93 T93 U93 V93 W93 byte93
P94 Q94 R94 S94 T94 U94 V94 W94 byte94
P95 Q95 R95 S95 T95 U95 V95 W95 byte95

We apply the cdg_interleave_delays, but we don’t delay, instead we wish to do the opposite (un-delaying), so we move bytes forward:

Example,

For the first one, R01, we move it forward 192 bytes, for S01, we move it forward 258 bytes, and so on. So for the first 24 bytes of raw subs, you should get them spread out into sectors 11 & 12 of the output:

Sector 11:

P192 Q192 R00 S00 T00 U00 V00 W00 byte192
P193 Q193 XXX XXX XXX XXX XXX XXX byte193
P194 Q194 XXX XXX XXX XXX XXX XXX byte194
P195 Q195 XXX XXX XXX XXX XXX XXX byte195

P200 Q200 R08 S08 T08 U08 V08 W08 byte200
P201 Q201 XXX XXX XXX XXX XXX XXX byte201
P202 Q202 XXX XXX XXX XXX XXX XXX byte202
P203 Q203 XXX XXX XXX XXX XXX XXX byte203

P208 Q208 R16 S16 T16 U16 V16 W16 byte208
P209 Q209 XXX XXX XXX XXX XXX XXX byte209
P210 Q210 XXX XXX XXX XXX XXX XXX byte210
P211 Q211 XXX XXX XXX XXX XXX XXX byte211

P216 Q216 XXX XXX XXX XXX XXX XXX byte216
P217 Q217 R18 S18 T18 U18 V18 W18 byte217
P218 Q218 XXX XXX XXX XXX XXX XXX byte218
P219 Q219 XXX XXX XXX XXX XXX XXX byte219

P224 Q224 XXX XXX XXX XXX XXX XXX byte224
P225 Q225 R09 S09 T09 U09 V09 W09 byte225
P226 Q226 XXX XXX XXX XXX XXX XXX byte226
P227 Q227 XXX XXX XXX XXX XXX XXX byte227

P232 Q232 XXX XXX XXX XXX XXX XXX byte232
P233 Q233 R17 S17 T17 U17 V17 W17 byte233
P234 Q234 XXX XXX XXX XXX XXX XXX byte234
P235 Q235 XXX XXX XXX XXX XXX XXX byte235

P240 Q240 XXX XXX XXX XXX XXX XXX byte240
P241 Q241 XXX XXX XXX XXX XXX XXX byte241
P242 Q242 R05 S05 T05 U05 V05 W05 byte242
P243 Q243 XXX XXX XXX XXX XXX XXX byte243

P248 Q248 XXX XXX XXX XXX XXX XXX byte248
P249 Q249 XXX XXX XXX XXX XXX XXX byte249
P250 Q250 R10 S10 T10 U10 V10 W10 byte250
P251 Q251 XXX XXX XXX XXX XXX XXX byte251

P256 Q256 XXX XXX XXX XXX XXX XXX byte256
P257 Q257 XXX XXX XXX XXX XXX XXX byte257
P258 Q258 R01 S01 T01 U01 V01 W01 byte258
P259 Q259 XXX XXX XXX XXX XXX XXX byte259

P264 Q264 XXX XXX XXX XXX XXX XXX byte264
P265 Q265 XXX XXX XXX XXX XXX XXX byte265
P266 Q266 XXX XXX XXX XXX XXX XXX byte266
P267 Q267 R23 S23 T23 U23 V23 W23 byte267

P272 Q272 XXX XXX XXX XXX XXX XXX byte272
P273 Q273 XXX XXX XXX XXX XXX XXX byte273
P274 Q274 XXX XXX XXX XXX XXX XXX byte274
P275 Q275 R11 S11 T11 U11 V11 W11 byte275

Sector 12

P292 Q292 R04 S04 T04 U04 V04 W04 byte292
P293 Q293 XXX XXX XXX XXX XXX XXX byte293
P294 Q294 XXX XXX XXX XXX XXX XXX byte294
P295 Q295 XXX XXX XXX XXX XXX XXX byte295

P212 Q212 XXX XXX XXX XXX XXX XXX byte280
P213 Q213 XXX XXX XXX XXX XXX XXX byte281
P214 Q214 XXX XXX XXX XXX XXX XXX byte282
P215 Q215 R19 S19 T19 U19 V19 W19 byte283

P300 Q300 R12 S12 T12 U12 V12 W12 byte300
P301 Q301 XXX XXX XXX XXX XXX XXX byte301
P302 Q302 XXX XXX XXX XXX XXX XXX byte302
P303 Q303 XXX XXX XXX XXX XXX XXX byte303

P308 Q308 R20 S20 T20 U20 V20 W20 byte308
P309 Q309 XXX XXX XXX XXX XXX XXX byte309
P310 Q310 XXX XXX XXX XXX XXX XXX byte310
P311 Q311 XXX XXX XXX XXX XXX XXX byte311

P316 Q316 XXX XXX XXX XXX XXX XXX byte316
P317 Q317 R02 S02 T02 U02 V02 W02 byte317
P318 Q318 XXX XXX XXX XXX XXX XXX byte318
P319 Q319 XXX XXX XXX XXX XXX XXX byte319

P324 Q324 XXX XXX XXX XXX XXX XXX byte324
P325 Q325 R13 S13 T13 U13 V13 W13 byte325
P326 Q326 XXX XXX XXX XXX XXX XXX byte326
P327 Q327 XXX XXX XXX XXX XXX XXX byte327

P332 Q332 XXX XXX XXX XXX XXX XXX byte332
P333 Q333 R21 S21 T21 U21 V21 W21 byte333
P334 Q334 XXX XXX XXX XXX XXX XXX byte334
P335 Q335 XXX XXX XXX XXX XXX XXX byte335

P340 Q340 XXX XXX XXX XXX XXX XXX byte340
P341 Q341 XXX XXX XXX XXX XXX XXX byte341
P342 Q342 R06 S06 T06 U06 V06 W06 byte342
P343 Q343 XXX XXX XXX XXX XXX XXX byte343

P348 Q348 XXX XXX XXX XXX XXX XXX byte348
P349 Q349 XXX XXX XXX XXX XXX XXX byte349
P350 Q350 R14 S14 T14 U14 V14 W14 byte350
P351 Q351 XXX XXX XXX XXX XXX XXX byte351

P356 Q356 XXX XXX XXX XXX XXX XXX byte356
P357 Q357 XXX XXX XXX XXX XXX XXX byte357
P358 Q358 R22 S22 T22 U22 V22 W22 byte358
P359 Q359 XXX XXX XXX XXX XXX XXX byte359

P364 Q364 XXX XXX XXX XXX XXX XXX byte364
P365 Q365 XXX XXX XXX XXX XXX XXX byte365
P366 Q366 XXX XXX XXX XXX XXX XXX byte366
P367 Q367 R07 S07 T07 U07 V07 W07 byte367

P372 Q372 XXX XXX XXX XXX XXX XXX byte372
P373 Q373 XXX XXX XXX XXX XXX XXX byte373
P374 Q374 XXX XXX XXX XXX XXX XXX byte374
P375 Q375 R15 S15 T15 U15 V15 W15 byte375

P380 Q380 XXX XXX XXX XXX XXX XXX byte380
P381 Q381 XXX XXX XXX XXX XXX XXX byte381
P382 Q382 XXX XXX XXX XXX XXX XXX byte382
P383 Q383 R03 S03 T03 U03 V03 W03 byte383

Notes:
The XXX are unknown yet, until we process more raw subs.
Have u noticed P & Q stays where they are and don’t change.

Phew, hope that helps. Now for some coffee…

Oops, seems I was thinking packed vs RAW instead of interleaved vs deinterleaved. :o

I like your delay table. I should have done it that way instead of like this:

BOOL RW_Convert::Interleave(unsigned char *In, unsigned char *Out)
{
//this function takes the input pack and interleaves it throughout a total of 8 packs
//the input is a pointer to a buffer that contains 24 bytes
//the output is a pointer to a buffer that is 8*24 bytes
	int offset=0;

	Out[0]		= In[offset++];
	Out[(2*24)+18]	= In[offset++];
	Out[(5*24)+5]	= In[offset++];
	Out[(7*24)+23]	= In[offset++];
	Out[(4*24)+4]	= In[offset++];
	Out[(2*24)+2]	= In[offset++];
	Out[(6*24)+6]	= In[offset++];
	Out[(7*24)+7]	= In[offset++];
	Out[8]		= In[offset++];
	Out[(1*24)+9]	= In[offset++];
	Out[(2*24)+10]	= In[offset++];
	Out[(3*24)+11]	= In[offset++];
	Out[(4*24)+12]	= In[offset++];
	Out[(5*24)+13]	= In[offset++];
	Out[(6*24)+14]	= In[offset++];
	Out[(7*24)+15]	= In[offset++];
	Out[16]		= In[offset++];
	Out[(1*24)+17]	= In[offset++];
	Out[(1*24)+1]	= In[offset++];
	Out[(3*24)+19]	= In[offset++];
	Out[(4*24)+20]	= In[offset++];
	Out[(5*24)+21]	= In[offset++];
	Out[(6*24)+22]	= In[offset++];
	Out[(3*24)+3]	= In[offset];

	return 1;

}