SameBoy | Accurate GB/GBC emulator |
| download: https://git.y1.nz/archives/sameboy.tar.gz | |
| README | Files | Log | Refs | LICENSE |
Core/symbol_hash.c
1 #include "gb.h"
2 #include <stdint.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/types.h>
6
7 static size_t map_find_symbol_index(GB_symbol_map_t *map, uint16_t addr, bool is_local)
8 {
9 if (!map->symbols) {
10 return 0;
11 }
12 ssize_t min = 0;
13 ssize_t max = map->n_symbols;
14 while (min < max) {
15 size_t pivot = (min + max) / 2;
16 if (map->symbols[pivot].addr == addr && map->symbols[pivot].is_local == is_local) return pivot;
17 if ((map->symbols[pivot].addr * 2 + !map->symbols[pivot].is_local) > (addr * 2 + !is_local)) {
18 max = pivot;
19 }
20 else {
21 min = pivot + 1;
22 }
23 }
24 return (size_t) min;
25 }
26
27 GB_bank_symbol_t *GB_map_add_symbol(GB_symbol_map_t *map, uint16_t addr, const char *name)
28 {
29 bool is_local = strchr(name, '.');
30 size_t index = map_find_symbol_index(map, addr, is_local);
31
32 map->symbols = realloc(map->symbols, (map->n_symbols + 1) * sizeof(map->symbols[0]));
33 memmove(&map->symbols[index + 1], &map->symbols[index], (map->n_symbols - index) * sizeof(map->symbols[0]));
34 map->symbols[index].addr = addr;
35 map->symbols[index].name = strdup(name);
36 map->symbols[index].is_local = is_local;
37 map->n_symbols++;
38 return &map->symbols[index];
39 }
40
41 const GB_bank_symbol_t *GB_map_find_symbol(GB_symbol_map_t *map, uint16_t addr, bool prefer_local)
42 {
43 if (!map) return NULL;
44 size_t index = map_find_symbol_index(map, addr, prefer_local);
45 if (index >= map->n_symbols || map->symbols[index].addr != addr) {
46 index--;
47 }
48 if (index < map->n_symbols) {
49 while (index && map->symbols[index].addr == map->symbols[index - 1].addr && map->symbols[index].is_local == map->symbols[index - 1].is_local) {
50 index--;
51 }
52 return &map->symbols[index];
53 }
54 return NULL;
55 }
56
57 GB_symbol_map_t *GB_map_alloc(void)
58 {
59 GB_symbol_map_t *map = malloc(sizeof(*map));
60 memset(map, 0, sizeof(*map));
61 return map;
62 }
63
64 void GB_map_free(GB_symbol_map_t *map)
65 {
66 for (unsigned i = 0; i < map->n_symbols; i++) {
67 free(map->symbols[i].name);
68 }
69
70 if (map->symbols) {
71 free(map->symbols);
72 }
73
74 free(map);
75 }
76
77 static unsigned hash_name(const char *name)
78 {
79 unsigned r = 0;
80 while (*name) {
81 r <<= 1;
82 if (r & 0x2000) {
83 r ^= 0x2001;
84 }
85 r ^= (unsigned char)*(name++);
86 }
87
88 return r;
89 }
90
91 void GB_reversed_map_add_symbol(GB_reversed_symbol_map_t *map, uint16_t bank, GB_bank_symbol_t *bank_symbol)
92 {
93 unsigned hash = hash_name(bank_symbol->name);
94 GB_symbol_t *symbol = malloc(sizeof(*symbol));
95 symbol->name = bank_symbol->name;
96 symbol->addr = bank_symbol->addr;
97 symbol->bank = bank;
98 symbol->next = map->buckets[hash];
99 map->buckets[hash] = symbol;
100 }
101
102 const GB_symbol_t *GB_reversed_map_find_symbol(GB_reversed_symbol_map_t *map, const char *name)
103 {
104 unsigned hash = hash_name(name);
105 GB_symbol_t *symbol = map->buckets[hash];
106
107 while (symbol) {
108 if (strcmp(symbol->name, name) == 0) return symbol;
109 symbol = symbol->next;
110 }
111
112 return NULL;
113 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.