Skip to content

Commit

Permalink
io: add display unit
Browse files Browse the repository at this point in the history
added rendering for modes 3,4,5
also changed how memory structuring works

Signed-off-by: Amneesh Singh <[email protected]>
  • Loading branch information
natto1784 committed Jun 21, 2024
1 parent 54fc472 commit 58a503d
Show file tree
Hide file tree
Showing 13 changed files with 656 additions and 279 deletions.
47 changes: 6 additions & 41 deletions include/bus.hh
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

#include "header.hh"
#include "io/io.hh"
#include "memory.hh"
#include <memory>
#include <optional>
#include <span>
#include <vector>

namespace matar {
Expand Down Expand Up @@ -85,7 +84,7 @@ class Bus {
}

template<typename T>
std::optional<T> read(uint32_t address) const;
T read(uint32_t address) const;

template<typename T>
void write(uint32_t address, T value);
Expand All @@ -101,45 +100,11 @@ class Bus {
static constexpr decltype(cycle_map) init_cycle_count();

std::unique_ptr<IoDevices> io;
Memory<BIOS_SIZE> bios = {};
Memory<0x40000> board_wram = {};
Memory<0x80000> chip_wram = {};
Memory<> rom;

#define MEMORY_REGION(name, start) \
static constexpr uint32_t name##_START = start; \
static constexpr uint8_t name##_REGION = start >> 24 & 0xF;

#define DECL_MEMORY(name, ident, start, end) \
MEMORY_REGION(name, start) \
std::array<uint8_t, end - start + 1> ident = {};

MEMORY_REGION(BIOS, 0x00000000)
std::array<uint8_t, BIOS_SIZE> bios = {};

// board working RAM
DECL_MEMORY(BOARD_WRAM, board_wram, 0x02000000, 0x0203FFFF)

// chip working RAM
DECL_MEMORY(CHIP_WRAM, chip_wram, 0x03000000, 0x03007FFF)

// palette RAM
DECL_MEMORY(PALETTE_RAM, palette_ram, 0x05000000, 0x050003FF)

// video RAM
DECL_MEMORY(VRAM, vram, 0x06000000, 0x06017FFF)

// OAM OBJ attributes
DECL_MEMORY(OAM_OBJ_ATTR, oam_obj_attr, 0x07000000, 0x070003FF)

#undef DECL_MEMORY

MEMORY_REGION(ROM_0, 0x08000000)
MEMORY_REGION(ROM_1, 0x0A000000)
MEMORY_REGION(ROM_2, 0x0C000000)

MEMORY_REGION(IO, 0x04000000)
static constexpr uint32_t IO_END = 0x040003FE;

#undef MEMORY_REGION

std::vector<uint8_t> rom;
Header header;
void parse_header();
};
Expand Down
159 changes: 159 additions & 0 deletions include/io/display/display.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#include "memory.hh"
#include <array>
#include <bit>
#include <cstdint>
#include <sys/types.h>

// NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays)
namespace matar {
namespace display {
static constexpr int LCD_WIDTH = 240;

// there are 5 modes
static constexpr uint N_MODES = 6;
// there are 4 backgrounds that can be layered depending on mode
// there is also 1 object layer
static constexpr uint N_BACKGROUNDS = 4;

static constexpr uint32_t PRAM_START = 0x5000000;
static constexpr uint32_t VRAM_START = 0x6000000;
static constexpr uint32_t OAM_START = 0x7000000;

template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
struct Point {
T x;
T y;
};

struct Color {
public:
Color(uint16_t raw)
: red(raw & 0b11111)
, green(raw >> 5 & 0b11111)
, blue(raw >> 10 & 0b11111) {}

uint16_t read() const {
return (red & 0b11111) | ((green << 5) & 0b11111) |
((blue << 10) & 0b11111);
}

private:
uint8_t red;
uint8_t green;
uint8_t blue;
};

struct DisplayControl {
struct {
uint8_t mode : 3;
int : 1; // unused
bool frame_select_1 : 1;
bool hblank_free_interval : 1;
bool obj_character_vram_mapping : 1;
bool forced_blank : 1;
bool screen_display_0 : 1;
bool screen_display_1 : 1;
bool screen_display_2 : 1;
bool screen_display_3 : 1;
bool screen_display_obj : 1;
bool window_display_0 : 1;
bool window_display_1 : 1;
bool obj_window_display : 1;
} value;

uint16_t read() const { return std::bit_cast<uint16_t>(value); };
void write(uint16_t raw) { value = std::bit_cast<decltype(value)>(raw); };
};

struct DisplayStatus {
struct {
bool vblank_flag : 1;
bool hblank_flag : 1;
bool vcounter_flag : 1;
bool vblank_irq_enable : 1;
bool hblank_irq_enable : 1;
bool vcounter_irq_enable : 1;
int : 2; // unused
uint8_t vcount_setting : 8;
} value;

uint16_t read() const { return std::bit_cast<uint16_t>(value); };
void write(uint16_t raw) { value = std::bit_cast<decltype(value)>(raw); };
};

struct BackgroundControl {
struct {
uint8_t priority : 2;
uint8_t character_base_block : 2;
int : 2; // unused
bool mosaic : 1;
bool colors256 : 1;
uint8_t screen_base_block : 5;
bool bg_2_3_wraparound : 1;
uint8_t screen_size : 2;
} value;

uint16_t read() const { return std::bit_cast<uint16_t>(value); };
void write(uint16_t raw) { value = std::bit_cast<decltype(value)>(raw); };
};

struct RotationScaling {
// these are all 16 bit signed "fixed point" floats
// shifted by 8
int16_t a;
int16_t b;
int16_t c;
int16_t d;

// following points have 28 bit signed "fixed point" floats as coords
// shifted by 8
Point<int32_t> ref;

private:
Point<int32_t> internal [[maybe_unused]]
;
};

struct Display {
public:
using u16 = uint16_t;

Memory<0x400> pram;
Memory<0x18000> vram;
Memory<0x400> oam;

DisplayControl lcd_control;
DisplayStatus general_lcd_status;
u16 vertical_counter;
BackgroundControl bg_control[4];
Point<u16> bg0_offset;
Point<u16> bg1_offset;
Point<u16> bg2_offset;
Point<u16> bg3_offset;
RotationScaling bg2_rot_scale;
RotationScaling bg3_rot_scale;
u16 win0_horizontal_dimensions;
u16 win1_horizontal_dimensions;
u16 win0_vertical_dimensions;
u16 win1_vertical_dimensions;
u16 inside_win_0_1;
u16 outside_win;
u16 mosaic_size;
u16 color_special_effects_selection;
u16 alpha_blending_coefficients;
u16 brightness_coefficient;

private:
// 1 color is 16 bits in ARGB555 format
std::array<std::array<uint16_t, LCD_WIDTH>, N_BACKGROUNDS> scanline_buffers;

template<int MODE,
typename = std::enable_if_t<MODE == 3 || MODE == 4 || MODE == 5>>
void render_bitmap_mode();

template<int LAYER, typename = std::enable_if_t<LAYER >= 0 && LAYER <= 3>>
void render_text_layer();
};
}
}
// NOLINTEND(cppcoreguidelines-avoid-c-arrays)
39 changes: 39 additions & 0 deletions include/io/dma.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include <bit>
#include <cstdint>

namespace matar {
// NOLINTBEGIN(cppcoreguidelines-avoid-c-arrays)
struct DmaControl {
struct {
int : 4; // this is supposed to be 5 bits, however, to align the struct
// to 16 bits, we will adjust for the first LSB in the
// read/write
uint8_t dst_adjustment : 2;
uint8_t src_adjustment : 2;
bool repeat : 1;
bool transfer_32 : 1;
int : 1;
uint8_t start_timing : 2;
bool irq_enable : 1;
bool enable : 1;
} value;

uint16_t read() const { return std::bit_cast<uint16_t>(value) << 1; };
void write(uint16_t raw) {
value = std::bit_cast<decltype(value)>(static_cast<uint16_t>(raw >> 1));
};
};

struct Dma {
using u16 = uint16_t;

struct {
u16 source[2];
u16 destination[2];
u16 word_count;
DmaControl control;
} channels[4];
};
// NOLINTEND(cppcoreguidelines-avoid-c-arrays)

}
13 changes: 9 additions & 4 deletions include/io/io.hh
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#pragma once
#include "lcd.hh"

#include "display/display.hh"
#include "dma.hh"
#include "sound.hh"
#include <cstdint>
#include <memory>

namespace matar {
class Bus;
class Bus; // forward declaration

class IoDevices {
public:
IoDevices(std::weak_ptr<Bus>);
Expand All @@ -30,9 +33,11 @@ class IoDevices {
bool low_power_mode;
} system = {};

struct lcd lcd = {};
struct sound sound = {};
display::Display display = {};
Sound sound = {};
Dma dma = {};

std::weak_ptr<Bus> bus;
friend class Bus;
};
}
84 changes: 0 additions & 84 deletions include/io/lcd.hh

This file was deleted.

2 changes: 1 addition & 1 deletion include/io/sound.hh
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
40000A4h 4 W FIFO_B Channel B FIFO, Data 0-3
*/

struct sound {
struct Sound {
using u16 = uint16_t;

// channel 1
Expand Down
Loading

0 comments on commit 58a503d

Please sign in to comment.