Skip to content

Commit

Permalink
Did the DMA. still a lot to finish
Browse files Browse the repository at this point in the history
  • Loading branch information
Cherrytree56567 committed Oct 29, 2023
1 parent 0dfeeab commit e8483e5
Show file tree
Hide file tree
Showing 16 changed files with 121 additions and 35 deletions.
96 changes: 70 additions & 26 deletions PSEMU/Bus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ uint32_t Bus::load32(uint32_t addr) {
return 0;
}
else if (auto offset = _DMA.contains(abs_addr); offset.has_value()) {
//dma_reg(offset.value());
dma_reg(offset.value());
}
else if (auto offset = GPU.contains(abs_addr); offset.has_value()) {
std::cout << "[BUS] WARNING: GPU NOT IMPLEMENTED. GPU read " << std::to_string(offset.value()) << "\n";
Expand Down Expand Up @@ -58,7 +58,7 @@ void Bus::store32(uint32_t addr, uint32_t value) {
return;
}
else if (auto offset = _DMA.contains(abs_addr); offset.has_value()) {
//set_dma_reg(offset.value(), value);
set_dma_reg(offset.value(), value);
return;
}
else if (auto offset = GPU.contains(abs_addr); offset.has_value()) {
Expand Down Expand Up @@ -283,13 +283,12 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
auto minor = offset & 0xf;

Port active_port;
auto port = dma.from_index(major);
auto channel = dma.channels[port];
switch (major) {
// Per-channel registers
// 0-6
case 0:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor){
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
Expand All @@ -307,9 +306,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
}
break;
case 1:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
Expand All @@ -327,9 +323,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
}
break;
case 2:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
Expand All @@ -347,9 +340,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
}
break;
case 3:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
Expand All @@ -367,9 +357,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
}
break;
case 4:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
Expand All @@ -387,9 +374,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
}
break;
case 5:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
Expand All @@ -407,9 +391,6 @@ void Bus::set_dma_reg(uint32_t offset, uint32_t value) {
}
break;
case 6:
auto port = dma.from_index(major);
auto channel = dma.channels[port];

switch (minor) {
case 0: channel.set_base(value);
case 4: channel.set_block_control(value);
Expand Down Expand Up @@ -462,9 +443,72 @@ void Bus::do_dma(Port port) {
break;

default:
std::cout << "[BUS] UNIMPLEMENTED: DO DMA BLOCK\n";
exit(0);
//do_dma_block(port);
do_dma_block(port);
break;
}
}

void Bus::do_dma_block(Port port) {
auto channel = dma.channels[port];

auto increment = [&]() {
switch (channel.step) {
case Step::Increment:
return 4;
case Step::Decrement:
return -4;
}
}();

auto addr = channel.get_base();

// Transfer size in words
auto remsz = [&]() {
auto transferSize = channel.transfer_size();
if (transferSize.has_value()) {
return transferSize.value();
}
else {
throw std::runtime_error("[Bus] ERROR: Couldn't figure out DMA block transfer size");
}
}();

while (remsz > 0) {
// Not sure what happens if address is
// bogus... Mednafen just masks addr this way, maybe
// that's how the hardware behaves (i.e. the RAM
// address wraps and the two LSB are ignored, seems
// reasonable enough
auto cur_addr = addr & 0x1ffffc;

switch (channel.direction){
case Direction::FromRam:
throw std::runtime_error("[Bus] ERROR: Unhandled DMA direction");

case Direction::ToRam:
uint32_t src_word;
switch (port) {
// Clear ordering table
case Port::Otc:
switch (remsz) {
// Last entry contains the end
// of table marker
case 1:
src_word = (uint32_t)0xffffff;
// Pointer to the previous entry
default:
uint32_t a = addr - (uint32_t)4;
src_word = (a & 0x1fffff);
};
default:
throw std::runtime_error("[Bus] ERROR: Unhandled DMA source port");
};
ram.store32(cur_addr, src_word);
}

addr = addr + increment;
remsz -= 1;
}

channel.done();
}
2 changes: 2 additions & 0 deletions PSEMU/Bus.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class Bus {

void set_dma_reg(uint32_t offset, uint32_t value);

void do_dma_block(Port port);

Bios bios;
RAM ram;
DMA dma;
Expand Down
42 changes: 35 additions & 7 deletions PSEMU/DMA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,39 @@ void DMAChannel::set_block_control(uint32_t val) {
bool DMAChannel::active() {
// In manual sync mode the CPU must set the "trigger" bit
// to start the transfer.
bool trigger;
switch (sync){
case Sync::Manual: trigger = trigger;
default: trigger = true;
};
auto triggera = [&]() {
switch (sync) {
case Sync::Manual:
return trigger;
default:
return true;
}
}();

return enable&& triggera;
}

std::optional<uint32_t> DMAChannel::transfer_size() {
auto bs = (uint32_t)block_size;
auto bc = (uint32_t)block_count;

switch (sync) {
case Sync::Manual:
return bs;

case Sync::Request:
return bc * bs;

case Sync::LinkedList:
return std::nullopt;
}
}

void DMAChannel::done() {
enable = false;
trigger = false;

// XXX Need to set the correct value for the other fields
// (in particular interrupts)
}

enable&& trigger;
}
3 changes: 3 additions & 0 deletions PSEMU/DMA.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <cstdint>
#include <string>
#include <iostream>
#include <optional>

enum Direction {
ToRam = 0,
Expand Down Expand Up @@ -63,6 +64,8 @@ class DMAChannel {
uint32_t control();
bool active();
void set_control(uint32_t val);
std::optional<uint32_t> transfer_size();
void done();
uint32_t block_control();
void set_block_control(uint32_t val);
uint32_t get_base() { return base; };
Expand Down
Binary file modified PSEMU/x64/Debug/CPU.obj
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.ilk
Binary file not shown.
13 changes: 11 additions & 2 deletions PSEMU/x64/Debug/PSEMU.log
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
 CPU.cpp
 DMA.cpp
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(26,36): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(30,33): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(54,22): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(63,29): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(72,28): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(95,31): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(96,32): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
PSEMU.cpp
C:\Users\RonitD\Desktop\PSEMU\PSEMU\CPU.h(114,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\RonitD\Desktop\PSEMU\PSEMU\CPU.h(123,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\RonitD\Desktop\PSEMU\PSEMU\CPU.h(132,1): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
C:\Users\RonitD\Desktop\PSEMU\PSEMU\CPU.cpp(440,48): warning C4554: '&': check operator precedence for possible error; use parentheses to clarify precedence
Generating Code...
C:\Users\RonitD\Desktop\PSEMU\PSEMU\DMA.cpp(143): warning C4715: 'DMAChannel::transfer_size': not all control paths return a value
PSEMU.vcxproj -> C:\Users\RonitD\Desktop\PSEMU\x64\Debug\PSEMU.exe
Binary file modified PSEMU/x64/Debug/PSEMU.obj
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.tlog/CL.command.1.tlog
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.tlog/CL.read.1.tlog
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.tlog/CL.write.1.tlog
Binary file not shown.
Binary file modified PSEMU/x64/Debug/PSEMU.tlog/link.read.1.tlog
Binary file not shown.
Binary file modified PSEMU/x64/Debug/vc143.idb
Binary file not shown.
Binary file modified PSEMU/x64/Debug/vc143.pdb
Binary file not shown.
Binary file modified x64/Debug/PSEMU.exe
Binary file not shown.
Binary file modified x64/Debug/PSEMU.pdb
Binary file not shown.

0 comments on commit e8483e5

Please sign in to comment.