Use new IO Port related types and further improvements of readability #1

Merged
jaby merged 18 commits from Overlay-The-Beginning_CDDrive_EndOfIO into Overlay-The-Beginning_CDDrive 2023-03-23 19:43:52 +00:00
25 changed files with 846 additions and 864 deletions

View File

@ -1,17 +1,88 @@
#ifndef __JABYENGINE_BITS_HPP__ #ifndef __JABYENGINE_BITS_HPP__
#define __JABYENGINE_BITS_HPP__ #define __JABYENGINE_BITS_HPP__
#include "../jabyengine_defines.h" #include "../jabyengine_defines.h"
#include "types.hpp"
namespace JabyEngine { namespace JabyEngine {
namespace bit { namespace bit {
namespace value {
template<typename T>
static constexpr T set_normalized(T raw_value, T value, size_t start_bit, size_t length);
}
}
struct ClearBit {
uint16_t pos;
constexpr ClearBit(uint16_t bit_pos) : pos(bit_pos) {
}
};
struct Bit {
uint16_t pos;
constexpr Bit(uint16_t bit_pos) : pos(bit_pos) {
}
constexpr ClearBit operator!() const {
return ClearBit(this->pos);
}
};
struct BitRange {
template<typename T>
using RangeValuePair = pair<BitRange, T>;
uint16_t pos;
uint16_t length;
constexpr BitRange(uint16_t pos, uint16_t length) : pos(pos), length(length) {
}
static constexpr BitRange from_to(uint16_t first_bit, uint16_t last_bit) {
return BitRange(first_bit, (last_bit - first_bit) + 1);
}
template<typename T>
constexpr RangeValuePair<T> with(T value) const {
return {*this, value};
}
template<typename T>
constexpr T as_value(T value) const {
return bit::value::set_normalized(static_cast<T>(0), value, this->pos, this->length);
}
template<typename T>
constexpr RangeValuePair<T> range_max() const {
return BitRange::with<T>((1 << this->length) - 1);
}
};
namespace bit {
template<typename T>
static constexpr T clear(T raw_value, size_t bit) {
return (raw_value & ~(1 << bit));
}
template<typename T>
static constexpr T clear(T raw_value, Bit bit) {
return clear(raw_value, bit.pos);
}
template<typename T> template<typename T>
static constexpr T set(T raw_value, size_t bit) { static constexpr T set(T raw_value, size_t bit) {
return (raw_value | (1 << bit)); return (raw_value | (1 << bit));
} }
template<typename T> template<typename T>
static constexpr T clear(T raw_value, size_t bit) { static constexpr T set(T raw_value, Bit bit) {
return (raw_value & ~(1 << bit)); return set(raw_value, bit.pos);
}
template<typename T>
static constexpr T set(T raw_value, ClearBit bit) {
return clear(raw_value, bit.pos);
} }
template<typename T> template<typename T>
@ -19,7 +90,13 @@ namespace JabyEngine {
return static_cast<bool>(raw_value & (1 << bit)); return static_cast<bool>(raw_value & (1 << bit));
} }
template<typename T>
static constexpr bool is_set(T raw_value, Bit bit) {
return is_set(raw_value, bit.pos);
}
namespace value { namespace value {
namespace helper {
template<typename T> template<typename T>
static constexpr T crop_value(T raw_value, size_t length) { static constexpr T crop_value(T raw_value, size_t length) {
return (raw_value & ((1 << length) - 1)); return (raw_value & ((1 << length) - 1));
@ -29,20 +106,36 @@ namespace JabyEngine {
static constexpr T range_mask(size_t start_bit, size_t length) { static constexpr T range_mask(size_t start_bit, size_t length) {
return (((1 << length) - 1) << start_bit); return (((1 << length) - 1) << start_bit);
} }
}
template<typename T> template<typename T>
static constexpr T clear_normalized(T raw_value, size_t start_bit, size_t length) { static constexpr T clear_normalized(T raw_value, size_t start_bit, size_t length) {
return (raw_value & ~range_mask<T>(start_bit, length)); return (raw_value & ~helper::range_mask<T>(start_bit, length));
} }
template<typename T> template<typename T>
static constexpr T set_normalized(T raw_value, T value, size_t start_bit, size_t length) { static constexpr T set_normalized(T raw_value, T value, size_t start_bit, size_t length) {
return (clear_normalized(raw_value, start_bit, length) | (value << start_bit)); return (clear_normalized(raw_value, start_bit, length) | (helper::crop_value(value, length) << start_bit));
}
template<typename T>
static constexpr T set_normalized(T raw_value, BitRange bits, T value) {
return set_normalized(raw_value, value, bits.pos, bits.length);
}
template<typename T, typename S>
static constexpr T set_normalized(T raw_value, const BitRange::RangeValuePair<S> &value_pair) {
return set_normalized(raw_value, value_pair.first, static_cast<T>(value_pair.second));
} }
template<typename T> template<typename T>
static constexpr T get_normalized(T raw_value, size_t start_bit, size_t length) { static constexpr T get_normalized(T raw_value, size_t start_bit, size_t length) {
return (raw_value & range_mask<T>(start_bit, length)) >> start_bit; return helper::crop_value((raw_value & helper::range_mask<T>(start_bit, length)) >> start_bit, length);
}
template<typename T>
static constexpr T get_normalized(T raw_value, BitRange range) {
return get_normalized(raw_value, range.pos, range.length);
} }
} }

View File

@ -1,210 +0,0 @@
#ifndef __JABYENGINE_COMPLEX_BITMAP_HPP__
#define __JABYENGINE_COMPLEX_BITMAP_HPP__
#include "bits.hpp"
namespace JabyEngine {
struct ClearBitValue {
size_t bit;
constexpr ClearBitValue(size_t bit) : bit(bit) {
}
};
template<typename T>
struct Bit {
typedef T ValueType;
size_t value;
constexpr Bit(size_t value) : value(value) {
}
constexpr operator size_t() const {
return this->value;
}
constexpr ClearBitValue operator!() const {
return ClearBitValue(this->value);
}
};
template<typename T>
struct BitRangeValue {
T value;
size_t begin;
size_t length;
constexpr BitRangeValue() = default;
constexpr BitRangeValue(T value, size_t begin, size_t length) : value(value), begin(begin), length(length) {
}
};
template<typename T>
struct BitRange {
typedef T ValueType;
size_t begin;
size_t length;
static constexpr BitRange<T> from_to(size_t start, size_t end) {
return {start, (end - start + 1)};
}
constexpr BitRangeValue<T> with(T value) const {
return BitRangeValue(value, this->begin, this->length);
}
constexpr BitRangeValue<T> max() const {
return BitRange<T>::with((1 << this->length) - 1);
}
};
template<typename T>
static constexpr __always_inline BitRangeValue<T> operator<<(const BitRange<T>& range, T value) {
return BitRangeValue{value, range.begin, range.length};
}
template<typename T>
class ComplexBitMap {
public:
typedef T UnderlyingType;
T raw;
private:
template<typename S>
constexpr __always_inline ComplexBitMap<T>& set_va(const S& value) {
return this->set(value);
}
template<typename S, typename...ARGS>
constexpr __always_inline ComplexBitMap<T>& set_va(const S& value, const ARGS&...args) {
return this->set_va(value).set_va(args...);
}
public:
template<typename...ARGS>
static constexpr __always_inline ComplexBitMap<T> with(ARGS...args) {
return ComplexBitMap().set_va(args...);
}
//Accesssing bits
template<typename S>
constexpr ComplexBitMap<T>& set_bit(S bit) {
this->raw = bit::set(this->raw, static_cast<size_t>(bit));
return *this;
}
template<typename S>
constexpr void set_bit(S bit) volatile {
this->raw = bit::set(this->raw, static_cast<size_t>(bit));
}
template<typename S>
constexpr ComplexBitMap<T>& clear_bit(S bit) {
this->raw = bit::clear(this->raw, static_cast<size_t>(bit));
return *this;
}
template<typename S>
constexpr void clear_bit(S bit) volatile {
this->raw = bit::clear(this->raw, static_cast<size_t>(bit));
}
template<typename S>
constexpr bool is_bit_set(S bit) {
return bit::is_set(this->raw, static_cast<size_t>(bit));
}
template<typename S>
constexpr bool is_bit_set(S bit) const volatile {
return bit::is_set(this->raw, static_cast<size_t>(bit));
}
//Accessing values
template<typename S>
constexpr ComplexBitMap<T>& set_value(S value, const BitRange<S>& range) {
this->raw = bit::value::set_normalized(this->raw, static_cast<T>(value), range.begin, range.length);
return *this;
}
template<typename S>
constexpr void set_value(S value, const BitRange<S>& range) volatile {
this->raw = bit::value::set_normalized(this->raw, static_cast<T>(value), range.begin, range.length);
}
template<typename S>
constexpr ComplexBitMap<T>& clear_value(const BitRange<S>& range) {
this->raw = bit::value::clear_normalized(this->raw, range.begin, range.length);
return *this;
}
template<typename S>
constexpr void clear_value(const BitRange<S>& range) volatile {
this->raw = bit::value::clear_normalized(this->raw, range.begin, range.length);
}
template<typename S>
constexpr S get_value(const BitRange<S>& range) const {
return static_cast<S>(bit::value::get_normalized(this->raw, range.begin, range.length));
}
template<typename S>
constexpr S get_value(const BitRange<S>& range) const volatile {
return static_cast<S>(bit::value::get_normalized(this->raw, range.begin, range.length));
}
//For easier checking
constexpr bool is(Bit<T> bit) const {
return ComplexBitMap::is_bit_set(bit);
}
constexpr bool is(Bit<T> bit) const volatile {
return ComplexBitMap::is_bit_set(bit);
}
// For easier constructing
template<typename S>
constexpr __always_inline ComplexBitMap<T>& set(const BitRange<S>& range, T value) {
this->set_value(value, range);
return *this;
}
template<typename S>
constexpr __always_inline ComplexBitMap<T>& set(const BitRangeValue<S>& value) {
this->set_value(value.value, {value.begin, value.length});
return *this;
}
template<typename S>
constexpr __always_inline ComplexBitMap<T>& set(const Bit<S>& bit) {
this->set_bit(bit.value);
return *this;
}
constexpr __always_inline ComplexBitMap<T>& set(const ClearBitValue& value) {
this->clear_bit(value.bit);
return *this;
}
constexpr __always_inline ComplexBitMap<T>& operator|(const BitRangeValue<T>& value) {
this->set_value(value.value, value.range);
return *this;
}
constexpr __always_inline ComplexBitMap<T>& operator|(const Bit<T>& bit) {
this->set_bit(bit.value);
return *this;
}
constexpr __always_inline ComplexBitMap<T>& operator|(const ClearBitValue& value) {
this->clear_bit(value.bit);
return *this;
}
constexpr __always_inline operator T() const {
return this->raw;
}
};
}
#endif //!__JABYENGINE_COMPLEX_BITMAP_HPP__

View File

@ -1,36 +1,37 @@
#ifndef __JABYENGINE_FILE_TYPES_HPP__ #ifndef __JABYENGINE_FILE_TYPES_HPP__
#define __JABYENGINE_FILE_TYPES_HPP__ #define __JABYENGINE_FILE_TYPES_HPP__
#include "../Auxiliary/complex_bitmap.hpp"
#include "../jabyengine_defines.h" #include "../jabyengine_defines.h"
namespace JabyEngine { namespace JabyEngine {
struct __no_align SimpleTIM : private ComplexBitMap<uint32_t> { struct __no_align SimpleTIM {
static constexpr auto TextureX = BitRange<uint32_t>(0, 8); static constexpr auto TextureX = BitRange::from_to(0, 8);
static constexpr auto TextureY = BitRange<uint32_t>(9, 16); static constexpr auto TextureY = BitRange::from_to(9, 16);
static constexpr auto ClutX = BitRange<uint32_t>(17, 22); static constexpr auto ClutX = BitRange::from_to(17, 22);
static constexpr auto ClutY = BitRange<uint32_t>(23, 31); static constexpr auto ClutY = BitRange::from_to(23, 31);
uint32_t raw;
constexpr SimpleTIM() { constexpr SimpleTIM() {
this->raw = 0; this->raw = 0;
} }
constexpr SimpleTIM(uint16_t texX, uint16_t texY, uint16_t clutX, uint16_t clutY) : ComplexBitMap(ComplexBitMap::with(TextureX.with(texX >> 1), TextureY.with(texY >> 1), ClutX.with(clutX >> 4), ClutY.with(clutY))) { constexpr SimpleTIM(uint16_t texX, uint16_t texY, uint16_t clutX, uint16_t clutY) : raw(TextureX.as_value(texX >> 1) | TextureY.as_value(texY >> 1) | ClutX.as_value(clutX >> 4) | ClutY.as_value(clutY)) {
} }
constexpr uint16_t getTextureX() const { constexpr uint16_t getTextureX() const {
return (ComplexBitMap<uint32_t>::get_value(SimpleTIM::TextureX) << 1); return bit::value::get_normalized(this->raw, TextureX) << 1;
} }
constexpr uint16_t getTextureY() const { constexpr uint16_t getTextureY() const {
return (ComplexBitMap<uint32_t>::get_value(SimpleTIM::TextureY) << 1); return bit::value::get_normalized(this->raw, TextureY) << 1;
} }
constexpr uint16_t getClutX() const { constexpr uint16_t getClutX() const {
return (ComplexBitMap<uint32_t>::get_value(SimpleTIM::ClutX) << 4); return bit::value::get_normalized(this->raw, SimpleTIM::ClutX) << 4;
} }
constexpr uint16_t getClutY() const { constexpr uint16_t getClutY() const {
return ComplexBitMap<uint32_t>::get_value(SimpleTIM::ClutY); return bit::value::get_normalized(this->raw, ClutY);
} }
}; };

View File

@ -22,11 +22,11 @@ namespace JabyEngine {
#endif #endif
static void enable() { static void enable() {
GPU_IO::GP1.write(GPU_IO::Command::GP1::SetDisplayState(GPU_IO::DisplayState::On)); GPU_IO::GP1 = GPU_IO::Command::SetDisplayState(GPU_IO::DisplayState::On);
cody marked this conversation as resolved
Review

This is definitely way nicer looking to me vs using a write method!

This is definitely way nicer looking to me vs using a write method!
} }
static void disable() { static void disable() {
GPU_IO::GP1.write(GPU_IO::Command::GP1::SetDisplayState(GPU_IO::DisplayState::Off)); GPU_IO::GP1 = GPU_IO::Command::SetDisplayState(GPU_IO::DisplayState::Off);
} }
}; };

View File

@ -1,7 +1,6 @@
#ifndef __JABYENGINE_GPU_TYPES_HPP__ #ifndef __JABYENGINE_GPU_TYPES_HPP__
#define __JABYENGINE_GPU_TYPES_HPP__ #define __JABYENGINE_GPU_TYPES_HPP__
#include "../jabyengine_defines.h" #include "../jabyengine_defines.h"
#include "../Auxiliary/complex_bitmap.hpp"
namespace JabyEngine { namespace JabyEngine {
namespace GPU { namespace GPU {
@ -41,12 +40,12 @@ namespace JabyEngine {
class Color { class Color {
private: private:
static constexpr auto RedRange = BitRange<uint16_t>::from_to(0, 4); static constexpr auto RedRange = BitRange::from_to(0, 4);
static constexpr auto GreenRange = BitRange<uint16_t>::from_to(5, 9); static constexpr auto GreenRange = BitRange::from_to(5, 9);
static constexpr auto BlueRange = BitRange<uint16_t>::from_to(10, 14); static constexpr auto BlueRange = BitRange::from_to(10, 14);
static constexpr auto SemiTransperancyBit = Bit<uint16_t>(15); static constexpr auto SemiTransperancyBit = Bit(15);
ComplexBitMap<uint16_t> value = {0}; uint16_t value = 0;
public: public:
static constexpr Color from_rgb(uint8_t r, uint8_t g, uint8_t b) { static constexpr Color from_rgb(uint8_t r, uint8_t g, uint8_t b) {
@ -58,17 +57,17 @@ namespace JabyEngine {
} }
constexpr Color& set_red(uint8_t red) { constexpr Color& set_red(uint8_t red) {
this->value.set_value(static_cast<uint16_t>(red), RedRange); this->value = bit::value::set_normalized(this->value, RedRange.with(red));
return *this; return *this;
} }
constexpr Color& set_green(uint8_t green) { constexpr Color& set_green(uint8_t green) {
this->value.set_value(static_cast<uint16_t>(green), GreenRange); this->value = bit::value::set_normalized(this->value, GreenRange.with(green));
return *this; return *this;
} }
constexpr Color& set_blue(uint8_t blue) { constexpr Color& set_blue(uint8_t blue) {
this->value.set_value(static_cast<uint16_t>(blue), BlueRange); this->value = bit::value::set_normalized(this->value, BlueRange.with(blue));
return *this; return *this;
} }
}; };

View File

@ -31,56 +31,54 @@ namespace JabyEngine {
static constexpr uint8_t Max = 0xFF; static constexpr uint8_t Max = 0xFF;
}; };
typedef struct IndexStatus : public ComplexBitMap<uint8_t> { __declare_io_type(IndexStatus, uint8_t,
static constexpr auto PortIndex = BitRange<Index>::from_to(0, 1); static constexpr auto PortIndex = BitRange::from_to(0, 1);
static constexpr auto HasXAFifoData = Bit<uint8_t>(2); static constexpr auto HasXAFifoData = Bit(2);
static constexpr auto IsParameterFifoEmpty = Bit<uint8_t>(3); static constexpr auto IsParameterFifoEmpty = Bit(3);
static constexpr auto HasParameterFifoSpace = Bit<uint8_t>(4); static constexpr auto HasParameterFifoSpace = Bit(4);
static constexpr auto HasResponseFifoData = Bit<uint8_t>(5); static constexpr auto HasResponseFifoData = Bit(5);
static constexpr auto HasDataFifoData = Bit<uint8_t>(6); static constexpr auto HasDataFifoData = Bit(6);
static constexpr auto IsTransmissionBusy = Bit<uint8_t>(7); static constexpr auto IsTransmissionBusy = Bit(7);
} IndexStatus_t; );
Review

Very good readability with this style of types and instantiation

Very good readability with this style of types and instantiation
struct InterruptEnable : public ComplexBitMap<uint8_t> { __declare_io_type(InterruptEnable, uint8_t,
static constexpr auto InterruptTypValue = BitRange<uint8_t>::from_to(0, 2); static constexpr auto InterruptTypValue = BitRange::from_to(0, 2);
static constexpr auto InterruptExtended = BitRange<uint8_t>::from_to(0, 4); static constexpr auto InterruptExtended = BitRange::from_to(0, 4);
static constexpr auto UnknownIRQ = Bit<uint8_t>(3); static constexpr auto UnknownIRQ = Bit(3);
static constexpr auto CommandStartIRQ = Bit<uint8_t>(4); static constexpr auto CommandStartIRQ = Bit(4);
}; );
typedef InterruptEnable InterruptFlag; typedef InterruptEnable_v InterruptFlag_v;
struct Request : public ComplexBitMap<uint8_t> { __declare_io_type(Request, uint8_t,
static constexpr auto WantCommandStartIRQ = Bit<uint8_t>(5); static constexpr auto WantCommandStartIRQ = Bit(5);
static constexpr auto WantData = Bit<uint8_t>(7); static constexpr auto WantData = Bit(7);
}; );
struct SoundMapCoding : public ComplexBitMap<uint8_t> { __declare_io_type(SoundMapCoding, uint8_t,
static constexpr auto Stereo = Bit<uint8_t>(0); static constexpr auto Stereo = Bit(0);
static constexpr auto Mono = !Stereo; static constexpr auto Mono = !Stereo;
static constexpr auto SampleRate_18900hz = Bit<uint8_t>(2); static constexpr auto SampleRate_18900hz = Bit(2);
static constexpr auto SampleRate_37800hz = !SampleRate_18900hz; static constexpr auto SampleRate_37800hz = !SampleRate_18900hz;
static constexpr auto BitsPerSample8 = Bit<uint8_t>(4); static constexpr auto BitsPerSample8 = Bit(4);
static constexpr auto BitsPerSample4 = !BitsPerSample8; static constexpr auto BitsPerSample4 = !BitsPerSample8;
static constexpr auto Emphasis = Bit<uint8_t>(6); static constexpr auto Emphasis = Bit(6);
}; );
struct AudioVolumeApply : public ComplexBitMap<uint8_t> { __declare_io_type(AudioVolumeApply, uint8_t,
static constexpr auto Mute = Bit<uint8_t>(0); static constexpr auto Mute = Bit(0);
static constexpr auto ApplyChanges = Bit<uint8_t>(5); static constexpr auto ApplyChanges = Bit(5);
}; );
typedef VolatilePOD<uint8_t> ResponseFifo_t; __declare_io_type(ResponseFifo, uint8_t,);
typedef VolatilePOD<uint8_t> CommandFifo_t; __declare_io_type(CommandFifo, uint8_t,);
typedef VolatilePOD<uint8_t> DataFifo_t; __declare_io_type(DataFifo, uint8_t,);
typedef VolatilePOD<uint16_t> DataFifo16_t; __declare_io_type(DataFifo16, uint16_t,);
typedef VolatilePOD<uint8_t> ParameterFifo_t; __declare_io_type(ParameterFifo, uint8_t,);
typedef VolatilePOD<uint8_t> SoundMapDataOut_t; __declare_io_type(SoundMapDataOut, uint8_t,);
typedef VolatilePOD<CDDAVolume::Type> VolumeRegister_t; __declare_io_type(LeftCD2LeftSPU, CDDAVolume::Type,);
typedef VolatileBitMapPOD<InterruptEnable> InterruptEnableRegister_t; __declare_io_type(LeftCD2RightSPU, CDDAVolume::Type,);
typedef VolatileBitMapPOD<InterruptFlag> InterruptFlagRegister_t; __declare_io_type(RightCD2RightSPU,CDDAVolume::Type,);
typedef VolatileBitMapPOD<Request> RequestRegister_t; __declare_io_type(RightCD2LeftSPU, CDDAVolume::Type,);
typedef VolatileBitMapPOD<SoundMapCoding> SoundMapCodingInfo_t;
typedef VolatileBitMapPOD<AudioVolumeApply> AudioVolumeApplyChange_t;
struct Interrupt { struct Interrupt {
enum Type : uint8_t { enum Type : uint8_t {
@ -92,110 +90,110 @@ namespace JabyEngine {
DiskError = 5 DiskError = 5
}; };
static void enable(InterruptEnableRegister_t& port) { static void enable(InterruptEnable_v& port) {
port.write(InterruptEnable::InterruptTypValue.max()); port.set(InterruptEnable_t::InterruptTypValue.range_max<uint8_t>());
} }
static void enable_extended(InterruptEnableRegister_t& port) { static void enable_extended(InterruptEnable_v& port) {
port.write({InterruptEnable::with(InterruptEnable::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)}); port = InterruptEnable_t::from(InterruptEnable_t::InterruptTypValue.range_max<uint8_t>(), InterruptEnable_t::UnknownIRQ, InterruptEnable_t::CommandStartIRQ);
} }
static Type get_type(const InterruptFlagRegister_t& port) { static Type get_type(const InterruptFlag_v& port) {
return static_cast<Type>(port.read().get_value(InterruptFlag::InterruptTypValue)); return static_cast<Type>(port.get(InterruptFlag_v::InterruptTypValue));
} }
static void ack(InterruptFlagRegister_t& port) { static void ack(InterruptFlag_v& port) {
port.write(InterruptFlag::InterruptTypValue.max()); port.set(InterruptFlag_v::InterruptTypValue.range_max<uint8_t>());
} }
static void ack_extended(InterruptFlagRegister_t& port) { static void ack_extended(InterruptFlag_v& port) {
port.write({InterruptFlag::with(InterruptFlag::InterruptTypValue.max(), InterruptEnable::UnknownIRQ, InterruptEnable::CommandStartIRQ)}); port = InterruptFlag_v::from(InterruptFlag_v::InterruptTypValue.range_max<uint8_t>(), InterruptEnable_v::UnknownIRQ, InterruptEnable_v::CommandStartIRQ);
} }
}; };
struct Command { struct Command {
struct Info { struct Desc {
uint8_t id; uint8_t id;
Interrupt::Type complete_irq; Interrupt::Type complete_irq;
}; };
static constexpr Info GetStat{0x01, Interrupt::Type::Acknowledge}; static constexpr Desc GetStat{0x01, Interrupt::Type::Acknowledge};
cody marked this conversation as resolved
Review

what is Desc?

what is Desc?
Review

It's the description of a CD command. I wanted to keep Command as the parent so developers can type Command::GetStat but then needed a sub type for the pair of the Command ID and the IRQ that indicates completion.
Better names are very welcome!

It's the description of a CD command. I wanted to keep `Command` as the parent so developers can type `Command::GetStat` but then needed a sub type for the pair of the Command ID and the IRQ that indicates completion. Better names are very welcome!
Review

Oh ok that totally makes sense as is. I just didn't understand why there would be a Description here at first.

Oh ok that totally makes sense as is. I just didn't understand why there would be a Description here at first.
static constexpr Info SetLoc{0x02, Interrupt::Type::Acknowledge}; static constexpr Desc SetLoc{0x02, Interrupt::Type::Acknowledge};
static constexpr Info ReadN{0x06, Interrupt::Type::DataReady}; static constexpr Desc ReadN{0x06, Interrupt::Type::DataReady};
static constexpr Info Pause{0x09, Interrupt::Type::Complete}; static constexpr Desc Pause{0x09, Interrupt::Type::Complete};
static constexpr Info Init{0x0A, Interrupt::Type::Complete}; static constexpr Desc Init{0x0A, Interrupt::Type::Complete};
static constexpr Info SetMode{0x0E, Interrupt::Type::Acknowledge}; static constexpr Desc SetMode{0x0E, Interrupt::Type::Acknowledge};
}; };
static constexpr auto IORegister1Adr = 0x1F801801; static constexpr auto IORegister1Adr = 0x1F801801;
static constexpr auto IORegister2Adr = 0x1F801802; static constexpr auto IORegister2Adr = 0x1F801802;
static constexpr auto IORegister3Adr = 0x1F801803; static constexpr auto IORegister3Adr = 0x1F801803;
__declare_io_port_global(IndexStatus_t, IndexStatus, 0x1F801800); __declare_new_io_port(IndexStatus, 0x1F801800);
#define __declare_index_io_port(type, name, adr) __cast_io_adr_with_type(inline, type, name, adr) #define __declare_index_io_port(type, name, adr) __cast_io_adr_with_type(inline, type, name, adr)
#define __declare_index_io_port_const(type, name, adr) __cast_io_adr_with_type(const inline, type, name, adr) #define __declare_index_io_port_const(type, name, adr) __cast_io_adr_with_type(const inline, type, name, adr)
struct PortIndex0 { struct PortIndex0 {
__declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr); __declare_new_const_io_port(ResponseFifo, IORegister1Adr);
__declare_index_io_port( CommandFifo_t, CommandFifo, IORegister1Adr); __declare_new_io_port(CommandFifo, IORegister1Adr);
__declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr); __declare_new_const_io_port(DataFifo, IORegister2Adr);
__declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr); __declare_new_const_io_port(DataFifo16, IORegister2Adr);
__declare_index_io_port( ParameterFifo_t, ParameterFifo, IORegister2Adr); __declare_new_io_port(ParameterFifo, IORegister2Adr);
__declare_index_io_port_const(InterruptEnableRegister_t, InterruptEnableRegister, IORegister3Adr); __declare_new_const_io_port(InterruptEnable, IORegister3Adr);
__declare_index_io_port( RequestRegister_t, RequestRegister, IORegister3Adr); __declare_new_io_port(Request, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus.write({static_cast<uint8_t>(Index::Index0)}); IndexStatus = Index::Index0;
} }
}; };
struct PortIndex1 { struct PortIndex1 {
__declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr); __declare_new_const_io_port(ResponseFifo, IORegister1Adr);
__declare_index_io_port( SoundMapDataOut_t, SoundMapDataOut, IORegister1Adr); __declare_new_io_port(SoundMapDataOut, IORegister1Adr);
__declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr); __declare_new_const_io_port(DataFifo, IORegister2Adr);
__declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr); __declare_new_const_io_port(DataFifo16, IORegister2Adr);
__declare_index_io_port( InterruptEnableRegister_t, InterruptEnableRegister, IORegister2Adr); __declare_new_io_port(InterruptEnable, IORegister2Adr);
__declare_index_io_port(InterruptFlagRegister_t, InterruptFlagRegister, IORegister3Adr); __declare_new_io_port(InterruptFlag, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus.write({static_cast<uint8_t>(Index::Index1)}); IndexStatus = Index::Index1;
} }
}; };
struct PortIndex2 { struct PortIndex2 {
__declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr); __declare_new_const_io_port(ResponseFifo, IORegister1Adr);
__declare_index_io_port( SoundMapCodingInfo_t, SoundMapCodingInfo, IORegister1Adr); __declare_new_io_port(SoundMapCoding, IORegister1Adr);
__declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr); __declare_new_const_io_port(DataFifo, IORegister2Adr);
__declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr); __declare_new_const_io_port(DataFifo16, IORegister2Adr);
__declare_index_io_port( VolumeRegister_t, LeftCD2LeftSPU, IORegister2Adr); __declare_new_io_port(LeftCD2LeftSPU, IORegister2Adr);
__declare_index_io_port_const(InterruptEnableRegister_t, InterruptEnableRegister, IORegister3Adr); __declare_new_const_io_port(InterruptEnable, IORegister3Adr);
__declare_index_io_port( VolumeRegister_t, LeftCD2RightSPU, IORegister3Adr); __declare_new_io_port(LeftCD2RightSPU, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus.write({static_cast<uint8_t>(Index::Index2)}); IndexStatus = Index::Index2;
} }
}; };
struct PortIndex3 { struct PortIndex3 {
__declare_index_io_port_const(ResponseFifo_t, ResponseFifo, IORegister1Adr); __declare_new_const_io_port(ResponseFifo, IORegister1Adr);
__declare_index_io_port( VolumeRegister_t, RightCD2RightSPU, IORegister1Adr); __declare_new_io_port(RightCD2RightSPU, IORegister1Adr);
__declare_index_io_port_const(DataFifo_t, DataFifo, IORegister2Adr); __declare_new_const_io_port(DataFifo, IORegister2Adr);
__declare_index_io_port_const(DataFifo16_t, DataFifo16, IORegister2Adr); __declare_new_const_io_port(DataFifo16, IORegister2Adr);
__declare_index_io_port( VolumeRegister_t, RightCD2LeftSPU, IORegister1Adr); __declare_new_io_port(RightCD2LeftSPU, IORegister1Adr);
__declare_index_io_port_const(InterruptFlagRegister_t, InterruptFlagRegister, IORegister3Adr); __declare_new_const_io_port(InterruptFlag, IORegister3Adr);
__declare_index_io_port( AudioVolumeApplyChange_t, AudioVolumeApplyChange, IORegister3Adr); __declare_new_io_port(AudioVolumeApply, IORegister3Adr);
static void change_to() { static void change_to() {
IndexStatus.write({static_cast<uint8_t>(Index::Index3)}); IndexStatus = Index::Index3;
} }
}; };

View File

@ -4,130 +4,147 @@
namespace JabyEngine { namespace JabyEngine {
namespace DMA_IO { namespace DMA_IO {
struct MADR : public ComplexBitMap<uint32_t> { __declare_io_type(MADR, uint32_t,
static constexpr auto MemoryAdr = BitRange<uint32_t>::from_to(0, 23); static constexpr auto MemoryAdr = BitRange::from_to(0, 23);
);
__declare_io_type(BCR, uint32_t,
struct SyncMode0 {
static constexpr auto NumberOfWords = BitRange::from_to(0, 15);
static constexpr auto CD_OneBlock = Bit(16);
}; };
struct BCR : public ComplexBitMap<uint32_t> { struct SyncMode1 {
struct __no_align SyncMode0 { static constexpr auto BlockSize = BitRange::from_to(0, 15);
static constexpr auto NumberOfWords = BitRange<uint16_t>::from_to(0, 15); static constexpr auto BlockAmount = BitRange::from_to(16, 31);
static constexpr auto CD_OneBlock = Bit<uint16_t>(16);
};
struct SyncMode1 : public ComplexBitMap<uint32_t> {
static constexpr auto BlockSize = BitRange<uint32_t>::from_to(0, 15);
static constexpr auto BlockAmount = BitRange<uint32_t>::from_to(16, 31);
}; };
struct SyncMode2 { struct SyncMode2 {
}; };
}; );
struct CHCHR : public ComplexBitMap<uint32_t> { __declare_io_type(CHCHR, uint32_t,
enum _SyncMode { enum SyncMode_t {
Sync0 = 0, //Start immediately, Sync0 = 0, //Start immediately,
Sync1 = 1, //Sync blocks to DMA requests Sync1 = 1, //Sync blocks to DMA requests
Sync2 = 2, //Linked List Sync2 = 2, //Linked List
}; };
static constexpr auto ManualStart = Bit<uint32_t>(28); static constexpr auto ManualStart = Bit(28);
static constexpr auto Start = Bit<uint32_t>(24); static constexpr auto Start = Bit(24);
static constexpr auto Busy = Start; static constexpr auto Busy = Start;
static constexpr auto ChoppingCPUWindowSize = BitRange<uint32_t>::from_to(20, 22); static constexpr auto ChoppingCPUWindowSize = BitRange::from_to(20, 22);
static constexpr auto ChoppingDMAWindowSize = BitRange<uint32_t>::from_to(16, 18); static constexpr auto ChoppingDMAWindowSize = BitRange::from_to(16, 18);
static constexpr auto SyncMode = BitRange<_SyncMode>::from_to(9, 10); static constexpr auto SyncMode = BitRange::from_to(9, 10);
static constexpr auto UseSyncMode0 = SyncMode.with(Sync0); static constexpr auto UseSyncMode0 = SyncMode.with(Sync0);
static constexpr auto UseSyncMode1 = SyncMode.with(Sync1); static constexpr auto UseSyncMode1 = SyncMode.with(Sync1);
static constexpr auto UseSyncMode2 = SyncMode.with(Sync2); static constexpr auto UseSyncMode2 = SyncMode.with(Sync2);
static constexpr auto UseChopping = Bit<uint32_t>(8); static constexpr auto UseChopping = Bit(8);
static constexpr auto MemoryAdrDecreaseBy4 = Bit<uint32_t>(1); static constexpr auto MemoryAdrDecreaseBy4 = Bit(1);
static constexpr auto MemoryAdrIncreaseBy4 = !MemoryAdrDecreaseBy4; static constexpr auto MemoryAdrIncreaseBy4 = !MemoryAdrDecreaseBy4;
static constexpr auto FromMainRAM = Bit<uint32_t>(0); static constexpr auto FromMainRAM = Bit(0);
static constexpr auto ToMainRAM = !FromMainRAM; static constexpr auto ToMainRAM = !FromMainRAM;
static constexpr CHCHR StartMDECin() { static constexpr Self StartMDECin() {
return CHCHR{0x01000201}; return Self{0x01000201};
} }
static constexpr CHCHR StartMDECout() { static constexpr Self StartMDECout() {
return CHCHR{0x01000200}; return Self{0x01000200};
} }
static constexpr CHCHR StartGPUReceive() { static constexpr Self StartGPUReceive() {
return CHCHR{0x01000201}; return Self{0x01000201};
} }
static constexpr CHCHR StartCDROM() { static constexpr Self StartCDROM() {
return CHCHR{0x11000000}; return Self{0x11000000};
} }
static constexpr CHCHR StartSPUReceive() { static constexpr Self StartSPUReceive() {
return CHCHR{0x01000201}; return Self{0x01000201};
} }
static constexpr CHCHR StartOTC() { static constexpr Self StartOTC() {
return CHCHR{0x11000002}; return Self{0x11000002};
} }
}; );
struct __no_align Registers { struct __no_align Registers {
VolatileBitMapPOD<MADR> adr; MADR_v adr;
VolatileBitMapPOD<BCR> block_ctrl; BCR_v block_ctrl;
VolatileBitMapPOD<CHCHR> channel_ctrl; CHCHR_v channel_ctrl;
void set_adr(uintptr_t adr) {
this->adr.set(MADR_t::MemoryAdr.with(adr));
}
void wait() {
while(this->channel_ctrl.is_set(CHCHR_t::Busy));
}
}; };
// Those types do not need to be volatile because there members are
typedef Registers MDECin_v;
typedef Registers MDECout_v;
typedef Registers GPU_v;
typedef Registers CDROM_v;
typedef Registers SPU_v;
typedef Registers PIO_v;
typedef Registers OTC_v;
//0: Highest, 7: Lowest //0: Highest, 7: Lowest
typedef uint32_t Priority; typedef uint32_t Priority;
static constexpr Priority HighestPriority = 0; static constexpr Priority HighestPriority = 0;
static constexpr Priority LowestPriority = 7; static constexpr Priority LowestPriority = 7;
struct DMAControlRegister : public ComplexBitMap<uint32_t> { __declare_io_type(DPCR, uint32_t,
static constexpr auto OTCEnable = Bit<uint32_t>(27); static constexpr auto OTCEnable = Bit(27);
static constexpr auto OTCPriority = BitRange<Priority>::from_to(24, 26); static constexpr auto OTCPriority = BitRange::from_to(24, 26);
static constexpr auto PIOEnable = Bit<uint32_t>(23); static constexpr auto PIOEnable = Bit(23);
static constexpr auto PIOPriority = BitRange<Priority>::from_to(20, 22); static constexpr auto PIOPriority = BitRange::from_to(20, 22);
static constexpr auto SPUEnable = Bit<uint32_t>(19); static constexpr auto SPUEnable = Bit(19);
static constexpr auto SPUPriority = BitRange<Priority>::from_to(16, 18); static constexpr auto SPUPriority = BitRange::from_to(16, 18);
static constexpr auto CDROMEnable = Bit<uint32_t>(15); static constexpr auto CDROMEnable = Bit(15);
static constexpr auto CDROMPriority = BitRange<Priority>::from_to(12, 14); static constexpr auto CDROMPriority = BitRange::from_to(12, 14);
static constexpr auto GPUEnable = Bit<uint32_t>(11); static constexpr auto GPUEnable = Bit(11);
static constexpr auto GPUPriority = BitRange<Priority>::from_to(8, 10); static constexpr auto GPUPriority = BitRange::from_to(8, 10);
static constexpr auto MDECoutEnable = Bit<uint32_t>(7); static constexpr auto MDECoutEnable = Bit(7);
static constexpr auto MDECoutPriority = BitRange<Priority>::from_to(4, 6); static constexpr auto MDECoutPriority = BitRange::from_to(4, 6);
static constexpr auto MDECinEnable = Bit<uint32_t>(3); static constexpr auto MDECinEnable = Bit(3);
static constexpr auto MDECinPriority = BitRange<Priority>::from_to(0, 2); static constexpr auto MDECinPriority = BitRange::from_to(0, 2);
}; );
struct DMAInterruptRegister : public ComplexBitMap<uint32_t> { __declare_io_type(DICR, uint32_t,
static constexpr auto MasterEnable = Bit<uint32_t>(31); static constexpr auto MasterEnable = Bit(31);
static constexpr auto Flags = BitRange<uint32_t>::from_to(24, 30); static constexpr auto Flags = BitRange::from_to(24, 30);
static constexpr auto MasterEnableDPCR = Bit<uint32_t>(23); static constexpr auto MasterEnableDPCR = Bit(23);
static constexpr auto EnableDPCR = BitRange<uint32_t>::from_to(16, 22); static constexpr auto EnableDPCR = BitRange::from_to(16, 22);
static constexpr auto ForceIRQ = Bit<uint32_t>(15); static constexpr auto ForceIRQ = Bit(15);
}; );
__declare_io_port_global_struct(Registers, MDECin, 0x1F801080); __declare_new_io_port(MDECin, 0x1F801080);
__declare_io_port_global_struct(Registers, MDECout, 0x1F801090); __declare_new_io_port(MDECout, 0x1F801090);
__declare_io_port_global_struct(Registers, GPU, 0x1F8010A0); __declare_new_io_port(GPU, 0x1F8010A0);
__declare_io_port_global_struct(Registers, CDROM, 0x1F8010B0); __declare_new_io_port(CDROM, 0x1F8010B0);
__declare_io_port_global_struct(Registers, SPU, 0x1F8010C0); __declare_new_io_port(SPU, 0x1F8010C0);
__declare_io_port_global_struct(Registers, PIO, 0x1F8010D0); __declare_new_io_port(PIO, 0x1F8010D0);
__declare_io_port_global_struct(Registers, OTC, 0x1F8010E0); __declare_new_io_port(OTC, 0x1F8010E0);
__declare_io_port_global(DMAControlRegister, DPCR, 0x1F8010F0); __declare_new_io_port(DPCR, 0x1F8010F0);
__declare_io_port_global(DMAInterruptRegister, DICR, 0x1F8010F4); __declare_new_io_port(DICR, 0x1F8010F4);
} }
} }
#endif //!__JABYENGINE_DMA_IO_HPP__ #endif //!__JABYENGINE_DMA_IO_HPP__

View File

@ -47,124 +47,162 @@ namespace JabyEngine {
Off = 1 Off = 1
}; };
struct Command { __declare_io_type(DisplayMode, uint32_t,
struct GP0 : public ComplexBitMap<uint32_t> { enum struct TVEncoding {
NTSC = 0,
static constexpr GP0 QuickFill(GPU::Color24 color) { PAL = 1,
return {(0x02 << 24) | color.raw()};
}
static constexpr GP0 CPU2VRAM_Blitting() {
return {(0b101u << 29)};
}
static constexpr GP0 DrawAreaTemplate(uint8_t code, uint16_t x, uint16_t y) {
constexpr auto Command = BitRange<uint32_t>::from_to(24, 31);
constexpr auto Y = BitRange<uint32_t>::from_to(10, 18);
constexpr auto X = BitRange<uint32_t>::from_to(0, 9);
return {GP0::with(Command.with(code), Y.with(y), X.with(x))};
}
static constexpr GP0 DrawAreaTopLeft(uint16_t x, uint16_t y) {
return DrawAreaTemplate(0xE3, x, y);
}
static constexpr GP0 DrawAreaBottomRight(uint16_t x, uint16_t y) {
return DrawAreaTemplate(0xE4, x, y);
}
static constexpr GP0 TopLeftPosition(uint16_t x, uint16_t y) {
return {static_cast<uint32_t>((y << 16u) | x)};
}
static constexpr GP0 WidthHeight(uint16_t w, uint16_t h) {
return {static_cast<uint32_t>((h << 16u) | w)};
}
}; };
struct GP1 : public ComplexBitMap<uint32_t> { static constexpr auto HorizontalResolution368 = Bit(6);
static constexpr auto VerticalInterlace = Bit(5);
static constexpr auto DisplayAreaColorDepth = BitRange::from_to(4, 4);
static constexpr auto VideoMode = BitRange::from_to(3, 3);
static constexpr auto VerticalResolution = BitRange::from_to(2, 2);
static constexpr auto HorizontalResolution = BitRange::from_to(0, 1);
static constexpr Self PAL() {
return Self::from(
HorizontalResolution.with(GPU_IO::HorizontalResolution::$320),
VerticalResolution.with(GPU_IO::VerticalResolution::$240),
VideoMode.with(TVEncoding::PAL),
DisplayAreaColorDepth.with(GPU_IO::DisplayAreaColorDepth::$15bit)
);
}
static constexpr Self NTSC() {
return Self::from(
HorizontalResolution.with(GPU_IO::HorizontalResolution::$320),
VerticalResolution.with(GPU_IO::VerticalResolution::$240),
VideoMode.with(TVEncoding::NTSC),
DisplayAreaColorDepth.with(GPU_IO::DisplayAreaColorDepth::$15bit)
);
}
);
__declare_io_type(GP0, uint32_t,
);
__declare_io_type(GP1, uint32_t,
);
struct Command {
struct Helper {
static constexpr GP0_t DrawAreaTemplate(uint8_t code, uint16_t x, uint16_t y) {
constexpr auto Command = BitRange::from_to(24, 31);
constexpr auto Y = BitRange::from_to(10, 18);
constexpr auto X = BitRange::from_to(0, 9);
return GP0_t::from(Command.with(code), Y.with(y), X.with(x));
}
static constexpr uint32_t construct_cmd(uint8_t cmd, uint32_t value) { static constexpr uint32_t construct_cmd(uint8_t cmd, uint32_t value) {
return ((cmd << 24) | value); return ((cmd << 24) | value);
} }
};
static constexpr GP1 Reset() { static constexpr GP0_t QuickFill(GPU::Color24 color) {
return {(0x02 << 24) | color.raw()};
}
static constexpr GP0_t CPU2VRAM_Blitting() {
return {(0b101u << 29)};
}
static constexpr GP0_t DrawAreaTopLeft(uint16_t x, uint16_t y) {
return Helper::DrawAreaTemplate(0xE3, x, y);
}
static constexpr GP0_t DrawAreaBottomRight(uint16_t x, uint16_t y) {
return Helper::DrawAreaTemplate(0xE4, x, y);
}
static constexpr GP0_t TopLeftPosition(uint16_t x, uint16_t y) {
return {static_cast<uint32_t>((y << 16u) | x)};
}
static constexpr GP0_t WidthHeight(uint16_t w, uint16_t h) {
return {static_cast<uint32_t>((h << 16u) | w)};
}
static constexpr GP1_t Reset() {
return {0}; return {0};
} }
static constexpr GP1 ResetCMDBufer() { static constexpr GP1_t ResetCMDBufer() {
return {construct_cmd(0x01, 0)}; return {Helper::construct_cmd(0x01, 0)};
} }
static constexpr GP1 SetDisplayState(DisplayState state) { static constexpr GP1_t SetDisplayState(DisplayState state) {
return {construct_cmd(0x03, static_cast<uint32_t>(state))}; return {Helper::construct_cmd(0x03, static_cast<uint32_t>(state))};
} }
static constexpr GP1 DMADirection(DMADirection dir) { static constexpr GP1_t DMADirection(DMADirection dir) {
return {construct_cmd(0x04, static_cast<uint32_t>(dir))}; return {Helper::construct_cmd(0x04, static_cast<uint32_t>(dir))};
} }
static constexpr GP1 DisplayArea(uint16_t x, uint16_t y) { static constexpr GP1_t DisplayArea(uint16_t x, uint16_t y) {
constexpr auto X = BitRange<uint32_t>::from_to(0, 9); constexpr auto X = BitRange::from_to(0, 9);
constexpr auto Y = BitRange<uint32_t>::from_to(10, 18); constexpr auto Y = BitRange::from_to(10, 18);
return {construct_cmd(0x05, ComplexBitMap<uint32_t>::with(X.with(x), Y.with(y)).raw)}; return {Helper::construct_cmd(0x05, X.as_value(x) | Y.as_value(y))};
} }
static constexpr GP1 HorizontalDisplayRange(uint32_t x1, uint32_t x2) { static constexpr GP1_t HorizontalDisplayRange(uint32_t x1, uint32_t x2) {
constexpr auto X1 = BitRange<uint32_t>::from_to(0, 11); constexpr auto X1 = BitRange::from_to(0, 11);
constexpr auto X2 = BitRange<uint32_t>::from_to(12, 23); constexpr auto X2 = BitRange::from_to(12, 23);
return {construct_cmd(0x06, ComplexBitMap<uint32_t>::with(X1.with(x1), X2.with(x2)).raw)}; return {Helper::construct_cmd(0x06, X1.as_value(x1) | X2.as_value(x2))};
} }
static constexpr GP1 VerticalDisplayRange(uint32_t y1, uint32_t y2) { static constexpr GP1_t VerticalDisplayRange(uint32_t y1, uint32_t y2) {
constexpr auto Y1 = BitRange<uint32_t>::from_to(0, 9); constexpr auto Y1 = BitRange::from_to(0, 9);
constexpr auto Y2 = BitRange<uint32_t>::from_to(10, 19); constexpr auto Y2 = BitRange::from_to(10, 19);
return {construct_cmd(0x07, ComplexBitMap<uint32_t>::with(Y1.with(y1), Y2.with(y2)).raw)}; return {Helper::construct_cmd(0x07, Y1.as_value(y1) | Y2.as_value(y2))};
} }
static constexpr GP1 DisplayMode(uint32_t mode) { static constexpr GP1_t DisplayMode(DisplayMode_t mode) {
return {construct_cmd(0x08, mode)}; return {Helper::construct_cmd(0x08, mode)};
} }
}; };
};
struct GPUStatusRegister : public ComplexBitMap<uint32_t> { __declare_io_type(GPUSTAT, uint32_t,
static constexpr auto DrawingOddLinesInterlaced = Bit<uint32_t>(31); static constexpr auto DrawingOddLinesInterlaced = Bit(31);
static constexpr auto DMADirectionValue = BitRange<DMADirection>::from_to(29, 30); static constexpr auto DMADirectionValue = BitRange::from_to(29, 30);
static constexpr auto DMAReady = Bit<uint32_t>(28); static constexpr auto DMAReady = Bit(28);
static constexpr auto VRAMtoCPUtransferReay = Bit<uint32_t>(27); static constexpr auto VRAMtoCPUtransferReay = Bit(27);
static constexpr auto GP0ReadyForCMD = Bit<uint32_t>(26); static constexpr auto GP0ReadyForCMD = Bit(26);
static constexpr auto FifoNotFull = Bit<uint32_t>(25); // Only for Fifo static constexpr auto FifoNotFull = Bit(25); // Only for Fifo
static constexpr auto InterruptRequest = Bit<uint32_t>(24); static constexpr auto InterruptRequest = Bit(24);
static constexpr auto DisplayDisabled = Bit<uint32_t>(23); static constexpr auto DisplayDisabled = Bit(23);
static constexpr auto VerticalInterlaceOn = Bit<uint32_t>(22); static constexpr auto VerticalInterlaceOn = Bit(22);
static constexpr auto DisplayAreaColorDepth = BitRange<GPU_IO::DisplayAreaColorDepth>::from_to(21, 21); static constexpr auto DisplayAreaColorDepth = BitRange::from_to(21, 21);
static constexpr auto VideoModePal = Bit<uint32_t>(20); static constexpr auto VideoModePal = Bit(20);
static constexpr auto VerticalResolutionValue = BitRange<VerticalResolution>::from_to(19, 19); static constexpr auto VerticalResolutionValue = BitRange::from_to(19, 19);
static constexpr auto HorizontalResolutionValue = BitRange<HorizontalResolution>::from_to(17, 18); static constexpr auto HorizontalResolutionValue = BitRange::from_to(17, 18);
static constexpr auto HorizontalResolution368 = Bit<uint32_t>(16); static constexpr auto HorizontalResolution368 = Bit(16);
static constexpr auto TexturesDisabled = Bit<uint32_t>(15); static constexpr auto TexturesDisabled = Bit(15);
static constexpr auto NotDrawingMaskedPixels = Bit<uint32_t>(12); static constexpr auto NotDrawingMaskedPixels = Bit(12);
static constexpr auto MaskBitSetDuringDrawEnabled = Bit<uint32_t>(11); static constexpr auto MaskBitSetDuringDrawEnabled = Bit(11);
static constexpr auto DrawingToDisplayAreadAllowed = Bit<uint32_t>(10); static constexpr auto DrawingToDisplayAreadAllowed = Bit(10);
static constexpr auto DitherEnabled = Bit<uint32_t>(9); static constexpr auto DitherEnabled = Bit(9);
static constexpr auto TexturePageColorValue = BitRange<TexturePageColor>::from_to(7, 8); static constexpr auto TexturePageColorValue = BitRange::from_to(7, 8);
static constexpr auto SemiTransparencyValue = BitRange<SemiTransparency>::from_to(5, 6); static constexpr auto SemiTransparencyValue = BitRange::from_to(5, 6);
static constexpr auto TexturePageY = BitRange<uint32_t>::from_to(4, 4); // N*256 static constexpr auto TexturePageY = BitRange::from_to(4, 4); // N*256
static constexpr auto TexturePageX = BitRange<uint32_t>::from_to(0, 3); // N*64 static constexpr auto TexturePageX = BitRange::from_to(0, 3); // N*64
static constexpr auto VerticalResolution480 = Bit<uint32_t>(19); static constexpr auto VerticalResolution480 = Bit(19);
static constexpr auto TexturePageY256 = Bit<uint32_t>(4); static constexpr auto TexturePageY256 = Bit(4);
}; );
__declare_io_port_global(Command::GP0, GP0, 0x1F801810); typedef volatile uint32_t GPUREAD_v;
__declare_io_port_global(Command::GP1, GP1, 0x1F801814);
__declare_io_port_global_const_simple(uint32_t, GPUREAD, 0x1F801810); __declare_new_io_port(GP0, 0x1F801810);
__declare_io_port_global_const(GPUStatusRegister, GPUSTAT, 0x1F801814); __declare_new_io_port(GP1, 0x1F801814);
__declare_new_const_io_port(GPUREAD, 0x1F801810);
__declare_new_const_io_port(GPUSTAT, 0x1F801814);
} }
} }
#endif //!__JABYENGINE_GPU_IO_HPP__ #endif //!__JABYENGINE_GPU_IO_HPP__

