changeset 19:7e8628911b4f src

Implement General Register Counters or GPRM counters. Navigation timers are not supported yet. SPRM[9] and SPRM[10].
author jcdutton
date Fri, 12 Apr 2002 20:06:41 +0000
parents e6ac0a8d9c14
children 6061277509ee
files decoder.c decoder.h vm.c
diffstat 3 files changed, 68 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/decoder.c	Fri Apr 12 12:43:36 2002 +0000
+++ b/decoder.c	Fri Apr 12 20:06:41 2002 +0000
@@ -58,6 +58,42 @@
   return (uint32_t) result;
 }
 
+static uint16_t get_GPRM(registers_t* registers, uint8_t reg) {
+  if (registers->GPRM_mode[reg] & 0x01) {
+    struct timeval current_time, time_offset;
+    uint16_t result;
+    /* Counter mode */
+    /* fprintf(stderr, "Getting counter %d\n",reg);*/
+    gettimeofday(&current_time, NULL);
+    time_offset.tv_sec = current_time.tv_sec - registers->GPRM_time[reg].tv_sec;
+    time_offset.tv_usec = current_time.tv_usec - registers->GPRM_time[reg].tv_usec;
+    if (time_offset.tv_usec < 0) { 
+      time_offset.tv_sec--; 
+      time_offset.tv_usec += 1000000;
+    }
+    result = (uint16_t) (time_offset.tv_sec & 0xffff);
+    registers->GPRM[reg]=result;
+    return result; 
+
+  } else {
+    /* Register mode */
+    return registers->GPRM[reg];
+  }
+  
+}
+
+static void set_GPRM(registers_t* registers, uint8_t reg, uint16_t value) {
+  if (registers->GPRM_mode[reg] & 0x01) {
+    struct timeval current_time;
+    /* Counter mode */
+    /* fprintf(stderr, "Setting counter %d\n",reg); */
+    gettimeofday(&current_time, NULL);
+    registers->GPRM_time[reg] = current_time;
+    registers->GPRM_time[reg].tv_sec -= value;
+  }
+  registers->GPRM[reg] = value;
+}
+
 /* Eval register code, can either be system or general register.
    SXXX_XXXX, where S is 1 if it is system register. */
 static uint16_t eval_reg(command_t* command, uint8_t reg) {
@@ -67,7 +103,7 @@
       }
     return command->registers->SPRM[reg & 0x1f]; /*  FIXME max 24 not 32 */
   } else {
-    return command->registers->GPRM[reg & 0x0f];
+    return get_GPRM(command->registers, reg & 0x0f) ;
   }
 }
 
@@ -90,7 +126,7 @@
   if(imm) /* immediate */
     return vm_getbits(command, ((byte*8)+1), 7);
   else
-    return command->registers->GPRM[vm_getbits(command, ((byte*8)+4), 4)];
+    return get_GPRM(command->registers, (vm_getbits(command, ((byte*8)+4), 4)) );
 }
 
 
@@ -341,14 +377,12 @@
       data = eval_reg_or_data(command, vm_getbits(command, 3, 1), 2);
       data2 = vm_getbits(command, 44, 4);
       if(vm_getbits(command, 40, 1)) {
-	fprintf(stderr, "Detected SetGPRMMD Counter!! This is unsupported.\n");
 	command->registers->GPRM_mode[data2] |= 1; /* Set bit 0 */
       } else {
-	fprintf(stderr, "Detected ResetGPRMMD Counter!! This is unsupported.\n");
 	command->registers->GPRM_mode[data2] &= ~ 0x01; /* Reset bit 0 */
       }
       if(cond) {
-	command->registers->GPRM[data2] = data;
+        set_GPRM(command->registers, data2, data);
       }
       break;
     case 6: /*  Set system reg 8 (Highlighted button) */
