-
Notifications
You must be signed in to change notification settings - Fork 4
/
clem_debug.c
136 lines (124 loc) · 4.96 KB
/
clem_debug.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
#include "clem_debug.h"
#include "clem_device.h"
#include "external/cross_endian.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
static FILE *g_fp_debug_out = NULL;
static char s_clem_debug_buffer[65536 * 102];
static unsigned s_clem_debug_cnt = 0;
static ClemensMachine *s_clem_machine = NULL;
static char s_log_buffer[CLEM_DEBUG_LOG_BUFFER_SIZE];
// TODO: this debug interface is a singleton. Making this context per machine
// instance will take some work due to how the logger works.
void clem_debug_context(ClemensMachine *context) { s_clem_machine = context; }
void clem_debug_log(int log_level, const char *fmt, ...) {
char *buffer;
va_list arg_list;
if (!s_clem_machine)
return;
buffer = s_log_buffer;
va_start(arg_list, fmt);
vsnprintf(buffer, CLEM_DEBUG_LOG_BUFFER_SIZE, fmt, arg_list);
va_end(arg_list);
s_clem_machine->logger_fn(log_level, s_clem_machine, buffer);
}
char *clem_debug_acquire_trace(unsigned amt) {
char *next;
unsigned next_debug_cnt = s_clem_debug_cnt + amt;
if (next_debug_cnt >= sizeof(s_clem_debug_buffer)) {
clem_debug_trace_flush();
}
next = &s_clem_debug_buffer[s_clem_debug_cnt];
s_clem_debug_cnt = next_debug_cnt;
return next;
}
void clem_debug_trace_flush() {
if (!g_fp_debug_out && s_clem_debug_cnt > 0) {
g_fp_debug_out = fopen("debug.out", "wb");
}
if (g_fp_debug_out) {
fwrite(s_clem_debug_buffer, 1, s_clem_debug_cnt, g_fp_debug_out);
fflush(g_fp_debug_out);
}
s_clem_debug_cnt = 0;
}
void clem_debug_reset(struct ClemensDeviceDebugger *dbg) { memset(dbg, 0, sizeof(*dbg)); }
void clem_debug_break(struct ClemensDeviceDebugger *dbg, unsigned debug_reason, unsigned param0,
unsigned param1) {
CLEM_WARN("PC=%02X:%04X", dbg->pbr, dbg->pc);
switch (debug_reason) {
case CLEM_DEBUG_BREAK_UNIMPL_IOREAD:
CLEM_UNIMPLEMENTED("IO Read: %04X, %02X", param0, param1);
break;
case CLEM_DEBUG_BREAK_UNIMPL_IOWRITE:
CLEM_UNIMPLEMENTED("IO Write: %04X, %02X", param0, param1);
break;
default:
break;
}
}
struct ClemensIIGSMemoryHandle {
uint32_t machine_addr;
uint32_t addr;
uint16_t attrs;
uint16_t owner;
uint32_t sz;
uint32_t prev;
uint32_t next;
};
// TODO: Does this work for ROM 01?
#define CLEM_DEBUG_IIGS_MMGR_HANDLE_ADDR 0x00e11700
#define CLEM_DEBUG_IIGS_MMGR_HANDLE_ADDR_TAIL 0x00e11b00
static void _debug_toolbox_mmgr(ClemensMachine *context) {
// insepct memory handles
// https://github.com/TomHarte/CLK/wiki/Investigation:-The-Apple-IIgs-Memory-Manager
// TODO: traverse into e0 bank as the memory pointers can go there apparently
struct ClemensIIGSMemoryHandle mmgr_handle;
const uint8_t *base_mem = context->mem.mega2_bank_map[1];
const uint8_t *mem = base_mem + (CLEM_DEBUG_IIGS_MMGR_HANDLE_ADDR & 0xffff);
unsigned base_addr = 0x00e10000;
unsigned count = 0;
while (count < 1000) {
mmgr_handle.machine_addr = base_addr + (uint16_t)((uintptr_t)(mem - base_mem) & 0xffff);
mmgr_handle.addr = le32toh(*(uint32_t *)(mem));
mmgr_handle.attrs = le16toh(*(uint16_t *)(mem + 4));
mmgr_handle.owner = le16toh(*(uint16_t *)(mem + 6));
mmgr_handle.sz = le16toh(*(uint32_t *)(mem + 8));
mmgr_handle.prev = le16toh(*(uint32_t *)(mem + 12));
mmgr_handle.next = le16toh(*(uint32_t *)(mem + 16));
if (mmgr_handle.sz > 0) {
CLEM_LOG("[debug.toolbox.mmgr]: handle @ %08X: [$%08X:%08X] attrs: %04X, size: %08X",
mmgr_handle.machine_addr, mmgr_handle.addr,
mmgr_handle.addr + mmgr_handle.sz - 1, mmgr_handle.attrs, mmgr_handle.sz);
} else {
CLEM_LOG("[debug.toolbox.mmgr]: handle @ %08X: [$%08X] attrs: %04X, no size",
mmgr_handle.machine_addr, mmgr_handle.addr, mmgr_handle.attrs);
}
CLEM_LOG("[debug.toolbox.mmgr]: prev: %08X", mmgr_handle.prev);
CLEM_LOG("[debug.toolbox.mmgr]: next: %08X", mmgr_handle.next);
if (mmgr_handle.next == 0)
break;
if ((mmgr_handle.next & 0x00ff0000) == 0x00e10000) {
base_addr = 0x00e10000;
base_mem = context->mem.mega2_bank_map[1];
mem = base_mem + (mmgr_handle.next & 0xffff);
} else if ((mmgr_handle.next & 0x00ff0000) == 0x00e00000) {
base_addr = 0x00e00000;
base_mem = context->mem.mega2_bank_map[0];
mem = base_mem + (mmgr_handle.next & 0xffff);
} else {
CLEM_WARN("[debug.toolbox.mmgr]: handle located at unexpected bank %02X",
(mmgr_handle.next >> 16) & 0xff);
}
++count;
}
CLEM_LOG("[debug.toolbox.mmgr]: count = %u", count);
}
void clemens_debug_status_toolbox(ClemensMachine *context, unsigned id) {
switch (id) {
case CLEM_DEBUG_TOOLBOX_MMGR:
_debug_toolbox_mmgr(context);
break;
}
}