View File

@ -4,42 +4,42 @@
namespace JabyEngine { namespace JabyEngine {
struct Interrupt { struct Interrupt {
static constexpr auto VBlank = Bit<uint32_t>(0); static constexpr auto VBlank = Bit(0);
static constexpr auto GPU = Bit<uint32_t>(1); static constexpr auto GPU = Bit(1);
static constexpr auto CDROM = Bit<uint32_t>(2); static constexpr auto CDROM = Bit(2);
static constexpr auto DMA = Bit<uint32_t>(3); static constexpr auto DMA = Bit(3);
static constexpr auto Timer0 = Bit<uint32_t>(4); static constexpr auto Timer0 = Bit(4);
static constexpr auto Timer1 = Bit<uint32_t>(5); static constexpr auto Timer1 = Bit(5);
static constexpr auto Timer2 = Bit<uint32_t>(6); static constexpr auto Timer2 = Bit(6);
static constexpr auto Periphery = Bit<uint32_t>(7); static constexpr auto Periphery = Bit(7);
static constexpr auto SIO = Bit<uint32_t>(8); static constexpr auto SIO = Bit(8);
static constexpr auto SPU = Bit<uint32_t>(9); static constexpr auto SPU = Bit(9);
static constexpr auto Controller = Bit<uint32_t>(10); static constexpr auto Controller = Bit(10);
static constexpr auto LightPen = Controller; static constexpr auto LightPen = Controller;
typedef struct Status : public ComplexBitMap<uint32_t> { __declare_io_type(Status, uint32_t,
} Status_t; );
typedef struct Mask : public ComplexBitMap<uint32_t> { __declare_io_type(Mask, uint32_t,
} Mask_t; );
__declare_io_port_member(Status_t, Status, 0x1F801070); __declare_new_io_port(Status, 0x1F801070);
__declare_io_port_member(Mask_t, Mask, 0x1F801074); __declare_new_io_port(Mask, 0x1F801074);
static bool is_irq(Bit<uint32_t> irq) { static bool is_irq(Bit irq) {
return Status.read().is_bit_set(irq); return Status.is_set(irq);
} }
static void ack_irq(Bit<uint32_t> irq) { static void ack_irq(Bit irq) {
Status.write({Status.read().clear_bit(irq)}); Status.clear(irq);
} }
static void disable_irq(Bit<uint32_t> irq) { static void disable_irq(Bit irq) {
Mask.write({Mask.read().clear_bit(irq)}); Mask.clear(irq);
} }
static void enable_irq(Bit<uint32_t> irq) { static void enable_irq(Bit irq) {
Mask.write({Mask.read().set_bit(irq)}); Mask.set(irq);
} }
}; };
} }

