Make description of the option more clear as suggested by
[mplayer/glamo.git] / libdvdread / cmd_print.c
blobfd3bdc138259cb6041c39eff2fe459588cf4f5d0
1 /* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 /*
3 * Copyright (C) 2000, 2001, 2002, 2003 Martin Norbäck, Håkan Hjort
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "config.h"
22 #include <stdio.h>
23 #include <ctype.h>
25 #if defined(HAVE_INTTYPES_H)
26 #include <inttypes.h>
27 #elif defined(HAVE_STDINT_H)
28 #include <stdint.h>
29 #endif
31 #include "cmd_print.h"
34 typedef struct
36 uint8_t bits[8];
37 uint8_t examined[8];
38 } cmd_t;
41 static const char *cmp_op_table[] = {
42 NULL, "&", "==", "!=", ">=", ">", "<=", "<"
44 static const char *set_op_table[] = {
45 NULL, "=", "<->", "+=", "-=", "*=", "/=", "%=", "rnd", "&=", "|=", "^="
48 static const char *link_table[] = {
49 "LinkNoLink", "LinkTopC", "LinkNextC", "LinkPrevC",
50 NULL, "LinkTopPG", "LinkNextPG", "LinkPrevPG",
51 NULL, "LinkTopPGC", "LinkNextPGC", "LinkPrevPGC",
52 "LinkGoUpPGC", "LinkTailPGC", NULL, NULL,
53 "RSM"
56 static const char *system_reg_table[] = {
57 "Menu Description Language Code",
58 "Audio Stream Number",
59 "Sub-picture Stream Number",
60 "Angle Number",
61 "Title Track Number",
62 "VTS Title Track Number",
63 "VTS PGC Number",
64 "PTT Number for One_Sequential_PGC_Title",
65 "Highlighted Button Number",
66 "Navigation Timer",
67 "Title PGC Number for Navigation Timer",
68 "Audio Mixing Mode for Karaoke",
69 "Country Code for Parental Management",
70 "Parental Level",
71 "Player Configurations for Video",
72 "Player Configurations for Audio",
73 "Initial Language Code for Audio",
74 "Initial Language Code Extension for Audio",
75 "Initial Language Code for Sub-picture",
76 "Initial Language Code Extension for Sub-picture",
77 "Player Regional Code",
78 "Reserved 21",
79 "Reserved 22",
80 "Reserved 23"
83 static const char *system_reg_abbr_table[] = {
84 NULL,
85 "ASTN",
86 "SPSTN",
87 "AGLN",
88 "TTN",
89 "VTS_TTN",
90 "TT_PGCN",
91 "PTTN",
92 "HL_BTNN",
93 "NVTMR",
94 "NV_PGCN",
95 NULL,
96 "CC_PLT",
97 "PLT",
98 NULL,
99 NULL,
100 NULL,
101 NULL,
102 NULL,
103 NULL,
104 NULL,
105 NULL,
106 NULL,
107 NULL,
112 static unsigned int bits(cmd_t *cmd, int byte, int bit, int count) {
113 unsigned int val = 0;
114 unsigned int bit_mask;
116 while(count--) {
117 if(bit > 7) {
118 bit = 0;
119 byte++;
121 bit_mask = 0x01 << (7-bit);
122 val <<= 1;
123 if((cmd->bits[byte]) & bit_mask)
124 val |= 1;
125 cmd->examined[byte] |= bit_mask;
126 bit++;
128 return val;
132 static void print_system_reg(unsigned int reg) {
133 if(reg < sizeof(system_reg_abbr_table) / sizeof(char *))
134 fprintf(stdout, system_reg_table[reg]);
135 else
136 fprintf(stdout, " WARNING: Unknown system register ");
139 static void print_reg(unsigned int reg) {
140 if(reg & 0x80)
141 print_system_reg(reg & 0x7f);
142 else
143 if(reg < 16)
144 fprintf(stdout, "g[%u]", reg);
145 else
146 fprintf(stdout, " WARNING: Unknown general register ");
149 static void print_cmp_op(unsigned int op) {
150 if(op < sizeof(cmp_op_table) / sizeof(char *) && cmp_op_table[op] != NULL)
151 fprintf(stdout, " %s ", cmp_op_table[op]);
152 else
153 fprintf(stdout, " WARNING: Unknown compare op ");
156 static void print_set_op(unsigned int op) {
157 if(op < sizeof(set_op_table) / sizeof(char *) && set_op_table[op] != NULL)
158 fprintf(stdout, " %s ", set_op_table[op]);
159 else
160 fprintf(stdout, " WARNING: Unknown set op ");
163 static void print_reg_or_data(cmd_t *cmd, unsigned int immediate, int byte) {
164 if(immediate) {
165 int i = bits(cmd,byte,0,16);
167 fprintf(stdout, "0x%x", i);
168 if(isprint(i & 0xff) && isprint((i>>8) & 0xff))
169 fprintf(stdout, " (\"%c%c\")", (char)((i>>8) & 0xff), (char)(i & 0xff));
170 } else {
171 print_reg(bits(cmd,byte + 1,0,8));
175 static void print_reg_or_data_2(cmd_t *cmd, unsigned int immediate, int byte) {
176 if(immediate)
177 fprintf(stdout, "0x%x", bits(cmd,byte,1,7));
178 else
179 fprintf(stdout, "g[%u]", bits(cmd,byte,4,4));
182 static void print_if_version_1(cmd_t *cmd) {
183 unsigned int op = bits(cmd,1,1,3);
185 if(op) {
186 fprintf(stdout, "if (");
187 print_reg(bits(cmd,3,0,8));
188 print_cmp_op(op);
189 print_reg_or_data(cmd,bits(cmd,1,0,1), 4);
190 fprintf(stdout, ") ");
194 static void print_if_version_2(cmd_t *cmd) {
195 unsigned int op = bits(cmd,1,1,3);
197 if(op) {
198 fprintf(stdout, "if (");
199 print_reg(bits(cmd,6,0,8));
200 print_cmp_op(op);
201 print_reg(bits(cmd,7,0,8));
202 fprintf(stdout, ") ");
206 static void print_if_version_3(cmd_t *cmd) {
207 unsigned int op = bits(cmd,1,1,3);
209 if(op) {
210 fprintf(stdout, "if (");
211 print_reg(bits(cmd,2,0,8));
212 print_cmp_op(op);
213 print_reg_or_data(cmd,bits(cmd,1,0,1), 6);
214 fprintf(stdout, ") ");
218 static void print_if_version_4(cmd_t *cmd) {
219 unsigned int op = bits(cmd,1,1,3);
221 if(op) {
222 fprintf(stdout, "if (");
223 print_reg(bits(cmd,1,4,4));
224 print_cmp_op(op);
225 print_reg_or_data(cmd,bits(cmd,1,0,1), 4);
226 fprintf(stdout, ") ");
230 static void print_if_version_5(cmd_t *cmd) {
231 unsigned int op = bits(cmd,1,1,3);
233 if(op) {
234 fprintf(stdout, "if (");
235 print_reg(bits(cmd,4,0,8));
236 print_cmp_op(op);
237 print_reg(bits(cmd,5,0,8));
238 fprintf(stdout, ") ");
242 static void print_special_instruction(cmd_t *cmd) {
243 unsigned int op = bits(cmd,1,4,4);
245 switch(op) {
246 case 0: // NOP
247 fprintf(stdout, "Nop");
248 break;
249 case 1: // Goto line
250 fprintf(stdout, "Goto %u", bits(cmd,7,0,8));
251 break;
252 case 2: // Break
253 fprintf(stdout, "Break");
254 break;
255 case 3: // Parental level
256 fprintf(stdout, "SetTmpPML %u, Goto %u",
257 bits(cmd,6,4,4), bits(cmd,7,0,8));
258 break;
259 default:
260 fprintf(stdout, "WARNING: Unknown special instruction (%u)",
261 bits(cmd,1,4,4));
265 static void print_linksub_instruction(cmd_t *cmd) {
266 unsigned int linkop = bits(cmd,7,3,5);
267 unsigned int button = bits(cmd,6,0,6);
269 if(linkop < sizeof(link_table)/sizeof(char *) && link_table[linkop] != NULL)
270 fprintf(stdout, "%s (button %u)", link_table[linkop], button);
271 else
272 fprintf(stdout, "WARNING: Unknown linksub instruction (%u)", linkop);
275 static void print_link_instruction(cmd_t *cmd, int optional) {
276 unsigned int op = bits(cmd,1,4,4);
278 if(optional && op)
279 fprintf(stdout, ", ");
281 switch(op) {
282 case 0:
283 if(!optional)
284 fprintf(stdout, "WARNING: NOP (link)!");
285 break;
286 case 1:
287 print_linksub_instruction(cmd);
288 break;
289 case 4:
290 fprintf(stdout, "LinkPGCN %u", bits(cmd,6,1,15));
291 break;
292 case 5:
293 fprintf(stdout, "LinkPTT %u (button %u)",
294 bits(cmd,6,6,10), bits(cmd,6,0,6));
295 break;
296 case 6:
297 fprintf(stdout, "LinkPGN %u (button %u)",
298 bits(cmd,7,1,7), bits(cmd,6,0,6));
299 break;
300 case 7:
301 fprintf(stdout, "LinkCN %u (button %u)",
302 bits(cmd,7,0,8), bits(cmd,6,0,6));
303 break;
304 default:
305 fprintf(stdout, "WARNING: Unknown link instruction");
309 static void print_jump_instruction(cmd_t *cmd) {
310 switch(bits(cmd,1,4,4)) {
311 case 1:
312 fprintf(stdout, "Exit");
313 break;
314 case 2:
315 fprintf(stdout, "JumpTT %u", bits(cmd,5,1,7));
316 break;
317 case 3:
318 fprintf(stdout, "JumpVTS_TT %u", bits(cmd,5,1,7));
319 break;
320 case 5:
321 fprintf(stdout, "JumpVTS_PTT %u:%u", bits(cmd,5,1,7), bits(cmd,2,6,10));
322 break;
323 case 6:
324 switch(bits(cmd,5,0,2)) {
325 case 0:
326 fprintf(stdout, "JumpSS FP");
327 break;
328 case 1:
329 fprintf(stdout, "JumpSS VMGM (menu %u)", bits(cmd,5,4,4));
330 break;
331 case 2:
332 fprintf(stdout, "JumpSS VTSM (vts %u, title %u, menu %u)",
333 bits(cmd,4,0,8), bits(cmd,3,0,8), bits(cmd,5,4,4));
334 break;
335 case 3:
336 fprintf(stdout, "JumpSS VMGM (pgc %u)", bits(cmd,2,1,15));
337 break;
339 break;
340 case 8:
341 switch(bits(cmd,5,0,2)) {
342 case 0:
343 fprintf(stdout, "CallSS FP (rsm_cell %u)",
344 bits(cmd,4,0,8));
345 break;
346 case 1:
347 fprintf(stdout, "CallSS VMGM (menu %u, rsm_cell %u)",
348 bits(cmd,5,4,4), bits(cmd,4,0,8));
349 break;
350 case 2:
351 fprintf(stdout, "CallSS VTSM (menu %u, rsm_cell %u)",
352 bits(cmd,5,4,4), bits(cmd,4,0,8));
353 break;
354 case 3:
355 fprintf(stdout, "CallSS VMGM (pgc %u, rsm_cell %u)",
356 bits(cmd,2,1,15), bits(cmd,4,0,8));
357 break;
359 break;
360 default:
361 fprintf(stdout, "WARNING: Unknown Jump/Call instruction");
365 static void print_system_set(cmd_t *cmd) {
366 int i;
368 switch(bits(cmd,0,4,4)) {
369 case 1: // Set system reg 1 &| 2 &| 3 (Audio, Subp. Angle)
370 for(i = 1; i <= 3; i++) {
371 if(bits(cmd,2+i,0,1)) {
372 print_system_reg((unsigned int)i);
373 fprintf(stdout, " = ");
374 print_reg_or_data_2(cmd,bits(cmd,0,3,1), 2 + i);
375 fprintf(stdout, " ");
378 break;
379 case 2: // Set system reg 9 & 10 (Navigation timer, Title PGC number)
380 print_system_reg(9);
381 fprintf(stdout, " = ");
382 print_reg_or_data(cmd,bits(cmd,0,3,1), 2);
383 fprintf(stdout, " ");
384 print_system_reg(10);
385 fprintf(stdout, " = %u", bits(cmd,5,0,8)); // ??
386 break;
387 case 3: // Mode: Counter / Register + Set
388 fprintf(stdout, "SetMode ");
389 if(bits(cmd,5,0,1))
390 fprintf(stdout, "Counter ");
391 else
392 fprintf(stdout, "Register ");
393 print_reg(bits(cmd,5,4,4));
394 print_set_op(0x1); // '='
395 print_reg_or_data(cmd,bits(cmd,0,3,1), 2);
396 break;
397 case 6: // Set system reg 8 (Highlighted button)
398 print_system_reg(8);
399 if(bits(cmd,0,3,1)) // immediate
400 fprintf(stdout, " = 0x%x (button no %u)",
401 bits(cmd,4,0,16), bits(cmd,4,0,6));
402 else
403 fprintf(stdout, " = g[%u]", bits(cmd,5,4,4));
404 break;
405 default:
406 fprintf(stdout, "WARNING: Unknown system set instruction (%u)",
407 bits(cmd,0,4,4));
411 static void print_set_version_1(cmd_t *cmd) {
412 unsigned int set_op = bits(cmd,0,4,4);
414 if(set_op) {
415 print_reg(bits(cmd,3,0,8));
416 print_set_op(set_op);
417 print_reg_or_data(cmd,bits(cmd,0,3,1), 4);
418 } else {
419 fprintf(stdout, "NOP");
423 static void print_set_version_2(cmd_t *cmd) {
424 unsigned int set_op = bits(cmd,0,4,4);
426 if(set_op) {
427 print_reg(bits(cmd,1,4,4));
428 print_set_op(set_op);
429 print_reg_or_data(cmd,bits(cmd,0,3,1), 2);
430 } else {
431 fprintf(stdout, "NOP");
435 static void print_set_version_3(cmd_t *cmd) {
436 unsigned int set_op = bits(cmd,0,4,4);
438 if(set_op) {
439 print_reg(bits(cmd,1,4,4));
440 print_set_op(set_op);
441 if(bits(cmd,0,3,1)) { // print_reg_or_data
442 unsigned int i = bits(cmd,2,0,16);
444 fprintf(stdout, "0x%x", i);
445 if(isprint(i & 0xff) && isprint((i>>8) & 0xff))
446 fprintf(stdout, " (\"%c%c\")",
447 (char)((i>>8) & 0xff), (char)(i & 0xff));
448 } else {
449 print_reg(bits(cmd,2,0,8));
451 } else {
452 fprintf(stdout, "NOP");
456 static void print_command(cmd_t *cmd) {
457 switch(bits(cmd,0,0,3)) { /* three first bits */
458 case 0: // Special instructions
459 print_if_version_1(cmd);
460 print_special_instruction(cmd);
461 break;
462 case 1: // Jump/Call or Link instructions
463 if(bits(cmd,0,3,1)) {
464 print_if_version_2(cmd);
465 print_jump_instruction(cmd);
466 } else {
467 print_if_version_1(cmd);
468 print_link_instruction(cmd,0); // must be pressent
470 break;
471 case 2: // Set System Parameters instructions
472 print_if_version_2(cmd);
473 print_system_set(cmd);
474 print_link_instruction(cmd,1); // either 'if' or 'link'
475 break;
476 case 3: // Set General Parameters instructions
477 print_if_version_3(cmd);
478 print_set_version_1(cmd);
479 print_link_instruction(cmd,1); // either 'if' or 'link'
480 break;
481 case 4: // Set, Compare -> LinkSub instructions
482 print_set_version_2(cmd);
483 fprintf(stdout, ", ");
484 print_if_version_4(cmd);
485 print_linksub_instruction(cmd);
486 break;
487 case 5: // Compare -> (Set and LinkSub) instructions
488 if(bits(cmd,0,3,1))
489 print_if_version_5(cmd);
490 else
491 print_if_version_1(cmd);
492 fprintf(stdout, "{ ");
493 print_set_version_3(cmd);
494 fprintf(stdout, ", ");
495 print_linksub_instruction(cmd);
496 fprintf(stdout, " }");
497 break;
498 case 6: // Compare -> Set, always LinkSub instructions
499 if(bits(cmd,0,3,1))
500 print_if_version_5(cmd);
501 else
502 print_if_version_1(cmd);
503 fprintf(stdout, "{ ");
504 print_set_version_3(cmd);
505 fprintf(stdout, " } ");
506 print_linksub_instruction(cmd);
507 break;
508 default:
509 fprintf(stdout, "WARNING: Unknown instruction type (%i)",
510 bits(cmd,0,0,3));
514 void cmdPrint_mnemonic(vm_cmd_t *command) {
515 int i, extra_bits;
516 cmd_t cmd;
518 for(i = 0; i < 8; i++) {
519 cmd.bits[i] = command->bytes[i];
520 cmd.examined[i] = 0;
523 print_command(&cmd);
525 // Check if there still are bits set that were not examined
526 extra_bits = 0;
527 for(i = 0; i < 8; i++)
528 if(cmd.bits[i] & ~ cmd.examined[i]) {
529 extra_bits = 1;
530 break;
532 if(extra_bits) {
533 fprintf(stdout, " [WARNING, unknown bits:");
534 for(i = 0; i < 8; i++)
535 fprintf(stdout, " %02x", cmd.bits[i] & ~ cmd.examined[i]);
536 fprintf(stdout, "]");
540 void cmdPrint_CMD(int row, vm_cmd_t *command) {
541 int i;
543 fprintf(stdout, "(%03d) ", row + 1);
544 for(i = 0; i < 8; i++)
545 fprintf(stdout, "%02x ", command->bytes[i]);
546 fprintf(stdout, "| ");
548 cmdPrint_mnemonic(command);
549 fprintf(stdout, "\n");