Skip to content

Commit e8483e5

Browse files
Did the DMA. still a lot to finish
1 parent 0dfeeab commit e8483e5

File tree

16 files changed

+121
-35
lines changed

16 files changed

+121
-35
lines changed

PSEMU/Bus.cpp

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ uint32_t Bus::load32(uint32_t addr) {
2626
return 0;
2727
}
2828
else if (auto offset = _DMA.contains(abs_addr); offset.has_value()) {
29-
//dma_reg(offset.value());
29+
dma_reg(offset.value());
3030
}
3131
else if (auto offset = GPU.contains(abs_addr); offset.has_value()) {
3232
std::cout << "[BUS] WARNING: GPU NOT IMPLEMENTED. GPU read " << std::to_string(offset.value()) << "\n";
@@ -58,7 +58,7 @@ void Bus::store32(uint32_t addr, uint32_t value) {
5858
return;
5959
}
6060
else if (auto offset = _DMA.contains(abs_addr); offset.has_value()) {
61-
//set_dma_reg(offset.value(), value);
61+
set_dma_reg(offset.value(), value);
6262
return;
6363
}
6464
else if (auto offset = GPU.contains(abs_addr); offset.has_value()) {
@@ -283,13 +283,12 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
283283
auto minor = offset & 0xf;
284284

285285
Port active_port;
286+
auto port = dma.from_index(major);
287+
auto channel = dma.channels[port];
286288
switch (major) {
287289
// Per-channel registers
288290
// 0-6
289291
case 0:
290-
auto port = dma.from_index(major);
291-
auto channel = dma.channels[port];
292-
293292
switch (minor){
294293
case 0: channel.set_base(value);
295294
case 4: channel.set_block_control(value);
@@ -307,9 +306,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
307306
}
308307
break;
309308
case 1:
310-
auto port = dma.from_index(major);
311-
auto channel = dma.channels[port];
312-
313309
switch (minor) {
314310
case 0: channel.set_base(value);
315311
case 4: channel.set_block_control(value);
@@ -327,9 +323,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
327323
}
328324
break;
329325
case 2:
330-
auto port = dma.from_index(major);
331-
auto channel = dma.channels[port];
332-
333326
switch (minor) {
334327
case 0: channel.set_base(value);
335328
case 4: channel.set_block_control(value);
@@ -347,9 +340,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
347340
}
348341
break;
349342
case 3:
350-
auto port = dma.from_index(major);
351-
auto channel = dma.channels[port];
352-
353343
switch (minor) {
354344
case 0: channel.set_base(value);
355345
case 4: channel.set_block_control(value);
@@ -367,9 +357,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
367357
}
368358
break;
369359
case 4:
370-
auto port = dma.from_index(major);
371-
auto channel = dma.channels[port];
372-
373360
switch (minor) {
374361
case 0: channel.set_base(value);
375362
case 4: channel.set_block_control(value);
@@ -387,9 +374,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
387374
}
388375
break;
389376
case 5:
390-
auto port = dma.from_index(major);
391-
auto channel = dma.channels[port];
392-
393377
switch (minor) {
394378
case 0: channel.set_base(value);
395379
case 4: channel.set_block_control(value);
@@ -407,9 +391,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
407391
}
408392
break;
409393
case 6:
410-
auto port = dma.from_index(major);
411-
auto channel = dma.channels[port];
412-
413394
switch (minor) {
414395
case 0: channel.set_base(value);
415396
case 4: channel.set_block_control(value);
@@ -462,9 +443,72 @@ void Bus::do_dma(Port port) {
462443
break;
463444

464445
default:
465-
std::cout << "[BUS] UNIMPLEMENTED: DO DMA BLOCK\n";
466-
exit(0);
467-
//do_dma_block(port);
446+
do_dma_block(port);
468447
break;
469448
}
449+
}
450+
451+
void Bus::do_dma_block(Port port) {
452+
auto channel = dma.channels[port];
453+
454+
auto increment = [&]() {
455+
switch (channel.step) {
456+
case Step::Increment:
457+
return 4;
458+
case Step::Decrement:
459+
return -4;
460+
}
461+
}();
462+
463+
auto addr = channel.get_base();
464+
465+
// Transfer size in words
466+
auto remsz = [&]() {
467+
auto transferSize = channel.transfer_size();
468+
if (transferSize.has_value()) {
469+
return transferSize.value();
470+
}
471+
else {
472+
throw std::runtime_error("[Bus] ERROR: Couldn't figure out DMA block transfer size");
473+
}
474+
}();
475+
476+
while (remsz > 0) {
477+
// Not sure what happens if address is
478+
// bogus... Mednafen just masks addr this way, maybe
479+
// that's how the hardware behaves (i.e. the RAM
480+
// address wraps and the two LSB are ignored, seems
481+
// reasonable enough
482+
auto cur_addr = addr & 0x1ffffc;
483+
484+
switch (channel.direction){
485+
case Direction::FromRam:
486+
throw std::runtime_error("[Bus] ERROR: Unhandled DMA direction");
487+
488+
case Direction::ToRam:
489+
uint32_t src_word;
490+
switch (port) {
491+
// Clear ordering table
492+
case Port::Otc:
493+
switch (remsz) {
494+
// Last entry contains the end
495+
// of table marker
496+
case 1:
497+
src_word = (uint32_t)0xffffff;
498+
// Pointer to the previous entry
499+
default:
500+
uint32_t a = addr - (uint32_t)4;
501+
src_word = (a & 0x1fffff);
502+
};
503+
default:
504+
throw std::runtime_error("[Bus] ERROR: Unhandled DMA source port");
505+
};
506+
ram.store32(cur_addr, src_word);
507+
}
508+
509+
addr = addr + increment;
510+
remsz -= 1;
511+
}
512+
513+
channel.done();
470514
}

PSEMU/Bus.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class Bus {
4545

4646
void set_dma_reg(uint32_t offset, uint32_t value);
4747

48+
void do_dma_block(Port port);
49+
4850
Bios bios;
4951
RAM ram;
5052
DMA dma;

PSEMU/DMA.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,11 +114,39 @@ void DMAChannel::set_block_control(uint32_t val) {
114114
bool DMAChannel::active() {
115115
// In manual sync mode the CPU must set the "trigger" bit
116116
// to start the transfer.
117-
bool trigger;
118-
switch (sync){
119-
case Sync::Manual: trigger = trigger;
120-
default: trigger = true;
121-
};
117+
auto triggera = [&]() {
118+
switch (sync) {
119+
case Sync::Manual:
120+
return trigger;
121+
default:
122+
return true;
123+
}
124+
}();
125+
126+
return enable&& triggera;
127+
}
128+
129+
std::optional<uint32_t> DMAChannel::transfer_size() {
130+
auto bs = (uint32_t)block_size;
131+
auto bc = (uint32_t)block_count;
132+
133+
switch (sync) {
134+
case Sync::Manual:
135+
return bs;
136+
137+
case Sync::Request:
138+
return bc * bs;
139+
140+
case Sync::LinkedList:
141+
return std::nullopt;
142+
}
143+
}
144+
145+
void DMAChannel::done() {
146+
enable = false;
147+
trigger = false;
148+
149+
// XXX Need to set the correct value for the other fields
150+
// (in particular interrupts)
151+
}
122152

123-
enable&& trigger;
124-
}

PSEMU/DMA.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <cstdint>
33
#include <string>
44
#include <iostream>
5+
#include <optional>
56

67
enum Direction {
78
ToRam = 0,
@@ -63,6 +64,8 @@ class DMAChannel {
6364
uint32_t control();
6465
bool active();
6566
void set_control(uint32_t val);
67+
std::optional<uint32_t> transfer_size();
68+
void done();
6669
uint32_t block_control();
6770
void set_block_control(uint32_t val);
6871
uint32_t get_base() { return base; };

PSEMU/x64/Debug/CPU.obj

2.66 KB
Binary file not shown.

PSEMU/x64/Debug/PSEMU.ilk

-1.24 MB
Binary file not shown.

PSEMU/x64/Debug/PSEMU.log

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
1-
 CPU.cpp
1+
 DMA.cpp
2+
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(26,36): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
3+
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(30,33): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
4+
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(54,22): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
5+
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(63,29): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
6+
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(72,28): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
7+
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(95,31): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
8+
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(96,32): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
9+
PSEMU.cpp
210
C:\Users\RonitD\Desktop\PSEMU\PSEMU\CPU.h(114,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
311
C:\Users\RonitD\Desktop\PSEMU\PSEMU\CPU.h(123,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
412
C:\Users\RonitD\Desktop\PSEMU\PSEMU\CPU.h(132,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
5-
C:\Users\RonitD\Desktop\PSEMU\PSEMU\CPU.cpp(440,48): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
13+
Generating Code...
14+
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(143): warning C4715: 'DMAChannel::transfer_size': not all control paths return a value
615
PSEMU.vcxproj -> C:\Users\RonitD\Desktop\PSEMU\x64\Debug\PSEMU.exe

PSEMU/x64/Debug/PSEMU.obj

42 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
-364 Bytes
Binary file not shown.
1.68 KB
Binary file not shown.
220 Bytes
Binary file not shown.

PSEMU/x64/Debug/vc143.idb

0 Bytes
Binary file not shown.

PSEMU/x64/Debug/vc143.pdb

0 Bytes
Binary file not shown.

x64/Debug/PSEMU.exe

8.5 KB
Binary file not shown.

x64/Debug/PSEMU.pdb

0 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)