View File

@ -1,60 +1,124 @@
#ifndef __JABYENGINE_IOPORT_HPP__ #ifndef __JABYENGINE_IOPORT_HPP__
#define __JABYENGINE_IOPORT_HPP__ #define __JABYENGINE_IOPORT_HPP__
#include "../../Auxiliary/complex_bitmap.hpp" #include "../../Auxiliary/types.hpp"
#include "../../Auxiliary/bits.hpp"
namespace JabyEngine { namespace JabyEngine {
namespace IOPort {
struct IOValueType {
template<typename T> template<typename T>
struct VolatilePOD { struct Normal {
volatile T raw; typedef T Value;
typedef T UnderlyingValue;
constexpr T read() const {
return this->raw;
}
constexpr void write(T value) {
this->raw = value;
}
}; };
// For use with ComplexBitMaps or what else satisfies this API
template<typename T> template<typename T>
struct VolatileBitMapPOD { struct Volatile {
typedef typename T::UnderlyingType Raw; typedef volatile T Value;
typedef T UnderlyingValue;
VolatilePOD<Raw> pod;
constexpr Raw read_raw() const {
return this->pod.read();
}
constexpr T read() const {
return T{this->pod.read()};
}
constexpr Raw read(const BitRange<Raw>& range) const {
return VolatileBitMapPOD<T>::read().get_value(range);
}
constexpr void write_raw(Raw value) {
this->pod.write(value);
}
constexpr void write(const T& value) {
this->pod.write(static_cast<Raw>(value));
}
constexpr void write(const BitRangeValue<Raw>& value) {
VolatileBitMapPOD<T>::write(T{T::with(value)});
}
}; };
};
}
namespace IOAdress {
constexpr uintptr_t patch_adr(uintptr_t adr) {
constexpr uintptr_t Mask = 0xF0000000;
constexpr uintptr_t Base = 0x10000000; // We might want to change this later to 0xB0000000 for caching and stuff (More research needed)
return (Base + (adr & ~Mask));
}
}
#define __declare_new_named_io_port(type, name, adr) \
static inline auto& name = *reinterpret_cast<type##_v*>(IOAdress::patch_adr(adr))
#define __declare_new_io_port(name, adr) \
__declare_new_named_io_port(name, name, adr)
#define __declare_new_const_io_port(name, adr) \
__declare_new_named_io_port(const name, name, adr)
#define __declare_new_io_port_array(name, adr, size) \
static inline auto& name = reinterpret_cast<name##_v(&)[size]>(*reinterpret_cast<name##_v*>(adr))
// We need this construct to ensure the types end up being a POD - Inheritance doesn't qualify for a POD
#define __declare_io_type(name, type, ...) \
template<template<typename> typename T> \
struct name##_io_base { \
typedef T<type>::UnderlyingValue UnderlyingValue; \
typedef name##_io_base Self; \
\
T<type>::Value raw_value = 0; \
\
__VA_ARGS__ \
\
template<typename...ARGS> \
static constexpr Self from(const ARGS&...args) { \
return Self().set_va(args...); \
} \
\
constexpr Self& set(Bit bit) { \
this->raw_value = bit::set(this->raw_value, bit); \
return *this; \
} \
\
constexpr Self& set(ClearBit bit) { \
this->raw_value = bit::set(this->raw_value, bit); \
return *this; \
} \
\
constexpr Self& set(BitRange bits, UnderlyingValue value) { \
this->raw_value = bit::value::set_normalized(this->raw_value, bits, value); \
return *this; \
} \
\
template<typename S> \
constexpr Self& set(const BitRange::RangeValuePair<S>& value) { \
this->raw_value = bit::value::set_normalized(this->raw_value, value); \
return *this; \
} \
\
template<typename S> \
constexpr Self& set_va(const S& head) { \
return this->set(head); \
} \
\
template<typename S, typename...ARGS> \
constexpr Self& set_va(const S& head, const ARGS&...tail) { \
return this->set(head).set_va(tail...); \
} \
\
constexpr UnderlyingValue get(BitRange bits) const { \
return bit::value::get_normalized(this->raw_value, bits.pos, bits.length); \
} \
\
constexpr Self& clear(Bit bit) { \
this->raw_value = bit::clear(this->raw_value, bit); \
return *this; \
} \
\
constexpr bool is_set(Bit bit) const { \
return bit::is_set(this->raw_value, bit); \
} \
\
constexpr void operator=(UnderlyingValue value) { \
this->raw_value = value; \
} \
\
constexpr operator UnderlyingValue() const { \
return this->raw_value; \
} \
}; \
\
typedef name##_io_base<IOPort::IOValueType::Volatile> name##_v; \
typedef name##_io_base<IOPort::IOValueType::Normal> name##_t
struct __no_align ubus32_t { struct __no_align ubus32_t {
typedef ComplexBitMap<uint16_t> Base16; __declare_io_type(uint16_t, uint16_t,);
uint16_t_v low;
uint16_t_v high;
VolatileBitMapPOD<Base16> low; constexpr ubus32_t(uint32_t value) : low{0}, high{0} {
VolatileBitMapPOD<Base16> high;
constexpr ubus32_t(uint32_t value) {
*this = value; *this = value;
} }
@ -63,34 +127,18 @@ namespace JabyEngine {
} }
constexpr operator uint32_t() const { constexpr operator uint32_t() const {
return ((this->high.read_raw() << 16) | this->low.read_raw()); const uint32_t high = this->high;
const uint32_t low = this->low;
return ((high << 16) | low);
} }
constexpr ubus32_t& operator=(uint32_t value) { constexpr ubus32_t& operator=(uint32_t value) {
this->low.write_raw(value & 0xFFFF); this->low = (value & 0xFFFF);
this->high.write_raw(value >> 16); this->high = (value >> 16);
return *this; return *this;
} }
}; };
static constexpr uintptr_t IO_Base_Mask = 0xF0000000;
static constexpr uintptr_t IO_Base_Adr = 0x10000000;
#define __io_port_adr(adr) (IO_Base_Adr + (adr & ~IO_Base_Mask))
#define __cast_io_adr_with_type(cv, type, name, adr) static __always_inline cv auto& name = *reinterpret_cast<type*>(__io_port_adr(adr))
#define __declare_io_port_global(type, name, adr) __cast_io_adr_with_type(, VolatileBitMapPOD<type>, name, adr)
#define __declare_io_port_global_const(type, name, adr) __cast_io_adr_with_type(const, VolatileBitMapPOD<type>, name, adr)
#define __declare_io_port_global_simple(type, name, adr) __cast_io_adr_with_type(, VolatilePOD<type>, name, adr)
#define __declare_io_port_global_const_simple(type, name, adr) __cast_io_adr_with_type(const, VolatilePOD<type>, name, adr)
#define __declare_io_port_member(type, name, adr) __cast_io_adr_with_type(inline, VolatileBitMapPOD<type>, name, adr)
#define __declare_io_port_member_const(type, name, adr) __cast_io_adr_with_type(const inline, VolatileBitMapPOD<type>, name, adr)
#define __declare_io_port_member_simple(type, name, adr) __cast_io_adr_with_type(inline, VolatilePOD<type>, name, adr)
#define __declare_io_port_member_const_simple(type, name, adr) __cast_io_adr_with_type(const inline, VolatilePOD<type>, name, adr)
#define __declare_io_port_global_array(type, name, adr, size) static __always_inline auto& name = reinterpret_cast<type(&)[size]>(*reinterpret_cast<type*>(__io_port_adr(adr)))
#define __declare_io_port_global_struct(type, name, adr) static __always_inline auto& name = *reinterpret_cast<type*>(__io_port_adr(adr))
} }
#endif //!__JABYENGINE_IOPORT_HPP__ #endif //!__JABYENGINE_IOPORT_HPP__

