aboutsummaryrefslogtreecommitdiff
path: root/arm9/source/dev.c
blob: 1b9a1dc43ca4edac7bcc8ae8daed56ff0c923b9a (plain) (blame)
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include "dev.h"


// Reset every device on a device bus.
void dev_reset(DeviceBus *d) {
    system_reset(&d->system);
    memory_reset(&d->memory);
    math_reset(&d->math);
    clock_reset(&d->clock);
    input_reset(&d->input);
    screen_reset(&d->screen);
    stream_reset(&d->stream);
    fs_reset(&d->file);
}

// Read a byte from a device bus.
u8 dev_read(DeviceBus *d, u8 port) {
    switch(port) {
    // SYSTEM DEVICE
    case 0x02: return d->system.wake;
    case 0x08: return readbuf_read(&d->system.name);
    case 0x09: return readbuf_read(&d->system.authors);
    case 0x0E: return GETH(connected_devices());
    case 0x0F: return GETL(connected_devices());
    // MEMORY DEVICE
    case 0x10: return GETH(d->memory.allocated);
    case 0x11: return GETL(d->memory.allocated);
    case 0x12: return GETH(d->memory.head1.offset);
    case 0x13: return GETL(d->memory.head1.offset);
    case 0x14: return d->memory.head1.page;
    case 0x15: return d->memory.head1.byte;
    case 0x16:
    case 0x17: return memory_read(&d->memory.head1);
    case 0x1A: return GETH(d->memory.head2.offset);
    case 0x1B: return GETL(d->memory.head2.offset);
    case 0x1C: return d->memory.head2.page;
    case 0x1D: return d->memory.head2.byte;
    case 0x1E:
    case 0x1F: return memory_read(&d->memory.head2);
    // MATH DEVICE
    case 0x20: return GETH(math_get_x(&d->math));
    case 0x21: return GETL(math_get_x(&d->math));
    case 0x22: return GETH(math_get_y(&d->math));
    case 0x23: return GETL(math_get_y(&d->math));
    case 0x24: return GETH(math_get_r(&d->math));
    case 0x25: return GETL(math_get_r(&d->math));
    case 0x26: return GETH(math_get_t(&d->math));
    case 0x27: return GETL(math_get_t(&d->math));
    case 0x28: return GETHH(math_get_prod(&d->math));
    case 0x29: return GETHL(math_get_prod(&d->math));
    case 0x2A: return GETLH(math_get_prod(&d->math));
    case 0x2B: return GETLL(math_get_prod(&d->math));
    case 0x2C: return GETH(math_get_quot(&d->math));
    case 0x2D: return GETL(math_get_quot(&d->math));
    case 0x2E: return GETH(math_get_rem(&d->math));
    case 0x2F: return GETL(math_get_rem(&d->math));
    // CLOCK DEVICE
    case 0x30: return   YEAR(get_datetime());
    case 0x31: return  MONTH(get_datetime());
    case 0x32: return    DAY(get_datetime());
    case 0x33: return   HOUR(get_datetime());
    case 0x34: return MINUTE(get_datetime());
    case 0x35: return SECOND(get_datetime());
    case 0x36: clock_uptime_read(&d->clock);
               return GETH(d->clock.uptime);
    case 0x37: return GETL(d->clock.uptime);
    case 0x38: timer_read(&d->clock.t1);
               return GETH(d->clock.t1.read);
    case 0x39: return GETL(d->clock.t1.read);
    case 0x3A: timer_read(&d->clock.t2);
               return GETH(d->clock.t2.read);
    case 0x3B: return GETL(d->clock.t2.read);
    case 0x3C: timer_read(&d->clock.t3);
               return GETH(d->clock.t3.read);
    case 0x3D: return GETL(d->clock.t3.read);
    case 0x3E: timer_read(&d->clock.t4);
               return GETH(d->clock.t4.read);
    case 0x3F: return GETL(d->clock.t4.read);
    // INPUT DEVICE
    case 0x40: input_read_x(&d->input);
               return GETH(d->input.x_read);
    case 0x41: return GETL(d->input.x_read);
    case 0x42: input_read_y(&d->input);
               return GETH(d->input.y_read);
    case 0x43: return GETL(d->input.y_read);
    case 0x48: return BOOL(d->input.pointer);
    case 0x49: return d->input.pointer << 7;
    case 0x4A: return circbuf_read(&d->input.keybuffer);
    case 0x4C: return d->input.gamepad;
    // SCREEN DEVICE
    case 0x50: return GETH(d->screen.x);
    case 0x51: return GETL(d->screen.x);
    case 0x52: return GETH(d->screen.y);
    case 0x53: return GETL(d->screen.y);
    case 0x54: return GETH(PIXELS_WIDTH);
    case 0x55: return GETL(PIXELS_WIDTH);
    case 0x56: return GETH(PIXELS_HEIGHT);
    case 0x57: return GETL(PIXELS_HEIGHT);
    // FILE DEVICE
    case 0x90: return BOOL(fs_get_open(&d->file));
    case 0x91: return BOOL(fs_get_error(&d->file));
    case 0x92:
    case 0x93: return fs_read_byte(&d->file);
    case 0x94: return pathbuf_read(&d->file.path);
    case 0x95: return BOOL(fs_get_type(&d->file));
    case 0x96: return pathbuf_read(&d->file.child_path);
    case 0x97: return BOOL(fs_get_child_type(&d->file));
    case 0x98: return GETHH(d->file.address);
    case 0x99: return GETHL(d->file.address);
    case 0x9A: return GETLH(d->file.address);
    case 0x9B: return GETLL(d->file.address);
    case 0x9C: fs_calculate_length(&d->file); return GETHH(d->file.length);
    case 0x9D: fs_calculate_length(&d->file); return GETHL(d->file.length);
    case 0x9E: fs_calculate_length(&d->file); return GETLH(d->file.length);
    case 0x9F: fs_calculate_length(&d->file); return GETLL(d->file.length);
    // DEFAULT
    default: return 0;
    }
}