@@ -374,48 +408,48 @@
   int32_t     tmp; 
   switch(op) {
     case 1:
-      command->registers->GPRM[reg] = data;
+      set_GPRM(command->registers, reg, data);
       break;
     case 2: /* SPECIAL CASE - SWAP! */
-      command->registers->GPRM[reg2] = command->registers->GPRM[reg];
-      command->registers->GPRM[reg] = data;
+      set_GPRM(command->registers, reg2, get_GPRM(command->registers, reg));
+      set_GPRM(command->registers, reg, data);
       break;
     case 3:
-      tmp = command->registers->GPRM[reg] + data;
+      tmp = get_GPRM(command->registers, reg) + data;
       if(tmp > shortmax) tmp = shortmax;
-      command->registers->GPRM[reg] = (uint16_t)tmp;
+      set_GPRM(command->registers, reg, (uint16_t)tmp);
       break;
     case 4:
-      tmp = command->registers->GPRM[reg] - data;
+      tmp = get_GPRM(command->registers, reg) - data;
       if(tmp < 0) tmp = 0;
-      command->registers->GPRM[reg] = (uint16_t)tmp;
+      set_GPRM(command->registers, reg, (uint16_t)tmp);
       break;
     case 5:
-      tmp = command->registers->GPRM[reg] * data;
+      tmp = get_GPRM(command->registers, reg) * data;
       if(tmp >= shortmax) tmp = shortmax;
-      command->registers->GPRM[reg] = (uint16_t)tmp;
+      set_GPRM(command->registers, reg, (uint16_t)tmp);
       break;
     case 6:
       if (data != 0) {
-       command->registers->GPRM[reg] /= data;
+        set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) / data) );
       } else {
-       command->registers->GPRM[reg] =  0; /* Avoid that divide by zero! */
+        set_GPRM(command->registers, reg, 0); /* Avoid that divide by zero! */
       }
       break;
     case 7:
-      command->registers->GPRM[reg] %= data;
+      set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) % data) );
       break;
     case 8: /* SPECIAL CASE - RND! */
-      command->registers->GPRM[reg] = (uint16_t) ((float) data * rand()/(RAND_MAX+1.0));
+      set_GPRM(command->registers, reg, ((uint16_t) ((float) data * rand()/(RAND_MAX+1.0))) );
       break;
     case 9:
-      command->registers->GPRM[reg] &= data;
+      set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) & data) );
       break;
     case 10:
-      command->registers->GPRM[reg] |= data;
+      set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) | data) );
       break;
     case 11:
-      command->registers->GPRM[reg] ^= data;
+      set_GPRM(command->registers, reg, (get_GPRM(command->registers, reg) ^ data) );
       break;
   }
 }
@@ -722,9 +756,12 @@
     fprintf(stderr, "%04x|", registers->SPRM[i]);
   fprintf(stderr, "\nGRPMS: ");
   for(i = 0; i < 16; i++)
-    fprintf(stderr, "%04x|", registers->GPRM[i]);
+    fprintf(stderr, "%04x|", get_GPRM(registers, i) );
   fprintf(stderr, "\nGmode: ");
   for(i = 0; i < 16; i++)
     fprintf(stderr, "%04x|", registers->GPRM_mode[i]);
+  fprintf(stderr, "\nGtime: ");
+  for(i = 0; i < 16; i++)
+    fprintf(stderr, "%04lx|", registers->GPRM_time[i].tv_sec & 0xffff);
   fprintf(stderr, "\n");
 }
--- a/decoder.h	Fri Apr 12 12:43:36 2002 +0000
+++ b/decoder.h	Fri Apr 12 20:06:41 2002 +0000
@@ -27,6 +27,8 @@
 
 #include "config.h"
 #include <inttypes.h>
+#include <sys/time.h>
+
 #include <dvdread/ifo_types.h> /*  vm_cmd_t */
 
 /* Uncomment for tracing */
@@ -86,6 +88,7 @@
   uint16_t SPRM[24];
   uint16_t GPRM[16];
   uint8_t  GPRM_mode[16];  /* Need to have some thing to indicate normal/counter mode for every GPRM */
+  struct timeval GPRM_time[16]; /* For counter mode */
 } registers_t;
 
 typedef struct
--- a/vm.c	Fri Apr 12 12:43:36 2002 +0000
+++ b/vm.c	Fri Apr 12 20:06:41 2002 +0000
@@ -167,6 +167,8 @@
   memset((vm->state).registers.SPRM, 0, sizeof(uint16_t)*24);
   memset((vm->state).registers.GPRM, 0, sizeof((vm->state).registers.GPRM));
   memset((vm->state).registers.GPRM_mode, 0, sizeof((vm->state).registers.GPRM_mode));
+  memset((vm->state).registers.GPRM_mode, 0, sizeof((vm->state).registers.GPRM_mode));
+  memset((vm->state).registers.GPRM_time, 0, sizeof((vm->state).registers.GPRM_time));
   (vm->state).registers.SPRM[0] = ('e'<<8)|'n'; /*  Player Menu Languange code */
   (vm->state).AST_REG = 15; /*  15 why? */
   (vm->state).SPST_REG = 62; /*  62 why? */
@@ -1572,6 +1574,10 @@
 
 /*
  * $Log$
+ * Revision 1.11  2002/04/12 20:06:41  jcdutton
+ * Implement General Register Counters or GPRM counters.
+ * Navigation timers are not supported yet. SPRM[9] and SPRM[10].
+ *
  * Revision 1.10  2002/04/12 12:43:36  jcdutton
  * Display DVD disk region setting.
  * Display possible RCE region protection message.