View File

@ -4,20 +4,20 @@
namespace JabyEngine { namespace JabyEngine {
namespace Memory_IO { namespace Memory_IO {
struct COM_DELAY { __declare_io_type(COM_DELAY, uint32_t,
typedef uint32_t Type; void setup() {
this->raw_value = 0x1325;
}
);
static constexpr uint32_t SetupValue = 0x1325; __declare_io_type(CD_DELAY, uint32_t,
}; void setup() {
this->raw_value = 0x20943;
}
);
struct CD_DELAY { __declare_new_io_port(COM_DELAY, 0x1F801020);
typedef uint32_t Type; __declare_new_io_port(CD_DELAY, 0x1F801018);
static constexpr uint32_t SetupValue = 0x20943;
};
__declare_io_port_global_simple(COM_DELAY::Type, COM_DELAY, 0x1F801020);
__declare_io_port_global_simple(CD_DELAY::Type, CD_DELAY, 0x1F801018);
} }
} }

View File

@ -26,59 +26,63 @@ namespace JabyEngine {
typedef uint8_t Step; typedef uint8_t Step;
typedef int16_t SimpleVolume; typedef int16_t SimpleVolume;
typedef volatile int16_t SimpleVolume_v;
struct SampleRate : public ComplexBitMap<uint16_t> { typedef volatile uint16_t Adr_v;
static constexpr SampleRate from_HZ(double freq) { typedef volatile uint16_t DataTransferControl_v;
__declare_io_type(SampleRate, uint16_t,
static constexpr Self from_HZ(double freq) {
//4096 == 44100Hz //4096 == 44100Hz
constexpr double Base = (4096.0 / 44100.0); constexpr double Base = (4096.0 / 44100.0);
return {static_cast<uint16_t>((freq*Base))}; return {static_cast<uint16_t>((freq*Base))};
} }
}; );
struct SweepVolume : public ComplexBitMap<int16_t> { __declare_io_type(SweepVolume, int16_t,
// For Volume Mode // For Volume Mode
static constexpr auto SweepEnable = Bit<int16_t>(15); static constexpr auto SweepEnable = Bit(15);
static constexpr auto VolumeEnable = !SweepEnable; static constexpr auto VolumeEnable = !SweepEnable;
static constexpr auto Volume = BitRange<int16_t>::from_to(0, 14); static constexpr auto Volume = BitRange::from_to(0, 14);
// For Sweep Mode // For Sweep Mode
static constexpr auto SweepMode = Bit<Mode>(14); static constexpr auto SweepMode = Bit(14);
static constexpr auto SweepDirection = Bit<Direction>(13); static constexpr auto SweepDirection = Bit(13);
static constexpr auto SweepPhase = Bit<Phase>(12); static constexpr auto SweepPhase = Bit(12);
static constexpr auto SweepShift = BitRange<Shift>::from_to(2, 6); static constexpr auto SweepShift = BitRange::from_to(2, 6);
static constexpr auto SweepStep = BitRange<Step>::from_to(0, 1); static constexpr auto SweepStep = BitRange::from_to(0, 1);
);
__declare_io_type(SR, uint16_t,
static constexpr auto SustainMode = Bit(31 - 16);
static constexpr auto SustainDirection = Bit(30 - 16);
static constexpr auto SustainShift = BitRange::from_to((24 - 16), (28 - 16));
static constexpr auto SustainStep = BitRange::from_to((22 - 16), (23 - 16));
static constexpr auto ReleaseMode = Bit(21 - 16);
static constexpr auto ReleaseShift = BitRange::from_to((16 - 16), (20 - 16));
);
__declare_io_type(AD, uint16_t,
static constexpr auto AttackMode = Bit(15);
static constexpr auto AttackShift = BitRange::from_to(10, 14);
static constexpr auto AttackStep = BitRange::from_to(8, 9);
static constexpr auto DecayShift = BitRange::from_to(4, 7);
static constexpr auto SustainLevel = BitRange::from_to(0, 3);
);
struct __no_align Voice_v {
SweepVolume_v volumeLeft; //Offset: 0x0
SweepVolume_v volumeRight; //Offset: 0x2
SampleRate_v sampleRate; //Offset: 0x4;
Adr_v adr; //Offset: 0x6
AD_v ad; //Offset: 0x8
SR_v sr; //Offset: 0xA
SimpleVolume_v currentVolume; //Offset: 0xC
Adr_v repeatAdr; //Offset: 0xE
}; };
struct SR : public ComplexBitMap<uint16_t> { __declare_io_type(ControlRegister, uint16_t,
static constexpr auto SustainMode = Bit<Mode>(31 - 16);
static constexpr auto SustainDirection = Bit<Direction>(30 - 16);
static constexpr auto SustainShift = BitRange<Shift>::from_to((24 - 16), (28 - 16));
static constexpr auto SustainStep = BitRange<Step>::from_to((22 - 16), (23 - 16));
static constexpr auto ReleaseMode = Bit<Mode>(21 - 16);
static constexpr auto ReleaseShift = BitRange<Shift>::from_to((16 - 16), (20 - 16));
};
struct AD : public ComplexBitMap<uint16_t> {
static constexpr auto AttackMode = Bit<Mode>(15);
static constexpr auto AttackShift = BitRange<Shift>::from_to(10, 14);
static constexpr auto AttackStep = BitRange<Step>::from_to(8, 9);
static constexpr auto DecayShift = BitRange<Shift>::from_to(4, 7);
static constexpr auto SustainLevel = BitRange<uint16_t>::from_to(0, 3);
};
struct __no_align Voice {
VolatileBitMapPOD<SweepVolume> volumeLeft; //Offset: 0x0
VolatileBitMapPOD<SweepVolume> volumeRight; //Offset: 0x2
VolatileBitMapPOD<SampleRate> sampleRate; //Offset: 0x4;
VolatilePOD<uint16_t> adr; //Offset: 0x6
VolatileBitMapPOD<AD> ad; //Offset: 0x8
VolatileBitMapPOD<SR> sr; //Offset: 0xA
VolatilePOD<SimpleVolume> currentVolume; //Offset: 0xC
VolatilePOD<uint16_t> repeatAdr; //Offset: 0xE
};
struct ControlRegister : public ComplexBitMap<uint16_t> {
enum RAMTransferMode { enum RAMTransferMode {
Stop = 0, Stop = 0,
ManualWrite = 1, ManualWrite = 1,
@ -86,69 +90,71 @@ namespace JabyEngine {
DMARead = 3 DMARead = 3
}; };
static constexpr auto Enable = Bit<uint16_t>(15); static constexpr auto Enable = Bit(15);
static constexpr auto Unmute = Bit<uint16_t>(14); static constexpr auto Unmute = Bit(14);
static constexpr auto NoiseFrequcenyShift = BitRange<Shift>::from_to(10, 13); static constexpr auto NoiseFrequcenyShift = BitRange::from_to(10, 13);
static constexpr auto NoiseFrequcenyStep = BitRange<Step>::from_to(8, 9); static constexpr auto NoiseFrequcenyStep = BitRange::from_to(8, 9);
static constexpr auto ReverbMasterEnable = Bit<uint16_t>(7); static constexpr auto ReverbMasterEnable = Bit(7);
static constexpr auto IRQ9Enable = Bit<uint16_t>(6); static constexpr auto IRQ9Enable = Bit(6);
static constexpr auto TransferMode = BitRange<RAMTransferMode>::from_to(4, 5); static constexpr auto TransferMode = BitRange::from_to(4, 5);
static constexpr auto ExternalAudioReverb = Bit<uint16_t>(3); static constexpr auto ExternalAudioReverb = Bit(3);
static constexpr auto CDAudioReverb = Bit<uint16_t>(2); static constexpr auto CDAudioReverb = Bit(2);
static constexpr auto ExternalAudioEnable = Bit<uint16_t>(1); static constexpr auto ExternalAudioEnable = Bit(1);
static constexpr auto CDAudioEnable = Bit<uint16_t>(0); static constexpr auto CDAudioEnable = Bit(0);
}; );
struct PitchModFlags : public ComplexBitMap<uint16_t> { __declare_io_type(PMON, uint16_t,
static constexpr BitRange<uint16_t> EnableBits = BitRange<uint16_t>::from_to(1, 23); static constexpr auto EnableBits = BitRange::from_to(1, 23);
}; );
struct NoiseGenerator : public ComplexBitMap<uint16_t> { __declare_io_type(NON, uint16_t,
static constexpr BitRange<uint16_t> NoiseBits = BitRange<uint16_t>::from_to(0, 23); static constexpr auto NoiseBits = BitRange::from_to(0, 23);
}; );
struct EchoOn : public ComplexBitMap<uint16_t> { __declare_io_type(EON, uint16_t,
static constexpr BitRange<uint16_t> EchoBits = BitRange<uint16_t>::from_to(0, 23); static constexpr auto EchoBits = BitRange::from_to(0, 23);
}; );
static constexpr size_t VoiceCount = 24; static constexpr size_t VoiceCount = 24;
struct Key { struct Key {
__cast_io_adr_with_type(inline, ubus32_t, On, 0x1F801D88); typedef ubus32_t ubus32_v;
__cast_io_adr_with_type(inline, ubus32_t, Off, 0x1F801D8C);
__cast_io_adr_with_type(inline, ubus32_t, Status, 0x1F801D9C); __declare_new_named_io_port(ubus32, On, 0x1F801D88);
__declare_new_named_io_port(ubus32, Off, 0x1F801D8C);
__declare_new_named_io_port(ubus32, Status, 0x1F801D9C);
}; };
struct MainVolume { struct MainVolume {
__declare_io_port_member(SweepVolume, Left, 0x1F801D80); __declare_new_named_io_port(SweepVolume, Left, 0x1F801D80);
__declare_io_port_member(SweepVolume, Right, 0x1F801D82); __declare_new_named_io_port(SweepVolume, Right, 0x1F801D82);
}; };
struct CDVolume { struct CDVolume {
__declare_io_port_member_simple(SimpleVolume, Left, 0x1F801DB0); __declare_new_named_io_port(SimpleVolume, Left, 0x1F801DB0);
__declare_io_port_member_simple(SimpleVolume, Right, 0x1F801DB2); __declare_new_named_io_port(SimpleVolume, Right, 0x1F801DB2);
}; };
struct ExternalAudioInputVolume { struct ExternalAudioInputVolume {
__declare_io_port_member_simple(SimpleVolume, Left, 0x1F801DB4); __declare_new_named_io_port(SimpleVolume, Left, 0x1F801DB4);
__declare_io_port_member_simple(SimpleVolume, Right, 0x1F801DB6); __declare_new_named_io_port(SimpleVolume, Right, 0x1F801DB6);
}; };
struct Reverb { struct Reverb {
struct Volume { struct Volume {
__declare_io_port_member_simple(SimpleVolume, Left, 0x1F801D84); __declare_new_named_io_port(SimpleVolume, Left, 0x1F801D84);
__declare_io_port_member_simple(SimpleVolume, Right, 0x1F801D86); __declare_new_named_io_port(SimpleVolume, Right, 0x1F801D86);
}; };
__declare_io_port_member_simple(uint16_t, WorkAreaAdr, 0x1F801DA2); __declare_new_named_io_port(Adr, WorkAreaAdr, 0x1F801DA2);
}; };
__declare_io_port_global(ControlRegister, Control, 0x1F801DAA); __declare_new_io_port(ControlRegister, 0x1F801DAA);
__declare_io_port_global_simple(uint16_t, DataTransferControl, 0x1F801DAC); __declare_new_io_port(DataTransferControl, 0x1F801DAC);
__declare_io_port_global(PitchModFlags, PMON, 0x1F801D90); __declare_new_io_port(PMON, 0x1F801D90);
__declare_io_port_global(NoiseGenerator, NON, 0x1F801D94); __declare_new_io_port(NON, 0x1F801D94);
__declare_io_port_global(EchoOn, EON, 0x1F801D98); __declare_new_io_port(EON, 0x1F801D98);
__declare_io_port_global_array(struct Voice, Voice, 0x1F801C00, VoiceCount); __declare_new_io_port_array(Voice, 0x1F801C00, VoiceCount);
} }
} }
#endif //!__JABYENGINE_SPU_IO_HPP__ #endif //!__JABYENGINE_SPU_IO_HPP__

