-
Notifications
You must be signed in to change notification settings - Fork 101
/
Copy pathsfc_cpu.c
144 lines (138 loc) · 5.25 KB
/
sfc_cpu.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
#include "sfc_6502.h"
#include "sfc_cpu.h"
#include "sfc_famicom.h"
#include <assert.h>
#include <string.h>
// BYTE -> HEX
extern inline void sfc_btoh(char o[], uint8_t b);
/// <summary>
/// StepFC: 指定地方反汇编
/// </summary>
/// <param name="address">The address.</param>
/// <param name="famicom">The famicom.</param>
/// <param name="buf">The buf.</param>
void sfc_fc_disassembly(uint16_t address, const sfc_famicom_t* famicom, char buf[]) {
// TODO: 根据操作码读取对应字节
enum {
OFFSET_M = SFC_DISASSEMBLY_BUF_LEN2 - SFC_DISASSEMBLY_BUF_LEN,
OFFSET = 8
};
static_assert(OFFSET < OFFSET_M, "LESS!");
memset(buf, ' ', OFFSET);
buf[0] = '$';
sfc_btoh(buf + 1, (uint8_t)(address >> 8));
sfc_btoh(buf + 3, (uint8_t)(address));
sfc_6502_code_t code;
code.data = 0;
// 暴力(NoMo)读取3字节
code.op = sfc_read_cpu_address(address, famicom);
code.a1 = sfc_read_cpu_address(address + 1, famicom);
code.a2 = sfc_read_cpu_address(address + 2, famicom);
// 反汇编
sfc_6502_disassembly(code, buf + OFFSET);
}
/// <summary>
/// StepFC: 读取CPU地址数据
/// </summary>
/// <param name="address">The address.</param>
/// <param name="famicom">The famicom.</param>
/// <returns></returns>
uint8_t sfc_read_cpu_address(uint16_t address, const sfc_famicom_t* famicom) {
/*
CPU 地址空间
+---------+-------+-------+-----------------------+
| 地址 | 大小 | 标记 | 描述 |
+---------+-------+-------+-----------------------+
| $0000 | $800 | | RAM |
| $0800 | $800 | M | RAM |
| $1000 | $800 | M | RAM |
| $1800 | $800 | M | RAM |
| $2000 | 8 | | Registers |
| $2008 | $1FF8 | R | Registers |
| $4000 | $20 | | Registers |
| $4020 | $1FDF | | Expansion ROM |
| $6000 | $2000 | | SRAM |
| $8000 | $4000 | | PRG-ROM |
| $C000 | $4000 | | PRG-ROM |
+---------+-------+-------+-----------------------+
标记图例: M = $0000的镜像
R = $2000-2008 每 8 bytes 的镜像
(e.g. $2008=$2000, $2018=$2000, etc.)
*/
switch (address >> 13)
{
case 0:
// 高三位为0: [$0000, $2000): 系统主内存, 4次镜像
return famicom->main_memory[address & (uint16_t)0x07ff];
case 1:
// 高三位为1, [$2000, $4000): PPU寄存器, 8字节步进镜像
assert(!"NOT IMPL");
return 0;
case 2:
// 高三位为2, [$4000, $6000): pAPU寄存器 扩展ROM区
assert(!"NOT IMPL");
return 0;
case 3:
// 高三位为3, [$6000, $8000): 存档 SRAM区
return famicom->save_memory[address & (uint16_t)0x1fff];
case 4: case 5: case 6: case 7:
// 高一位为1, [$8000, $10000) 程序PRG-ROM区
return famicom->prg_banks[address >> 13][address & (uint16_t)0x1fff];
}
assert(!"invalid address");
return 0;
}
/// <summary>
/// SFCs the write cpu address.
/// </summary>
/// <param name="address">The address.</param>
/// <param name="data">The data.</param>
/// <param name="famicom">The famicom.</param>
void sfc_write_cpu_address(uint16_t address, uint8_t data, sfc_famicom_t* famicom) {
/*
CPU 地址空间
+---------+-------+-------+-----------------------+
| 地址 | 大小 | 标记 | 描述 |
+---------+-------+-------+-----------------------+
| $0000 | $800 | | RAM |
| $0800 | $800 | M | RAM |
| $1000 | $800 | M | RAM |
| $1800 | $800 | M | RAM |
| $2000 | 8 | | Registers |
| $2008 | $1FF8 | R | Registers |
| $4000 | $20 | | Registers |
| $4020 | $1FDF | | Expansion ROM |
| $6000 | $2000 | | SRAM |
| $8000 | $4000 | | PRG-ROM |
| $C000 | $4000 | | PRG-ROM |
+---------+-------+-------+-----------------------+
标记图例: M = $0000的镜像
R = $2000-2008 每 8 bytes 的镜像
(e.g. $2008=$2000, $2018=$2000, etc.)
*/
switch (address >> 13)
{
case 0:
// 高三位为0: [$0000, $2000): 系统主内存, 4次镜像
famicom->main_memory[address & (uint16_t)0x07ff] = data;
return;
case 1:
// 高三位为1, [$2000, $4000): PPU寄存器, 8字节步进镜像
assert(!"NOT IMPL");
return;
case 2:
// 高三位为2, [$4000, $6000): pAPU寄存器 扩展ROM区
assert(!"NOT IMPL");
return;
case 3:
// 高三位为3, [$6000, $8000): 存档 SRAM区
famicom->save_memory[address & (uint16_t)0x1fff] = data;
return;
case 4: case 5: case 6: case 7:
// 高一位为1, [$8000, $10000) 程序PRG-ROM区
assert(!"WARNING: PRG-ROM");
famicom->prg_banks[address >> 13][address & (uint16_t)0x1fff] = data;
return;
}
assert(!"invalid address");
}