-
Notifications
You must be signed in to change notification settings - Fork 0
/
watches.c
165 lines (147 loc) · 5.48 KB
/
watches.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "watches.h"
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "fake6502.h"
#include "dissassembler.h"
#include "util.h"
typedef struct {
watch_t watch;
bool enabled;
} internalWatch_t;
// Watches need an address and length and type.
static internalWatch_t watches[MAX_WATCHES] = {0};
static size_t numWatches = 0;
// Simply returns the number of watches that have been added.
size_t countWatches() {
return numWatches;
}
// Can add up to MAX_WATCHES watches.
size_t addWatch(watch_t watch) {
if (numWatches >= MAX_WATCHES) {
printf("ERROR: Cannot add watch as the maximum number of watches (%d) has been reached!\n", MAX_WATCHES);
return 0;
}
for (size_t i = 0; i < MAX_WATCHES; ++i) {
if (!watches[i].enabled) {
watches[i].watch = watch;
watches[i].enabled = true;
++numWatches;
break;
}
}
return numWatches;
}
// Add a watch in string form of <address><type><length>.
// If no length is specified then it defaults to 16 except for strings which is 64.
// Returns the number of watches added or zero on error.
size_t addWatchString(char const *str) {
watch_t watch = {0, 0x10, hex};
// Copy string as we will mutate.
char buffer[64];
strncpy(buffer, str, sizeof(buffer)/sizeof(char));
buffer[sizeof(buffer)/sizeof(char) - 1] = 0;
// We split each string into substrings.
char *hyphen = strchr(buffer, '-');
if (hyphen) *hyphen = 0; // Make it a terminal character.
char *address = buffer;
while(*address && isspace(*address)) ++address; // trim leading space
if (isHexNumber(address)) {
watch.address = (uint16_t) strtol(buffer, NULL, 16);
} else {
// TODO: Check for label
printf("ERROR: The value '%s' specified for the address in the watch '%s' is not a valid hexadecimal number!\n", address, str);
return 0;
}
// Now look for type (this should be safe as we have padding);
char *type = hyphen + 1;
if (hyphen && *type != 0) {
while(*type && isspace(*type)) ++type; // trim leading space
switch (*type) {
case 'a':
case 'A':
watch.type = assembler;
break;
case 'c':
case 'C':
watch.type = ascii;
break;
case 'h':
case 'H':
watch.type = hex;
break;
case 's':
case 'S':
watch.type = string;
watch.length = 0x40; // Default length for string.
break;
default:
printf("ERROR: The value '%c' specified for the type in the watch '%s' is not one of a, A, c, C, h, H, s or S!\n", *type, str);
return 0;
}
hyphen = strchr(type, '-');
if (hyphen) *hyphen = 0; // Make it a terminal character.
// Now do the length.
char *length = hyphen + 1;
if (hyphen && *length != 0) {
if (!isHexNumber(length)) {
printf("ERROR: The value '%s' specified for the length in the watch '%s' is not a valid hexadecimal number!\n", length, str);
return 0;
}
watch.length = (uint16_t)strtol(length, NULL, 16);
}
}
return addWatch(watch);
}
// Removes the watch numbered n.
size_t removeWatch(size_t n) {
int num = 0;
for(int w = 0; w < MAX_WATCHES; ++w) {
if (!watches[w].enabled) continue;
++num;
if (num == n) {
watches[w].enabled = false;
--numWatches;
return numWatches;
}
}
// If we got here we couldn't find the watch to remove.
printf("ERROR: Cannot find watch number %zx!\n", n);
return 0;
}
// Prints out the defined watches in 16 byte chunks.
void listWatches(FILE *fp, uint8_t *ram) {
int num = 0;
for(int w = 0; w < MAX_WATCHES; ++w) {
if (!watches[w].enabled) continue;
++num;
// Get the watch and loop over the memory addressed.
watch_t *watch = &watches[w].watch;
uint16_t address = watch->address;
for (size_t i = 0; i < watch->length; ++i) {
if (address >= MAX_ADDRESS) break;
// We print out 16 bytes for hex and ascii, 64 for string and 1(ish) for assembler.
const int rowLength = watch->type == hex || watch->type == ascii ? 0x10 : watch->type == string ? 0x40 : 0x01;
if (i % rowLength == 0) {
// We need to put a new line on all but the first line.
if (i) printf("\n");
fprintf(fp, "WATCH %02x : $%04x: ", num, address);
}
if (watch->type == hex) fprintf(fp, "$%02x ", ram[address]);
if (watch->type == ascii) fprintf(fp, "'%c' ", ram[address]);
if (watch->type == string) {
if (ram[address] == 0 || ram[address] == 10 || ram[address] == 13) break; // Null, CR or LF indicate end of string.
fprintf(fp, "%c", ram[address]);
}
if (watch->type == assembler) {
const diassembleResult_t dasm = dissassemble(&ram[address]); // This call could exceed the array bounds.
fprintf(fp, "%s", dasm.assembler);
// We may now need to advance the address and i;
if (dasm.length > 1) {++address; ++i;}
if (dasm.length > 2) {++address; ++i;}
}
++address;
}
fprintf(fp, "\n");
}
}