1 /* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
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
25 #if defined(HAVE_INTTYPES_H)
27 #elif defined(HAVE_STDINT_H)
31 #include "cmd_print.h"
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
,
56 static const char *system_reg_table
[] = {
57 "Menu Description Language Code",
58 "Audio Stream Number",
59 "Sub-picture Stream Number",
62 "VTS Title Track Number",
64 "PTT Number for One_Sequential_PGC_Title",
65 "Highlighted Button Number",
67 "Title PGC Number for Navigation Timer",
68 "Audio Mixing Mode for Karaoke",
69 "Country Code for Parental Management",
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",
83 static const char *system_reg_abbr_table
[] = {
112 static unsigned int bits(cmd_t
*cmd
, int byte
, int bit
, int count
) {
113 unsigned int val
= 0;
114 unsigned int bit_mask
;
121 bit_mask
= 0x01 << (7-bit
);
123 if((cmd
->bits
[byte
]) & bit_mask
)
125 cmd
->examined
[byte
] |= bit_mask
;
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
]);
136 fprintf(stdout
, " WARNING: Unknown system register ");
139 static void print_reg(unsigned int reg
) {
141 print_system_reg(reg
& 0x7f);
144 fprintf(stdout
, "g[%u]", reg
);
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
]);
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
]);
160 fprintf(stdout
, " WARNING: Unknown set op ");
163 static void print_reg_or_data(cmd_t
*cmd
, unsigned int immediate
, int byte
) {
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));
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
) {
177 fprintf(stdout
, "0x%x", bits(cmd
,byte
,1,7));
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);
186 fprintf(stdout
, "if (");
187 print_reg(bits(cmd
,3,0,8));
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);
198 fprintf(stdout
, "if (");
199 print_reg(bits(cmd
,6,0,8));
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);
210 fprintf(stdout
, "if (");
211 print_reg(bits(cmd
,2,0,8));
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);
222 fprintf(stdout
, "if (");
223 print_reg(bits(cmd
,1,4,4));
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);
234 fprintf(stdout
, "if (");
235 print_reg(bits(cmd
,4,0,8));
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);
247 fprintf(stdout
, "Nop");
250 fprintf(stdout
, "Goto %u", bits(cmd
,7,0,8));
253 fprintf(stdout
, "Break");
255 case 3: // Parental level
256 fprintf(stdout
, "SetTmpPML %u, Goto %u",
257 bits(cmd
,6,4,4), bits(cmd
,7,0,8));
260 fprintf(stdout
, "WARNING: Unknown special instruction (%u)",
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
);
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);
279 fprintf(stdout
, ", ");
284 fprintf(stdout
, "WARNING: NOP (link)!");
287 print_linksub_instruction(cmd
);
290 fprintf(stdout
, "LinkPGCN %u", bits(cmd
,6,1,15));
293 fprintf(stdout
, "LinkPTT %u (button %u)",
294 bits(cmd
,6,6,10), bits(cmd
,6,0,6));
297 fprintf(stdout
, "LinkPGN %u (button %u)",
298 bits(cmd
,7,1,7), bits(cmd
,6,0,6));
301 fprintf(stdout
, "LinkCN %u (button %u)",
302 bits(cmd
,7,0,8), bits(cmd
,6,0,6));
305 fprintf(stdout
, "WARNING: Unknown link instruction");
309 static void print_jump_instruction(cmd_t
*cmd
) {
310 switch(bits(cmd
,1,4,4)) {
312 fprintf(stdout
, "Exit");
315 fprintf(stdout
, "JumpTT %u", bits(cmd
,5,1,7));
318 fprintf(stdout
, "JumpVTS_TT %u", bits(cmd
,5,1,7));
321 fprintf(stdout
, "JumpVTS_PTT %u:%u", bits(cmd
,5,1,7), bits(cmd
,2,6,10));
324 switch(bits(cmd
,5,0,2)) {
326 fprintf(stdout
, "JumpSS FP");
329 fprintf(stdout
, "JumpSS VMGM (menu %u)", bits(cmd
,5,4,4));
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));
336 fprintf(stdout
, "JumpSS VMGM (pgc %u)", bits(cmd
,2,1,15));
341 switch(bits(cmd
,5,0,2)) {
343 fprintf(stdout
, "CallSS FP (rsm_cell %u)",
347 fprintf(stdout
, "CallSS VMGM (menu %u, rsm_cell %u)",
348 bits(cmd
,5,4,4), bits(cmd
,4,0,8));
351 fprintf(stdout
, "CallSS VTSM (menu %u, rsm_cell %u)",
352 bits(cmd
,5,4,4), bits(cmd
,4,0,8));
355 fprintf(stdout
, "CallSS VMGM (pgc %u, rsm_cell %u)",
356 bits(cmd
,2,1,15), bits(cmd
,4,0,8));
361 fprintf(stdout
, "WARNING: Unknown Jump/Call instruction");
365 static void print_system_set(cmd_t
*cmd
) {
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
, " ");
379 case 2: // Set system reg 9 & 10 (Navigation timer, Title PGC number)
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)); // ??
387 case 3: // Mode: Counter / Register + Set
388 fprintf(stdout
, "SetMode ");
390 fprintf(stdout
, "Counter ");
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);
397 case 6: // Set system reg 8 (Highlighted button)
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));
403 fprintf(stdout
, " = g[%u]", bits(cmd
,5,4,4));
406 fprintf(stdout
, "WARNING: Unknown system set instruction (%u)",
411 static void print_set_version_1(cmd_t
*cmd
) {
412 unsigned int set_op
= bits(cmd
,0,4,4);
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);
419 fprintf(stdout
, "NOP");
423 static void print_set_version_2(cmd_t
*cmd
) {
424 unsigned int set_op
= bits(cmd
,0,4,4);
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);
431 fprintf(stdout
, "NOP");
435 static void print_set_version_3(cmd_t
*cmd
) {
436 unsigned int set_op
= bits(cmd
,0,4,4);
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));
449 print_reg(bits(cmd
,2,0,8));
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
);
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
);
467 print_if_version_1(cmd
);
468 print_link_instruction(cmd
,0); // must be pressent
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'
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'
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
);
487 case 5: // Compare -> (Set and LinkSub) instructions
489 print_if_version_5(cmd
);
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
, " }");
498 case 6: // Compare -> Set, always LinkSub instructions
500 print_if_version_5(cmd
);
502 print_if_version_1(cmd
);
503 fprintf(stdout
, "{ ");
504 print_set_version_3(cmd
);
505 fprintf(stdout
, " } ");
506 print_linksub_instruction(cmd
);
509 fprintf(stdout
, "WARNING: Unknown instruction type (%i)",
514 void cmdPrint_mnemonic(vm_cmd_t
*command
) {
518 for(i
= 0; i
< 8; i
++) {
519 cmd
.bits
[i
] = command
->bytes
[i
];
525 // Check if there still are bits set that were not examined
527 for(i
= 0; i
< 8; i
++)
528 if(cmd
.bits
[i
] & ~ cmd
.examined
[i
]) {
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
) {
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");