-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDma.hpp
180 lines (161 loc) · 4.48 KB
/
Dma.hpp
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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#pragma once
#include <memory>
#include <stdexcept>
#include "Bus.hpp"
union DMA_base_address
{
unsigned int int_value;
unsigned char byte_value[4];
struct
{
unsigned int memory_address : 24;
unsigned int na : 8;
};
};
union DMA_block_control
{
unsigned int int_value;
unsigned char byte_value[4];
struct
{
// number of words
unsigned int BC : 16;
unsigned int na : 16;
};
struct
{
// block size
unsigned int BS : 16;
// amount of blocks
unsigned int BA : 16;
};
};
union DMA_channel_control
{
unsigned int int_value;
unsigned char byte_value[4];
struct
{
unsigned int transfer_direction : 1;
unsigned int memory_address_step : 1;
unsigned int na1 : 6;
unsigned int chopping_enable : 1;
unsigned int sync_mode : 2;
unsigned int na2 : 5;
unsigned int chopping_dma_window_size : 3;
unsigned int na3 : 1;
unsigned int chopping_cpu_window_size : 3;
unsigned int na4 : 1;
unsigned int start_busy : 1;
unsigned int na5 : 3;
unsigned int start_trigger : 1;
unsigned int unknown1 : 1;
unsigned int unknown2 : 1;
unsigned int na6 : 1;
};
};
union DMA_control_register
{
unsigned int int_value;
unsigned char byte_value[4];
struct
{
unsigned int MDECin_priority : 3;
unsigned int MDECin_master_enable : 1;
unsigned int MDECout_priority : 3;
unsigned int MDECout_master_enable : 1;
unsigned int GPU_priority : 3;
unsigned int GPU_master_enable : 1;
unsigned int CDROM_priority : 3;
unsigned int CDROM_master_enable : 1;
unsigned int SPU_priority : 3;
unsigned int SPU_master_enable : 1;
unsigned int PIO_priority : 3;
unsigned int PIO_master_enable : 1;
unsigned int OTC_priority : 3;
unsigned int OTC_master_enable : 1;
unsigned int unknown_priority : 3;
unsigned int unknown_master_enable : 1;
};
};
union DMA_interrupt_register
{
unsigned int value;
unsigned char byte_value[4];
struct
{
unsigned int unknown : 6;
unsigned int na : 9;
unsigned int force_irq : 1;
unsigned int irq_enable : 7;
unsigned int irq_master_enable : 1;
unsigned int irq_flags : 7;
unsigned int irq_master_flag : 1;
};
};
enum class DMA_sync_mode
{
manual = 0,
request = 1,
linked_list = 2
};
enum class DMA_direction
{
to_ram = 0,
from_ram = 1
};
enum class DMA_address_step
{
increment = 0,
decrement = 1
};
enum class DMA_channel_type
{
MDECin = 0,
MDECout = 1,
GPU = 2,
CDROM = 3,
SPU = 4,
PIO = 5,
OTC = 6
};
class DMA_interface
{
public:
virtual void sync_mode_manual(DMA_base_address& base_address, DMA_block_control& block_control, DMA_channel_control& channel_control) { throw std::logic_error("not supported"); }
virtual void sync_mode_request(DMA_base_address& base_address, DMA_block_control& block_control, DMA_channel_control& channel_control) { throw std::logic_error("not supported"); }
virtual void sync_mode_linked_list(DMA_base_address& base_address, DMA_block_control& block_control, DMA_channel_control& channel_control) { throw std::logic_error("not supported"); }
};
class Dma : public DMA_interface, public Bus::BusDevice
{
public:
virtual bool is_address_for_device(unsigned int address) final;
virtual unsigned char get_byte(unsigned int address) final;
virtual void set_byte(unsigned int address, unsigned char value) final;
void init();
void reset();
void tick();
void save_state(std::stringstream& file);
void load_state(std::stringstream& file);
// for OTC channel - since its basically DMA to ram
virtual void sync_mode_manual(DMA_base_address& base_address, DMA_block_control& block_control, DMA_channel_control& channel_control) override;
DMA_interface* devices[7] = { nullptr };
DMA_interrupt_register interrupt_register;
static Dma * get_instance();
private:
static const unsigned int NUM_CHANNELS = 7;
static const unsigned int DMA_SIZE = 128;
static const unsigned int DMA_START = 0x1F801080;
static const unsigned int DMA_END = DMA_START + DMA_SIZE;
static const unsigned int DMA_BASE_ADDRESS_START = 0x1F801080;
static const unsigned int DMA_BLOCK_CONTROL_START = 0x1F801084;
static const unsigned int DMA_CHANNEL_CONTROL_START = 0x1F801088;
static const unsigned int DMA_CONTROL_REGISTER_START = 0x1F8010F0;
static const unsigned int DMA_INTERRUPT_REGISTER_START = 0x1F8010F4;
static const unsigned int DMA_GARBAGE_START = 0x1F8010F8;
unsigned char dma_registers[128] = { 0 };
unsigned int * base_address_registers[7] = { nullptr };
unsigned int * block_control_registers[7] = { nullptr };
unsigned int * channel_control_registers[7] = { nullptr };
unsigned int * control_register = nullptr;
};