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