// Write a byte to a device bus.
Signal dev_write(DeviceBus *d, u8 port, u8 v) {
    switch(port) {
    // SYSTEM DEVICE
    case 0x00: SETH(d->system.sleep, v);                                  break;
    case 0x01: SETL(d->system.sleep, v);                       return SIG_SLEEP;
    case 0x03: if (v) { return SIG_FORK; } else { return SIG_RESET; }
    case 0x08: readbuf_set_pointer(&d->system.name);                      break;
    case 0x09: readbuf_set_pointer(&d->system.authors);                   break;
    // MEMORY DEVICE
    case 0x10: SETH(d->memory.count, v);                                  break;
    case 0x11: SETL(d->memory.count, v); memory_allocate(&d->memory);     break;
    case 0x12: SETH(d->memory.head1.offset, v);
               memory_refresh_cache(&d->memory, &d->memory.head1);        break;
    case 0x13: SETL(d->memory.head1.offset, v);
               memory_refresh_cache(&d->memory, &d->memory.head1);        break;
    case 0x14: d->memory.head1.page = v;
               memory_refresh_page(&d->memory.head1);                     break;
    case 0x15: d->memory.head1.byte = v;                                  break;
    case 0x16:
    case 0x17: memory_write(&d->memory.head1, v);                         break;
    case 0x18: SETH(d->memory.copy, v);                                   break;
    case 0x19: SETL(d->memory.copy, v); memory_copy(&d->memory);          break;
    case 0x1A: SETH(d->memory.head2.offset, v);
               memory_refresh_cache(&d->memory, &d->memory.head2);        break;
    case 0x1B: SETL(d->memory.head2.offset, v);
               memory_refresh_cache(&d->memory, &d->memory.head2);        break;
    case 0x1C: d->memory.head2.page = v;
               memory_refresh_page(&d->memory.head2);                     break;
    case 0x1D: d->memory.head2.byte = v;                                  break;
    case 0x1E:
    case 0x1F: memory_write(&d->memory.head2, v);                         break;
    // MATH DEVICE
    case 0x20: math_clear_cartesian(&d->math); SETH(d->math.x, v);        break;
    case 0x21: math_clear_cartesian(&d->math); SETL(d->math.x, v);        break;
    case 0x22: math_clear_cartesian(&d->math); SETH(d->math.y, v);        break;
    case 0x23: math_clear_cartesian(&d->math); SETL(d->math.y, v);        break;
    case 0x24: math_clear_polar(&d->math);     SETH(d->math.r, v);        break;
    case 0x25: math_clear_polar(&d->math);     SETL(d->math.r, v);        break;
    case 0x26: math_clear_polar(&d->math);     SETH(d->math.t, v);        break;
    case 0x27: math_clear_polar(&d->math);     SETL(d->math.t, v);        break;
    // CLOCK DEVICE
    case 0x38: SETH(d->clock.t1.write, v);                                break;
    case 0x39: SETL(d->clock.t1.write, v); timer_write(&d->clock.t1);     break;
    case 0x3A: SETH(d->clock.t2.write, v);                                break;
    case 0x3B: SETL(d->clock.t2.write, v); timer_write(&d->clock.t2);     break;
    case 0x3C: SETH(d->clock.t3.write, v);                                break;
    case 0x3D: SETL(d->clock.t3.write, v); timer_write(&d->clock.t3);     break;
    case 0x3E: SETH(d->clock.t4.write, v);                                break;
    case 0x3F: SETL(d->clock.t4.write, v); timer_write(&d->clock.t4);     break;
    // INPUT DEVICE
    case 0x4A: circbuf_clear(&d->input.keybuffer);
               v ? open_keyboard() : close_keyboard();                    break;
    // SCREEN DEVICE
    case 0x50: SETH(d->screen.x, v);                                      break;
    case 0x51: SETL(d->screen.x, v);                                      break;
    case 0x52: SETH(d->screen.y, v);                                      break;
    case 0x53: SETL(d->screen.y, v);                                      break;
    case 0x58: SETH(d->screen.colour, v);                                 break;
    case 0x59: SETL(d->screen.colour, v);
               screen_commit_colour(&d->screen);                          break;
    case 0x5A: SETH(d->screen.selected, v);                               break;
    case 0x5B: SETL(d->screen.selected, v);                               break;
    case 0x5C:
    case 0x5D: spritebuf_push(&d->screen.sprite, v);                      break;
    case 0x5E: screen_draw(&d->screen, v);                                break;
    case 0x5F: screen_move_cursor(&d->screen, v);                         break;
    // STREAM DEVICE
    case 0x83: stream_end(&d->stream);                                    break;
    case 0x86:
    case 0x87: stream_write(&d->stream, v);                               break;
    // FILE DEVICE
    case 0x90: fs_push_open(&d->file, v);                                 break;
    case 0x91: fs_push_action(&d->file, v);                               break;
    case 0x92:
    case 0x93: fs_write_byte(&d->file, v);                                break;
    case 0x94: pathbuf_set_pointer(&d->file.path, v);                     break;
    case 0x95: fs_ascend(&d->file);                                       break;
    case 0x96: pathbuf_set_pointer(&d->file.child_path, v);               break;
    case 0x97: fs_descend(&d->file);                                      break;
    case 0x98: SETHH(d->file.address_write, v);                           break;
    case 0x99: SETHL(d->file.address_write, v);                           break;
    case 0x9A: SETLH(d->file.address_write, v);                           break;
    case 0x9B: SETLL(d->file.address_write, v); fs_seek(&d->file);        break;
    case 0x9C: SETHH(d->file.length_write, v);                            break;
    case 0x9D: SETHL(d->file.length_write, v);                            break;
    case 0x9E: SETLH(d->file.length_write, v);                            break;
    case 0x9F: SETLL(d->file.length_write, v); fs_resize(&d->file);       break;
    // DEFAULT
    default: break;
    }
    return SIG_NONE;
}