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