comparison vm/decoder.c @ 388:90ca650854e0 src

Remove all trailing whitespace, patch by Erik Hovland *erik$hovland dot org%
author rathann
date Sat, 06 Sep 2008 21:55:51 +0000
parents 579a3538d284
children d3c273ced49c
comparison
equal deleted inserted replaced
387:4e28052eb201 388:90ca650854e0
1 /* 1 /*
2 * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort 2 * Copyright (C) 2000, 2001 Martin Norbäck, Håkan Hjort
3 * 2002-2004 the dvdnav project 3 * 2002-2004 the dvdnav project
4 * 4 *
5 * This file is part of libdvdnav, a DVD navigation library. It is modified 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. 6 * from a file originally part of the Ogle DVD player.
7 * 7 *
8 * libdvdnav is free software; you can redistribute it and/or modify 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 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 10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version. 11 * (at your option) any later version.
12 * 12 *
13 * libdvdnav is distributed in the hope that it will be useful, 13 * libdvdnav is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details. 16 * GNU General Public License for more details.
17 * 17 *
18 * You should have received a copy of the GNU General Public License 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 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 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
21 * 21 *
22 * $Id$ 22 * $Id$
47 uint32_t vm_getbits(command_t *command, int32_t start, int32_t count) { 47 uint32_t vm_getbits(command_t *command, int32_t start, int32_t count) {
48 uint64_t result = 0; 48 uint64_t result = 0;
49 uint64_t bit_mask = 0; 49 uint64_t bit_mask = 0;
50 uint64_t examining = 0; 50 uint64_t examining = 0;
51 int32_t bits; 51 int32_t bits;
52 52
53 if (count == 0) return 0; 53 if (count == 0) return 0;
54 54
55 if ( ((start - count) < -1) || 55 if ( ((start - count) < -1) ||
56 (count > 32) || 56 (count > 32) ||
57 (start > 63) || 57 (start > 63) ||
77 /* Counter mode */ 77 /* Counter mode */
78 /* fprintf(MSG_OUT, "libdvdnav: Getting counter %d\n",reg);*/ 78 /* fprintf(MSG_OUT, "libdvdnav: Getting counter %d\n",reg);*/
79 gettimeofday(&current_time, NULL); 79 gettimeofday(&current_time, NULL);
80 time_offset.tv_sec = current_time.tv_sec - registers->GPRM_time[reg].tv_sec; 80 time_offset.tv_sec = current_time.tv_sec - registers->GPRM_time[reg].tv_sec;
81 time_offset.tv_usec = current_time.tv_usec - registers->GPRM_time[reg].tv_usec; 81 time_offset.tv_usec = current_time.tv_usec - registers->GPRM_time[reg].tv_usec;
82 if (time_offset.tv_usec < 0) { 82 if (time_offset.tv_usec < 0) {
83 time_offset.tv_sec--; 83 time_offset.tv_sec--;
84 time_offset.tv_usec += 1000000; 84 time_offset.tv_usec += 1000000;
85 } 85 }
86 result = (uint16_t) (time_offset.tv_sec & 0xffff); 86 result = (uint16_t) (time_offset.tv_sec & 0xffff);
87 registers->GPRM[reg]=result; 87 registers->GPRM[reg]=result;
88 return result; 88 return result;
89 89
90 } else { 90 } else {
91 /* Register mode */ 91 /* Register mode */
92 return registers->GPRM[reg]; 92 return registers->GPRM[reg];
93 } 93 }
94 94
95 } 95 }
96 96
97 static void set_GPRM(registers_t* registers, uint8_t reg, uint16_t value) { 97 static void set_GPRM(registers_t* registers, uint8_t reg, uint16_t value) {
98 if (registers->GPRM_mode[reg] & 0x01) { 98 if (registers->GPRM_mode[reg] & 0x01) {
99 struct timeval current_time; 99 struct timeval current_time;
132 132
133 /* Eval register or immediate data. 133 /* Eval register or immediate data.
134 xBBB_BBBB, if immediate use all 7 bits for data else use 134 xBBB_BBBB, if immediate use all 7 bits for data else use
135 lower four bits for the general purpose register number. */ 135 lower four bits for the general purpose register number. */
136 /* Evaluates gprm or data depending on bit, data is in byte n */ 136 /* Evaluates gprm or data depending on bit, data is in byte n */
137 static uint16_t eval_reg_or_data_2(command_t* command, 137 static uint16_t eval_reg_or_data_2(command_t* command,
138 int32_t imm, int32_t start) { 138 int32_t imm, int32_t start) {
139 if(imm) /* immediate */ 139 if(imm) /* immediate */
140 return vm_getbits(command, (start - 1), 7); 140 return vm_getbits(command, (start - 1), 7);
141 else 141 else
142 return get_GPRM(command->registers, (vm_getbits(command, (start - 4), 4)) ); 142 return get_GPRM(command->registers, (vm_getbits(command, (start - 4), 4)) );
143 } 143 }
144 144
145 145
146 /* Compare data using operation, return result from comparison. 146 /* Compare data using operation, return result from comparison.
147 Helper function for the different if functions. */ 147 Helper function for the different if functions. */
148 static int32_t eval_compare(uint8_t operation, uint16_t data1, uint16_t data2) { 148 static int32_t eval_compare(uint8_t operation, uint16_t data1, uint16_t data2) {
149 switch(operation) { 149 switch(operation) {
150 case 1: 150 case 1:
151 return data1 & data2; 151 return data1 & data2;
170 /* Evaluate if version 1. 170 /* Evaluate if version 1.
171 Has comparison data in byte 3 and 4-5 (immediate or register) */ 171 Has comparison data in byte 3 and 4-5 (immediate or register) */
172 static int32_t eval_if_version_1(command_t* command) { 172 static int32_t eval_if_version_1(command_t* command) {
173 uint8_t op = vm_getbits(command, 54, 3); 173 uint8_t op = vm_getbits(command, 54, 3);
174 if(op) { 174 if(op) {
175 return eval_compare(op, eval_reg(command, vm_getbits(command, 39, 8)), 175 return eval_compare(op, eval_reg(command, vm_getbits(command, 39, 8)),
176 eval_reg_or_data(command, vm_getbits(command, 55, 1), 31)); 176 eval_reg_or_data(command, vm_getbits(command, 55, 1), 31));
177 } 177 }
178 return 1; 178 return 1;
179 } 179 }
180 180
181 /* Evaluate if version 2. 181 /* Evaluate if version 2.
182 This version only compares register which are in byte 6 and 7 */ 182 This version only compares register which are in byte 6 and 7 */
183 static int32_t eval_if_version_2(command_t* command) { 183 static int32_t eval_if_version_2(command_t* command) {
184 uint8_t op = vm_getbits(command, 54, 3); 184 uint8_t op = vm_getbits(command, 54, 3);
185 if(op) { 185 if(op) {
186 return eval_compare(op, eval_reg(command, vm_getbits(command, 15, 8)), 186 return eval_compare(op, eval_reg(command, vm_getbits(command, 15, 8)),
187 eval_reg(command, vm_getbits(command, 7, 8))); 187 eval_reg(command, vm_getbits(command, 7, 8)));
188 } 188 }
189 return 1; 189 return 1;
190 } 190 }
191 191
192 /* Evaluate if version 3. 192 /* Evaluate if version 3.
193 Has comparison data in byte 2 and 6-7 (immediate or register) */ 193 Has comparison data in byte 2 and 6-7 (immediate or register) */
194 static int32_t eval_if_version_3(command_t* command) { 194 static int32_t eval_if_version_3(command_t* command) {
195 uint8_t op = vm_getbits(command, 54, 3); 195 uint8_t op = vm_getbits(command, 54, 3);
196 if(op) { 196 if(op) {
197 return eval_compare(op, eval_reg(command, vm_getbits(command, 47, 8)), 197 return eval_compare(op, eval_reg(command, vm_getbits(command, 47, 8)),
198 eval_reg_or_data(command, vm_getbits(command, 55, 1), 15)); 198 eval_reg_or_data(command, vm_getbits(command, 55, 1), 15));
199 } 199 }
200 return 1; 200 return 1;
201 } 201 }
202 202
203 /* Evaluate if version 4. 203 /* Evaluate if version 4.
204 Has comparison data in byte 1 and 4-5 (immediate or register) 204 Has comparison data in byte 1 and 4-5 (immediate or register)
205 The register in byte 1 is only the lowe nibble (4 bits) */ 205 The register in byte 1 is only the lowe nibble (4 bits) */
206 static int32_t eval_if_version_4(command_t* command) { 206 static int32_t eval_if_version_4(command_t* command) {
207 uint8_t op = vm_getbits(command, 54, 3); 207 uint8_t op = vm_getbits(command, 54, 3);
208 if(op) { 208 if(op) {
209 return eval_compare(op, eval_reg(command, vm_getbits(command, 51, 4)), 209 return eval_compare(op, eval_reg(command, vm_getbits(command, 51, 4)),
210 eval_reg_or_data(command, vm_getbits(command, 55, 1), 31)); 210 eval_reg_or_data(command, vm_getbits(command, 55, 1), 31));
211 } 211 }
212 return 1; 212 return 1;
213 } 213 }
214 214
215 /* Evaluate special instruction.... returns the new row/line number, 215 /* Evaluate special instruction.... returns the new row/line number,
216 0 if no new row and 256 if Break. */ 216 0 if no new row and 256 if Break. */
217 static int32_t eval_special_instruction(command_t* command, int32_t cond) { 217 static int32_t eval_special_instruction(command_t* command, int32_t cond) {
218 int32_t line, level; 218 int32_t line, level;
219 219
220 switch(vm_getbits(command, 51, 4)) { 220 switch(vm_getbits(command, 51, 4)) {
221 case 0: /* NOP */ 221 case 0: /* NOP */
222 line = 0; 222 line = 0;
223 return cond ? line : 0; 223 return cond ? line : 0;
224 case 1: /* Goto line */ 224 case 1: /* Goto line */
227 case 2: /* Break */ 227 case 2: /* Break */
228 /* max number of rows < 256, so we will end this set */ 228 /* max number of rows < 256, so we will end this set */
229 line = 256; 229 line = 256;
230 return cond ? 256 : 0; 230 return cond ? 256 : 0;
231 case 3: /* Set temporary parental level and goto */ 231 case 3: /* Set temporary parental level and goto */
232 line = vm_getbits(command, 7, 8); 232 line = vm_getbits(command, 7, 8);
233 level = vm_getbits(command, 11, 4); 233 level = vm_getbits(command, 11, 4);
234 if(cond) { 234 if(cond) {
235 /* This always succeeds now, if we want real parental protection */ 235 /* This always succeeds now, if we want real parental protection */
236 /* we need to ask the user and have passwords and stuff. */ 236 /* we need to ask the user and have passwords and stuff. */
237 command->registers->SPRM[13] = level; 237 command->registers->SPRM[13] = level;
245 Return 1 if link, or 0 if no link 245 Return 1 if link, or 0 if no link
246 Actual link instruction is in return_values parameter */ 246 Actual link instruction is in return_values parameter */
247 static int32_t eval_link_subins(command_t* command, int32_t cond, link_t *return_values) { 247 static int32_t eval_link_subins(command_t* command, int32_t cond, link_t *return_values) {
248 uint16_t button = vm_getbits(command, 15, 6); 248 uint16_t button = vm_getbits(command, 15, 6);
249 uint8_t linkop = vm_getbits(command, 4, 5); 249 uint8_t linkop = vm_getbits(command, 4, 5);
250 250
251 if(linkop > 0x10) 251 if(linkop > 0x10)
252 return 0; /* Unknown Link by Sub-Instruction command */ 252 return 0; /* Unknown Link by Sub-Instruction command */
253 253
254 /* Assumes that the link_cmd_t enum has the same values as the LinkSIns codes */ 254 /* Assumes that the link_cmd_t enum has the same values as the LinkSIns codes */
255 return_values->command = linkop; 255 return_values->command = linkop;
261 /* Evaluate link instruction. 261 /* Evaluate link instruction.
262 Return 1 if link, or 0 if no link 262 Return 1 if link, or 0 if no link
263 Actual link instruction is in return_values parameter */ 263 Actual link instruction is in return_values parameter */
264 static int32_t eval_link_instruction(command_t* command, int32_t cond, link_t *return_values) { 264 static int32_t eval_link_instruction(command_t* command, int32_t cond, link_t *return_values) {
265 uint8_t op = vm_getbits(command, 51, 4); 265 uint8_t op = vm_getbits(command, 51, 4);
266 266
267 switch(op) { 267 switch(op) {
268 case 1: 268 case 1:
269 return eval_link_subins(command, cond, return_values); 269 return eval_link_subins(command, cond, return_values);
270 case 4: 270 case 4:
271 return_values->command = LinkPGCN; 271 return_values->command = LinkPGCN;
293 293
294 /* Evaluate a jump instruction. 294 /* Evaluate a jump instruction.
295 returns 1 if jump or 0 if no jump 295 returns 1 if jump or 0 if no jump
296 actual jump instruction is in return_values parameter */ 296 actual jump instruction is in return_values parameter */
297 static int32_t eval_jump_instruction(command_t* command, int32_t cond, link_t *return_values) { 297 static int32_t eval_jump_instruction(command_t* command, int32_t cond, link_t *return_values) {
298 298
299 switch(vm_getbits(command, 51, 4)) { 299 switch(vm_getbits(command, 51, 4)) {
300 case 1: 300 case 1:
301 return_values->command = Exit; 301 return_values->command = Exit;
302 return cond; 302 return cond;
303 case 2: 303 case 2:
359 break; 359 break;
360 } 360 }
361 return 0; 361 return 0;
362 } 362 }
363 363
364 /* Evaluate a set sytem register instruction 364 /* Evaluate a set sytem register instruction
365 May contain a link so return the same as eval_link */ 365 May contain a link so return the same as eval_link */
366 static int32_t eval_system_set(command_t* command, int32_t cond, link_t *return_values) { 366 static int32_t eval_system_set(command_t* command, int32_t cond, link_t *return_values) {
367 int32_t i; 367 int32_t i;
368 uint16_t data, data2; 368 uint16_t data, data2;
369 369
370 switch(vm_getbits(command, 59, 4)) { 370 switch(vm_getbits(command, 59, 4)) {
371 case 1: /* Set system reg 1 &| 2 &| 3 (Audio, Subp. Angle) */ 371 case 1: /* Set system reg 1 &| 2 &| 3 (Audio, Subp. Angle) */
372 for(i = 1; i <= 3; i++) { 372 for(i = 1; i <= 3; i++) {
373 if(vm_getbits(command, 63 - ((2 + i)*8), 1)) { 373 if(vm_getbits(command, 63 - ((2 + i)*8), 1)) {
374 data = eval_reg_or_data_2(command, vm_getbits(command, 60, 1), (47 - (i*8))); 374 data = eval_reg_or_data_2(command, vm_getbits(command, 60, 1), (47 - (i*8)));
416 Sets the register given to the value indicated by op and data. 416 Sets the register given to the value indicated by op and data.
417 For the swap case the contents of reg is stored in reg2. 417 For the swap case the contents of reg is stored in reg2.
418 */ 418 */
419 static void eval_set_op(command_t* command, int32_t op, int32_t reg, int32_t reg2, int32_t data) { 419 static void eval_set_op(command_t* command, int32_t op, int32_t reg, int32_t reg2, int32_t data) {
420 static const int32_t shortmax = 0xffff; 420 static const int32_t shortmax = 0xffff;
421 int32_t tmp; 421 int32_t tmp;
422 switch(op) { 422 switch(op) {
423 case 1: 423 case 1:
424 set_GPRM(command->registers, reg, data); 424 set_GPRM(command->registers, reg, data);
425 break; 425 break;
426 case 2: /* SPECIAL CASE - SWAP! */ 426 case 2: /* SPECIAL CASE - SWAP! */
587 587
588 return res; 588 return res;
589 } 589 }
590 590
591 /* Evaluate a set of commands in the given register set (which is modified) */ 591 /* Evaluate a set of commands in the given register set (which is modified) */
592 int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands, 592 int32_t vmEval_CMD(vm_cmd_t commands[], int32_t num_commands,
593 registers_t *registers, link_t *return_values) { 593 registers_t *registers, link_t *return_values) {
594 int32_t i = 0; 594 int32_t i = 0;
595 int32_t total = 0; 595 int32_t total = 0;
596 596
597 #ifdef TRACE 597 #ifdef TRACE
598 /* DEBUG */ 598 /* DEBUG */
599 fprintf(MSG_OUT, "libdvdnav: Registers before transaction\n"); 599 fprintf(MSG_OUT, "libdvdnav: Registers before transaction\n");
600 vm_print_registers( registers ); 600 vm_print_registers( registers );
601 fprintf(MSG_OUT, "libdvdnav: Full list of commands to execute\n"); 601 fprintf(MSG_OUT, "libdvdnav: Full list of commands to execute\n");
603 vm_print_cmd(i, &commands[i]); 603 vm_print_cmd(i, &commands[i]);
604 fprintf(MSG_OUT, "libdvdnav: --------------------------------------------\n"); 604 fprintf(MSG_OUT, "libdvdnav: --------------------------------------------\n");
605 fprintf(MSG_OUT, "libdvdnav: Single stepping commands\n"); 605 fprintf(MSG_OUT, "libdvdnav: Single stepping commands\n");
606 #endif 606 #endif
607 607
608 i = 0; 608 i = 0;
609 while(i < num_commands && total < 100000) { 609 while(i < num_commands && total < 100000) {
610 int32_t line; 610 int32_t line;
611 611
612 #ifdef TRACE 612 #ifdef TRACE
613 vm_print_cmd(i, &commands[i]); 613 vm_print_cmd(i, &commands[i]);
614 #endif 614 #endif
615 615
616 line = eval_command(&commands[i].bytes[0], registers, return_values); 616 line = eval_command(&commands[i].bytes[0], registers, return_values);
617 617
618 if (line < 0) { /* Link command */ 618 if (line < 0) { /* Link command */
619 #ifdef TRACE 619 #ifdef TRACE
620 fprintf(MSG_OUT, "libdvdnav: Registers after transaction\n"); 620 fprintf(MSG_OUT, "libdvdnav: Registers after transaction\n");
621 vm_print_registers( registers ); 621 vm_print_registers( registers );
622 fprintf(MSG_OUT, "libdvdnav: eval: Doing Link/Jump/Call\n"); 622 fprintf(MSG_OUT, "libdvdnav: eval: Doing Link/Jump/Call\n");
623 #endif 623 #endif
624 return 1; 624 return 1;
625 } 625 }
626 626
627 if (line > 0) /* Goto command */ 627 if (line > 0) /* Goto command */
628 i = line - 1; 628 i = line - 1;
629 else /* Just continue on the next line */ 629 else /* Just continue on the next line */
630 i++; 630 i++;
631 631
632 total++; 632 total++;
633 } 633 }
634 634
635 memset(return_values, 0, sizeof(link_t)); 635 memset(return_values, 0, sizeof(link_t));
636 #ifdef TRACE 636 #ifdef TRACE
637 fprintf(MSG_OUT, "libdvdnav: Registers after transaction\n"); 637 fprintf(MSG_OUT, "libdvdnav: Registers after transaction\n");
638 vm_print_registers( registers ); 638 vm_print_registers( registers );
639 #endif 639 #endif
708 return "*** (bug)"; 708 return "*** (bug)";
709 } 709 }
710 710
711 void vm_print_link(link_t value) { 711 void vm_print_link(link_t value) {
712 char *cmd = linkcmd2str(value.command); 712 char *cmd = linkcmd2str(value.command);
713 713
714 switch(value.command) { 714 switch(value.command) {
715 case LinkNoLink: 715 case LinkNoLink:
716 case LinkTopC: 716 case LinkTopC:
717 case LinkNextC: 717 case LinkNextC:
718 case LinkPrevC: 718 case LinkPrevC:
746 break; 746 break;
747 case JumpVTS_PTT: 747 case JumpVTS_PTT:
748 fprintf(MSG_OUT, "libdvdnav: %s %d:%d\n", cmd, value.data1, value.data2); 748 fprintf(MSG_OUT, "libdvdnav: %s %d:%d\n", cmd, value.data1, value.data2);
749 break; 749 break;
750 case JumpSS_VTSM: 750 case JumpSS_VTSM:
751 fprintf(MSG_OUT, "libdvdnav: %s vts %d title %d menu %d\n", 751 fprintf(MSG_OUT, "libdvdnav: %s vts %d title %d menu %d\n",
752 cmd, value.data1, value.data2, value.data3); 752 cmd, value.data1, value.data2, value.data3);
753 break; 753 break;
754 case CallSS_FP: 754 case CallSS_FP:
755 fprintf(MSG_OUT, "libdvdnav: %s resume cell %d\n", cmd, value.data1); 755 fprintf(MSG_OUT, "libdvdnav: %s resume cell %d\n", cmd, value.data1);
756 break; 756 break;