duckstation

duckstation, but archived from the revision just before upstream changed it to a proprietary software project, this version is the libre one
git clone https://git.neptards.moe/u3shit/duckstation.git
Log | Files | Refs | README | LICENSE

operand.c (13124B)


      1 #include "rc_internal.h"
      2 
      3 #include <stdlib.h>
      4 #include <ctype.h>
      5 #include <math.h>
      6 #include <string.h>
      7 
      8 #ifndef RC_DISABLE_LUA
      9 
     10 RC_BEGIN_C_DECLS
     11 
     12 #include <lua.h>
     13 #include <lauxlib.h>
     14 
     15 RC_END_C_DECLS
     16 
     17 #endif /* RC_DISABLE_LUA */
     18 
     19 static int rc_parse_operand_lua(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse) {
     20   const char* aux = *memaddr;
     21 #ifndef RC_DISABLE_LUA
     22   const char* id;
     23 #endif
     24 
     25   if (*aux++ != '@') {
     26     return RC_INVALID_LUA_OPERAND;
     27   }
     28 
     29   if (!isalpha((unsigned char)*aux)) {
     30     return RC_INVALID_LUA_OPERAND;
     31   }
     32 
     33 #ifndef RC_DISABLE_LUA
     34   id = aux;
     35 #endif
     36 
     37   while (isalnum((unsigned char)*aux) || *aux == '_') {
     38     aux++;
     39   }
     40 
     41 #ifndef RC_DISABLE_LUA
     42 
     43   if (parse->L != 0) {
     44     if (!lua_istable(parse->L, parse->funcs_ndx)) {
     45       return RC_INVALID_LUA_OPERAND;
     46     }
     47 
     48     lua_pushlstring(parse->L, id, aux - id);
     49     lua_gettable(parse->L, parse->funcs_ndx);
     50 
     51     if (!lua_isfunction(parse->L, -1)) {
     52       lua_pop(parse->L, 1);
     53       return RC_INVALID_LUA_OPERAND;
     54     }
     55 
     56     self->value.luafunc = luaL_ref(parse->L, LUA_REGISTRYINDEX);
     57   }
     58 
     59 #else
     60   (void)parse;
     61 #endif /* RC_DISABLE_LUA */
     62 
     63   self->type = RC_OPERAND_LUA;
     64   *memaddr = aux;
     65   return RC_OK;
     66 }
     67 
     68 static int rc_parse_operand_variable(rc_operand_t* self, const char** memaddr) {
     69   const char* aux = *memaddr;
     70   size_t i;
     71   char varName[RC_VALUE_MAX_NAME_LENGTH + 1] = { 0 };
     72 
     73   for (i = 0; i < RC_VALUE_MAX_NAME_LENGTH && *aux != '}'; i++) {
     74     if (!rc_is_valid_variable_character(*aux, i == 0))
     75       return RC_INVALID_VARIABLE_NAME;
     76 
     77     varName[i] = *aux++;
     78   }
     79 
     80   if (i == 0)
     81     return RC_INVALID_VARIABLE_NAME;
     82 
     83   if (*aux != '}')
     84     return RC_INVALID_VARIABLE_NAME;
     85 
     86   ++aux;
     87 
     88   if (strcmp(varName, "recall") == 0) {
     89     self->type = RC_OPERAND_RECALL;
     90   }
     91   else { /* process named variable when feature is available.*/
     92     return RC_UNKNOWN_VARIABLE_NAME;
     93   }
     94 
     95   *memaddr = aux;
     96   return RC_OK;
     97 }
     98 
     99 static int rc_parse_operand_memory(rc_operand_t* self, const char** memaddr, rc_parse_state_t* parse, uint8_t is_indirect) {
    100   const char* aux = *memaddr;
    101   uint32_t address;
    102   uint8_t size;
    103   int ret;
    104 
    105   switch (*aux) {
    106     case 'd': case 'D':
    107       self->type = RC_OPERAND_DELTA;
    108       ++aux;
    109       break;
    110 
    111     case 'p': case 'P':
    112       self->type = RC_OPERAND_PRIOR;
    113       ++aux;
    114       break;
    115 
    116     case 'b': case 'B':
    117       self->type = RC_OPERAND_BCD;
    118       ++aux;
    119       break;
    120 
    121     case '~':
    122       self->type = RC_OPERAND_INVERTED;
    123       ++aux;
    124       break;
    125 
    126     default:
    127       self->type = RC_OPERAND_ADDRESS;
    128       break;
    129   }
    130 
    131   ret = rc_parse_memref(&aux, &self->size, &address);
    132   if (ret != RC_OK)
    133     return ret;
    134 
    135   size = rc_memref_shared_size(self->size);
    136   if (size != self->size && self->type == RC_OPERAND_PRIOR) {
    137     /* if the shared size differs from the requested size and it's a prior operation, we
    138      * have to check to make sure both sizes use the same mask, or the prior value may be
    139      * updated when bits outside the mask are modified, which would make it look like the
    140      * current value once the mask is applied. if the mask differs, create a new 
    141      * non-shared record for tracking the prior data. */
    142     if (rc_memref_mask(size) != rc_memref_mask(self->size))
    143       size = self->size;
    144   }
    145 
    146   self->value.memref = rc_alloc_memref(parse, address, size, is_indirect);
    147   if (parse->offset < 0)
    148     return parse->offset;
    149 
    150   *memaddr = aux;
    151   return RC_OK;
    152 }
    153 
    154 int rc_parse_operand(rc_operand_t* self, const char** memaddr, uint8_t is_indirect, rc_parse_state_t* parse) {
    155   const char* aux = *memaddr;
    156   char* end;
    157   int ret;
    158   unsigned long value;
    159   int negative;
    160   int allow_decimal = 0;
    161 
    162   self->size = RC_MEMSIZE_32_BITS;
    163 
    164   switch (*aux) {
    165     case 'h': case 'H': /* hex constant */
    166       if (aux[2] == 'x' || aux[2] == 'X') {
    167         /* H0x1234 is a typo - either H1234 or 0xH1234 was probably meant */
    168         return RC_INVALID_CONST_OPERAND;
    169       }
    170 
    171       value = strtoul(++aux, &end, 16);
    172       if (end == aux)
    173         return RC_INVALID_CONST_OPERAND;
    174 
    175       if (value > 0xffffffffU)
    176         value = 0xffffffffU;
    177 
    178       self->type = RC_OPERAND_CONST;
    179       self->value.num = (unsigned)value;
    180 
    181       aux = end;
    182       break;
    183 
    184     case 'f': case 'F': /* floating point constant */
    185       if (isalpha((unsigned char)aux[1])) {
    186         ret = rc_parse_operand_memory(self, &aux, parse, is_indirect);
    187 
    188         if (ret < 0)
    189           return ret;
    190 
    191         break;
    192       }
    193       allow_decimal = 1;
    194       /* fall through */
    195     case 'v': case 'V': /* signed integer constant */
    196       ++aux;
    197       /* fall through */
    198     case '+': case '-': /* signed integer constant */
    199       negative = 0;
    200       if (*aux == '-') {
    201         negative = 1;
    202         ++aux;
    203       }
    204       else if (*aux == '+') {
    205         ++aux;
    206       }
    207 
    208       value = strtoul(aux, &end, 10);
    209 
    210       if (*end == '.' && allow_decimal) {
    211         /* custom parser for decimal values to ignore locale */
    212         unsigned long shift = 1;
    213         unsigned long fraction = 0;
    214 
    215         aux = end + 1;
    216         if (*aux < '0' || *aux > '9')
    217           return RC_INVALID_FP_OPERAND;
    218 
    219         do {
    220           /* only keep as many digits as will fit in a 32-bit value to prevent overflow.
    221            * float only has around 7 digits of precision anyway. */
    222           if (shift < 1000000000) {
    223             fraction *= 10;
    224             fraction += (*aux - '0');
    225             shift *= 10;
    226           }
    227           ++aux;
    228         } while (*aux >= '0' && *aux <= '9');
    229 
    230         if (fraction != 0) {
    231           /* non-zero fractional part, convert to double and merge in integer portion */
    232           const double dbl_fraction = ((double)fraction) / ((double)shift);
    233           if (negative)
    234             self->value.dbl = ((double)(-((long)value))) - dbl_fraction;
    235           else
    236             self->value.dbl = (double)value + dbl_fraction;
    237         }
    238         else {
    239           /* fractional part is 0, just convert the integer portion */
    240           if (negative)
    241             self->value.dbl = (double)(-((long)value));
    242           else
    243             self->value.dbl = (double)value;
    244         }
    245 
    246         self->type = RC_OPERAND_FP;
    247       }
    248       else {
    249         /* not a floating point value, make sure something was read and advance the read pointer */
    250         if (end == aux)
    251           return allow_decimal ? RC_INVALID_FP_OPERAND : RC_INVALID_CONST_OPERAND;
    252 
    253         aux = end;
    254 
    255         if (value > 0x7fffffffU)
    256           value = 0x7fffffffU;
    257 
    258         self->type = RC_OPERAND_CONST;
    259 
    260         if (negative)
    261           self->value.num = (unsigned)(-((long)value));
    262         else
    263           self->value.num = (unsigned)value;
    264       }
    265       break;
    266     case '{': /* variable */
    267       ++aux;
    268       ret = rc_parse_operand_variable(self, &aux);
    269       if (ret < 0)
    270         return ret;
    271 
    272       break;
    273 
    274     case '0':
    275       if (aux[1] == 'x' || aux[1] == 'X') { /* hex integer constant */
    276         /* fallthrough */ /* to default */
    277     default:
    278         ret = rc_parse_operand_memory(self, &aux, parse, is_indirect);
    279 
    280         if (ret < 0)
    281           return ret;
    282 
    283         break;
    284       }
    285       /* fallthrough */ /* to case '1' for case '0' where not '0x' */
    286     case '1': case '2': case '3': case '4': case '5': /* unsigned integer constant */
    287     case '6': case '7': case '8': case '9':
    288       value = strtoul(aux, &end, 10);
    289       if (end == aux)
    290         return RC_INVALID_CONST_OPERAND;
    291 
    292       if (value > 0xffffffffU)
    293         value = 0xffffffffU;
    294 
    295       self->type = RC_OPERAND_CONST;
    296       self->value.num = (unsigned)value;
    297 
    298       aux = end;
    299       break;
    300 
    301     case '@':
    302       ret = rc_parse_operand_lua(self, &aux, parse);
    303 
    304       if (ret < 0)
    305         return ret;
    306 
    307       break;
    308   }
    309 
    310   *memaddr = aux;
    311   return RC_OK;
    312 }
    313 
    314 #ifndef RC_DISABLE_LUA
    315 
    316 typedef struct {
    317   rc_peek_t peek;
    318   void* ud;
    319 }
    320 rc_luapeek_t;
    321 
    322 static int rc_luapeek(lua_State* L) {
    323   uint32_t address = (uint32_t)luaL_checkinteger(L, 1);
    324   uint32_t num_bytes = (uint32_t)luaL_checkinteger(L, 2);
    325   rc_luapeek_t* luapeek = (rc_luapeek_t*)lua_touserdata(L, 3);
    326 
    327   uint32_t value = luapeek->peek(address, num_bytes, luapeek->ud);
    328 
    329   lua_pushinteger(L, value);
    330   return 1;
    331 }
    332 
    333 #endif /* RC_DISABLE_LUA */
    334 
    335 int rc_operand_is_float_memref(const rc_operand_t* self) {
    336   switch (self->size) {
    337     case RC_MEMSIZE_FLOAT:
    338     case RC_MEMSIZE_FLOAT_BE:
    339     case RC_MEMSIZE_DOUBLE32:
    340     case RC_MEMSIZE_DOUBLE32_BE:
    341     case RC_MEMSIZE_MBF32:
    342     case RC_MEMSIZE_MBF32_LE:
    343       return 1;
    344 
    345     default:
    346       return 0;
    347   }
    348 }
    349 
    350 int rc_operand_is_memref(const rc_operand_t* self) {
    351   switch (self->type) {
    352     case RC_OPERAND_CONST:
    353     case RC_OPERAND_FP:
    354     case RC_OPERAND_LUA:
    355     case RC_OPERAND_RECALL:
    356       return 0;
    357 
    358     default:
    359       return 1;
    360   }
    361 }
    362 
    363 int rc_operand_is_recall(const rc_operand_t* self) {
    364   switch (self->type) {
    365     case RC_OPERAND_RECALL:
    366       return 1;
    367 
    368     default:
    369       return 0;
    370   }
    371 }
    372 
    373 int rc_operand_is_float(const rc_operand_t* self) {
    374   if (self->type == RC_OPERAND_FP)
    375     return 1;
    376 
    377   return rc_operand_is_float_memref(self);
    378 }
    379 
    380 uint32_t rc_transform_operand_value(uint32_t value, const rc_operand_t* self) {
    381   switch (self->type)
    382   {
    383     case RC_OPERAND_BCD:
    384       switch (self->size)
    385       {
    386         case RC_MEMSIZE_8_BITS:
    387           value = ((value >> 4) & 0x0f) * 10
    388                 + ((value     ) & 0x0f);
    389           break;
    390 
    391         case RC_MEMSIZE_16_BITS:
    392         case RC_MEMSIZE_16_BITS_BE:
    393           value = ((value >> 12) & 0x0f) * 1000
    394                 + ((value >> 8) & 0x0f) * 100
    395                 + ((value >> 4) & 0x0f) * 10
    396                 + ((value     ) & 0x0f);
    397           break;
    398 
    399         case RC_MEMSIZE_24_BITS:
    400         case RC_MEMSIZE_24_BITS_BE:
    401           value = ((value >> 20) & 0x0f) * 100000
    402                 + ((value >> 16) & 0x0f) * 10000
    403                 + ((value >> 12) & 0x0f) * 1000
    404                 + ((value >> 8) & 0x0f) * 100
    405                 + ((value >> 4) & 0x0f) * 10
    406                 + ((value     ) & 0x0f);
    407           break;
    408 
    409         case RC_MEMSIZE_32_BITS:
    410         case RC_MEMSIZE_32_BITS_BE:
    411         case RC_MEMSIZE_VARIABLE:
    412           value = ((value >> 28) & 0x0f) * 10000000
    413                 + ((value >> 24) & 0x0f) * 1000000
    414                 + ((value >> 20) & 0x0f) * 100000
    415                 + ((value >> 16) & 0x0f) * 10000
    416                 + ((value >> 12) & 0x0f) * 1000
    417                 + ((value >> 8) & 0x0f) * 100
    418                 + ((value >> 4) & 0x0f) * 10
    419                 + ((value     ) & 0x0f);
    420           break;
    421 
    422         default:
    423           break;
    424       }
    425       break;
    426 
    427     case RC_OPERAND_INVERTED:
    428       switch (self->size)
    429       {
    430         case RC_MEMSIZE_LOW:
    431         case RC_MEMSIZE_HIGH:
    432           value ^= 0x0f;
    433           break;
    434 
    435         case RC_MEMSIZE_8_BITS:
    436           value ^= 0xff;
    437           break;
    438 
    439         case RC_MEMSIZE_16_BITS:
    440         case RC_MEMSIZE_16_BITS_BE:
    441           value ^= 0xffff;
    442           break;
    443 
    444         case RC_MEMSIZE_24_BITS:
    445         case RC_MEMSIZE_24_BITS_BE:
    446           value ^= 0xffffff;
    447           break;
    448 
    449         case RC_MEMSIZE_32_BITS:
    450         case RC_MEMSIZE_32_BITS_BE:
    451         case RC_MEMSIZE_VARIABLE:
    452           value ^= 0xffffffff;
    453           break;
    454 
    455         default:
    456           value ^= 0x01;
    457           break;
    458       }
    459       break;
    460 
    461     default:
    462       break;
    463   }
    464 
    465   return value;
    466 }
    467 
    468 void rc_evaluate_operand(rc_typed_value_t* result, rc_operand_t* self, rc_eval_state_t* eval_state) {
    469 #ifndef RC_DISABLE_LUA
    470   rc_luapeek_t luapeek;
    471 #endif /* RC_DISABLE_LUA */
    472 
    473   /* step 1: read memory */
    474   switch (self->type) {
    475     case RC_OPERAND_CONST:
    476       result->type = RC_VALUE_TYPE_UNSIGNED;
    477       result->value.u32 = self->value.num;
    478       return;
    479 
    480     case RC_OPERAND_FP:
    481       result->type = RC_VALUE_TYPE_FLOAT;
    482       result->value.f32 = (float)self->value.dbl;
    483       return;
    484 
    485     case RC_OPERAND_LUA:
    486       result->type = RC_VALUE_TYPE_UNSIGNED;
    487       result->value.u32 = 0;
    488 
    489 #ifndef RC_DISABLE_LUA
    490       if (eval_state->L != 0) {
    491         lua_rawgeti(eval_state->L, LUA_REGISTRYINDEX, self->value.luafunc);
    492         lua_pushcfunction(eval_state->L, rc_luapeek);
    493 
    494         luapeek.peek = eval_state->peek;
    495         luapeek.ud = eval_state->peek_userdata;
    496 
    497         lua_pushlightuserdata(eval_state->L, &luapeek);
    498 
    499         if (lua_pcall(eval_state->L, 2, 1, 0) == LUA_OK) {
    500           if (lua_isboolean(eval_state->L, -1)) {
    501             result->value.u32 = (uint32_t)lua_toboolean(eval_state->L, -1);
    502           }
    503           else {
    504             result->value.u32 = (uint32_t)lua_tonumber(eval_state->L, -1);
    505           }
    506         }
    507 
    508         lua_pop(eval_state->L, 1);
    509       }
    510 
    511 #endif /* RC_DISABLE_LUA */
    512 
    513       break;
    514 
    515     case RC_OPERAND_RECALL:
    516       result->type = eval_state->recall_value.type;
    517       result->value = eval_state->recall_value.value;
    518       return;
    519 
    520     default:
    521       result->type = RC_VALUE_TYPE_UNSIGNED;
    522       result->value.u32 = rc_get_memref_value(self->value.memref, self->type, eval_state);
    523       break;
    524   }
    525 
    526   /* step 2: convert read memory to desired format */
    527   rc_transform_memref_value(result, self->size);
    528 
    529   /* step 3: apply logic (BCD/invert) */
    530   if (result->type == RC_VALUE_TYPE_UNSIGNED)
    531     result->value.u32 = rc_transform_operand_value(result->value.u32, self);
    532 }