View File

@ -4,94 +4,108 @@
namespace JabyEngine { namespace JabyEngine {
namespace Timer_IO { namespace Timer_IO {
struct CounterMode : public ComplexBitMap<uint32_t> { __declare_io_type(CounterMode, uint32_t,
static constexpr auto SyncEnable = Bit<uint32_t>(0); static constexpr auto SyncEnable = Bit(0);
static constexpr auto FreeRun = !SyncEnable; static constexpr auto FreeRun = !SyncEnable;
static constexpr auto SyncMode = BitRange<uint32_t>::from_to(1, 2); static constexpr auto SyncMode = BitRange::from_to(1, 2);
static constexpr auto ResetAfterTarget = Bit<uint32_t>(3); static constexpr auto ResetAfterTarget = Bit(3);
static constexpr auto IRQAtTarget = Bit<uint32_t>(4); static constexpr auto IRQAtTarget = Bit(4);
static constexpr auto IRQAtMax = Bit<uint32_t>(5); static constexpr auto IRQAtMax = Bit(5);
static constexpr auto IRQEveryTime = Bit<uint32_t>(6); static constexpr auto IRQEveryTime = Bit(6);
static constexpr auto IRQOneShot = !IRQEveryTime; static constexpr auto IRQOneShot = !IRQEveryTime;
static constexpr auto IRQToggle = Bit<uint32_t>(7); static constexpr auto IRQToggle = Bit(7);
static constexpr auto IRQPulse = !IRQToggle; static constexpr auto IRQPulse = !IRQToggle;
static constexpr auto ClockSource = BitRange<uint32_t>::from_to(8, 9); static constexpr auto ClockSource = BitRange::from_to(8, 9);
static constexpr auto HasIRQRequest = Bit<uint32_t>(10); static constexpr auto HasIRQRequest = Bit(10);
static constexpr auto IsTargetReached = Bit<uint32_t>(11); static constexpr auto IsTargetReached = Bit(11);
static constexpr auto IsMaxReached = Bit<uint32_t>(12); static constexpr auto IsMaxReached = Bit(12);
}; );
struct CounterTarget : public ComplexBitMap<uint32_t> { __declare_io_type(CounterTarget, uint32_t,
static constexpr auto CounterTargetValue = BitRange<uint32_t>::from_to(0, 15); static constexpr auto CounterTargetValue = BitRange::from_to(0, 15);
}; );
struct CounterValue : public ComplexBitMap<uint32_t> { __declare_io_type(CounterValue, uint32_t,
static constexpr auto Value = BitRange<uint32_t>::from_to(0, 15); static constexpr auto Value = BitRange::from_to(0, 15);
}; );
struct __no_align Counter { struct __no_align Counter {
VolatileBitMapPOD<CounterValue> value; CounterValue_v value;
VolatileBitMapPOD<CounterMode> mode; CounterMode_v mode;
VolatileBitMapPOD<CounterTarget> target; CounterTarget_v target;
private: private:
uint32_t _unused; uint32_t _unused;
public:
constexpr uint16_t get_current_value() const {
return this->value.get(CounterValue_v::Value);
}
constexpr void set_target_value(uint16_t value) {
this->target.set(CounterTarget_v::CounterTargetValue, value);
}
constexpr void set_mode(CounterMode_t mode) {
this->mode = mode;
}
}; };
static constexpr uintptr_t counter_base_adr(size_t ID) { static constexpr uintptr_t counter_base_adr(size_t ID) {
return (0x1F801100 + (ID*0x10)); return (0x1F801100 + (ID*0x10));
} }
struct __no_align Counter0 : public Counter { struct __no_align Counter0_v : public Counter {
struct SyncMode { struct SyncMode {
static constexpr auto Pause_During_Hblank = CounterMode::SyncMode.with(0); static constexpr auto Pause_During_Hblank = CounterMode_v::SyncMode.with(0u);
static constexpr auto Zero_At_Hblank = CounterMode::SyncMode.with(1); static constexpr auto Zero_At_Hblank = CounterMode_v::SyncMode.with(1u);
static constexpr auto Zero_At_Hblank_Pause_Outside_Hblank = CounterMode::SyncMode.with(2); static constexpr auto Zero_At_Hblank_Pause_Outside_Hblank = CounterMode_v::SyncMode.with(2u);
static constexpr auto Pause_Until_Hblank_Then_Freerun = CounterMode::SyncMode.with(3); static constexpr auto Pause_Until_Hblank_Then_Freerun = CounterMode_v::SyncMode.with(3u);
}; };
struct Source { struct Source {
static constexpr auto System_Clock = CounterMode::ClockSource.with(0); static constexpr auto System_Clock = CounterMode_v::ClockSource.with(0u);
static constexpr auto Dot_Clock = CounterMode::ClockSource.with(1); static constexpr auto Dot_Clock = CounterMode_v::ClockSource.with(1u);
static constexpr auto System_Clock_Too = CounterMode::ClockSource.with(2); static constexpr auto System_Clock_Too = CounterMode_v::ClockSource.with(2u);
static constexpr auto Dot_Clock_Too = CounterMode::ClockSource.with(3); static constexpr auto Dot_Clock_Too = CounterMode_v::ClockSource.with(3u);
}; };
}; };
struct __no_align Counter1 : public Counter { struct __no_align Counter1_v : public Counter {
struct SyncMode { struct SyncMode {
static constexpr auto Pause_During_Vblank = CounterMode::SyncMode.with(0); static constexpr auto Pause_During_Vblank = CounterMode_v::SyncMode.with(0u);
static constexpr auto Zero_At_Vblank = CounterMode::SyncMode.with(1); static constexpr auto Zero_At_Vblank = CounterMode_v::SyncMode.with(1u);
static constexpr auto Zero_At_Vblank_Pause_Outside_Vblank = CounterMode::SyncMode.with(2); static constexpr auto Zero_At_Vblank_Pause_Outside_Vblank = CounterMode_v::SyncMode.with(2u);
static constexpr auto Pause_Until_Vblank_Then_Freerun = CounterMode::SyncMode.with(3); static constexpr auto Pause_Until_Vblank_Then_FreeRun = CounterMode_v::SyncMode.with(3u);
}; };
struct Source { struct Source {
static constexpr auto System_Clock = CounterMode::ClockSource.with(0); static constexpr auto System_Clock = CounterMode_v::ClockSource.with(0u);
static constexpr auto Hblank = CounterMode::ClockSource.with(1); static constexpr auto Hblank = CounterMode_v::ClockSource.with(1u);
static constexpr auto System_Clock_Too = CounterMode::ClockSource.with(2); static constexpr auto System_Clock_Too = CounterMode_v::ClockSource.with(2u);
static constexpr auto Hblank_Too = CounterMode::ClockSource.with(3); static constexpr auto Hblank_Too = CounterMode_v::ClockSource.with(3u);
}; };
}; };
struct __no_align Counter2 : public Counter { struct __no_align Counter2_v : public Counter {
struct SyncMode { struct SyncMode {
static constexpr auto Stop_Counter = CounterMode::SyncMode.with(0); static constexpr auto Stop_Counter = CounterMode_v::SyncMode.with(0u);
static constexpr auto Freerun = CounterMode::SyncMode.with(1); static constexpr auto FreeRun = CounterMode_v::SyncMode.with(1u);
static constexpr auto Freerun_Too = CounterMode::SyncMode.with(2); static constexpr auto FreeRun_Too = CounterMode_v::SyncMode.with(2u);
static constexpr auto Stop_Counter_Too = CounterMode::SyncMode.with(3); static constexpr auto Stop_Counter_Too = CounterMode_v::SyncMode.with(3u);
}; };
struct Source { struct Source {
static constexpr auto System_Clock = CounterMode::ClockSource.with(0); static constexpr auto System_Clock = CounterMode_v::ClockSource.with(0u);
static constexpr auto System_Clock_Too = CounterMode::ClockSource.with(1); static constexpr auto System_Clock_Too = CounterMode_v::ClockSource.with(1u);
static constexpr auto System_Clock_Div_8 = CounterMode::ClockSource.with(2); static constexpr auto System_Clock_Div_8 = CounterMode_v::ClockSource.with(2u);
static constexpr auto System_Clock_Div_8_Too = CounterMode::ClockSource.with(3); static constexpr auto System_Clock_Div_8_Too = CounterMode_v::ClockSource.with(3u);
}; };
}; };
__declare_io_port_global_struct(struct Counter0, Counter0, counter_base_adr(0)); __declare_new_io_port(Counter0, counter_base_adr(0));
__declare_io_port_global_struct(struct Counter1, Counter1, counter_base_adr(1)); __declare_new_io_port(Counter1, counter_base_adr(1));
__declare_io_port_global_struct(struct Counter2, Counter2, counter_base_adr(2)); __declare_new_io_port(Counter2, counter_base_adr(2));
} }
} }

