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 <stdlib.h>
00030 #include <inttypes.h>
00031 #include <string.h>
00032 #include "ifo_types.h"
00033
00034 #include "dvdnav_internal.h"
00035
00036 uint32_t vm_getbits(command_t *command, int32_t start, int32_t count) {
00037 uint64_t result = 0;
00038 uint64_t bit_mask = 0;
00039 uint64_t examining = 0;
00040 int32_t bits;
00041
00042 if (count == 0) return 0;
00043
00044 if ( ((start - count) < -1) ||
00045 (count > 32) ||
00046 (start > 63) ||
00047 (count < 0) ||
00048 (start < 0) ) {
00049 fprintf(MSG_OUT, "libdvdnav: Bad call to vm_getbits. Parameter out of range\n");
00050 abort();
00051 }
00052
00053 bit_mask = ~bit_mask;
00054 bit_mask >>= 63 - start;
00055 bits = start + 1 - count;
00056 examining = ((bit_mask >> bits) << bits );
00057 command->examined |= examining;
00058 result = (command->instruction & bit_mask) >> bits;
00059 return (uint32_t) result;
00060 }
00061
00062 static uint16_t get_GPRM(registers_t* registers, uint8_t reg) {
00063 if (registers->GPRM_mode[reg] & 0x01) {
00064 struct timeval current_time, time_offset;
00065 uint16_t result;
00066
00067
00068 gettimeofday(¤t_time, NULL);
00069 time_offset.tv_sec = current_time.tv_sec - registers->GPRM_time[reg].tv_sec;
00070 time_offset.tv_usec = current_time.tv_usec - registers->GPRM_time[reg].tv_usec;
00071 if (time_offset.tv_usec < 0) {
00072 time_offset.tv_sec--;
00073 time_offset.tv_usec += 1000000;
00074 }
00075 result = (uint16_t) (time_offset.tv_sec & 0xffff);
00076 registers->GPRM[reg]=result;
00077 return result;
00078
00079 } else {
00080
00081 return registers->GPRM[reg];
00082 }
00083
00084 }
00085
00086 static void set_GPRM(registers_t* registers, uint8_t reg, uint16_t value) {
00087 if (registers->GPRM_mode[reg] & 0x01) {
00088 struct timeval current_time;
00089
00090
00091 gettimeofday(¤t_time, NULL);
00092 registers->GPRM_time[reg] = current_time;
00093 registers->GPRM_time[reg].tv_sec -= value;
00094 }
00095 registers->GPRM[reg] = value;
00096 }
00097
00098
00099
00100 static uint16_t eval_reg(command_t* command, uint8_t reg) {
00101 if(reg & 0x80) {
00102 if ((reg & 0x1f) == 20) {
00103 fprintf(MSG_OUT, "libdvdnav: Suspected RCE Region Protection!!!\n");
00104 }
00105 return command->registers->SPRM[reg & 0x1f];
00106 } else {
00107 return get_GPRM(command->registers, reg & 0x0f) ;
00108 }
00109 }
00110
00111
00112
00113
00114 static uint16_t eval_reg_or_data(command_t* command, int32_t imm, int32_t start) {
00115 if(imm) {
00116 return vm_getbits(command, start, 16);
00117 } else {
00118 return eval_reg(command, vm_getbits(command, (start - 8), 8));
00119 }
00120 }
00121
00122
00123
00124
00125
00126 static uint16_t eval_reg_or_data_2(command_t* command,
00127 int32_t imm, int32_t start) {
00128 if(imm)
00129 return vm_getbits(command, (start - 1), 7);
00130 else
00131 return get_GPRM(command->registers, (vm_getbits(command, (start - 4), 4)) );
00132 }
00133
00134
00135
00136
00137 static int32_t eval_compare(uint8_t operation, uint16_t data1, uint16_t data2) {
00138 switch(operation) {
00139 case 1:
00140 return data1 & data2;
00141 case 2:
00142 return data1 == data2;
00143 case 3:
00144 return data1 != data2;
00145 case 4:
00146 return data1 >= data2;
00147 case 5:
00148 return data1 > data2;
00149 case 6:
00150 return data1 <= data2;
00151 case 7:
00152 return data1 < data2;
00153 }
00154 fprintf(MSG_OUT, "libdvdnav: eval_compare: Invalid comparison code\n");
00155 return 0;
00156 }
00157
00158
00159
00160
00161 static int32_t eval_if_version_1(command_t* command) {
00162 uint8_t op = vm_getbits(command, 54, 3);
00163 if(op) {
00164 return eval_compare(op, eval_reg(command, vm_getbits(command, 39, 8)),
00165 eval_reg_or_data(command, vm_getbits(command, 55, 1), 31));
00166 }
00167 return 1;
00168 }
00169
00170
00171
00172 static int32_t eval_if_version_2(command_t* command) {
00173 uint8_t op = vm_getbits(command, 54, 3);
00174 if(op) {
00175 return eval_compare(op, eval_reg(command, vm_getbits(command, 15, 8)),
00176 eval_reg(command, vm_getbits(command, 7, 8)));
00177 }
00178 return 1;
00179 }
00180
00181
00182
00183 static int32_t eval_if_version_3(command_t* command) {
00184 uint8_t op = vm_getbits(command, 54, 3);
00185 if(op) {
00186 return eval_compare(op, eval_reg(command, vm_getbits(command, 47, 8)),
00187 eval_reg_or_data(command, vm_getbits(command, 55, 1), 15));
00188 }
00189 return 1;
00190 }
00191
00192
00193
00194
00195 static int32_t eval_if_version_4(command_t* command) {
00196 uint8_t op = vm_getbits(command, 54, 3);
00197 if(op) {
00198 return eval_compare(op, eval_reg(command, vm_getbits(command, 51, 4)),
00199 eval_reg_or_data(command, vm_getbits(command, 55, 1), 31));
00200 }
00201 return 1;
00202 }
00203
00204
00205
00206 static int32_t eval_special_instruction(command_t* command, int32_t cond) {
00207 int32_t line, level;
00208
00209 switch(vm_getbits(command, 51, 4)) {
00210 case 0:
00211 line = 0;
00212 return cond ? line : 0;
00213 case 1:
00214 line = vm_getbits(command, 7, 8);
00215 return cond ? line : 0;
00216 case 2:
00217
00218 line = 256;
00219 return cond ? 256 : 0;
00220 case 3:
00221 line = vm_getbits(command, 7, 8);
00222 level = vm_getbits(command, 11, 4);
00223 if(cond) {
00224
00225
00226 command->registers->SPRM[13] = level;
00227 }
00228 return cond ? line : 0;
00229 }
00230 return 0;
00231 }
00232
00233
00234
00235
00236 static int32_t eval_link_subins(command_t* command, int32_t cond, link_t *return_values) {
00237 uint16_t button = vm_getbits(command, 15, 6);
00238 uint8_t linkop = vm_getbits(command, 4, 5);
00239
00240 if(linkop > 0x10)
00241 return 0;
00242
00243
00244 return_values->command = linkop;
00245 return_values->data1 = button;
00246 return cond;
00247 }
00248
00249
00250
00251
00252
00253 static int32_t eval_link_instruction(command_t* command, int32_t cond, link_t *return_values) {
00254 uint8_t op = vm_getbits(command, 51, 4);
00255
00256 switch(op) {
00257 case 1:
00258 return eval_link_subins(command, cond, return_values);
00259 case 4:
00260 return_values->command = LinkPGCN;
00261 return_values->data1 = vm_getbits(command, 14, 15);
00262 return cond;
00263 case 5:
00264 return_values->command = LinkPTTN;
00265 return_values->data1 = vm_getbits(command, 9, 10);
00266 return_values->data2 = vm_getbits(command, 15, 6);
00267 return cond;
00268 case 6:
00269 return_values->command = LinkPGN;
00270 return_values->data1 = vm_getbits(command, 6, 7);
00271 return_values->data2 = vm_getbits(command, 15, 6);
00272 return cond;
00273 case 7:
00274 return_values->command = LinkCN;
00275 return_values->data1 = vm_getbits(command, 7, 8);
00276 return_values->data2 = vm_getbits(command, 15, 6);
00277 return cond;
00278 }
00279 return 0;
00280 }
00281
00282
00283
00284
00285
00286 static int32_t eval_jump_instruction(command_t* command, int32_t cond, link_t *return_values) {
00287
00288 switch(vm_getbits(command, 51, 4)) {
00289 case 1:
00290 return_values->command = Exit;
00291 return cond;
00292 case 2:
00293 return_values->command = JumpTT;
00294 return_values->data1 = vm_getbits(command, 22, 7);
00295 return cond;
00296 case 3:
00297 return_values->command = JumpVTS_TT;
00298 return_values->data1 = vm_getbits(command, 22, 7);
00299 return cond;
00300 case 5:
00301 return_values->command = JumpVTS_PTT;
00302 return_values->data1 = vm_getbits(command, 22, 7);
00303 return_values->data2 = vm_getbits(command, 41, 10);
00304 return cond;
00305 case 6:
00306 switch(vm_getbits(command, 23, 2)) {
00307 case 0:
00308 return_values->command = JumpSS_FP;
00309 return cond;
00310 case 1:
00311 return_values->command = JumpSS_VMGM_MENU;
00312 return_values->data1 = vm_getbits(command, 19, 4);
00313 return cond;
00314 case 2:
00315 return_values->command = JumpSS_VTSM;
00316 return_values->data1 = vm_getbits(command, 31, 8);
00317 return_values->data2 = vm_getbits(command, 39, 8);
00318 return_values->data3 = vm_getbits(command, 19, 4);
00319 return cond;
00320 case 3:
00321 return_values->command = JumpSS_VMGM_PGC;
00322 return_values->data1 = vm_getbits(command, 46, 15);
00323 return cond;
00324 }
00325 break;
00326 case 8:
00327 switch(vm_getbits(command, 23, 2)) {
00328 case 0:
00329 return_values->command = CallSS_FP;
00330 return_values->data1 = vm_getbits(command, 31, 8);
00331 return cond;
00332 case 1:
00333 return_values->command = CallSS_VMGM_MENU;
00334 return_values->data1 = vm_getbits(command, 19, 4);
00335 return_values->data2 = vm_getbits(command, 31, 8);
00336 return cond;
00337 case 2:
00338 return_values->command = CallSS_VTSM;
00339 return_values->data1 = vm_getbits(command, 19, 4);
00340 return_values->data2 = vm_getbits(command, 31, 8);
00341 return cond;
00342 case 3:
00343 return_values->command = CallSS_VMGM_PGC;
00344 return_values->data1 = vm_getbits(command, 46, 15);
00345 return_values->data2 = vm_getbits(command, 31, 8);
00346 return cond;
00347 }
00348 break;
00349 }
00350 return 0;
00351 }
00352
00353
00354
00355 static int32_t eval_system_set(command_t* command, int32_t cond, link_t *return_values) {
00356 int32_t i;
00357 uint16_t data, data2;
00358
00359 switch(vm_getbits(command, 59, 4)) {
00360 case 1:
00361 for(i = 1; i <= 3; i++) {
00362 if(vm_getbits(command, 63 - ((2 + i)*8), 1)) {
00363 data = eval_reg_or_data_2(command, vm_getbits(command, 60, 1), (47 - (i*8)));
00364 if(cond) {
00365 command->registers->SPRM[i] = data;
00366 }
00367 }
00368 }
00369 break;
00370 case 2:
00371 data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 47);
00372 data2 = vm_getbits(command, 23, 8);
00373 if(cond) {
00374 command->registers->SPRM[9] = data;
00375 command->registers->SPRM[10] = data2;
00376 }
00377 break;
00378 case 3:
00379 data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 47);
00380 data2 = vm_getbits(command, 19, 4);
00381 if(vm_getbits(command, 23, 1)) {
00382 command->registers->GPRM_mode[data2] |= 1;
00383 } else {
00384 command->registers->GPRM_mode[data2] &= ~ 0x01;
00385 }
00386 if(cond) {
00387 set_GPRM(command->registers, data2, data);
00388 }
00389 break;
00390 case 6:
00391 data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 31);
00392 if(cond) {
00393 command->registers->SPRM[8] = data;
00394 }
00395 break;
00396 }
00397 if(vm_getbits(command, 51, 4)) {
00398 return eval_link_instruction(command, cond, return_values);
00399 }
00400 return 0;
00401 }
00402
00403
00404
00405
00406
00407
00408 static void eval_set_op(command_t* command, int32_t op, int32_t reg, int32_t reg2, int32_t data) {
00409 const int32_t shortmax = 0xffff;
00410 int32_t tmp;
00411 switch(op) {
00412 case 1:
00413 set_GPRM(command->registers, reg, data);
00414 break;
00415 case 2:
00416 set_GPRM(command->registers, reg2, get_GPRM(command->registers, reg));
00417 set_GPRM(command->registers, reg, data);
00418 break;
00419 case 3:
00420 tmp = get_GPRM(command->registers, reg) + data;
00421 if(tmp > shortmax) tmp = shortmax;
00422 set_GPRM(command->registers, reg, (uint16_t)tmp);
00423 break;
00424 case 4:
00425 tmp = get_GPRM(command->registers, reg) - data;
00426 if(tmp < 0) tmp = 0;
00427 set_GPRM(command->registers, reg, (uint16_t)tmp);
00428 break;
00429 case 5:
00430 tmp = get_GPRM(command->registers, reg) * data;
00431 if(tmp > shortmax) tmp = shortmax;
00432 set_GPRM(command->registers, reg, (uint16_t)tmp);
00433 break;
00434 case 6:
00435 if (data != 0) {
00436 set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) / data) );
00437 } else {
00438 set_GPRM(command->registers, reg, 0xffff);
00439 }
00440 break;
00441 case 7:
00442 if (data != 0) {
00443 set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) % data) );
00444 } else {
00445 set_GPRM(command->registers, reg, 0xffff);
00446 }
00447 break;
00448 case 8:
00449 set_GPRM(command->registers, reg, 1 + ((uint16_t) ((float) data * rand()/(RAND_MAX+1.0))) );
00450 break;
00451 case 9:
00452 set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) & data) );
00453 break;
00454 case 10:
00455 set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) | data) );
00456 break;
00457 case 11:
00458 set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) ^ data) );
00459 break;
00460 }
00461 }
00462
00463
00464 static void eval_set_version_1(command_t* command, int32_t cond) {
00465 uint8_t op = vm_getbits(command, 59, 4);
00466 uint8_t reg = vm_getbits(command, 35, 4);
00467 uint8_t reg2 = vm_getbits(command, 19, 4);
00468 uint16_t data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 31);
00469
00470 if(cond) {
00471 eval_set_op(command, op, reg, reg2, data);
00472 }
00473 }
00474
00475
00476
00477 static void eval_set_version_2(command_t* command, int32_t cond) {
00478 uint8_t op = vm_getbits(command, 59, 4);
00479 uint8_t reg = vm_getbits(command, 51, 4);
00480 uint8_t reg2 = vm_getbits(command, 35, 4);
00481 uint16_t data = eval_reg_or_data(command, vm_getbits(command, 60, 1), 47);
00482
00483 if(cond) {
00484 eval_set_op(command, op, reg, reg2, data);
00485 }
00486 }
00487
00488
00489
00490
00491
00492 static int32_t eval_command(uint8_t *bytes, registers_t* registers, link_t *return_values) {
00493 int32_t cond, res = 0;
00494 command_t command;
00495 command.instruction =( (uint64_t) bytes[0] << 56 ) |
00496 ( (uint64_t) bytes[1] << 48 ) |
00497 ( (uint64_t) bytes[2] << 40 ) |
00498 ( (uint64_t) bytes[3] << 32 ) |
00499 ( (uint64_t) bytes[4] << 24 ) |
00500 ( (uint64_t) bytes[5] << 16 ) |
00501 ( (uint64_t) bytes[6] << 8 ) |
00502 (uint64_t) bytes[7] ;
00503 command.examined = 0;
00504 command.registers = registers;
00505 memset(return_values, 0, sizeof(link_t));
00506
00507 switch(vm_getbits(&command, 63, 3)) {
00508 case 0:
00509 cond = eval_if_version_1(&command);
00510 res = eval_special_instruction(&command, cond);
00511 if(res == -1) {
00512 fprintf(MSG_OUT, "libdvdnav: Unknown Instruction!\n");
00513 abort();
00514 }
00515 break;
00516 case 1:
00517 if(vm_getbits(&command, 60, 1)) {
00518 cond = eval_if_version_2(&command);
00519 res = eval_jump_instruction(&command, cond, return_values);
00520 } else {
00521 cond = eval_if_version_1(&command);
00522 res = eval_link_instruction(&command, cond, return_values);
00523 }
00524 if(res)
00525 res = -1;
00526 break;
00527 case 2:
00528 cond = eval_if_version_2(&command);
00529 res = eval_system_set(&command, cond, return_values);
00530 if(res)
00531 res = -1;
00532 break;
00533 case 3:
00534 cond = eval_if_version_3(&command);
00535 eval_set_version_1(&command, cond);
00536 if(vm_getbits(&command, 51, 4)) {
00537 res = eval_link_instruction(&command, cond, return_values);
00538 }
00539 if(res)
00540 res = -1;
00541 break;
00542 case 4:
00543 eval_set_version_2(&command, 1);
00544 cond = eval_if_version_4(&command);
00545 res = eval_link_subins(&command, cond, return_values);
00546 if(res)
00547 res = -1;
00548 break;
00549 case 5:
00550
00551 cond = eval_if_version_4(&command);
00552 eval_set_version_2(&command, cond);
00553 res = eval_link_subins(&command, cond, return_values);
00554 if(res)
00555 res = -1;
00556 break;
00557 case 6:
00558
00559 cond = eval_if_version_4(&command);
00560 eval_set_version_2(&command, cond);
00561 res = eval_link_subins(&command, 1, return_values);
00562 if(res)
00563 res = -1;
00564 break;
00565 default:
00566 fprintf(MSG_OUT, "libdvdnav: WARNING: Unknown Command=%x\n", vm_getbits(&command, 63, 3));
00567 abort();
00568 }
00569
00570
00571 if(command.instruction & ~ command.examined) {
00572 fprintf(MSG_OUT, "libdvdnav: decoder.c: [WARNING, unknown bits:");
00573 fprintf(MSG_OUT, " %08llx", (command.instruction & ~ command.examined) );
00574 fprintf(MSG_OUT, "]\n");
00575 }
00576
00577 return res;
00578 }
00579
00580
00581 int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands,
00582 registers_t *registers, link_t *return_values) {
00583 int32_t i = 0;
00584 int32_t total = 0;
00585
00586 #ifdef TRACE
00587
00588 fprintf(MSG_OUT, "libdvdnav: Registers before transaction\n");
00589 vm_print_registers( registers );
00590 fprintf(MSG_OUT, "libdvdnav: Full list of commands to execute\n");
00591 for(i = 0; i < num_commands; i++)
00592 vm_print_cmd(i, &commands[i]);
00593 fprintf(MSG_OUT, "libdvdnav: --------------------------------------------\n");
00594 fprintf(MSG_OUT, "libdvdnav: Single stepping commands\n");
00595 #endif
00596
00597 i = 0;
00598 while(i < num_commands && total < 100000) {
00599 int32_t line;
00600
00601 #ifdef TRACE
00602 vm_print_cmd(i, &commands[i]);
00603 #endif
00604
00605 line = eval_command(&commands[i].bytes[0], registers, return_values);
00606
00607 if (line < 0) {
00608 #ifdef TRACE
00609 fprintf(MSG_OUT, "libdvdnav: Registers after transaction\n");
00610 vm_print_registers( registers );
00611 fprintf(MSG_OUT, "libdvdnav: eval: Doing Link/Jump/Call\n");
00612 #endif
00613 return 1;
00614 }
00615
00616 if (line > 0)
00617 i = line - 1;
00618 else
00619 i++;
00620
00621 total++;
00622 }
00623
00624 memset(return_values, 0, sizeof(link_t));
00625 #ifdef TRACE
00626 fprintf(MSG_OUT, "libdvdnav: Registers after transaction\n");
00627 vm_print_registers( registers );
00628 #endif
00629 return 0;
00630 }
00631
00632 #ifdef TRACE
00633
00634 static char *linkcmd2str(link_cmd_t cmd) {
00635 switch(cmd) {
00636 case LinkNoLink:
00637 return "LinkNoLink";
00638 case LinkTopC:
00639 return "LinkTopC";
00640 case LinkNextC:
00641 return "LinkNextC";
00642 case LinkPrevC:
00643 return "LinkPrevC";
00644 case LinkTopPG:
00645 return "LinkTopPG";
00646 case LinkNextPG:
00647 return "LinkNextPG";
00648 case LinkPrevPG:
00649 return "LinkPrevPG";
00650 case LinkTopPGC:
00651 return "LinkTopPGC";
00652 case LinkNextPGC:
00653 return "LinkNextPGC";
00654 case LinkPrevPGC:
00655 return "LinkPrevPGC";
00656 case LinkGoUpPGC:
00657 return "LinkGoUpPGC";
00658 case LinkTailPGC:
00659 return "LinkTailPGC";
00660 case LinkRSM:
00661 return "LinkRSM";
00662 case LinkPGCN:
00663 return "LinkPGCN";
00664 case LinkPTTN:
00665 return "LinkPTTN";
00666 case LinkPGN:
00667 return "LinkPGN";
00668 case LinkCN:
00669 return "LinkCN";
00670 case Exit:
00671 return "Exit";
00672 case JumpTT:
00673 return "JumpTT";
00674 case JumpVTS_TT:
00675 return "JumpVTS_TT";
00676 case JumpVTS_PTT:
00677 return "JumpVTS_PTT";
00678 case JumpSS_FP:
00679 return "JumpSS_FP";
00680 case JumpSS_VMGM_MENU:
00681 return "JumpSS_VMGM_MENU";
00682 case JumpSS_VTSM:
00683 return "JumpSS_VTSM";
00684 case JumpSS_VMGM_PGC:
00685 return "JumpSS_VMGM_PGC";
00686 case CallSS_FP:
00687 return "CallSS_FP";
00688 case CallSS_VMGM_MENU:
00689 return "CallSS_VMGM_MENU";
00690 case CallSS_VTSM:
00691 return "CallSS_VTSM";
00692 case CallSS_VMGM_PGC:
00693 return "CallSS_VMGM_PGC";
00694 case PlayThis:
00695 return "PlayThis";
00696 }
00697 return "*** (bug)";
00698 }
00699
00700 void vm_print_link(link_t value) {
00701 char *cmd = linkcmd2str(value.command);
00702
00703 switch(value.command) {
00704 case LinkNoLink:
00705 case LinkTopC:
00706 case LinkNextC:
00707 case LinkPrevC:
00708 case LinkTopPG:
00709 case LinkNextPG:
00710 case LinkPrevPG:
00711 case LinkTopPGC:
00712 case LinkNextPGC:
00713 case LinkPrevPGC:
00714 case LinkGoUpPGC:
00715 case LinkTailPGC:
00716 case LinkRSM:
00717 fprintf(MSG_OUT, "libdvdnav: %s (button %d)\n", cmd, value.data1);
00718 break;
00719 case LinkPGCN:
00720 case JumpTT:
00721 case JumpVTS_TT:
00722 case JumpSS_VMGM_MENU:
00723 case JumpSS_VMGM_PGC:
00724 fprintf(MSG_OUT, "libdvdnav: %s %d\n", cmd, value.data1);
00725 break;
00726 case LinkPTTN:
00727 case LinkPGN:
00728 case LinkCN:
00729 fprintf(MSG_OUT, "libdvdnav: %s %d (button %d)\n", cmd, value.data1, value.data2);
00730 break;
00731 case Exit:
00732 case JumpSS_FP:
00733 case PlayThis:
00734 fprintf(MSG_OUT, "libdvdnav: %s\n", cmd);
00735 break;
00736 case JumpVTS_PTT:
00737 fprintf(MSG_OUT, "libdvdnav: %s %d:%d\n", cmd, value.data1, value.data2);
00738 break;
00739 case JumpSS_VTSM:
00740 fprintf(MSG_OUT, "libdvdnav: %s vts %d title %d menu %d\n",
00741 cmd, value.data1, value.data2, value.data3);
00742 break;
00743 case CallSS_FP:
00744 fprintf(MSG_OUT, "libdvdnav: %s resume cell %d\n", cmd, value.data1);
00745 break;
00746 case CallSS_VMGM_MENU:
00747 case CallSS_VTSM:
00748 fprintf(MSG_OUT, "libdvdnav: %s %d resume cell %d\n", cmd, value.data1, value.data2);
00749 break;
00750 case CallSS_VMGM_PGC:
00751 fprintf(MSG_OUT, "libdvdnav: %s %d resume cell %d\n", cmd, value.data1, value.data2);
00752 break;
00753 }
00754 }
00755
00756 void vm_print_registers( registers_t *registers ) {
00757 int32_t i;
00758 fprintf(MSG_OUT, "libdvdnav: # ");
00759 for(i = 0; i < 24; i++)
00760 fprintf(MSG_OUT, " %2d |", i);
00761 fprintf(MSG_OUT, "\nlibdvdnav: SRPMS: ");
00762 for(i = 0; i < 24; i++)
00763 fprintf(MSG_OUT, "%04x|", registers->SPRM[i]);
00764 fprintf(MSG_OUT, "\nlibdvdnav: GRPMS: ");
00765 for(i = 0; i < 16; i++)
00766 fprintf(MSG_OUT, "%04x|", get_GPRM(registers, i) );
00767 fprintf(MSG_OUT, "\nlibdvdnav: Gmode: ");
00768 for(i = 0; i < 16; i++)
00769 fprintf(MSG_OUT, "%04x|", registers->GPRM_mode[i]);
00770 fprintf(MSG_OUT, "\nlibdvdnav: Gtime: ");
00771 for(i = 0; i < 16; i++)
00772 fprintf(MSG_OUT, "%04lx|", registers->GPRM_time[i].tv_sec & 0xffff);
00773 fprintf(MSG_OUT, "\n");
00774 }
00775
00776 #endif
00777