OXYGENHUB
# 9120e87480a6 enhanced-x16-emulator / src / testbench.c
8.9 KiB · C · last changed chore(): initial commit 25 days ago source blame history raw
1
// Commander X16 Emulator
2
// Copyright (c) 2019 Michael Steil
3
// All rights reserved. License: 2-clause BSD
4
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <string.h>
8
#include "memory.h"
9
#include "cpu/fake6502.h"
10
#include "glue.h"
11
#include "testbench.h"
12
13
int hex_to_int8(char* str);
14
int hex_to_int16(char* str);
15
bool hex_validate(char* str);
16
void invalid();
17
void ready();
18
19
size_t get_testline(char **lineptr, size_t *n, FILE *stream)
20
{
21
    char *cptr;
22
    size_t maxlen;
23
    size_t slen;
24
    int c;
25
26
    if(*lineptr == NULL) {
27
        *lineptr = malloc(256);
28
        *n = 256;
29
    }
30
31
    cptr = *lineptr;
32
    maxlen = *n;
33
    slen = 0;
34
35
    do {
36
        c = fgetc(stream);
37
38
        if (c == EOF) {
39
            break;
40
        }
41
42
        *cptr = c;
43
        ++cptr;
44
        ++slen;
45
46
        if (slen >= maxlen) {
47
            maxlen = maxlen << 1;
48
            *lineptr = realloc(*lineptr, maxlen);
49
            cptr = *lineptr + slen;
50
        }
51
    } while(c != '\n');
52
53
    *cptr = '\0';
54
    *n = maxlen;
55
    return slen;
56
}
57
58
void testbench_init()
59
{
60
    char* line = NULL;
61
62
    char addr[5] = "0000";
63
    char addr2[5] = "0000";
64
    char val[3] = "00";
65
66
    int iaddr, iaddr2, ival;
67
    size_t slen = 0;
68
69
    bool init_done = false;
70
71
    ready();
72
73
    while (!init_done) {
74
        size_t len = get_testline(&line, &slen, stdin);     //Read command from stdin
75
76
		if(len==0) {
77
			puts("Exit testbench.");
78
			exit(0);
79
		}
80
81
        if (strncmp(line, "RAM", 3) == 0) {                 //Set RAM bank
82
            if (len < 7) {
83
                invalid();
84
            } else {
85
                strncpy(val, line + 4, 2);
86
                ival = hex_to_int8(val);
87
                if (ival == -1) {
88
                    invalid();
89
                } else {
90
                    memory_set_ram_bank((uint8_t)ival);
91
                    ready();
92
                }
93
            }
94
        }
95
96
        else if (strncmp(line, "ROM", 3) == 0) {            //Set ROM bank
97
            if (len < 7) {
98
                invalid();
99
            } else {
100
                strncpy(val, line + 4, 2);
101
                ival = hex_to_int8(val);
102
                if (ival == -1) {
103
                    invalid();
104
                } else {
105
                    memory_set_rom_bank((uint8_t)ival);
106
                    ready();
107
                }
108
            }
109
        }
110
111
        else if (strncmp(line, "STM", 3) == 0) {            //Set memory address value
112
            if (len < 12) {
113
                invalid();
114
            } else {
115
                strncpy(addr, line + 4, 4);
116
                strncpy(val, line + 9, 2);
117
118
                iaddr = hex_to_int16(addr);
119
                ival = hex_to_int8(val);
120
121
                if (iaddr == -1 || ival == -1) {
122
                    invalid();
123
                } else {
124
                    write6502((uint16_t)iaddr, regs.db, (uint8_t)ival);
125
                    ready();
126
                }
127
            }
128
        }
129
130
        else if (strncmp(line, "FLM", 3) == 0) {            //Fill memory address range with value
131
            if (len < 17) {
132
                invalid();
133
            } else {
134
                strncpy(addr, line + 4, 4);
135
                strncpy(addr2, line + 9, 4);
136
                strncpy(val, line + 14, 2);
137
138
                iaddr = hex_to_int16(addr);
139
                iaddr2 = hex_to_int16(addr2);
140
                ival = hex_to_int8(val);
141
142
                if (iaddr == -1 || iaddr2 == -1 || ival == -1) {
143
                    invalid();
144
                } else {
145
                    for (; iaddr <= iaddr2; iaddr++) {
146
                        write6502((uint16_t)iaddr, regs.db, (uint8_t)ival);
147
                    }
148
                    ready();
149
                }
150
            }
151
        }
152
153
        else if (strncmp(line, "STA", 3) == 0) {            //Set accumulator value
154
            if (len < 7) {
155
                invalid();
156
            } else {
157
                strncpy(val, line + 4, 2);
158
                ival = hex_to_int8(val);
159
                if (ival == -1) {
160
                    invalid();
161
                } else {
162
                    regs.a = (uint8_t)ival;
163
                    ready();
164
                }
165
            }
166
        }
167
168
        else if (strncmp(line, "STX", 3) == 0) {            //Set X register value
169
            if (len < 7) {
170
                invalid();
171
            } else {
172
                strncpy(val, line + 4, 2);
173
                ival = hex_to_int8(val);
174
                if (ival == -1) {
175
                    invalid();
176
                } else {
177
                    regs.x = (uint8_t)ival;
178
                    ready();
179
                }
180
            }
181
        }
182
183
        else if (strncmp(line, "STY", 3) == 0) {            //Set Y register value
184
            if (len < 7) {
185
                invalid();
186
            } else {
187
                strncpy(val, line + 4, 2);
188
                ival = hex_to_int8(val);
189
                if (ival == -1) {
190
                    invalid();
191
                } else {
192
                    regs.y = (uint8_t)ival;
193
                    ready();
194
                }
195
            }
196
        }
197
198
        else if (strncmp(line, "SST", 3) == 0) {            //Set status register value
199
            if (len < 7) {
200
                invalid();
201
            } else {
202
                strncpy(val, line + 4, 2);
203
                ival = hex_to_int8(val);
204
                if (ival == -1) {
205
                    invalid();
206
                } else {
207
                    regs.status = (uint8_t)ival;
208
                    ready();
209
                }
210
            }
211
        }
212
213
        else if (strncmp(line, "SSP", 3) == 0) {            //Set stack pointer value
214
            if (len < 7) {
215
                invalid();
216
            } else {
217
                strncpy(val, line + 4, 2);
218
                ival = hex_to_int8(val);
219
                if (ival == -1) {
220
                    invalid();
221
                } else {
222
                    regs.sp = (regs.sp & 0xFF00) | (uint8_t)ival;
223
                    ready();
224
                }
225
            }
226
        }
227
228
        else if (strncmp(line, "RUN", 3) == 0) {            //Run code at address
229
            if (len < 9) {
230
                invalid();
231
            } else {
232
                strncpy(addr, line + 4, 4);
233
234
                iaddr = hex_to_int16(addr);
235
                if (iaddr == -1) {
236
                    invalid();
237
                } else {
238
                    write6502(regs.sp, 0, (0xfffd -1) >> 8);
239
                    decrement_wrap_at_page_boundary(&regs.sp);
240
                    write6502(regs.sp, 0, (0xfffd - 1) & 255);
241
                    decrement_wrap_at_page_boundary(&regs.sp);
242
                    regs.pc = (uint16_t)iaddr;
243
244
                    init_done=true;
245
                }
246
            }
247
        }
248
249
        else if(strncmp(line, "RQM", 3) == 0) {             //Request memory address value
250
            if (len < 9) {
251
                invalid();
252
            } else {
253
                strncpy(addr, line + 4, 4);
254
                iaddr = hex_to_int16(addr);
255
                if (iaddr == -1) {
256
                    invalid();
257
                } else {
258
                    printf("%lx\n", (long)debug_read6502((uint16_t)iaddr, regs.db, USE_CURRENT_X16_BANK));
259
                    fflush(stdout);
260
                }
261
            }
262
        }
263
264
        else if(strncmp(line, "RQA", 3) == 0) {             //Request accumulator value
265
            printf("%lx\n", (long)regs.a);
266
            fflush(stdout);
267
        }
268
269
        else if(strncmp(line, "RQX", 3) == 0) {             //Request X register value
270
            printf("%lx\n", (long)regs.xl);
271
            fflush(stdout);
272
        }
273
274
        else if(strncmp(line, "RQY", 3) == 0) {             //Request Y register value
275
            printf("%lx\n", (long)regs.yl);
276
            fflush(stdout);
277
        }
278
279
        else if(strncmp(line, "RST", 3) == 0) {             //Request status register value
280
            printf("%lx\n", (long)regs.status);
281
            fflush(stdout);
282
        }
283
284
        else if(strncmp(line, "RSP", 3) == 0) {             //Request stack pointer value
285
            printf("%lx\n", (long)regs.sp);
286
            fflush(stdout);
287
        }
288
289
        else {
290
            printf("ERR Unknown command\n");
291
            fflush(stdout);
292
        }
293
    }
294
    free(line);
295
}
296
297
int hex_to_int8(char* str)
298
{
299
    int val;
300
301
    if (strlen(str) != 2 || !hex_validate(str)) {
302
        return -1;
303
    } else {
304
        val = (int)strtol(str, NULL, 16);
305
        if (val < 0 || val > 0xff) return -1; else return val;
306
    }
307
}
308
309
int hex_to_int16(char* str)
310
{
311
    int val;
312
313
    if (strlen(str) != 4 || !hex_validate(str)) {
314
        return -1;
315
    } else {
316
        val = (int)strtol(str, NULL, 16);
317
        if (val < 0 || val > 0xffff) return -1; else return val;
318
    }
319
}
320
321
bool hex_validate(char* str)
322
{
323
    int i=0;
324
    char c;
325
326
    c = str[i];
327
    while (c != 0) {
328
        if ( (c>= '0' && c<= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
329
            i++;
330
        } else {
331
            return false;
332
        }
333
        c = str[i];
334
    }
335
    return true;
336
}
337
338
void invalid()
339
{
340
    printf("ERR Invalid command\n");
341
    fflush(stdout);
342
}
343
344
void ready()
345
{
346
    printf("RDY\n");
347
    fflush(stdout);
348
}