-
Notifications
You must be signed in to change notification settings - Fork 47
Expand file tree
/
Copy pathzextest.c
More file actions
124 lines (92 loc) · 3.27 KB
/
zextest.c
File metadata and controls
124 lines (92 loc) · 3.27 KB
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
/* zextest.c
* Example program using z80emu to run the zexall and zexdoc tests. This will
* check if the Z80 is correctly emulated.
*
* Copyright (c) 2012, 2016 Lin Ke-Fong
* Copyright (c) 2012 Chris Pressey
*
* This code is free, do whatever you want with it.
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "zextest.h"
#include "z80emu.h"
#define Z80_CPU_SPEED 4000000 /* In Hz. */
#define CYCLES_PER_STEP (Z80_CPU_SPEED / 50)
#define MAXIMUM_STRING_LENGTH 100
static void emulate (char *filename);
int main (void)
{
time_t start, stop;
start = time(NULL);
emulate("testfiles/zexdoc.com");
emulate("testfiles/zexall.com");
stop = time(NULL);
printf("Emulating zexdoc and zexall took a total of %d second(s).\n",
(int) (stop - start));
return EXIT_SUCCESS;
}
/* Emulate "zexdoc.com" or "zexall.com". */
static void emulate (char *filename)
{
FILE *file;
long l;
ZEXTEST context;
double total;
printf("Testing \"%s\"...\n", filename);
if ((file = fopen(filename, "rb")) == NULL) {
fprintf(stderr, "Can't open file!\n");
exit(EXIT_FAILURE);
}
fseek(file, 0, SEEK_END);
l = ftell(file);
fseek(file, 0, SEEK_SET);
fread(context.memory + 0x100, 1, l, file);
fclose(file);
/* Patch the memory of the program. Reset at 0x0000 is trapped by an
* OUT which will stop emulation. CP/M bdos call 5 is trapped by an IN.
* See Z80_INPUT_BYTE() and Z80_OUTPUT_BYTE() definitions in z80user.h.
*/
context.memory[0] = 0xd3; /* OUT N, A */
context.memory[1] = 0x00;
context.memory[5] = 0xdb; /* IN A, N */
context.memory[6] = 0x00;
context.memory[7] = 0xc9; /* RET */
context.is_done = 0;
/* Emulate. */
Z80Reset(&context.state);
context.state.pc = 0x100;
total = 0.0;
do
total += Z80Emulate(&context.state, CYCLES_PER_STEP, &context);
while (!context.is_done);
printf("\n%.0f cycle(s) emulated.\n"
"For a Z80 running at %.2fMHz, "
"that would be %d second(s) or %.2f hour(s).\n",
total,
Z80_CPU_SPEED / 1000000.0,
(int) (total / Z80_CPU_SPEED),
total / ((double) 3600 * Z80_CPU_SPEED));
}
/* Emulate CP/M bdos call 5 functions 2 (output character on screen) and 9
* (output $-terminated string to screen).
*/
void SystemCall (ZEXTEST *zextest)
{
if (zextest->state.registers.byte[Z80_C] == 2)
printf("%c", zextest->state.registers.byte[Z80_E]);
else if (zextest->state.registers.byte[Z80_C] == 9) {
int i, c;
for (i = zextest->state.registers.word[Z80_DE], c = 0;
zextest->memory[i] != '$';
i++) {
printf("%c", zextest->memory[i & 0xffff]);
if (c++ > MAXIMUM_STRING_LENGTH) {
fprintf(stderr,
"String to print is too long!\n");
exit(EXIT_FAILURE);
}
}
}
}