00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027
00028 #include <stdio.h>
00029 #include <ctype.h>
00030 #include <inttypes.h>
00031
00032 #include "dvdnav_internal.h"
00033
00034
00035 #ifndef PRIu8
00036 #define PRIu8 "d"
00037 #endif
00038
00039
00040 #ifndef PRIu16
00041 #define PRIu16 "d"
00042 #endif
00043
00044 static const char *cmp_op_table[] = {
00045 NULL, "&", "==", "!=", ">=", ">", "<=", "<"
00046 };
00047 static const char *set_op_table[] = {
00048 NULL, "=", "<->", "+=", "-=", "*=", "/=", "%=", "rnd", "&=", "|=", "^="
00049 };
00050
00051 static const char *link_table[] = {
00052 "LinkNoLink", "LinkTopC", "LinkNextC", "LinkPrevC",
00053 NULL, "LinkTopPG", "LinkNextPG", "LinkPrevPG",
00054 NULL, "LinkTopPGC", "LinkNextPGC", "LinkPrevPGC",
00055 "LinkGoUpPGC", "LinkTailPGC", NULL, NULL,
00056 "RSM"
00057 };
00058
00059 static const char *system_reg_table[] = {
00060 "Menu Description Language Code",
00061 "Audio Stream Number",
00062 "Sub-picture Stream Number",
00063 "Angle Number",
00064 "Title Track Number",
00065 "VTS Title Track Number",
00066 "VTS PGC Number",
00067 "PTT Number for One_Sequential_PGC_Title",
00068 "Highlighted Button Number",
00069 "Navigation Timer",
00070 "Title PGC Number for Navigation Timer",
00071 "Audio Mixing Mode for Karaoke",
00072 "Country Code for Parental Management",
00073 "Parental Level",
00074 "Player Configurations for Video",
00075 "Player Configurations for Audio",
00076 "Initial Language Code for Audio",
00077 "Initial Language Code Extension for Audio",
00078 "Initial Language Code for Sub-picture",
00079 "Initial Language Code Extension for Sub-picture",
00080 "Player Regional Code",
00081 "Reserved 21",
00082 "Reserved 22",
00083 "Reserved 23"
00084 };
00085
00086 static const char *system_reg_abbr_table[] = {
00087 NULL,
00088 "ASTN",
00089 "SPSTN",
00090 "AGLN",
00091 "TTN",
00092 "VTS_TTN",
00093 "TT_PGCN",
00094 "PTTN",
00095 "HL_BTNN",
00096 "NVTMR",
00097 "NV_PGCN",
00098 NULL,
00099 "CC_PLT",
00100 "PLT",
00101 NULL,
00102 NULL,
00103 NULL,
00104 NULL,
00105 NULL,
00106 NULL,
00107 NULL,
00108 NULL,
00109 NULL,
00110 NULL,
00111 };
00112
00113 static void print_system_reg(uint16_t reg) {
00114 if(reg < sizeof(system_reg_abbr_table) / sizeof(char *))
00115 fprintf(MSG_OUT, "%s (SRPM:%d)", system_reg_table[reg], reg);
00116 else
00117 fprintf(MSG_OUT, " WARNING: Unknown system register ( reg=%d ) ", reg);
00118 }
00119
00120 static void print_g_reg(uint8_t reg) {
00121 if(reg < 16)
00122 fprintf(MSG_OUT, "g[%" PRIu8 "]", reg);
00123 else
00124 fprintf(MSG_OUT, " WARNING: Unknown general register ");
00125 }
00126
00127 static void print_reg(uint8_t reg) {
00128 if(reg & 0x80)
00129 print_system_reg(reg & 0x7f);
00130 else
00131 print_g_reg(reg & 0x7f);
00132 }
00133
00134 static void print_cmp_op(uint8_t op) {
00135 if(op < sizeof(cmp_op_table) / sizeof(char *) && cmp_op_table[op] != NULL)
00136 fprintf(MSG_OUT, " %s ", cmp_op_table[op]);
00137 else
00138 fprintf(MSG_OUT, " WARNING: Unknown compare op ");
00139 }
00140
00141 static void print_set_op(uint8_t op) {
00142 if(op < sizeof(set_op_table) / sizeof(char *) && set_op_table[op] != NULL)
00143 fprintf(MSG_OUT, " %s ", set_op_table[op]);
00144 else
00145 fprintf(MSG_OUT, " WARNING: Unknown set op ");
00146 }
00147
00148 static void print_reg_or_data(command_t* command, int immediate, int start) {
00149 if(immediate) {
00150 uint32_t i = vm_getbits(command, start, 16);
00151
00152 fprintf(MSG_OUT, "0x%x", i);
00153 if(isprint(i & 0xff) && isprint((i>>8) & 0xff))
00154 fprintf(MSG_OUT, " (\"%c%c\")", (char)((i>>8) & 0xff), (char)(i & 0xff));
00155 } else {
00156 print_reg(vm_getbits(command, start - 8, 8));
00157 }
00158 }
00159
00160 static void print_reg_or_data_2(command_t* command, int immediate, int start) {
00161 if(immediate)
00162 fprintf(MSG_OUT, "0x%x", vm_getbits(command, start - 1, 7));
00163 else
00164 fprintf(MSG_OUT, "g[%" PRIu8 "]", vm_getbits(command, start - 4, 4));
00165 }
00166
00167 static void print_reg_or_data_3(command_t* command, int immediate, int start) {
00168 if(immediate) {
00169 uint32_t i = vm_getbits(command, start, 16);
00170
00171 fprintf(MSG_OUT, "0x%x", i);
00172 if(isprint(i & 0xff) && isprint((i>>8) & 0xff))
00173 fprintf(MSG_OUT, " (\"%c%c\")", (char)((i>>8) & 0xff), (char)(i & 0xff));
00174 } else {
00175 print_reg(vm_getbits(command, start, 8));
00176 }
00177 }
00178
00179
00180 static void print_if_version_1(command_t* command) {
00181 uint8_t op = vm_getbits(command, 54, 3);
00182
00183 if(op) {
00184 fprintf(MSG_OUT, "if (");
00185 print_g_reg(vm_getbits(command,39,8));
00186 print_cmp_op(op);
00187 print_reg_or_data(command, vm_getbits(command, 55,1), 31);
00188 fprintf(MSG_OUT, ") ");
00189 }
00190 }
00191
00192 static void print_if_version_2(command_t* command) {
00193 uint8_t op = vm_getbits(command, 54, 3);
00194
00195 if(op) {
00196 fprintf(MSG_OUT, "if (");
00197 print_reg(vm_getbits(command, 15, 8));
00198 print_cmp_op(op);
00199 print_reg(vm_getbits(command, 7, 8));
00200 fprintf(MSG_OUT, ") ");
00201 }
00202 }
00203
00204 static void print_if_version_3(command_t* command) {
00205 uint8_t op = vm_getbits(command, 54, 3);
00206
00207 if(op) {
00208 fprintf(MSG_OUT, "if (");
00209 print_g_reg(vm_getbits(command, 43, 4));
00210 print_cmp_op(op);
00211 print_reg_or_data(command, vm_getbits(command, 55, 1), 15);
00212 fprintf(MSG_OUT, ") ");
00213 }
00214 }
00215
00216 static void print_if_version_4(command_t* command) {
00217 uint8_t op = vm_getbits(command, 54, 3);
00218
00219 if(op) {
00220 fprintf(MSG_OUT, "if (");
00221 print_g_reg(vm_getbits(command, 51, 4));
00222 print_cmp_op(op);
00223 print_reg_or_data(command, vm_getbits(command, 55, 1), 31);
00224 fprintf(MSG_OUT, ") ");
00225 }
00226 }
00227
00228 static void print_if_version_5(command_t* command) {
00229 uint8_t op = vm_getbits(command, 54, 3);
00230 int set_immediate = vm_getbits(command, 60, 1);
00231
00232 if(op) {
00233 if (set_immediate) {
00234 fprintf(MSG_OUT, "if (");
00235 print_g_reg(vm_getbits(command, 31, 8));
00236 print_cmp_op(op);
00237 print_reg(vm_getbits(command, 23, 8));
00238 fprintf(MSG_OUT, ") ");
00239 } else {
00240 fprintf(MSG_OUT, "if (");
00241 print_g_reg(vm_getbits(command, 39, 8));
00242 print_cmp_op(op);
00243 print_reg_or_data(command, vm_getbits(command, 55, 1), 31);
00244 fprintf(MSG_OUT, ") ");
00245 }
00246 }
00247 }
00248
00249 static void print_special_instruction(command_t* command) {
00250 uint8_t op = vm_getbits(command, 51, 4);
00251
00252 switch(op) {
00253 case 0:
00254 fprintf(MSG_OUT, "Nop");
00255 break;
00256 case 1:
00257 fprintf(MSG_OUT, "Goto %" PRIu8, vm_getbits(command, 7, 8));
00258 break;
00259 case 2:
00260 fprintf(MSG_OUT, "Break");
00261 break;
00262 case 3:
00263 fprintf(MSG_OUT, "SetTmpPML %" PRIu8 ", Goto %" PRIu8,
00264 vm_getbits(command, 11, 4), vm_getbits(command, 7, 8));
00265 break;
00266 default:
00267 fprintf(MSG_OUT, "WARNING: Unknown special instruction (%i)",
00268 vm_getbits(command, 51, 4));
00269 }
00270 }
00271
00272 static void print_linksub_instruction(command_t* command) {
00273 uint32_t linkop = vm_getbits(command, 7, 8);
00274 uint32_t button = vm_getbits(command, 15, 6);
00275
00276 if(linkop < sizeof(link_table)/sizeof(char *) && link_table[linkop] != NULL)
00277 fprintf(MSG_OUT, "%s (button %" PRIu8 ")", link_table[linkop], button);
00278 else
00279 fprintf(MSG_OUT, "WARNING: Unknown linksub instruction (%i)", linkop);
00280 }
00281
00282 static void print_link_instruction(command_t* command, int optional) {
00283 uint8_t op = vm_getbits(command, 51, 4);
00284
00285 if(optional && op)
00286 fprintf(MSG_OUT, ", ");
00287
00288 switch(op) {
00289 case 0:
00290 if(!optional)
00291 fprintf(MSG_OUT, "WARNING: NOP (link)!");
00292 break;
00293 case 1:
00294 print_linksub_instruction(command);
00295 break;
00296 case 4:
00297 fprintf(MSG_OUT, "LinkPGCN %" PRIu16, vm_getbits(command, 14, 15));
00298 break;
00299 case 5:
00300 fprintf(MSG_OUT, "LinkPTT %" PRIu16 " (button %" PRIu8 ")",
00301 vm_getbits(command, 9, 10), vm_getbits(command, 15, 6));
00302 break;
00303 case 6:
00304 fprintf(MSG_OUT, "LinkPGN %" PRIu8 " (button %" PRIu8 ")",
00305 vm_getbits(command, 6, 7), vm_getbits(command, 15, 6));
00306 break;
00307 case 7:
00308 fprintf(MSG_OUT, "LinkCN %" PRIu8 " (button %" PRIu8 ")",
00309 vm_getbits(command, 7, 8), vm_getbits(command, 15, 6));
00310 break;
00311 default:
00312 fprintf(MSG_OUT, "WARNING: Unknown link instruction");
00313 }
00314 }
00315
00316 static void print_jump_instruction(command_t* command) {
00317 switch(vm_getbits(command, 51, 4)) {
00318 case 1:
00319 fprintf(MSG_OUT, "Exit");
00320 break;
00321 case 2:
00322 fprintf(MSG_OUT, "JumpTT %" PRIu8, vm_getbits(command, 22, 7));
00323 break;
00324 case 3:
00325 fprintf(MSG_OUT, "JumpVTS_TT %" PRIu8, vm_getbits(command, 22, 7));
00326 break;
00327 case 5:
00328 fprintf(MSG_OUT, "JumpVTS_PTT %" PRIu8 ":%" PRIu16,
00329 vm_getbits(command, 22, 7), vm_getbits(command, 41, 10));
00330 break;
00331 case 6:
00332 switch(vm_getbits(command, 23, 2)) {
00333 case 0:
00334 fprintf(MSG_OUT, "JumpSS FP");
00335 break;
00336 case 1:
00337 fprintf(MSG_OUT, "JumpSS VMGM (menu %" PRIu8 ")", vm_getbits(command, 19, 4));
00338 break;
00339 case 2:
00340 fprintf(MSG_OUT, "JumpSS VTSM (vts %" PRIu8 ", title %" PRIu8
00341 ", menu %" PRIu8 ")", vm_getbits(command, 30, 7), vm_getbits(command, 38, 7), vm_getbits(command, 19, 4));
00342 break;
00343 case 3:
00344 fprintf(MSG_OUT, "JumpSS VMGM (pgc %" PRIu8 ")", vm_getbits(command, 46, 15));
00345 break;
00346 }
00347 break;
00348 case 8:
00349 switch(vm_getbits(command, 23, 2)) {
00350 case 0:
00351 fprintf(MSG_OUT, "CallSS FP (rsm_cell %" PRIu8 ")",
00352 vm_getbits(command, 31, 8));
00353 break;
00354 case 1:
00355 fprintf(MSG_OUT, "CallSS VMGM (menu %" PRIu8
00356 ", rsm_cell %" PRIu8 ")", vm_getbits(command, 19, 4), vm_getbits(command, 31, 8));
00357 break;
00358 case 2:
00359 fprintf(MSG_OUT, "CallSS VTSM (menu %" PRIu8
00360 ", rsm_cell %" PRIu8 ")", vm_getbits(command, 19, 4), vm_getbits(command, 31, 8));
00361 break;
00362 case 3:
00363 fprintf(MSG_OUT, "CallSS VMGM (pgc %" PRIu8 ", rsm_cell %" PRIu8 ")",
00364 vm_getbits(command, 46, 15), vm_getbits(command, 31, 8));
00365 break;
00366 }
00367 break;
00368 default:
00369 fprintf(MSG_OUT, "WARNING: Unknown Jump/Call instruction");
00370 }
00371 }
00372
00373 static void print_system_set(command_t* command) {
00374 int i;
00375
00376
00377
00378 switch(vm_getbits(command, 59, 4)) {
00379 case 1:
00380 for(i = 1; i <= 3; i++) {
00381 if(vm_getbits(command, 47 - (i*8), 1)) {
00382 print_system_reg(i);
00383 fprintf(MSG_OUT, " = ");
00384 print_reg_or_data_2(command, vm_getbits(command, 60, 1), 47 - (i*8) );
00385 fprintf(MSG_OUT, " ");
00386 }
00387 }
00388 break;
00389 case 2:
00390 print_system_reg(9);
00391 fprintf(MSG_OUT, " = ");
00392 print_reg_or_data(command, vm_getbits(command, 60, 1), 47);
00393 fprintf(MSG_OUT, " ");
00394 print_system_reg(10);
00395 fprintf(MSG_OUT, " = %" PRIu16, vm_getbits(command, 30, 15));
00396 break;
00397 case 3:
00398 fprintf(MSG_OUT, "SetMode ");
00399 if(vm_getbits(command, 23, 1))
00400 fprintf(MSG_OUT, "Counter ");
00401 else
00402 fprintf(MSG_OUT, "Register ");
00403 print_g_reg(vm_getbits(command, 19, 4));
00404 print_set_op(0x1);
00405 print_reg_or_data(command, vm_getbits(command, 60, 1), 47);
00406 break;
00407 case 6:
00408 print_system_reg(8);
00409 if(vm_getbits(command, 60, 1))
00410 fprintf(MSG_OUT, " = 0x%x (button no %d)", vm_getbits(command, 31, 16), vm_getbits(command, 31, 6));
00411 else
00412 fprintf(MSG_OUT, " = g[%" PRIu8 "]", vm_getbits(command, 19, 4));
00413 break;
00414 default:
00415 fprintf(MSG_OUT, "WARNING: Unknown system set instruction (%i)",
00416 vm_getbits(command, 59, 4));
00417 }
00418 }
00419
00420 static void print_set_version_1(command_t* command) {
00421 uint8_t set_op = vm_getbits(command, 59, 4);
00422
00423 if(set_op) {
00424 print_g_reg(vm_getbits(command, 35, 4));
00425 print_set_op(set_op);
00426 print_reg_or_data(command, vm_getbits(command, 60, 1), 31);
00427 } else {
00428 fprintf(MSG_OUT, "NOP");
00429 }
00430 }
00431
00432 static void print_set_version_2(command_t* command) {
00433 uint8_t set_op = vm_getbits(command, 59, 4);
00434
00435 if(set_op) {
00436 print_g_reg(vm_getbits(command, 51, 4));
00437 print_set_op(set_op);
00438 print_reg_or_data(command, vm_getbits(command, 60, 1), 47);
00439 } else {
00440 fprintf(MSG_OUT, "NOP");
00441 }
00442 }
00443
00444 static void print_set_version_3(command_t* command) {
00445 uint8_t set_op = vm_getbits(command, 59, 4);
00446
00447 if(set_op) {
00448 print_g_reg(vm_getbits(command, 51, 4));
00449 print_set_op(set_op);
00450 print_reg_or_data_3(command, vm_getbits(command, 60, 1), 47);
00451 } else {
00452 fprintf(MSG_OUT, "NOP");
00453 }
00454 }
00455
00456
00457 void vm_print_mnemonic(vm_cmd_t *vm_command) {
00458 command_t command;
00459 command.instruction =( (uint64_t) vm_command->bytes[0] << 56 ) |
00460 ( (uint64_t) vm_command->bytes[1] << 48 ) |
00461 ( (uint64_t) vm_command->bytes[2] << 40 ) |
00462 ( (uint64_t) vm_command->bytes[3] << 32 ) |
00463 ( (uint64_t) vm_command->bytes[4] << 24 ) |
00464 ( (uint64_t) vm_command->bytes[5] << 16 ) |
00465 ( (uint64_t) vm_command->bytes[6] << 8 ) |
00466 (uint64_t) vm_command->bytes[7] ;
00467 command.examined = 0;
00468
00469 switch(vm_getbits(&command,63,3)) {
00470 case 0:
00471 print_if_version_1(&command);
00472 print_special_instruction(&command);
00473 break;
00474 case 1:
00475 if(vm_getbits(&command,60,1)) {
00476 print_if_version_2(&command);
00477 print_jump_instruction(&command);
00478 } else {
00479 print_if_version_1(&command);
00480 print_link_instruction(&command, 0);
00481 }
00482 break;
00483 case 2:
00484 print_if_version_2(&command);
00485 print_system_set(&command);
00486 print_link_instruction(&command, 1);
00487 break;
00488 case 3:
00489 print_if_version_3(&command);
00490 print_set_version_1(&command);
00491 print_link_instruction(&command, 1);
00492 break;
00493 case 4:
00494 print_set_version_2(&command);
00495 fprintf(MSG_OUT, ", ");
00496 print_if_version_4(&command);
00497 print_linksub_instruction(&command);
00498 break;
00499 case 5:
00500 print_if_version_5(&command);
00501 fprintf(MSG_OUT, "{ ");
00502 print_set_version_3(&command);
00503 fprintf(MSG_OUT, ", ");
00504 print_linksub_instruction(&command);
00505 fprintf(MSG_OUT, " }");
00506 break;
00507 case 6:
00508 print_if_version_5(&command);
00509 fprintf(MSG_OUT, "{ ");
00510 print_set_version_3(&command);
00511 fprintf(MSG_OUT, " } ");
00512 print_linksub_instruction(&command);
00513 break;
00514 default:
00515 fprintf(MSG_OUT, "WARNING: Unknown instruction type (%i)", vm_getbits(&command, 63, 3));
00516 }
00517
00518
00519 if(command.instruction & ~ command.examined) {
00520 fprintf(MSG_OUT, " libdvdnav: vmcmd.c: [WARNING, unknown bits:");
00521 fprintf(MSG_OUT, " %08llx", (command.instruction & ~ command.examined) );
00522 fprintf(MSG_OUT, "]");
00523 }
00524 }
00525
00526 void vm_print_cmd(int row, vm_cmd_t *vm_command) {
00527 int i;
00528
00529 fprintf(MSG_OUT, "(%03d) ", row + 1);
00530 for(i = 0; i < 8; i++)
00531 fprintf(MSG_OUT, "%02x ", vm_command->bytes[i]);
00532 fprintf(MSG_OUT, "| ");
00533
00534 vm_print_mnemonic(vm_command);
00535 fprintf(MSG_OUT, "\n");
00536 }
00537