git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

Core/cheat_search.c

      1 #include "gb.h"
      2 
      3 void GB_cheat_search_reset(GB_gameboy_t *gb)
      4 {
      5     if (gb->cheat_search_data) {
      6         free(gb->cheat_search_data);
      7         gb->cheat_search_data = NULL;
      8     }
      9     if (gb->cheat_search_bitmap) {
     10         free(gb->cheat_search_bitmap);
     11         gb->cheat_search_bitmap = NULL;
     12     }
     13     gb->cheat_search_count = 0;
     14 }
     15 
     16 bool GB_cheat_search_filter(GB_gameboy_t *gb, const char *expression, GB_cheat_search_data_type_t data_type)
     17 {
     18     GB_ASSERT_NOT_RUNNING(gb)
     19     
     20     // Make sure the expression is valid first
     21     if (GB_debugger_evaluate_cheat_filter(gb, expression, NULL, 0, 0)) {
     22         return false;
     23     }
     24     gb->cheat_search_data_type = data_type;
     25 
     26     if (gb->cheat_search_count == 0) {
     27         GB_cheat_search_reset(gb);
     28         gb->cheat_search_count = gb->ram_size + gb->mbc_ram_size + sizeof(gb->hram);
     29         gb->cheat_search_data = malloc(gb->cheat_search_count);
     30         gb->cheat_search_bitmap = malloc((gb->cheat_search_count + 7) / 8);
     31         memset(gb->cheat_search_data, 0, gb->cheat_search_count);
     32         memset(gb->cheat_search_bitmap, 0, (gb->cheat_search_count + 7) / 8);
     33     }
     34     
     35     uint8_t mask = 1;
     36     uint8_t *old_data = gb->cheat_search_data;
     37     uint8_t *bitmap = gb->cheat_search_bitmap;
     38     uint8_t *new_data = gb->ram;
     39     
     40     for (unsigned i = gb->ram_size + gb->mbc_ram_size + sizeof(gb->hram); i--;) {
     41         if (*bitmap & mask) {
     42             goto skip;
     43         }
     44         bool result = false;
     45         if (data_type & GB_CHEAT_SEARCH_DATA_TYPE_16BIT) {
     46             // The last byte of each section always fails on 16-bit searches
     47             if ((new_data != gb->ram + gb->ram_size - 1 &&
     48                  new_data != gb->mbc_ram + gb->mbc_ram_size - 1 &&
     49                  new_data != gb->hram + sizeof(gb->hram) - 1)) {
     50                 uint16_t old = old_data[0] | (old_data[1] << 8);
     51                 uint16_t new = new_data[0] | (new_data[1] << 8);
     52                 if (data_type & GB_CHEAT_SEARCH_DATA_TYPE_BE_BIT) {
     53                     old = __builtin_bswap16(old);
     54                     new = __builtin_bswap16(new);
     55                 }
     56                 GB_debugger_evaluate_cheat_filter(gb, expression, &result, old, new);
     57             }
     58         }
     59         else {
     60             GB_debugger_evaluate_cheat_filter(gb, expression, &result, *old_data, *new_data);
     61         }
     62         if (result) {
     63             // Filter passed, update old value
     64             *old_data = *new_data;
     65             if (data_type & GB_CHEAT_SEARCH_DATA_TYPE_16BIT) {
     66                 old_data[1] = new_data[1];
     67             }
     68         }
     69         else {
     70             // Did not pass filter, remove address
     71             *bitmap |= mask;
     72             gb->cheat_search_count--;
     73         }
     74     skip:;
     75         old_data++;
     76         if (new_data == gb->ram + gb->ram_size - 1 && gb->mbc_ram_size) {
     77             new_data = gb->mbc_ram;
     78         }
     79         else if (new_data == gb->mbc_ram + gb->mbc_ram_size - 1) {
     80             new_data = gb->hram;
     81         }
     82         else {
     83             new_data++;
     84         }
     85         mask <<= 1;
     86         if (mask == 0) {
     87             mask = 1;
     88             bitmap++;
     89         }
     90     }
     91     
     92     return true;
     93 }
     94 
     95 size_t GB_cheat_search_result_count(GB_gameboy_t *gb)
     96 {
     97     return gb->cheat_search_count;
     98 }
     99 
    100 void GB_cheat_search_get_results(GB_gameboy_t *gb, GB_cheat_search_result_t *results)
    101 {
    102     uint8_t mask = 1;
    103     uint8_t *old_data = gb->cheat_search_data;
    104     uint8_t *bitmap = gb->cheat_search_bitmap;
    105     size_t count = gb->cheat_search_count;
    106     while (count) {
    107         if (!(*bitmap & mask)) {
    108             count--;
    109             if (gb->cheat_search_data_type & GB_CHEAT_SEARCH_DATA_TYPE_16BIT) {
    110                 // Do not check for end of section, data_type is required to be the same as the last filter call
    111                 uint16_t old = old_data[0] | (old_data[1] << 8);
    112                 if (gb->cheat_search_data_type & GB_CHEAT_SEARCH_DATA_TYPE_BE_BIT) {
    113                     old = __builtin_bswap16(old);
    114                 }
    115                 results->value = old;
    116             }
    117             else {
    118                 results->value = *old_data;
    119             }
    120             size_t offset = old_data - gb->cheat_search_data;
    121             if (offset < gb->ram_size) {
    122                 results->bank = offset / 0x1000;
    123                 results->addr = (offset & 0xfff) + (results->bank? 0xd000 : 0xc000);
    124             }
    125             else if (offset < gb->ram_size + gb->mbc_ram_size) {
    126                 results->addr = (offset & 0x1fff) + 0xa000;
    127                 results->bank = (offset - gb->ram_size) / 0x2000;
    128             }
    129             else {
    130                 results->addr = (offset & 0x7f) + 0xff80;
    131                 results->bank = 0;
    132             }
    133             results++;
    134         }
    135         old_data++;
    136         mask <<= 1;
    137         if (mask == 0) {
    138             mask = 1;
    139             bitmap++;
    140         }
    141     }
    142 }

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.