comparison vm/vmcmd.c @ 0:427b7da5cbdb src

first split of dvdread; it's just a copy of dvdnav still to be cleaned
author nicodvb
date Sun, 01 Jun 2008 08:39:07 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:427b7da5cbdb
1 /*
2 * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort
3 * 2002-2004 the dvdnav project
4 *
5 * This file is part of libdvdnav, a DVD navigation library. It is modified
6 * from a file originally part of the Ogle DVD player.
7 *
8 * libdvdnav is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * libdvdnav is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 *
22 * $Id$
23 *
24 */
25
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
29
30 #include <stdio.h>
31 #include <ctype.h>
32 #include <inttypes.h>
33 #include <limits.h>
34 #include <sys/time.h>
35
36 #include "dvd_types.h"
37 #include "nav_types.h"
38 #include "ifo_types.h"
39 #include "decoder.h"
40 #include "remap.h"
41 #include "vm.h"
42 #include "vmcmd.h"
43 #include "dvdnav.h"
44 #include "dvdnav_internal.h"
45
46 /* freebsd compatibility */
47 #ifndef PRIu8
48 #define PRIu8 "d"
49 #endif
50
51 /* freebsd compatibility */
52 #ifndef PRIu16
53 #define PRIu16 "d"
54 #endif
55
56 static const char cmp_op_table[][4] = {
57 "", "&", "==", "!=", ">=", ">", "<=", "<"
58 };
59 static const char set_op_table[][4] = {
60 "", "=", "<->", "+=", "-=", "*=", "/=", "%=", "rnd", "&=", "|=", "^="
61 };
62
63 static const char link_table[][16] = {
64 "LinkNoLink", "LinkTopC", "LinkNextC", "LinkPrevC",
65 "", "LinkTopPG", "LinkNextPG", "LinkPrevPG",
66 "", "LinkTopPGC", "LinkNextPGC", "LinkPrevPGC",
67 "LinkGoUpPGC", "LinkTailPGC", "", "",
68 "RSM"
69 };
70
71 static const char *const system_reg_table[] = {
72 "Menu Description Language Code",
73 "Audio Stream Number",
74 "Sub-picture Stream Number",
75 "Angle Number",
76 "Title Track Number",
77 "VTS Title Track Number",
78 "VTS PGC Number",
79 "PTT Number for One_Sequential_PGC_Title",
80 "Highlighted Button Number",
81 "Navigation Timer",
82 "Title PGC Number for Navigation Timer",
83 "Audio Mixing Mode for Karaoke",
84 "Country Code for Parental Management",
85 "Parental Level",
86 "Player Configurations for Video",
87 "Player Configurations for Audio",
88 "Initial Language Code for Audio",
89 "Initial Language Code Extension for Audio",
90 "Initial Language Code for Sub-picture",
91 "Initial Language Code Extension for Sub-picture",
92 "Player Regional Code",
93 "Reserved 21",
94 "Reserved 22",
95 "Reserved 23"
96 };
97
98 static const char system_reg_abbr_table[][8] = {
99 "",
100 "ASTN",
101 "SPSTN",
102 "AGLN",
103 "TTN",
104 "VTS_TTN",
105 "TT_PGCN",
106 "PTTN",
107 "HL_BTNN",
108 "NVTMR",
109 "NV_PGCN",
110 "",
111 "CC_PLT",
112 "PLT",
113 "",
114 "",
115 "",
116 "",
117 "",
118 "",
119 "",
120 "",
121 "",
122 "",
123 };
124
125 static void print_system_reg(uint16_t reg) {
126 if(reg < sizeof(system_reg_abbr_table) / sizeof(system_reg_abbr_table[0]))
127 fprintf(MSG_OUT, "%s (SRPM:%d)", system_reg_table[reg], reg);
128 else
129 fprintf(MSG_OUT, " WARNING: Unknown system register ( reg=%d ) ", reg);
130 }
131
132 static void print_g_reg(uint8_t reg) {
133 if(reg < 16)
134 fprintf(MSG_OUT, "g[%" PRIu8 "]", reg);
135 else
136 fprintf(MSG_OUT, " WARNING: Unknown general register ");
137 }
138
139 static void print_reg(uint8_t reg) {
140 if(reg & 0x80)
141 print_system_reg(reg & 0x7f);
142 else
143 print_g_reg(reg & 0x7f);
144 }
145
146 static void print_cmp_op(uint8_t op) {
147 if(op < sizeof(cmp_op_table) / sizeof(cmp_op_table[0]))
148 fprintf(MSG_OUT, " %s ", cmp_op_table[op]);
149 else
150 fprintf(MSG_OUT, " WARNING: Unknown compare op ");
151 }
152
153 static void print_set_op(uint8_t op) {
154 if(op < sizeof(set_op_table) / sizeof(cmp_op_table[0]))
155 fprintf(MSG_OUT, " %s ", set_op_table[op]);
156 else
157 fprintf(MSG_OUT, " WARNING: Unknown set op ");
158 }
159
160 static void print_reg_or_data(command_t* command, int immediate, int start) {
161 if(immediate) {
162 uint32_t i = vm_getbits(command, start, 16);
163
164 fprintf(MSG_OUT, "0x%x", i);
165 if(isprint(i & 0xff) && isprint((i>>8) & 0xff))
166 fprintf(MSG_OUT, " (\"%c%c\")", (char)((i>>8) & 0xff), (char)(i & 0xff));
167 } else {
168 print_reg(vm_getbits(command, start - 8, 8));
169 }
170 }
171
172 static void print_reg_or_data_2(command_t* command, int immediate, int start) {
173 if(immediate)
174 fprintf(MSG_OUT, "0x%x", vm_getbits(command, start - 1, 7));
175 else
176 fprintf(MSG_OUT, "g[%" PRIu8 "]", vm_getbits(command, start - 4, 4));
177 }
178
179 static void print_reg_or_data_3(command_t* command, int immediate, int start) {
180 if(immediate) {
181 uint32_t i = vm_getbits(command, start, 16);
182
183 fprintf(MSG_OUT, "0x%x", i);
184 if(isprint(i & 0xff) && isprint((i>>8) & 0xff))
185 fprintf(MSG_OUT, " (\"%c%c\")", (char)((i>>8) & 0xff), (char)(i & 0xff));
186 } else {
187 print_reg(vm_getbits(command, start, 8));
188 }
189 }
190
191
192 static void print_if_version_1(command_t* command) {
193 uint8_t op = vm_getbits(command, 54, 3);
194
195 if(op) {
196 fprintf(MSG_OUT, "if (");
197 print_g_reg(vm_getbits(command,39,8));
198 print_cmp_op(op);
199 print_reg_or_data(command, vm_getbits(command, 55,1), 31);
200 fprintf(MSG_OUT, ") ");
201 }
202 }
203
204 static void print_if_version_2(command_t* command) {
205 uint8_t op = vm_getbits(command, 54, 3);
206
207 if(op) {
208 fprintf(MSG_OUT, "if (");
209 print_reg(vm_getbits(command, 15, 8));
210 print_cmp_op(op);
211 print_reg(vm_getbits(command, 7, 8));
212 fprintf(MSG_OUT, ") ");
213 }
214 }
215
216 static void print_if_version_3(command_t* command) {
217 uint8_t op = vm_getbits(command, 54, 3);
218
219 if(op) {
220 fprintf(MSG_OUT, "if (");
221 print_g_reg(vm_getbits(command, 43, 4));
222 print_cmp_op(op);
223 print_reg_or_data(command, vm_getbits(command, 55, 1), 15);
224 fprintf(MSG_OUT, ") ");
225 }
226 }
227
228 static void print_if_version_4(command_t* command) {
229 uint8_t op = vm_getbits(command, 54, 3);
230
231 if(op) {
232 fprintf(MSG_OUT, "if (");
233 print_g_reg(vm_getbits(command, 51, 4));
234 print_cmp_op(op);
235 print_reg_or_data(command, vm_getbits(command, 55, 1), 31);
236 fprintf(MSG_OUT, ") ");
237 }
238 }
239
240 static void print_if_version_5(command_t* command) {
241 uint8_t op = vm_getbits(command, 54, 3);
242 int set_immediate = vm_getbits(command, 60, 1);
243
244 if(op) {
245 if (set_immediate) {
246 fprintf(MSG_OUT, "if (");
247 print_g_reg(vm_getbits(command, 31, 8));
248 print_cmp_op(op);
249 print_reg(vm_getbits(command, 23, 8));
250 fprintf(MSG_OUT, ") ");
251 } else {
252 fprintf(MSG_OUT, "if (");
253 print_g_reg(vm_getbits(command, 39, 8));
254 print_cmp_op(op);
255 print_reg_or_data(command, vm_getbits(command, 55, 1), 31);
256 fprintf(MSG_OUT, ") ");
257 }
258 }
259 }
260
261 static void print_special_instruction(command_t* command) {
262 uint8_t op = vm_getbits(command, 51, 4);
263
264 switch(op) {
265 case 0: /* NOP */
266 fprintf(MSG_OUT, "Nop");
267 break;
268 case 1: /* Goto line */
269 fprintf(MSG_OUT, "Goto %" PRIu8, vm_getbits(command, 7, 8));
270 break;
271 case 2: /* Break */
272 fprintf(MSG_OUT, "Break");
273 break;
274 case 3: /* Parental level */
275 fprintf(MSG_OUT, "SetTmpPML %" PRIu8 ", Goto %" PRIu8,
276 vm_getbits(command, 11, 4), vm_getbits(command, 7, 8));
277 break;
278 default:
279 fprintf(MSG_OUT, "WARNING: Unknown special instruction (%i)",
280 vm_getbits(command, 51, 4));
281 }
282 }
283
284 static void print_linksub_instruction(command_t* command) {
285 uint32_t linkop = vm_getbits(command, 7, 8);
286 uint32_t button = vm_getbits(command, 15, 6);
287
288 if(linkop < sizeof(link_table)/sizeof(link_table[0]))
289 fprintf(MSG_OUT, "%s (button %" PRIu8 ")", link_table[linkop], button);
290 else
291 fprintf(MSG_OUT, "WARNING: Unknown linksub instruction (%i)", linkop);
292 }
293
294 static void print_link_instruction(command_t* command, int optional) {
295 uint8_t op = vm_getbits(command, 51, 4);
296
297 if(optional && op)
298 fprintf(MSG_OUT, ", ");
299
300 switch(op) {
301 case 0:
302 if(!optional)
303 fprintf(MSG_OUT, "WARNING: NOP (link)!");
304 break;
305 case 1:
306 print_linksub_instruction(command);
307 break;
308 case 4:
309 fprintf(MSG_OUT, "LinkPGCN %" PRIu16, vm_getbits(command, 14, 15));
310 break;
311 case 5:
312 fprintf(MSG_OUT, "LinkPTT %" PRIu16 " (button %" PRIu8 ")",
313 vm_getbits(command, 9, 10), vm_getbits(command, 15, 6));
314 break;
315 case 6:
316 fprintf(MSG_OUT, "LinkPGN %" PRIu8 " (button %" PRIu8 ")",
317 vm_getbits(command, 6, 7), vm_getbits(command, 15, 6));
318 break;
319 case 7:
320 fprintf(MSG_OUT, "LinkCN %" PRIu8 " (button %" PRIu8 ")",
321 vm_getbits(command, 7, 8), vm_getbits(command, 15, 6));
322 break;
323 default:
324 fprintf(MSG_OUT, "WARNING: Unknown link instruction");
325 }
326 }
327
328 static void print_jump_instruction(command_t* command) {
329 switch(vm_getbits(command, 51, 4)) {
330 case 1:
331 fprintf(MSG_OUT, "Exit");
332 break;
333 case 2:
334 fprintf(MSG_OUT, "JumpTT %" PRIu8, vm_getbits(command, 22, 7));
335 break;
336 case 3:
337 fprintf(MSG_OUT, "JumpVTS_TT %" PRIu8, vm_getbits(command, 22, 7));
338 break;
339 case 5:
340 fprintf(MSG_OUT, "JumpVTS_PTT %" PRIu8 ":%" PRIu16,
341 vm_getbits(command, 22, 7), vm_getbits(command, 41, 10));
342 break;
343 case 6:
344 switch(vm_getbits(command, 23, 2)) {
345 case 0:
346 fprintf(MSG_OUT, "JumpSS FP");
347 break;
348 case 1:
349 fprintf(MSG_OUT, "JumpSS VMGM (menu %" PRIu8 ")", vm_getbits(command, 19, 4));
350 break;
351 case 2:
352 fprintf(MSG_OUT, "JumpSS VTSM (vts %" PRIu8 ", title %" PRIu8
353 ", menu %" PRIu8 ")", vm_getbits(command, 30, 7), vm_getbits(command, 38, 7), vm_getbits(command, 19, 4));
354 break;
355 case 3:
356 fprintf(MSG_OUT, "JumpSS VMGM (pgc %" PRIu8 ")", vm_getbits(command, 46, 15));
357 break;
358 }
359 break;
360 case 8:
361 switch(vm_getbits(command, 23, 2)) {
362 case 0:
363 fprintf(MSG_OUT, "CallSS FP (rsm_cell %" PRIu8 ")",
364 vm_getbits(command, 31, 8));
365 break;
366 case 1:
367 fprintf(MSG_OUT, "CallSS VMGM (menu %" PRIu8
368 ", rsm_cell %" PRIu8 ")", vm_getbits(command, 19, 4), vm_getbits(command, 31, 8));
369 break;
370 case 2:
371 fprintf(MSG_OUT, "CallSS VTSM (menu %" PRIu8
372 ", rsm_cell %" PRIu8 ")", vm_getbits(command, 19, 4), vm_getbits(command, 31, 8));
373 break;
374 case 3:
375 fprintf(MSG_OUT, "CallSS VMGM (pgc %" PRIu8 ", rsm_cell %" PRIu8 ")",
376 vm_getbits(command, 46, 15), vm_getbits(command, 31, 8));
377 break;
378 }
379 break;
380 default:
381 fprintf(MSG_OUT, "WARNING: Unknown Jump/Call instruction");
382 }
383 }
384
385 static void print_system_set(command_t* command) {
386 int i;
387 /* FIXME: What about SPRM11 ? Karaoke */
388 /* Surely there must be some system set command for that ? */
389
390 switch(vm_getbits(command, 59, 4)) {
391 case 1: /* Set system reg 1 &| 2 &| 3 (Audio, Subp. Angle) */
392 for(i = 1; i <= 3; i++) {
393 if(vm_getbits(command, 47 - (i*8), 1)) {
394 print_system_reg(i);
395 fprintf(MSG_OUT, " = ");
396 print_reg_or_data_2(command, vm_getbits(command, 60, 1), 47 - (i*8) );
397 fprintf(MSG_OUT, " ");
398 }
399 }
400 break;
401 case 2: /* Set system reg 9 & 10 (Navigation timer, Title PGC number) */
402 print_system_reg(9);
403 fprintf(MSG_OUT, " = ");
404 print_reg_or_data(command, vm_getbits(command, 60, 1), 47);
405 fprintf(MSG_OUT, " ");
406 print_system_reg(10);
407 fprintf(MSG_OUT, " = %" PRIu16, vm_getbits(command, 30, 15)); /* ?? */
408 break;
409 case 3: /* Mode: Counter / Register + Set */
410 fprintf(MSG_OUT, "SetMode ");
411 if(vm_getbits(command, 23, 1))
412 fprintf(MSG_OUT, "Counter ");
413 else
414 fprintf(MSG_OUT, "Register ");
415 print_g_reg(vm_getbits(command, 19, 4));
416 print_set_op(0x1); /* '=' */
417 print_reg_or_data(command, vm_getbits(command, 60, 1), 47);
418 break;
419 case 6: /* Set system reg 8 (Highlighted button) */
420 print_system_reg(8);
421 if(vm_getbits(command, 60, 1)) /* immediate */
422 fprintf(MSG_OUT, " = 0x%x (button no %d)", vm_getbits(command, 31, 16), vm_getbits(command, 31, 6));
423 else
424 fprintf(MSG_OUT, " = g[%" PRIu8 "]", vm_getbits(command, 19, 4));
425 break;
426 default:
427 fprintf(MSG_OUT, "WARNING: Unknown system set instruction (%i)",
428 vm_getbits(command, 59, 4));
429 }
430 }
431
432 static void print_set_version_1(command_t* command) {
433 uint8_t set_op = vm_getbits(command, 59, 4);
434
435 if(set_op) {
436 print_g_reg(vm_getbits(command, 35, 4));
437 print_set_op(set_op);
438 print_reg_or_data(command, vm_getbits(command, 60, 1), 31);
439 } else {
440 fprintf(MSG_OUT, "NOP");
441 }
442 }
443
444 static void print_set_version_2(command_t* command) {
445 uint8_t set_op = vm_getbits(command, 59, 4);
446
447 if(set_op) {
448 print_g_reg(vm_getbits(command, 51, 4));
449 print_set_op(set_op);
450 print_reg_or_data(command, vm_getbits(command, 60, 1), 47);
451 } else {
452 fprintf(MSG_OUT, "NOP");
453 }
454 }
455
456 static void print_set_version_3(command_t* command) {
457 uint8_t set_op = vm_getbits(command, 59, 4);
458
459 if(set_op) {
460 print_g_reg(vm_getbits(command, 51, 4));
461 print_set_op(set_op);
462 print_reg_or_data_3(command, vm_getbits(command, 60, 1), 47);
463 } else {
464 fprintf(MSG_OUT, "NOP");
465 }
466 }
467
468
469 void vm_print_mnemonic(vm_cmd_t *vm_command) {
470 command_t command;
471 command.instruction =( (uint64_t) vm_command->bytes[0] << 56 ) |
472 ( (uint64_t) vm_command->bytes[1] << 48 ) |
473 ( (uint64_t) vm_command->bytes[2] << 40 ) |
474 ( (uint64_t) vm_command->bytes[3] << 32 ) |
475 ( (uint64_t) vm_command->bytes[4] << 24 ) |
476 ( (uint64_t) vm_command->bytes[5] << 16 ) |
477 ( (uint64_t) vm_command->bytes[6] << 8 ) |
478 (uint64_t) vm_command->bytes[7] ;
479 command.examined = 0;
480
481 switch(vm_getbits(&command,63,3)) { /* three first bits */
482 case 0: /* Special instructions */
483 print_if_version_1(&command);
484 print_special_instruction(&command);
485 break;
486 case 1: /* Jump/Call or Link instructions */
487 if(vm_getbits(&command,60,1)) {
488 print_if_version_2(&command);
489 print_jump_instruction(&command);
490 } else {
491 print_if_version_1(&command);
492 print_link_instruction(&command, 0); /* must be pressent */
493 }
494 break;
495 case 2: /* Set System Parameters instructions */
496 print_if_version_2(&command);
497 print_system_set(&command);
498 print_link_instruction(&command, 1); /* either 'if' or 'link' */
499 break;
500 case 3: /* Set General Parameters instructions */
501 print_if_version_3(&command);
502 print_set_version_1(&command);
503 print_link_instruction(&command, 1); /* either 'if' or 'link' */
504 break;
505 case 4: /* Set, Compare -> LinkSub instructions */
506 print_set_version_2(&command);
507 fprintf(MSG_OUT, ", ");
508 print_if_version_4(&command);
509 print_linksub_instruction(&command);
510 break;
511 case 5: /* Compare -> (Set and LinkSub) instructions */
512 print_if_version_5(&command);
513 fprintf(MSG_OUT, "{ ");
514 print_set_version_3(&command);
515 fprintf(MSG_OUT, ", ");
516 print_linksub_instruction(&command);
517 fprintf(MSG_OUT, " }");
518 break;
519 case 6: /* Compare -> Set, always LinkSub instructions */
520 print_if_version_5(&command);
521 fprintf(MSG_OUT, "{ ");
522 print_set_version_3(&command);
523 fprintf(MSG_OUT, " } ");
524 print_linksub_instruction(&command);
525 break;
526 default:
527 fprintf(MSG_OUT, "WARNING: Unknown instruction type (%i)", vm_getbits(&command, 63, 3));
528 }
529 /* Check if there still are bits set that were not examined */
530
531 if(command.instruction & ~ command.examined) {
532 fprintf(MSG_OUT, " libdvdnav: vmcmd.c: [WARNING, unknown bits:");
533 fprintf(MSG_OUT, " %08"PRIx64, (command.instruction & ~ command.examined) );
534 fprintf(MSG_OUT, "]");
535 }
536 }
537
538 void vm_print_cmd(int row, vm_cmd_t *vm_command) {
539 int i;
540
541 fprintf(MSG_OUT, "(%03d) ", row + 1);
542 for(i = 0; i < 8; i++)
543 fprintf(MSG_OUT, "%02x ", vm_command->bytes[i]);
544 fprintf(MSG_OUT, "| ");
545
546 vm_print_mnemonic(vm_command);
547 fprintf(MSG_OUT, "\n");
548 }
549