View File

@ -66,7 +66,7 @@ namespace JabyEngine {
~HighResTime() = delete; ~HighResTime() = delete;
static TimeStamp get_time_stamp() { static TimeStamp get_time_stamp() {
return TimeStamp(HighResTime::global_counter_10ms, Timer_IO::Counter2.value.read(Timer_IO::CounterValue::Value)); return TimeStamp(HighResTime::global_counter_10ms, Timer_IO::Counter2.get_current_value());
} }
}; };
#endif //JABYENGINE_USE_HIGH_PERCISION_TIMER #endif //JABYENGINE_USE_HIGH_PERCISION_TIMER

View File

@ -1,13 +1,21 @@
{ {
"folders": [ "folders": [
{ {
"name": "JabyEngine", "name": "Internal Include",
"path": ".", "path": "include"
},
{
"name": "Internal Source",
"path": "src"
}, },
{ {
"name": "Include", "name": "Include",
"path": "..\\..\\include" "path": "..\\..\\include"
}, },
{
"name": "JabyEngine",
"path": ".",
},
{ {
"name": "Root", "name": "Root",
"path": "..\\.." "path": "..\\.."

View File

@ -22,26 +22,26 @@ namespace JabyEngine {
} }
template<typename...ARGS> template<typename...ARGS>
static void send(CD_IO::CommandFifo_t& cmd_fifo, CD_IO::ParameterFifo_t& parameter_fifo, CD_IO::Command::Info cmd, ARGS...args) { static void send(CD_IO::CommandFifo_v& cmd_fifo, CD_IO::ParameterFifo_v& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) {
while(CD_IO::IndexStatus.read().is_bit_set(CD_IO::IndexStatus::IsTransmissionBusy)); while(CD_IO::IndexStatus.is_set(CD_IO::IndexStatus_t::IsTransmissionBusy));
(parameter_fifo.write(static_cast<uint8_t>(args)), ...); ((parameter_fifo = args),...);
cmd_fifo.write(cmd.id); cmd_fifo = cmd.id;
} }
template<typename T, typename...ARGS> template<typename T, typename...ARGS>
static void send(CD_IO::Command::Info cmd, ARGS...args) { static void send(CD_IO::Command::Desc cmd, ARGS...args) {
send(T::CommandFifo, T::ParameterFifo, cmd, args...); send(T::CommandFifo, T::ParameterFifo, cmd, args...);
} }
template<typename...ARGS> template<typename...ARGS>
static void send_wait(CD_IO::CommandFifo_t& cmd_fifo, CD_IO::ParameterFifo_t& parameter_fifo, CD_IO::Command::Info cmd, ARGS...args) { static void send_wait(CD_IO::CommandFifo_v& cmd_fifo, CD_IO::ParameterFifo_v& parameter_fifo, CD_IO::Command::Desc cmd, ARGS...args) {
send(cmd_fifo, parameter_fifo, cmd, args...); send(cmd_fifo, parameter_fifo, cmd, args...);
wait_until(cmd.complete_irq); wait_until(cmd.complete_irq);
} }
template<typename T, typename...ARGS> template<typename T, typename...ARGS>
static void send_wait(CD_IO::Command::Info cmd, ARGS...args) { static void send_wait(CD_IO::Command::Desc cmd, ARGS...args) {
send_wait(T::CommandFifo, T::ParameterFifo, cmd, args...); send_wait(T::CommandFifo, T::ParameterFifo, cmd, args...);
} }
}; };

View File

@ -8,50 +8,18 @@ namespace JabyEngine {
namespace GPU { namespace GPU {
namespace internal { namespace internal {
struct Screen { struct Screen {
struct Mode {
enum struct TVEncoding {
NTSC = 0,
PAL = 1,
};
static constexpr auto HorizontalResolution368 = Bit<uint32_t>(6);
static constexpr auto VerticalInterlace = Bit<uint32_t>(5);
static constexpr auto DisplayAreaColorDepth = BitRange<GPU_IO::DisplayAreaColorDepth>::from_to(4, 4);
static constexpr auto VideoMode = BitRange<TVEncoding>::from_to(3, 3);
static constexpr auto VerticalResolution = BitRange<GPU_IO::VerticalResolution>::from_to(2, 2);
static constexpr auto HorizontalResolution = BitRange<GPU_IO::HorizontalResolution>::from_to(0, 1);
static constexpr uint32_t PAL() {
return ComplexBitMap<uint32_t>::with(
Mode::HorizontalResolution.with(GPU_IO::HorizontalResolution::$320),
Mode::VerticalResolution.with(GPU_IO::VerticalResolution::$240),
Mode::VideoMode.with(TVEncoding::PAL),
Mode::DisplayAreaColorDepth.with(GPU_IO::DisplayAreaColorDepth::$15bit)
).raw;
}
static constexpr uint32_t NTSC() {
return ComplexBitMap<uint32_t>::with(
Mode::HorizontalResolution.with(GPU_IO::HorizontalResolution::$320),
Mode::VerticalResolution.with(GPU_IO::VerticalResolution::$240),
Mode::VideoMode.with(TVEncoding::NTSC),
Mode::DisplayAreaColorDepth.with(GPU_IO::DisplayAreaColorDepth::$15bit)
).raw;
}
};
static void configurate() { static void configurate() {
static constexpr uint16_t FirstVisiblePixelH = 0x260; static constexpr uint16_t FirstVisiblePixelH = 0x260;
#ifdef JABYENGINE_PAL #ifdef JABYENGINE_PAL
static constexpr uint16_t FirstVisiblePixelV = 0xA3; static constexpr uint16_t FirstVisiblePixelV = 0xA3;
GPU_IO::GP1.write(GPU_IO::Command::GP1::DisplayMode(Mode::PAL())); GPU_IO::GP1 = GPU_IO::Command::DisplayMode(GPU_IO::DisplayMode_t::PAL());
GPU::Screen::set_offset(0, 0); GPU::Screen::set_offset(0, 0);
#else #else
static constexpr uint16_t FirstVisiblePixelV = 0x88; static constexpr uint16_t FirstVisiblePixelV = 0x88;
GPU_IO::GP1.write(GPU_IO::Command::GP1::DisplayMode(Mode::NTSC())); GPU_IO::GP1 = GPU_IO::Command::DisplayMode(GPU_IO::DisplayMode_t::NTSC());
GPU::Screen::set_offset(0, 5); //< Random values GPU::Screen::set_offset(0, 5); //< Random values
#endif #endif
} }
@ -60,27 +28,27 @@ namespace JabyEngine {
}; };
static void set_draw_area(uint16_t x, uint16_t y) { static void set_draw_area(uint16_t x, uint16_t y) {
GPU_IO::GP0.write(GPU_IO::Command::GP0::DrawAreaTopLeft(x, y)); GPU_IO::GP0 = GPU_IO::Command::DrawAreaTopLeft(x, y);
GPU_IO::GP0.write(GPU_IO::Command::GP0::DrawAreaBottomRight((x + Display::Width), (y + Display::Height))); GPU_IO::GP0 = GPU_IO::Command::DrawAreaBottomRight((x + Display::Width), (y + Display::Height));
} }
static void quick_fill_fast(const Color24& color, const PositionU16& pos, const SizeU16& size) { static void quick_fill_fast(const Color24& color, const PositionU16& pos, const SizeU16& size) {
GPU_IO::GP0.write(GPU_IO::Command::GP0::QuickFill(color)); GPU_IO::GP0 = GPU_IO::Command::QuickFill(color);
GPU_IO::GP0.write(GPU_IO::Command::GP0::TopLeftPosition(pos.x, pos.y)); GPU_IO::GP0 = GPU_IO::Command::TopLeftPosition(pos.x, pos.y);
GPU_IO::GP0.write(GPU_IO::Command::GP0::WidthHeight(size.width, size.height)); GPU_IO::GP0 = GPU_IO::Command::WidthHeight(size.width, size.height);
} }
static void reset_cmd_buffer() { static void reset_cmd_buffer() {
GPU_IO::GP1.write(GPU_IO::Command::GP1::ResetCMDBufer()); GPU_IO::GP1 = GPU_IO::Command::ResetCMDBufer();
} }
static void wait_ready_for_CMD() { static void wait_ready_for_CMD() {
while(!GPU_IO::GPUSTAT.read().is(GPU_IO::GPUStatusRegister::GP0ReadyForCMD)); while(!GPU_IO::GPUSTAT.is_set(GPU_IO::GPUSTAT_t::GP0ReadyForCMD));
} }
namespace DMA { namespace DMA {
static void wait() { static void wait() {
while(::JabyEngine::DMA_IO::GPU.channel_ctrl.read().is(::JabyEngine::DMA_IO::CHCHR::Busy)); ::JabyEngine::DMA_IO::GPU.wait();
} }
static void end() { static void end() {
@ -88,28 +56,27 @@ namespace JabyEngine {
} }
namespace Receive { namespace Receive {
static void prepare() static void prepare() {
{ GPU_IO::GP1 = GPU_IO::Command::DMADirection(GPU_IO::DMADirection::CPU2GPU);
GPU_IO::GP1.write(GPU_IO::Command::GP1::DMADirection(GPU_IO::DMADirection::CPU2GPU));
reset_cmd_buffer(); reset_cmd_buffer();
} }
static void set_src(uintptr_t adr) { static void set_src(uintptr_t adr) {
DMA_IO::GPU.adr.write(DMA_IO::MADR::MemoryAdr.with(static_cast<uint32_t>(adr))); DMA_IO::GPU.set_adr(adr);
} }
static void set_dst(const PositionU16& position, const SizeU16& size) { static void set_dst(const PositionU16& position, const SizeU16& size) {
wait_ready_for_CMD(); wait_ready_for_CMD();
GPU_IO::GP0.write(GPU_IO::Command::GP0::CPU2VRAM_Blitting()); GPU_IO::GP0 = GPU_IO::Command::CPU2VRAM_Blitting();
GPU_IO::GP0.write(GPU_IO::Command::GP0::TopLeftPosition(position.x, position.y)); GPU_IO::GP0 = GPU_IO::Command::TopLeftPosition(position.x, position.y);
GPU_IO::GP0.write(GPU_IO::Command::GP0::WidthHeight(size.width, size.height)); GPU_IO::GP0 = GPU_IO::Command::WidthHeight(size.width, size.height);
} }
static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) { static void start(uint16_t blockCount, uint16_t wordsPerBlock = 0x10) {
typedef DMA_IO::BCR::SyncMode1 SyncMode1; typedef DMA_IO::BCR_t::SyncMode1 SyncMode1;
DMA_IO::GPU.block_ctrl.write(DMA_IO::BCR{SyncMode1::with(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount))}); DMA_IO::GPU.block_ctrl = DMA_IO::BCR_t::from(SyncMode1::BlockSize.with(wordsPerBlock), SyncMode1::BlockAmount.with(blockCount));
DMA_IO::GPU.channel_ctrl.write(DMA_IO::CHCHR::StartGPUReceive()); DMA_IO::GPU.channel_ctrl = DMA_IO::CHCHR_t::StartGPUReceive();
} }
} }
} }

View File

@ -16,14 +16,14 @@ namespace JabyEngine {
void setup() { void setup() {
__syscall_EnterCriticalSection(); __syscall_EnterCriticalSection();
Memory_IO::COM_DELAY.write(Memory_IO::COM_DELAY::SetupValue); Memory_IO::COM_DELAY.setup();
Memory_IO::CD_DELAY.write(Memory_IO::CD_DELAY::SetupValue); Memory_IO::CD_DELAY.setup();
__syscall_SysEnqIntRP(CdromIoIrq, &::JabyEngine::CD::internal::callback); __syscall_SysEnqIntRP(CdromIoIrq, &::JabyEngine::CD::internal::callback);
CD_IO::PortIndex1::change_to(); CD_IO::PortIndex1::change_to();
CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlagRegister); CD_IO::Interrupt::ack_extended(CD_IO::PortIndex1::InterruptFlag);
CD_IO::Interrupt::enable(CD_IO::PortIndex1::InterruptEnableRegister); CD_IO::Interrupt::enable(CD_IO::PortIndex1::InterruptEnable);
Interrupt::ack_irq(Interrupt::CDROM); Interrupt::ack_irq(Interrupt::CDROM);
Interrupt::enable_irq(Interrupt::CDROM); Interrupt::enable_irq(Interrupt::CDROM);

View File

@ -49,7 +49,7 @@ namespace JabyEngine {
} }
void setup() { void setup() {
GPU_IO::GP1.write(GPU_IO::Command::GP1::Reset()); GPU_IO::GP1 = GPU_IO::Command::Reset();
internal::Screen::configurate(); internal::Screen::configurate();
internal::Screen::exchange_buffer_and_display(); internal::Screen::exchange_buffer_and_display();

View File

@ -6,65 +6,66 @@ namespace JabyEngine {
namespace boot { namespace boot {
namespace SPU { namespace SPU {
using namespace JabyEngine; using namespace JabyEngine;
using namespace SPU_IO;
static void clear_main_volume() { static void clear_main_volume() {
static constexpr auto StartVol = SPU_IO::SweepVolume::with(SPU_IO::SweepVolume::VolumeEnable, SPU_IO::SweepVolume::Volume.with(I16_MAX >> 2)); static constexpr auto StartVol = SweepVolume_t::from(SweepVolume_t::VolumeEnable, SweepVolume_t::Volume.with(static_cast<int16_t>(I16_MAX >> 2)));
SPU_IO::MainVolume::Left.write({StartVol}); MainVolume::Left = StartVol;
SPU_IO::MainVolume::Right.write({StartVol}); MainVolume::Right = StartVol;
} }
static void clear_cd_and_ext_audio_volume() { static void clear_cd_and_ext_audio_volume() {
SPU_IO::CDVolume::Left.write(0); CDVolume::Left = 0;
SPU_IO::CDVolume::Right.write(0); CDVolume::Right = 0;
SPU_IO::ExternalAudioInputVolume::Left.write(0); ExternalAudioInputVolume::Left = 0;
SPU_IO::ExternalAudioInputVolume::Right.write(0); ExternalAudioInputVolume::Right = 0;
} }
static void clear_control_register() { static void clear_control_register() {
SPU_IO::Control.write(SPU_IO::ControlRegister()); ControlRegister = 0;
} }
static void clear_voice() { static void clear_voice() {
for(auto& voice : SPU_IO::Voice) { for(auto& voice : SPU_IO::Voice) {
voice.volumeLeft.write(SPU_IO::SweepVolume()); voice.volumeLeft = SweepVolume_t();
voice.volumeRight.write(SPU_IO::SweepVolume()); voice.volumeRight = SweepVolume_t();
voice.sampleRate.write(SPU_IO::SampleRate()); voice.sampleRate = SampleRate_t();
voice.ad.write(SPU_IO::AD()); voice.ad = AD_t();
voice.sr.write(SPU_IO::SR()); voice.sr = SR_t();
voice.currentVolume.write(SPU_IO::SimpleVolume(0)); voice.currentVolume = 0;
voice.adr.write(0x200); voice.adr = 0x200;
voice.repeatAdr.write(0x200); voice.repeatAdr = 0x200;
} }
} }
static void clear_pmon() { static void clear_pmon() {
SPU_IO::PMON.write(SPU_IO::PitchModFlags()); SPU_IO::PMON = PMON_t();
} }
static void clear_noise_and_echo() { static void clear_noise_and_echo() {
SPU_IO::NON.write(SPU_IO::NoiseGenerator()); SPU_IO::NON = NON_t();
SPU_IO::EON.write(SPU_IO::EchoOn()); SPU_IO::EON = EON_t();
} }
static void clear_reverb() { static void clear_reverb() {
SPU_IO::Reverb::Volume::Left.write(0); Reverb::Volume::Left = 0;
SPU_IO::Reverb::Volume::Right.write(0); Reverb::Volume::Right = 0;
SPU_IO::Reverb::WorkAreaAdr.write(0); Reverb::WorkAreaAdr = 0;
} }
static void setup_control_register() { static void setup_control_register() {
static constexpr auto SetupValue = SPU_IO::ControlRegister::with(SPU_IO::ControlRegister::Enable, SPU_IO::ControlRegister::Unmute, SPU_IO::ControlRegister::CDAudioEnable); static constexpr auto SetupValue = ControlRegister_t::from(ControlRegister_t::Enable, ControlRegister_t::Unmute, ControlRegister_t::CDAudioEnable);
SPU_IO::Control.write({SetupValue}); SPU_IO::ControlRegister = SetupValue;
} }
static void setup_data_transfer_control() { static void setup_data_transfer_control() {
static constexpr uint16_t RequiredValue = (2 << 1); static constexpr uint16_t RequiredValue = (2 << 1);
SPU_IO::DataTransferControl.write(RequiredValue); DataTransferControl = RequiredValue;
} }
static void wait_voices() { static void wait_voices() {
@ -72,7 +73,7 @@ namespace JabyEngine {
try_again: try_again:
for(const auto& voice : SPU_IO::Voice) { for(const auto& voice : SPU_IO::Voice) {
if(voice.currentVolume.read() > Treshhold) { if(voice.currentVolume > Treshhold) {
goto try_again; goto try_again;
} }
} }

View File

@ -1,6 +1,7 @@
#include "BootLoader/boot_loader.hpp" #include "BootLoader/boot_loader.hpp"
#include <PSX/System/IOPorts/dMa_io.hpp> #include <PSX/System/IOPorts/dMa_io.hpp>
// 2x For setup timing
#include <PSX/Timer/high_res_timer.hpp> #include <PSX/Timer/high_res_timer.hpp>
#include <stdio.h> #include <stdio.h>
@ -8,7 +9,8 @@ namespace JabyEngine {
namespace boot { namespace boot {
namespace Start { namespace Start {
static void enable_DMA() { static void enable_DMA() {
DMA_IO::DPCR.write(DMA_IO::DMAControlRegister{DMA_IO::DPCR.read() | DMA_IO::DMAControlRegister::SPUEnable | DMA_IO::DMAControlRegister::GPUEnable}); const auto dpcr = DMA_IO::DPCR_t(DMA_IO::DPCR).set(DMA_IO::DPCR_t::SPUEnable).set(DMA_IO::DPCR_t::GPUEnable);
DMA_IO::DPCR = dpcr;
} }
JabyEngine::NextRoutine setup() { JabyEngine::NextRoutine setup() {

View File

@ -18,7 +18,7 @@
void setup() { void setup() {
using namespace Timer_IO; using namespace Timer_IO;
static constexpr auto Mode = CounterMode::with(CounterMode::FreeRun, Counter2::SyncMode::Freerun, CounterMode::ResetAfterTarget, CounterMode::IRQAtTarget, CounterMode::IRQEveryTime, CounterMode::IRQPulse, Counter2::Source::System_Clock_Div_8); static constexpr auto Mode = CounterMode_t::from(CounterMode_t::FreeRun, Counter2_v::SyncMode::FreeRun, CounterMode_t::ResetAfterTarget, CounterMode_t::IRQAtTarget, CounterMode_t::IRQEveryTime, CounterMode_t::IRQPulse, Counter2_v::Source::System_Clock_Div_8);
Interrupt::disable_irq(Interrupt::Timer2); Interrupt::disable_irq(Interrupt::Timer2);
@ -26,8 +26,8 @@
__syscall_SysEnqIntRP(Timer2Irq, &IRQCallback); __syscall_SysEnqIntRP(Timer2Irq, &IRQCallback);
__syscall_ExitCriticalSection(); __syscall_ExitCriticalSection();
Counter2.target.write(CounterTarget::CounterTargetValue.with(HighResTime::TicksFor10ms)); Counter2.set_target_value(HighResTime::TicksFor10ms);
Counter2.mode.write({Mode}); Counter2.set_mode(Mode);
Interrupt::enable_irq(Interrupt::Timer2); Interrupt::enable_irq(Interrupt::Timer2);
} }

View File

@ -7,19 +7,19 @@
namespace JabyEngine { namespace JabyEngine {
namespace CD { namespace CD {
namespace internal { namespace internal {
struct Mode : public ComplexBitMap<uint8_t> { __declare_io_type(Mode, uint8_t,
static constexpr auto DoubleSpeed = Bit<uint8_t>(7); static constexpr auto DoubleSpeed = Bit(7);
static constexpr auto SingleSpeed = !DoubleSpeed; static constexpr auto SingleSpeed = !DoubleSpeed;
static constexpr auto XADPCM = Bit<uint8_t>(6); static constexpr auto XADPCM = Bit(6);
static constexpr auto WholeSector = Bit<uint8_t>(5); static constexpr auto WholeSector = Bit(5);
static constexpr auto DataSector = !WholeSector; static constexpr auto DataSector = !WholeSector;
static constexpr auto UseXAFilter = Bit<uint8_t>(3); static constexpr auto UseXAFilter = Bit(3);
static constexpr auto AudioPlayIRQ = Bit<uint8_t>(2); static constexpr auto AudioPlayIRQ = Bit(2);
static constexpr auto AutoPauseTrack = Bit<uint8_t>(1); static constexpr auto AutoPauseTrack = Bit(1);
static constexpr auto CDDA = Bit<uint8_t>(0); static constexpr auto CDDA = Bit(0);
}; );
static constexpr auto DataSectorMode = Mode::with(Mode::DoubleSpeed, Mode::DataSector); static constexpr auto DataSectorMode = Mode_t::from(Mode_t::DoubleSpeed, Mode_t::DataSector);
static SectorBufferAllocator sector_allocator; static SectorBufferAllocator sector_allocator;
static uint16_t sectors_left; static uint16_t sectors_left;
@ -31,12 +31,12 @@ namespace JabyEngine {
}; };
if(Interrupt::is_irq(Interrupt::CDROM)) { if(Interrupt::is_irq(Interrupt::CDROM)) {
const uint8_t old_idx = (CD_IO::IndexStatus.read() & 0x3); const uint8_t old_idx = (CD_IO::IndexStatus & 0x3);
CD_IO::PortIndex1::change_to(); CD_IO::PortIndex1::change_to();
const auto cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlagRegister); const auto cur_irq = CD_IO::Interrupt::get_type(CD_IO::PortIndex1::InterruptFlag);
last_interrupt = cur_irq; last_interrupt = cur_irq;
CD_IO::Interrupt::ack(CD_IO::PortIndex1::InterruptFlagRegister); CD_IO::Interrupt::ack(CD_IO::PortIndex1::InterruptFlag);
if(cur_irq == CD_IO::Interrupt::DataReady) { if(cur_irq == CD_IO::Interrupt::DataReady) {
//Obtain sector content here //Obtain sector content here
@ -67,7 +67,7 @@ namespace JabyEngine {
current_state = State::Error; current_state = State::Error;
} }
CD_IO::IndexStatus.write({old_idx}); CD_IO::IndexStatus = old_idx;
return InterruptVerifierResult::ExecuteHandler; return InterruptVerifierResult::ExecuteHandler;
} }

View File

@ -16,7 +16,7 @@ namespace JabyEngine {
void Screen :: exchange_buffer_and_display() { void Screen :: exchange_buffer_and_display() {
GPU::internal::set_draw_area(0, (Display::Height*PublicScreenClass::CurrentDisplayAreaID)); GPU::internal::set_draw_area(0, (Display::Height*PublicScreenClass::CurrentDisplayAreaID));
PublicScreenClass::CurrentDisplayAreaID ^= 1; PublicScreenClass::CurrentDisplayAreaID ^= 1;
GPU_IO::GP1.write(GPU_IO::Command::GP1::DisplayArea(0, (Display::Height*PublicScreenClass::CurrentDisplayAreaID))); GPU_IO::GP1 = GPU_IO::Command::DisplayArea(0, (Display::Height*PublicScreenClass::CurrentDisplayAreaID));
} }
} }
@ -25,13 +25,13 @@ namespace JabyEngine {
x += 78; x += 78;
y += 43; y += 43;
GPU_IO::GP1.write(GPU_IO::Command::GP1::HorizontalDisplayRange((x << 3), (x + Display::Width) << 3)); GPU_IO::GP1 = GPU_IO::Command::HorizontalDisplayRange((x << 3), (x + Display::Width) << 3);
GPU_IO::GP1.write(GPU_IO::Command::GP1::VerticalDisplayRange(y, y + Display::Height)); GPU_IO::GP1 = GPU_IO::Command::VerticalDisplayRange(y, y + Display::Height);
} }
#else #else
void Screen :: set_offset(uint16_t x, uint16_t y) { void Screen :: set_offset(uint16_t x, uint16_t y) {
GP1.write(Command::GP1::HorizontalDisplayRange(x, (x + Display::Width*8))); GPU_IO::GP1 = GPU_IO::Command::HorizontalDisplayRange(x, (x + Display::Width*8));
GP1.write(Command::GP1::VerticalDisplayRange(y - (ScanlinesV/2), y + (ScanlinesV/2))); GPU_IO::GP1 = GPU_IO::Command::VerticalDisplayRange(y - (ScanlinesV/2), y + (ScanlinesV/2));
} }
#endif //USE_NO$PSX #endif //USE_NO$PSX
} }

View File

@ -10,7 +10,7 @@ namespace JabyEngine {
void start() { void start() {
NextRoutine next_routine = JabyEngine::NextRoutine::from(boot::Start::setup); NextRoutine next_routine = JabyEngine::NextRoutine::from(boot::Start::setup);
printf("Starting Planschbecken 0x%p\n", next_routine.value); printf("Starting Planschbecken Version 0 0x%p\n", next_routine.value);
while(true) { while(true) {
if(next_routine.is_null()) { if(next_routine.is_null()) {
break; break;