Compare commits

..

No commits in common. "4d51b4704645b538c23b71cd4c10f42d4615020b" and "25f4cc50f72a077b41e494aff07f6ad073989a32" have entirely different histories.

38 changed files with 16 additions and 52658 deletions

3
.gitignore vendored
View File

@ -11,12 +11,9 @@
*.pcm
*.su
*.ss
*.dsp
*.exe
res/mai.data
tools/ttf-convert
tools/ttf-bitmap
tools/ttf_bitmap2
common/keyboard.cpp
common/keyboard.hpp
wordle/word_list.hpp

View File

@ -1,5 +1,5 @@
CFLAGS = -Isaturn -I. -D__saturn__
OPT ?= -O2
CFLAGS = -Isaturn
OPT ?= -Og
LIB = ./saturn
ALL =
@ -28,9 +28,6 @@ include $(LIB)/common.mk
%.data.o: %.data
$(BUILD_BINARY_O)
%.data.h: %.data
$(BUILD_BINARY_H)
%.pattern.o: %.pattern
$(BUILD_BINARY_O)
@ -40,15 +37,6 @@ include $(LIB)/common.mk
%.bin.o: %.bin
$(BUILD_BINARY_O)
%.bin.h: %.bin
$(BUILD_BINARY_H)
%.dsp.o: %.dsp
$(BUILD_BINARY_O)
%.dsp.h: %.dsp
$(BUILD_BINARY_H)
%.pcm.o: %.pcm
$(BUILD_BINARY_O)
@ -64,19 +52,11 @@ vdp2/nbg0.elf: vdp2/nbg0.o res/butterfly.data.o res/butterfly.data.pal.o
vdp2/nbg0_16color.elf: vdp2/nbg0_16color.o res/kirby.data.o res/kirby.data.pal.o
vdp2/nbg0_font.elf: vdp2/nbg0_font.o saturn/start.o font/hp_100lx_4bit.data.o
vdp2/rbg0_font.elf: vdp2/rbg0_font.o saturn/start.o font/hp_100lx_4bit.data.o
vdp2/color_calculation_ratio.elf: vdp2/color_calculation_ratio.o res/mai00.data.o res/mai.data.pal.o res/haohmaru.data.o res/haohmaru.data.pal.o res/forest.data.pal.o res/forest.pattern.o res/forest.tile.o
vdp2/line_color_screen.elf: vdp2/line_color_screen.o $(LIBGCC)
vdp1/polygon.elf: vdp1/polygon.o
vdp1/cube.elf: vdp1/cube.o $(LIBGCC)
vdp1/cube2.elf: vdp1/cube2.o
vdp1/bear.elf: CFLAGS += -DUSE_SH2_DVSR
vdp1/bear.elf: vdp1/bear.o $(LIBGCC)
vdp1/normal_sprite.elf: vdp1/normal_sprite.o res/mai00.data.o res/mai.data.pal.o
vdp1/normal_sprite_color_bank.elf: vdp1/normal_sprite_color_bank.o res/mai00.data.o res/mai.data.pal.o
@ -173,15 +153,6 @@ editor/main_saturn.elf: editor/main_saturn.o res/nec.bitmap.bin.o res/nec_bold.b
cdc/cdc.elf: cdc/cdc.o saturn/start.o memcpy.o cdc/serial.o
scu-dsp/add.elf: scu-dsp/add.o saturn/start.o cdc/serial.o scu-dsp/input.bin.o
scu-dsp/div10.elf: scu-dsp/div10.o saturn/start.o cdc/serial.o scu-dsp/div10.dsp.o
scu-dsp/div10_vdp2.elf: scu-dsp/div10_vdp2.o saturn/start.o cdc/serial.o scu-dsp/div10_vdp2.dsp.o font/hp_100lx_4bit_flip.data.o
%.dsp: %.asm
~/scu-dsp-asm/scu-dsp-asm $< $@
# clean
clean: clean-sh
clean-sh:

View File

@ -4,14 +4,14 @@
void serial_char(const char c)
{
//while ((sh2.reg.SSR & SSR__TDRE) == 0); // wait for transmit data empty
while ((sh2.reg.SSR & SSR__TDRE) == 0); // wait for transmit data empty
sh2.reg.TDR = c;
}
void serial_string(const char * s)
{
while (*s) {
//while ((sh2.reg.SSR & SSR__TDRE) == 0); // wait for transmit data empty
while ((sh2.reg.SSR & SSR__TDRE) == 0); // wait for transmit data empty
sh2.reg.TDR = *s++;
}
}
@ -19,7 +19,7 @@ void serial_string(const char * s)
void serial_bytes(const char * s, uint32_t length)
{
while (length > 0) {
//while ((sh2.reg.SSR & SSR__TDRE) == 0); // wait for transmit data empty
while ((sh2.reg.SSR & SSR__TDRE) == 0); // wait for transmit data empty
sh2.reg.TDR = *s++;
length -= 1;
}

Binary file not shown.

Binary file not shown.

View File

@ -1,5 +0,0 @@
#pragma once
#include <stdint.h>
extern uint32_t _binary_font_hp_100lx_4bit_data_start __asm("_binary_font_hp_100lx_4bit_data_start");
extern uint32_t _binary_font_hp_100lx_4bit_data_end __asm("_binary_font_hp_100lx_4bit_data_end");
extern uint32_t _binary_font_hp_100lx_4bit_data_size __asm("_binary_font_hp_100lx_4bit_data_size");

Binary file not shown.

View File

@ -1,5 +0,0 @@
#pragma once
#include <stdint.h>
extern uint32_t _binary_font_hp_100lx_4bit_flip_data_start __asm("_binary_font_hp_100lx_4bit_flip_data_start");
extern uint32_t _binary_font_hp_100lx_4bit_flip_data_end __asm("_binary_font_hp_100lx_4bit_flip_data_end");
extern uint32_t _binary_font_hp_100lx_4bit_flip_data_size __asm("_binary_font_hp_100lx_4bit_flip_data_size");

View File

@ -1,105 +0,0 @@
#pragma once
#include <utility>
#include "vec2.hpp"
template <int R, int C, typename T>
struct mat;
//
// mat4x4
//
template <typename T>
struct mat<2, 2, T>
{
typedef vec<2, T> row_type;
typedef vec<2, T> col_type;
private:
row_type value[2];
public:
inline constexpr mat();
inline constexpr mat
(
T const& a00, T const& a01,
T const& a10, T const& a11
);
inline static constexpr int length() { return 4; }
inline constexpr typename mat<2, 2, T>::row_type const &
operator[](int i) const;
void operator=(const mat<2, 2, T>&) = delete;
};
template<typename T>
inline constexpr mat<2, 2, T>::mat()
: value{std::move(row_type(1, 0)),
std::move(row_type(0, 1))}
{ }
template<typename T>
inline constexpr mat<2, 2, T>::mat
(
T const& a00, T const& a01,
T const& a10, T const& a11
)
: value{std::move(row_type(a00, a01)),
std::move(row_type(a10, a11))}
{ }
template <typename T>
inline constexpr typename mat<2, 2, T>::row_type const &
mat<2, 2, T>::operator[](int i) const
{
switch (i)
{
default: [[fallthrough]];
case 0:
return value[0];
case 1:
return value[1];
}
}
template<typename T>
inline constexpr mat<2, 2, T> operator*(mat<2, 2, T> const& m1, mat<2, 2, T> const& m2)
{
#define c(i, j) ( \
m1[i][0] * m2[0][j] \
+ m1[i][1] * m2[1][j])
return mat<2, 2, T>(c(0,0), c(0,1),
c(1,0), c(1,1));
#undef c
}
template<typename T>
inline constexpr typename mat<2, 2, T>::row_type operator*
(
mat<2, 2, T> const& m,
typename mat<2, 2, T>::col_type const& v
)
{
#define c(i) ( \
m[i][0] * v[0] \
+ m[i][1] * v[1])
return typename mat<2, 2, T>::row_type(c(0), c(1));
#undef c
}
template<typename T>
inline constexpr mat<2, 2, T> transpose(mat<2, 2, T> const& m)
{
return mat<2, 2, T>(
m[0][0], m[1][0],
m[0][1], m[1][1]
);
}

View File

@ -74,17 +74,6 @@ mat<3, 3, T>::operator[](int i) const
}
}
template<typename T>
inline constexpr mat<3, 3, T> operator+(mat<3, 3, T> const& m1, mat<3, 3, T> const& m2)
{
#define c(i, j) ( m1[i][j] + m2[i][j] )
return mat<3, 3, T>(c(0,0), c(0,1), c(0,2),
c(1,0), c(1,1), c(1,2),
c(2,0), c(2,1), c(2,2));
#undef c
}
template<typename T>
inline constexpr mat<3, 3, T> operator*(mat<3, 3, T> const& m1, mat<3, 3, T> const& m2)
{
@ -99,17 +88,6 @@ inline constexpr mat<3, 3, T> operator*(mat<3, 3, T> const& m1, mat<3, 3, T> con
#undef c
}
template<typename T>
inline constexpr mat<3, 3, T> operator*(mat<3, 3, T> const& m1, float s)
{
#define c(i, j) ( m1[i][j] * s )
return mat<3, 3, T>(c(0,0), c(0,1), c(0,2),
c(1,0), c(1,1), c(1,2),
c(2,0), c(2,1), c(2,2));
#undef c
}
template<typename T>
inline constexpr typename mat<3, 3, T>::row_type operator*
(

View File

@ -35,7 +35,7 @@ public:
inline constexpr typename mat<4, 4, T>::row_type const &
operator[](int i) const;
//void operator=(const mat<4, 4, T>&) = delete;
void operator=(const mat<4, 4, T>&) = delete;
};
@ -80,18 +80,6 @@ mat<4, 4, T>::operator[](int i) const
}
}
template<typename T>
inline constexpr mat<4, 4, T> operator+(mat<4, 4, T> const& m1, mat<4, 4, T> const& m2)
{
#define c(i, j) ( m1[i][j] + m2[i][j] )
return mat<4, 4, T>(c(0,0), c(0,1), c(0,2), c(0,3),
c(1,0), c(1,1), c(1,2), c(1,3),
c(2,0), c(2,1), c(2,2), c(2,3),
c(3,0), c(3,1), c(3,2), c(3,3));
#undef c
}
template<typename T>
inline constexpr mat<4, 4, T> operator*(mat<4, 4, T> const& m1, mat<4, 4, T> const& m2)
{
@ -108,18 +96,6 @@ inline constexpr mat<4, 4, T> operator*(mat<4, 4, T> const& m1, mat<4, 4, T> con
#undef c
}
template<typename T>
inline constexpr mat<4, 4, T> operator*(mat<4, 4, T> const& m1, float s)
{
#define c(i, j) ( m1[i][j] * s )
return mat<4, 4, T>(c(0,0), c(0,1), c(0,2), c(0,3),
c(1,0), c(1,1), c(1,2), c(1,3),
c(2,0), c(2,1), c(2,2), c(2,3),
c(3,0), c(3,1), c(3,2), c(3,3));
#undef c
}
template<typename T>
inline constexpr typename mat<4, 4, T>::row_type operator*
(
@ -137,23 +113,6 @@ inline constexpr typename mat<4, 4, T>::row_type operator*
#undef c
}
template<typename T>
inline constexpr vec<3, T> operator*
(
mat<4, 4, T> const& m,
vec<3, T> const& v
)
{
#define c(i) ( \
m[i][0] * v[0] \
+ m[i][1] * v[1] \
+ m[i][2] * v[2] \
+ m[i][3] )
return vec<3, T>(c(0), c(1), c(2));
#undef c
}
template<typename T>
inline constexpr mat<4, 4, T> transpose(mat<4, 4, T> const& m)
{

View File

@ -1,158 +0,0 @@
#pragma once
#include "math.hpp"
#include "vec.hpp"
//
// vec3
//
template <typename T>
struct vec<2, T>
{
union {
struct { T x, y; };
struct { T u, v; };
};
inline constexpr vec();
inline constexpr vec(T scalar);
inline constexpr vec(T _x, T _y);
constexpr inline vec<2, T> operator-() const;
inline constexpr T const& operator[](int i) const;
inline constexpr vec<2, T>& operator=(vec<2, T> const& v);
inline constexpr vec<2, T>& operator+=(vec<2, T> const& v);
inline constexpr vec<2, T>& operator-=(vec<2, T> const& v);
};
template <typename T>
inline constexpr vec<2, T>::vec()
: x(0), y(0)
{}
template <typename T>
inline constexpr vec<2, T>::vec(T scalar)
: x(scalar), y(scalar)
{}
template <typename T>
inline constexpr vec<2, T>::vec(T _x, T _y)
: x(_x), y(_y)
{}
template <typename T>
constexpr inline vec<2, T> vec<2, T>::operator-() const
{
return vec<2, T>(-x, -y);
}
template <typename T>
inline constexpr T const& vec<2, T>::operator[](int i) const
{
switch(i)
{
default: [[fallthrough]];
case 0: return x;
case 1: return y;
}
}
template <typename T>
inline constexpr vec<2, T>& vec<2, T>::operator=(vec<2, T> const& v)
{
this->x = static_cast<T>(v.x);
this->y = static_cast<T>(v.y);
return *this;
}
template <typename T>
inline constexpr vec<2, T>& vec<2, T>::operator+=(vec<2, T> const& v)
{
*this = *this + vec<2, T>(v);
return *this;
}
template <typename T>
inline constexpr vec<2, T>& vec<2, T>::operator-=(vec<2, T> const& v)
{
*this = *this - vec<2, T>(v);
return *this;
}
template <typename T>
inline constexpr vec<2, T> operator+(vec<2, T> const& v1, vec<2, T> const& v2)
{
return vec<2, T>(v1.x + v2.x,
v1.y + v2.y);
}
template <typename T>
inline constexpr vec<2, T> operator-(vec<2, T> const& v1, vec<2, T> const& v2)
{
return vec<2, T>(v1.x - v2.x,
v1.y - v2.y);
}
template <typename T>
inline constexpr vec<2, T> operator*(vec<2, T> const& v1, vec<2, T> const& v2)
{
return vec<2, T>(v1.x * v2.x,
v1.y * v2.y);
}
template <typename T>
inline constexpr vec<2, T> operator*(vec<2, T> const& v1, T const& scalar)
{
return v1 * vec<2, T>(scalar);
}
template <typename T>
inline constexpr vec<2, T> operator*(T const& scalar, vec<2, T> const& v1)
{
return vec<2, T>(scalar) * v1;
}
template <typename T>
inline constexpr vec<2, T> operator/(vec<2, T> const& v1, vec<2, T> const& v2)
{
return vec<2, T>(v1.x / v2.x,
v1.y / v2.y);
}
template <typename T>
inline constexpr vec<2, T> operator/(vec<2, T> const& v1, T const& scalar)
{
return v1 / vec<2, T>(scalar);
}
template <typename T>
inline constexpr T dot(vec<2, T> const& v1, vec<2, T> const& v2)
{
vec<2, T> tmp(v1 * v2);
return tmp.x + tmp.y;
}
template <typename T>
inline constexpr T cross(vec<2, T> const& v1, vec<2, T> const& v2)
{
return v1.x * v2.y - v2.x * v1.y;
}
template <typename T>
inline constexpr vec<2, T> functor1(T (&func) (T const& x), vec<2, T> const& v)
{
return vec<2, T>(func(v.x), func(v.y));
}
template <typename T, typename U>
inline constexpr vec<2, U> functor1(U (&func) (T const& x), vec<2, T> const& v)
{
return vec<2, U>(func(v.x), func(v.y));
}
template <typename T>
inline constexpr T magnitude(vec<2, T> const& v)
{
return sqrt(dot(v, v));
}

View File

@ -10,10 +10,7 @@
template <typename T>
struct vec<3, T>
{
union {
struct { T x, y, z; };
struct { T r, g, b; };
};
T x, y, z;
inline constexpr vec();
inline constexpr vec(T scalar);
@ -112,12 +109,6 @@ inline constexpr vec<3, T> operator*(vec<3, T> const& v1, T const& scalar)
return v1 * vec<3, T>(scalar);
}
template <typename T>
inline constexpr vec<3, T> operator*(T const& scalar, vec<3, T> const& v1)
{
return vec<3, T>(scalar) * v1;
}
template <typename T>
inline constexpr vec<3, T> operator/(vec<3, T> const& v1, vec<3, T> const& v2)
{
@ -139,14 +130,6 @@ inline constexpr T dot(vec<3, T> const& v1, vec<3, T> const& v2)
return tmp.x + tmp.y + tmp.z;
}
template <typename T>
inline constexpr vec<3, T> cross(vec<3, T> const& v1, vec<3, T> const& v2)
{
return vec<3, T>(v1.y * v2.z - v2.y * v1.z,
v1.z * v2.x - v2.z * v1.x,
v1.x * v2.y - v2.x * v1.y);
}
template <typename T>
inline constexpr vec<3, T> functor1(T (&func) (T const& x), vec<3, T> const& v)
{
@ -160,7 +143,15 @@ inline constexpr vec<3, U> functor1(U (&func) (T const& x), vec<3, T> const& v)
}
template <typename T>
inline constexpr T magnitude(vec<3, T> const& v)
inline constexpr T length(vec<3, T> const& v)
{
return sqrt(dot(v, v));
}
template<typename T>
inline constexpr vec<3, T> cross(vec<3, T> const& x, vec<3, T> const& y)
{
return vec<3, T>(x.y * y.z - y.y * x.z,
x.z * y.x - y.z * x.x,
x.x * y.y - y.x * x.y);
}

Binary file not shown.

View File

@ -1,15 +0,0 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
extern uint32_t _binary_model_bear_bear_data_start __asm("_binary_model_bear_bear_data_start");
extern uint32_t _binary_model_bear_bear_data_end __asm("_binary_model_bear_bear_data_end");
extern uint32_t _binary_model_bear_bear_data_size __asm("_binary_model_bear_bear_data_size");
#ifdef __cplusplus
}
#endif

View File

@ -1,22 +0,0 @@
# Blender 4.3.2 MTL File: 'bear.blend'
# www.blender.org
newmtl matBear
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.800000 0.800000 0.800000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 1
newmtl matOutline
Ns 250.000000
Ka 1.000000 1.000000 1.000000
Kd 0.000000 0.000000 0.000000
Ks 0.000000 0.000000 0.000000
Ke 0.000000 0.000000 0.000000
Ni 1.000000
d 1.000000
illum 1

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +0,0 @@
#pragma once
#include <stdint.h>
#include "model/material.h"
enum material {
bear_matBear,
bear_matOutline,
};
const struct material_descriptor bear_material[] = {
};

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +0,0 @@
#pragma once
#include <stdint.h>
struct pixel_descriptor {
uint8_t * start;
int32_t size;
int32_t vram_offset; // offset into vram texture address space
int16_t width;
int16_t height;
};
struct palette_descriptor {
uint8_t * start;
int32_t size;
int32_t vram_offset; // offset into vram palette address space
int32_t palette_size;
};
struct material_descriptor {
struct pixel_descriptor pixel;
struct palette_descriptor palette;
};

View File

@ -1,59 +0,0 @@
#pragma once
#include <stdint.h>
#include "math/vec3.hpp"
#include "math/vec2.hpp"
#ifdef __dreamcast__
using vertex_position = vec<3, float>;
using vertex_normal = vec<3, float>;
using vertex_texture = vec<2, float>;
#endif
#ifdef __saturn__
#include "math/fp.hpp"
using vertex_position = vec<3, fp16_16>;
using vertex_normal = vec<3, fp16_16>;
using vertex_texture = vec<2, fp16_16>;
#endif
struct index_ptn {
uint16_t position;
uint16_t texture;
uint16_t normal;
};
union triangle {
struct {
struct index_ptn a;
struct index_ptn b;
struct index_ptn c;
};
struct index_ptn v[3];
};
union quadrilateral {
struct {
struct index_ptn a;
struct index_ptn b;
struct index_ptn c;
struct index_ptn d;
};
struct index_ptn v[4];
};
struct object {
const union triangle * triangle;
const union quadrilateral * quadrilateral;
const int triangle_count;
const int quadrilateral_count;
const int material;
};
struct model {
const vertex_position * position;
const vertex_texture * texture;
const vertex_normal * normal;
const struct object ** object;
const int object_count;
};

View File

@ -1,76 +0,0 @@
mov 0,ct0 ; num
mov 0,ct1 ; vdp2 address
mov 0,ct3 ; output
mvi 12345,mc0 ; m0[0] (12345)
;; output: m3
base10_loop:
mov 0,ct0
mvi div10_unsigned,pc
;; [X ] [Y ] [D1 ]
mov mc0,y mov 1,lop ; mvi imm,pc delay slot (executed twice)
;; after function return:
mov all,mc0 ; m0[1] (1234)
mov all,pl ; ??? why can't this happen in the next instruction?
;; mod10: multiply by 10:
sl mov alu,a
sl mov alu,a
sl mov alu,a
add mov alu,a
add mov alu,a mov 0,ct0 ; restore ct0 after 'mov all,mc1'
;; a: 12340
mov mc0,a mov all,pl
;; a: 12345 m0[0]
;; p: 12340
;; mod10: subtract (a - p)
sub mov alu,a
;; a: 5
;; store digit in m3
mov mc0,p clr a mov all,mc3 ; m0[1]
;; p: 1234
;; a: 0
add mov alu,a mov 0,ct0
;; a: 1234
jmp nz,base10_loop
mov all,mc0 ; jmp delay slot
endi
nop
;; argument: ry
;; return: a ← ry / 10
;; maximum ry is somewhere between 2 ^ 21 and 2 ^ 22
div10_unsigned:
;; 1 / 10 * (2 ^ 24) ~= 1677722 = 0x19999a
mvi 1677722,rx
mov mul,p clr a
ad2 mov alu,a
;; ALH: [nmlkjihgfedcba9876543210________]
;; ALL: [76543210________________________]
clr a mov alh,pl ; alh is (a >> 16)
add mov alu,a
;; ALL: [nmlkjihgfedcba9876543210________]
;; rotate left 24 requires fewer cycles than shift right 8
rl8 mov alu,a
rl8 mov alu,a
rl8 mov alu,a
;; ALL: [________nmlkjihgfedcba9876543210]
;; mask 24 bit result
mvi 0xffffff,pl
;; return to caller ; reset ct0
btm
and mov alu,a mov 0,ct0

View File

@ -1,35 +0,0 @@
#include "cdc/serial.h"
#include "scu.h"
#include "vdp2.h"
#include "scu-dsp/div10.dsp.h"
void main()
{
scu.reg.PPAF = 0; // stop execution
scu.reg.PPAF = (1 << 15) | 0; // reset PC
uint32_t * program = (uint32_t *)&_binary_scu_dsp_div10_dsp_start;
int program_length = ((int)&_binary_scu_dsp_div10_dsp_size) / 4;
for (int i = 0; i < program_length; i++) {
uint32_t p = program[i];
scu.reg.PPD = p;
serial_integer(p, 8, '\n');
}
scu.reg.PPAF = (1 << 16); // execute
int end_flag = 0;
while (end_flag == 0) {
end_flag = (scu.reg.PPAF >> 18) & 1;
}
scu.reg.PPAF = 0;
scu.reg.PDA = 64 * 3; // m3[0]
serial_string("answer:\n");
for (int i = 0; i < 8; i++) {
serial_integer(scu.reg.PDD, 8, '\n');
}
}

View File

@ -1,5 +0,0 @@
#pragma once
#include <stdint.h>
extern uint32_t _binary_scu_dsp_div10_dsp_start __asm("_binary_scu_dsp_div10_dsp_start");
extern uint32_t _binary_scu_dsp_div10_dsp_end __asm("_binary_scu_dsp_div10_dsp_end");
extern uint32_t _binary_scu_dsp_div10_dsp_size __asm("_binary_scu_dsp_div10_dsp_size");

View File

@ -1,104 +0,0 @@
mov 0,ct0 ; num
mov 0,ct1 ; vdp2 address
mov 0,ct3 ; output
mvi 12345,mc0 ; m0[0] (12345)
;; clear m3
mov 7,lop
lps
mov 0,mc3
mov 0,ct3
;; output: m3
base10_loop:
mov 0,ct0
mvi div10_unsigned,pc
;; [X ] [Y ] [D1 ]
mov mc0,y mov 1,lop ; mvi imm,pc delay slot (executed twice)
;; after function return:
mov all,mc0 ; m0[1] (1234)
mov all,pl ; ??? why can't this happen in the next instruction?
;; mod10: multiply by 10:
sl mov alu,a
sl mov alu,a
sl mov alu,a
add mov alu,a
add mov alu,a mov 0,ct0 ; restore ct0 after 'mov all,mc1'
;; a: 12340
mov mc0,a mov all,pl
;; a: 12345 m0[0]
;; p: 12340
;; mod10: subtract (a - p)
sub mov alu,a
;; a: 5
;; convert to vdp2 character
mvi 16,pl
add mov alu,a
;; store digit in m3
mov mc0,p clr a mov all,mc3 ; m0[1]
;; p: 1234
;; a: 0
add mov alu,a mov 0,ct0
;; a: 1234
jmp nz,base10_loop
mov all,mc0 ; jmp delay slot
;;
;; transfer to vdp2
;;
;; vdp2 address calculation
mvi ((8 * 0x4000 + (64 - 8) * 4 + 0x05e00000) >> 2),wa0
mov 0,ct3
;; clr a mov 0,ct3
;; add mov alu,a
;; mov all,wa0
;; end vdp2 address calculation
dma1 mc3,d0,8
dma_wait:
jmp t0,dma_wait
nop
endi
nop
;; argument: ry
;; return: a ← ry / 10
;; maximum ry is somewhere between 2 ^ 21 and 2 ^ 22
div10_unsigned:
;; 1 / 10 * (2 ^ 24) ~= 1677722 = 0x19999a
mvi 1677722,rx
mov mul,p clr a
ad2 mov alu,a
;; ALH: [nmlkjihgfedcba9876543210________]
;; ALL: [76543210________________________]
clr a mov alh,pl ; alh is (a >> 16)
add mov alu,a
;; ALL: [nmlkjihgfedcba9876543210________]
;; rotate left 24 requires fewer cycles than shift right 8
rl8 mov alu,a
rl8 mov alu,a
rl8 mov alu,a
;; ALL: [________nmlkjihgfedcba9876543210]
;; mask 24 bit result
mvi 0xffffff,pl
;; return to caller ; reset ct0
btm
and mov alu,a mov 0,ct0

View File

@ -1,171 +0,0 @@
#include "cdc/serial.h"
#include "scu.h"
#include "vdp2.h"
#include "../common/vdp2_func.hpp"
#include "scu-dsp/div10_vdp2.dsp.h"
#include "font/hp_100lx_4bit_flip.data.h"
void cell_data()
{
const uint32_t * start = reinterpret_cast<uint32_t *>(&_binary_font_hp_100lx_4bit_flip_data_start);
const int size = reinterpret_cast<uint32_t>(&_binary_font_hp_100lx_4bit_flip_data_size);
// the start of VRAM-A0
for (int i = 0; i < (size / 4); i++) {
vdp2.vram.u32[i] = start[i];
}
}
void palette_data()
{
vdp2.cram.u16[0] = 0x0000;
vdp2.cram.u16[1] = 0xffff;
}
void vdp2_init()
{
v_blank_in();
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
/* set the color mode to 5bits per channel, 1024 colors */
vdp2.reg.RAMCTL = RAMCTL__CRMD__RGB_5BIT_1024
| RAMCTL__VRAMD
| RAMCTL__VRBMD
| RAMCTL__RDBSA0__CHARACTER_PATTERN_TABLE // VRAM-A0 0x000000
| RAMCTL__RDBSA1__PATTERN_NAME_TABLE; // VRAM-A1 0x020000
vdp2.reg.VRSIZE = 0;
/* enable display of NBG0 */
vdp2.reg.BGON = BGON__R0ON | BGON__R0TPON;
/* set character format for NBG0 to palettized 16 color
set enable "cell format" for NBG0
set character size for NBG0 to 1x1 cell */
vdp2.reg.CHCTLB = CHCTLB__R0CHCN__16_COLOR
| CHCTLB__R0BMEN__CELL_FORMAT
| CHCTLB__R0CHSZ__1x1_CELL;
/* plane size */
vdp2.reg.PLSZ = PLSZ__RAPLSZ__1x1
| PLSZ__RBPLSZ__1x1;
/* map plane offset
1-word: value of bit 6-0 * 0x2000
2-word: value of bit 5-0 * 0x4000
*/
// plane_a_offset is at the start of VRAM-A1
constexpr int plane_a = 8;
constexpr int plane_a_offset = plane_a * 0x4000;
constexpr int page_size = 64 * 64 * 2; // N0PNB__1WORD (16-bit)
constexpr int plane_size = page_size * 1;
/* cycle pattern table not used for RBG0 ? */
vdp2.reg.CYCA0 = 0x0F44F99F;
vdp2.reg.CYCA1 = 0x0F44F99F;
vdp2.reg.CYCB0 = 0x0F44F99F;
vdp2.reg.CYCB1 = 0x0F44F99F;
vdp2.reg.MPOFR = MPOFR__RAMP(0); // bits 8~6
vdp2.reg.MPABRA = MPABRA__RAMPB(plane_a) | MPABRA__RAMPA(plane_a); // bits 5~0
vdp2.reg.MPCDRA = MPCDRA__RAMPD(plane_a) | MPCDRA__RAMPC(plane_a); // bits 5~0
vdp2.reg.MPEFRA = MPEFRA__RAMPF(plane_a) | MPEFRA__RAMPE(plane_a); // bits 5~0
vdp2.reg.MPGHRA = MPGHRA__RAMPH(plane_a) | MPGHRA__RAMPG(plane_a); // bits 5~0
vdp2.reg.MPIJRA = MPIJRA__RAMPJ(plane_a) | MPIJRA__RAMPI(plane_a); // bits 5~0
vdp2.reg.MPKLRA = MPKLRA__RAMPL(plane_a) | MPKLRA__RAMPK(plane_a); // bits 5~0
vdp2.reg.MPMNRA = MPMNRA__RAMPN(plane_a) | MPMNRA__RAMPM(plane_a); // bits 5~0
vdp2.reg.MPOPRA = MPOPRA__RAMPP(plane_a) | MPOPRA__RAMPO(plane_a); // bits 5~0
vdp2.reg.PNCR = PNCR__R0PNB__2WORD;
vdp2.reg.RPMD = RPMD__ROTATION_PARAMETER_A;
//vdp2.reg.RPRCTL = 0;
vdp2.reg.KTCTL = 0;
vdp2.reg.KTAOF = 0;
vdp2.reg.PRIR = 3;
palette_data();
cell_data();
volatile struct vdp2_rotation_parameter_table * table = (struct vdp2_rotation_parameter_table *)&vdp2.vram.u32[0x4000 / 4];
table->screen_start_coordinate_xst = 0;
table->screen_start_coordinate_yst = 0;
table->screen_start_coordinate_zst = 0;
table->screen_vertical_coordinate_increment_dxst = 0;
table->screen_vertical_coordinate_increment_dyst = (1 << 16);
table->screen_horizontal_coordinate_increment_dx = (1 << 16);
table->screen_horizontal_coordinate_increment_dy = 0;
table->rotation_matrix_parameter_a = (-1 << 16);
table->rotation_matrix_parameter_b = 0;
table->rotation_matrix_parameter_c = 0;
table->rotation_matrix_parameter_d = 0;
table->rotation_matrix_parameter_e = (1 << 16);
table->rotation_matrix_parameter_f = 0;
table->viewpoint_coordinate_px = 0;
table->viewpoint_coordinate_py = 0;
table->viewpoint_coordinate_pz = 0;
table->center_point_coordinate_px = 0;
table->center_point_coordinate_py = 0;
table->center_point_coordinate_pz = 0;
table->horizontal_shift_mx = 0;
table->horizontal_shift_my = 0;
table->scaling_coefficient_kx = (1 << 16);
table->scaling_coefficient_ky = (1 << 16);
vdp2.reg.RPTA = (((uint32_t)table) >> 1) & 0x7ffff;
/* */
for (int i = 0; i < 64 * 64; i++) {
vdp2.vram.u32[(plane_a_offset / 4) + i] = ' ' - 0x20;
}
}
void main()
{
vdp2_init();
scu.reg.PPAF = 0; // stop execution
scu.reg.PPAF = (1 << 15) | 0; // reset PC
uint32_t * program = (uint32_t *)&_binary_scu_dsp_div10_vdp2_dsp_start;
int program_length = ((int)&_binary_scu_dsp_div10_vdp2_dsp_size) / 4;
for (int i = 0; i < program_length; i++) {
uint32_t p = program[i];
scu.reg.PPD = p;
//serial_integer(p, 8, '\n');
}
scu.reg.PPAF = (1 << 16); // execute
int end_flag = 0;
while (end_flag == 0) {
end_flag = (scu.reg.PPAF >> 18) & 1;
}
scu.reg.PPAF = 0;
scu.reg.PDA = 64 * 3; // m3[0]
serial_string("answer:\n");
for (int i = 0; i < 8; i++) {
serial_integer(scu.reg.PDD, 8, '\n');
}
serial_string("answer2:\n");
volatile uint32_t * buf = &vdp2.vram.u32[(8 * 0x4000) / 4 + 64];
for (int i = 0; i < 8; i++) {
uint32_t addr = (uint32_t)&buf[-(i + 1)];
serial_integer(addr, 8, ' ');
serial_integer(buf[-(i + 1)], 8, '\n');
}
}

View File

@ -1,5 +0,0 @@
#pragma once
#include <stdint.h>
extern uint32_t _binary_scu_dsp_div10_vdp2_dsp_start __asm("_binary_scu_dsp_div10_vdp2_dsp_start");
extern uint32_t _binary_scu_dsp_div10_vdp2_dsp_end __asm("_binary_scu_dsp_div10_vdp2_dsp_end");
extern uint32_t _binary_scu_dsp_div10_vdp2_dsp_size __asm("_binary_scu_dsp_div10_vdp2_dsp_size");

View File

@ -1,93 +0,0 @@
;; input m0[0] start address
;; [X ] [Y ] [D1 ]
;; mov 0,ct0
;; mov mc0,ra0
;; variables:
;; m0[0]
;; m0[1] dma read value (local); post-shift 4-byte remainder (global)
;; m0[2] saved accumulator (global)
setup:
;; [X ] [Y ] [D1 ]
mov 1,ct0
mov 0,ct3
mov 0,mc0
mov 0,mc0
mvi parse_base10,pc
mov 1,lop
;; parse_base10 return
mov all,mc3
mvi parse_base10,pc
mov 1,lop
;; parse_base10 return
mov all,mc3
nop
nop
nop
parse_base10:
;; [X ] [Y ] [D1 ]
mov 1,ct0
mov m0,p mov m0,a
add
jmp nz,parse_loop
clr a ; delay slot
dma_next_chunk:
;; dma d0,mc0,1
;; begin fake number 0x39322033 "92 3"
mvi 0x393220,pl
add mov alu,a mov 0x33,pl
rl8 mov alu,a mov 1,ct0
add mov all,mc0
;; end fake number
end_dma_next_chunk:
parse_loop:
;; extract first (leftmost) digit
mov 1,ct0
mov mc0,a mov 0x7f,pl
or
jmp s,end_of_input
rl8 mov alu,a mov 10,rx ; m0[2] 0x00000000
jmp z,dma_next_chunk
and mov m0,y mov all,pl
;; MUL: post-multiplication accumulator
;; P: post-mask digit
;; A: pre-xor string
mov 1,ct0
xor clr a mov all,mc0 ; m0[1] 0x20323300
add mov alu,a mov 0x30,pl ; 0x30 ascii '0'
;; A: post-mask digit
;;
sub mov alu,a mov 10,pl
;; if ((0x39 - 0x30) < 0) goto non_digit;
jmp s,non_digit
;; possibly set S flag for `jmp ns,non_digit`
sub mov 2,ct0 ; sub in delay slot
;; if (((0x39 - 0x30) - 10) >= 0) goto non_digit;
jmp ns,non_digit
mov mul,p mov 2,ct0 ; mov in delay slot
;; P: accumulator * 10 result
digit:
;; we have a valid digit; add it to the accumulator; save to m0[2]
;; [X ] [Y ] [D1 ]
jmp parse_loop
add mov all,mc0 ; add in delay slot ; m0[2] 0x00000009
non_digit:
;; this is not a valid digit; return and clear the accumulator as A
;; [X ] [Y ] [D1 ]
btm
mov m0,a mov 0,mc0 ; clr in delay slot ; m0[2]
;; m0:
;; 00000000 32330000 00000009 0000000
end_of_input:
btm
clr a

View File

@ -1,164 +0,0 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <ft2build.h>
#include FT_FREETYPE_H
int
load_bitmap_char(FT_Face face,
FT_ULong char_code,
bool hflip,
uint8_t * buf)
{
FT_Error error;
FT_UInt glyph_index = FT_Get_Char_Index(face, char_code);
error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
if (error) {
fprintf(stderr, "FT_Load_Glyph %s\n", FT_Error_String(error));
return -1;
}
printf("horiBearingX: %ld\n", face->glyph->metrics.horiBearingX >> 6);
printf("horiBearingY: %ld\n", face->glyph->metrics.horiBearingY >> 6);
printf("horiAdvance: %ld\n", face->glyph->metrics.horiAdvance >> 6);
printf("width: %ld\n", face->glyph->metrics.width >> 6);
printf("height: %ld\n", face->glyph->metrics.height >> 6);
assert(face->glyph->format == FT_GLYPH_FORMAT_BITMAP);
assert(face->glyph->bitmap.num_grays == 2);
for (int y = 0; y < (int)face->glyph->bitmap.rows; y++) {
uint8_t * row = &face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch];
for (int x = 0; x < (int)face->glyph->bitmap.width; x += 1) {
const int bit = (row[x / 8] >> (7 - (x % 8))) & 1;
//std::cerr << (bit ? "█" : " ");
if (hflip)
buf[y * face->glyph->bitmap.width + (7 - x)] = bit;
else
buf[y * face->glyph->bitmap.width + x] = bit;
}
//std::cerr << "|\n";
}
return face->glyph->bitmap.rows * face->glyph->bitmap.width;
}
int load_font(FT_Library * library, FT_Face * face, const char * font_file_path)
{
FT_Error error;
error = FT_Init_FreeType(library);
if (error) {
fprintf(stderr, "FT_Init_FreeType\n");
return -1;
}
error = FT_New_Face(*library, font_file_path, 0, face);
if (error) {
fprintf(stderr, "FT_New_Face\n");
return -1;
}
error = FT_Select_Size(*face, 0);
if (error) {
fprintf(stderr, "FT_Select_Size: %d: %s\n", error, FT_Error_String(error));
return -1;
}
return 0;
}
void usage(const char * argv_0)
{
printf("%s [start-hex] [end-hex] [font-width] [font-height] [hflip] [font-file-path] [output-file-path]\n", argv_0);
}
void pack_4bit(const uint8_t * src, int width, int height, int size, uint8_t * dst)
{
int offset = 0;
while (offset < size) {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x += 2) {
int px0 = src[offset + y * width + x + 0];
int px1 = src[offset + y * width + x + 1];
dst[(offset / 2) + y * (width / 2) + (x / 2)] = (px0 << 4) | (px1 << 0);
}
}
offset += width * height;
}
}
int main(int argc, const char * argv[])
{
if (argc != 8) {
usage(argv[0]);
return -1;
}
char * endptr;
int start_hex = strtol(argv[1], &endptr, 16);
assert(*endptr == 0);
int end_hex = strtol(argv[2], &endptr, 16);
assert(*endptr == 0);
int font_width = strtol(argv[3], &endptr, 10);
assert(*endptr == 0);
int font_height = strtol(argv[4], &endptr, 10);
assert(*endptr == 0);
int hflip = strtol(argv[5], &endptr, 10);
assert(*endptr == 0);
assert(hflip == 0 || hflip == 1);
const char * font_file_path = argv[6];
const char * output_file_path = argv[7];
printf("start_hex %x\n", start_hex);
printf("end_hex %x\n", start_hex);
printf("font_width %d\n", font_width);
printf("font_height %d\n", font_height);
printf("font_file_path %s\n", font_file_path);
printf("output_file_path %s\n", output_file_path);
FT_Library library;
FT_Face face;
int res;
res = load_font(&library, &face, font_file_path);
if (res < 0)
return -1;
int texture_buf_size = font_width * font_height * ((end_hex - start_hex) + 1);
uint8_t * texture = (uint8_t *)malloc(texture_buf_size);
int offset = 0;
for (int char_code = start_hex; char_code <= end_hex; char_code++) {
assert(offset < texture_buf_size);
res = load_bitmap_char(face,
char_code,
hflip,
&texture[offset]);
if (res < 0)
return - 1;
assert(res == font_width * font_height);
offset += res;
}
uint8_t * pack = (uint8_t *)malloc(texture_buf_size / 2);
pack_4bit(texture, font_width, font_height, offset, pack);
FILE * out = fopen(output_file_path, "w");
if (out == NULL) {
perror("fopen(w)");
return -1;
}
//fwrite((void *)texture, texture_buf_size, 1, out);
fwrite((void *)pack, texture_buf_size / 2, 1, out);
fclose(out);
}

View File

@ -1,243 +0,0 @@
#include <stdint.h>
#include "vdp2.h"
#include "vdp1.h"
#include <concepts>
#include "common/vdp2_func.hpp"
#include "math/fp.hpp"
#include "math/vec3.hpp"
#include "math/mat4x4.hpp"
#include "cos.hpp"
#include "model/model.h"
#include "model/bear/material.h"
#include "model/bear/model.h"
// |--
// |
// |
using vec3 = vec<3, fp16_16>;
using mat4x4 = mat<4, 4, fp16_16>;
struct canvas {
fp16_16 width;
fp16_16 height;
};
constexpr struct canvas canvas = { 240, 240 };
template <typename T>
vec<3, T> viewport_to_canvas(T x, T y)
{
return vec<3, T>(x * canvas.width, y * canvas.height, T(1));
}
template <typename T>
inline constexpr vec<3, T> project_vertex(vec<3, T> const& v)
{
// / (v.z - T(5))
// / (v.z - T(5))
return viewport_to_canvas<T>((v.x * T(0.5) + T(2.0/3.0)),
(v.y * T(0.5) + T(0.5)));
}
constexpr inline uint16_t rgb15(int32_t r, int32_t g, int32_t b)
{
return ((b & 31) << 10) | ((g & 31) << 5) | ((r & 31) << 0);
}
constexpr uint16_t colors[] = {
rgb15(31, 0, 0), // red
rgb15( 0, 31, 0), // green
rgb15( 0, 0, 31), // blue
rgb15(31, 0, 31), // magenta
rgb15( 0, 31, 31), // cyan
rgb15(31, 31, 0), // yellow
};
static int32_t tick = 0;
static inline void render_quad(int ix, const vec3 a, const vec3 b, const vec3 c, const vec3 d)
{
vdp1.vram.cmd[ix].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__POLYGON;
vdp1.vram.cmd[ix].LINK = 0;
vdp1.vram.cmd[ix].PMOD = PMOD__ECD | PMOD__SPD;
vdp1.vram.cmd[ix].COLR = COLR__RGB | colors[ix & 3];
vdp1.vram.cmd[ix].A.X = static_cast<int>(a.x);
vdp1.vram.cmd[ix].A.Y = static_cast<int>(a.y);
vdp1.vram.cmd[ix].B.X = static_cast<int>(b.x);
vdp1.vram.cmd[ix].B.Y = static_cast<int>(b.y);
vdp1.vram.cmd[ix].C.X = static_cast<int>(c.x);
vdp1.vram.cmd[ix].C.Y = static_cast<int>(c.y);
vdp1.vram.cmd[ix].D.X = static_cast<int>(d.x);
vdp1.vram.cmd[ix].D.Y = static_cast<int>(d.y);
}
int render_object(int ix,
const mat4x4& screen,
const struct model * model,
const struct object * object0)
{
mat4x4 trans = screen;
for (int i = 0; i < object0->quadrilateral_count; i++) {
const union quadrilateral * quad0 = &object0->quadrilateral[i];
vec3 a0 = model->position[quad0->v[0].position];
vec3 b0 = model->position[quad0->v[1].position];
vec3 c0 = model->position[quad0->v[2].position];
vec3 d0 = model->position[quad0->v[3].position];
vec3 a = trans * a0;
vec3 b = trans * b0;
vec3 c = trans * c0;
vec3 d = trans * d0;
vec3 an0 = trans * model->normal[quad0->v[0].normal];
//vec3 l = {0, 0, 1};
fp16_16 cull = dot(a, an0);
if (cull.value > 0) {
// `origin` above is p==0 below; the `origin` calculation could
// be reused, though it would hurt readability slightly
/*
for (int p = 0; p < 4; p++) {
const vec3& v0 = vertices[face[p]];
// rotation
const vec3 v1 = transform * v0;
// translation
const vec3 v2{v1.x, v1.y + fp16_16(1), v1.z + fp16_16(2)};
const vec3 v3 = project_vertex(v2 / v2.z);
}
*/
render_quad(ix,
project_vertex(a / a.z),
project_vertex(b / b.z),
project_vertex(c / c.z),
project_vertex(d / d.z));
ix++;
}
}
return ix;
}
void render()
{
tick++;
int ix = 2;
const mat4x4 scale {
1, 0, 0, 0,
0, -1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
};
const int rx = tick >> 2;
const mat4x4 rotationX {
1, 0, 0, 0,
0, cos(rx), sin(rx), 0,
0, -sin(rx), cos(rx), 0,
0, 0, 0, 1,
};
const int ry = tick >> 1;
const mat4x4 rotationY {
cos(ry), 0, -sin(ry), 0,
0, 1, 0, 0,
sin(ry), 0, cos(ry), 0,
0, 0, 0, 1,
};
const mat4x4 translation = {
1, 0, 0, 0,
0, 1, 0, 4.5,
0, 0, 1, 6.5,
0, 0, 0, 1,
};
const mat4x4 screen = translation * rotationY * scale;
//const vec3 camera = {0, 0, 0};
const int frame_ix0 = 0;
const struct model * model = &bear_model;
const struct object * object0 = bear_object[frame_ix0 * 2];
//const struct object * object1 = bear_object[frame_ix1 * 2];
ix = render_object(ix, screen, model, object0);
vdp1.vram.cmd[ix].CTRL = CTRL__END;
}
void main()
{
v_blank_in();
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
// disable all VDP2 backgrounds (e.g: the Sega bios logo)
vdp2.reg.BGON = 0;
// VDP2 User's Manual:
// "When sprite data is in an RGB format, sprite register 0 is selected"
// "When the value of a priority number is 0h, it is read as transparent"
//
// The power-on value of PRISA is zero. Set the priority for sprite register 0
// to some number greater than zero, so that the color data is not interpreted
// as "transparent".
vdp2.reg.PRISA = PRISA__S0PRIN(1); // Sprite register 0 Priority Number
/* TVM settings must be performed from the second H-blank IN interrupt after the
V-blank IN interrupt to the H-blank IN interrupt immediately after the V-blank
OUT interrupt. */
// "normal" display resolution, 16 bits per pixel, 512x256 framebuffer
vdp1.reg.TVMR = TVMR__TVM__NORMAL;
// swap framebuffers every 1 cycle; non-interlace
vdp1.reg.FBCR = 0;
// during a framebuffer erase cycle, write the color "black" to each pixel
constexpr uint16_t black = 0x0000;
vdp1.reg.EWDR = black;
// the EWLR/EWRR macros use somewhat nontrivial math for the X coordinates
// erase upper-left coordinate
vdp1.reg.EWLR = EWLR__16BPP_X1(0) | EWLR__Y1(0);
// erase lower-right coordinate
vdp1.reg.EWRR = EWRR__16BPP_X3(319) | EWRR__Y3(239);
vdp1.vram.cmd[0].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__SYSTEM_CLIP_COORDINATES;
vdp1.vram.cmd[0].LINK = 0;
vdp1.vram.cmd[0].XC = 319;
vdp1.vram.cmd[0].YC = 239;
vdp1.vram.cmd[1].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__LOCAL_COORDINATE;
vdp1.vram.cmd[1].LINK = 0;
vdp1.vram.cmd[1].XA = 0;
vdp1.vram.cmd[1].YA = 0;
vdp1.vram.cmd[2].CTRL = CTRL__END;
// start drawing (execute the command list) on every frame
vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE;
while (true) {
v_blank_in();
render();
}
}

View File

@ -1,189 +0,0 @@
/*
color data
255 colors, 3 bytes per channel, packed
*/
/*
image data
64*64 px, 1 byte per palette index
*/
#include <stdint.h>
#include "vdp2.h"
#include "../common/vdp2_func.hpp"
inline constexpr uint16_t rgb555(int r, int g, int b)
{
if (r > 255) r = 255;
if (g > 255) g = 255;
if (b > 255) b = 255;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
return ((b >> 3) << 10) // blue
| ((g >> 3) << 5) // green
| ((r >> 3) << 0); // red
}
template <typename T>
void fill(T * buf, T v, int32_t n) noexcept
{
while (n > 0) {
*buf++ = v;
n -= (sizeof (T));
}
}
struct color {
uint8_t r;
uint8_t g;
uint8_t b;
};
struct interp {
int line;
struct color color;
};
struct interp gradient[] = {
{ 0, {0x59, 0x6b, 0x88}},
{ 40, {0x59, 0x6b, 0x88}},
{ 80, {0xa8, 0x34, 0x14}},
{110, {0xac, 0xa5, 0x30}},
{120, {0xac, 0xa5, 0x30}},
{140, {0xa8, 0x34, 0x14}},
{999, {0xa8, 0x34, 0x14}},
};
const int gradient_len = (sizeof (gradient)) / (sizeof (gradient[0]));
struct color lerp(struct color a, struct color b, int start, int end, int y)
{
if (start == end) {
return (struct color){a.r, a.g, a.b};
}
if (end == 999) {
return (struct color){a.r, a.g, a.b};
}
int dr = ((int)b.r - (int)a.r);
int dg = ((int)b.g - (int)a.g);
int db = ((int)b.b - (int)a.b);
int t1 = end - start;
int t0 = y - start;
return (struct color){
(uint8_t)((int)a.r + dr * t0 / t1),
(uint8_t)((int)a.g + dg * t0 / t1),
(uint8_t)((int)a.b + db * t0 / t1),
};
}
void gen_gradient()
{
struct interp * prev = &gradient[0];
struct interp * cur = prev;
int i = 0;
for (int y = 0; y < 240; y++) {
if (y >= cur->line) {
prev = cur;
i += 1;
cur = &gradient[i];
}
struct color c = lerp(prev->color, cur->color, prev->line, cur->line, y);
vdp2.vram.u16[y] = rgb555(c.r, c.g, c.b);
//vdp2.vram.u16[y] = rgb555(cur->color.r, cur->color.g, cur->color.b);
}
}
void main()
{
v_blank_in();
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
/* set the color mode to 5bits per channel, 1024 colors */
vdp2.reg.RAMCTL = RAMCTL__CRMD__RGB_5BIT_1024;
/* enable display of NBG0 */
//vdp2.reg.BGON = BGON__N0ON;
/* set character format for NBG0 to palettized 2048 color
set enable "cell format" for NBG0
set character size for NBG0 to 1x1 cell */
vdp2.reg.CHCTLA = CHCTLA__N0CHCN__2048_COLOR
| CHCTLA__N0BMEN__CELL_FORMAT
| CHCTLA__N0CHSZ__1x1_CELL;
/* "Note: In color RAM modes 0 and 2, 2048-color becomes 1024-color" */
/* use 1-word (16-bit) pattern names */
vdp2.reg.PNCN0 = PNCN0__N0PNB__1WORD;
/* plane size */
vdp2.reg.PLSZ = PLSZ__N0PLSZ__1x1;
/* map plane offset
1-word: value of bit 6-0 * 0x2000
2-word: value of bit 5-0 * 0x4000
*/
constexpr int plane_a = 2;
constexpr int plane_a_offset = plane_a * 0x2000;
constexpr int page_size = 64 * 64 * 2; // N0PNB__1WORD (16-bit)
constexpr int plane_size = page_size * 1;
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
vdp2.reg.MPABN0 = MPABN0__N0MPB(plane_a) | MPABN0__N0MPA(plane_a); // bits 5~0
vdp2.reg.MPCDN0 = MPCDN0__N0MPD(plane_a) | MPCDN0__N0MPC(plane_a); // bits 5~0
constexpr int cell_size = (8 * 8) * 2; // N0CHCN__2048_COLOR (16-bit)
constexpr int character_size = cell_size * (1 * 1); // N0CHSZ__1x1_CELL
constexpr int character_offset = character_size / 0x20;
// zeroize character/cell data from 0 up to plane_a_offset
fill<uint32_t>(&vdp2.vram.u32[(0 / 2)], 0, plane_a_offset);
// "zeroize" plane_a to the 0x40th (64th) character index (an unused/transparent character)
// this creates the '40' indexes in the below picture
fill<uint16_t>(&vdp2.vram.u16[(plane_a_offset / 2)], character_offset * 0x40, plane_size);
constexpr int pixel_width = 64;
constexpr int pixel_height = 64;
constexpr int cell_horizontal = pixel_width / 8;
constexpr int cell_vertical = pixel_height / 8;
constexpr int page_width = 64;
/*
set plane_a character index data to this (hex):
|
00 01 02 03 04 05 06 07 40 40 ..
08 09 0a 0b 0c 0d 0e 0f 40 40 ..
10 11 12 13 14 15 16 17 40 40 ..
18 19 1a 1b 1c 1d 1e 1f 40 40 ..
20 21 22 23 24 25 26 27 40 40 ..
28 29 2a 2b 2c 2d 2e 2f 40 40 ..
30 31 32 33 34 35 36 37 40 40 ..
-- 38 39 3a 3b 3c 3d 3e 3f 40 40 ..
40 40 40 40 40 40 40 40 40 40 ..
40 40 40 40 40 40 40 40 40 40 ..
.. .. .. .. .. .. .. .. .. .. ..
(the above numbers are not pre-multiplied by character_offset)
*/
vdp2.reg.BKTA = BKTA__BKCLMD_PER_LINE;
gen_gradient();
}

View File

@ -1,86 +0,0 @@
#include <stdint.h>
#include "vdp2.h"
#include "../common/vdp2_func.hpp"
#include "font/hp_100lx_4bit.data.h"
void cell_data()
{
const uint32_t * start = reinterpret_cast<uint32_t *>(&_binary_font_hp_100lx_4bit_data_start);
const int size = reinterpret_cast<uint32_t>(&_binary_font_hp_100lx_4bit_data_size);
for (int i = 0; i < (size / 4); i++) {
vdp2.vram.u32[i] = start[i];
}
}
void palette_data()
{
vdp2.cram.u16[0] = 0x0000;
vdp2.cram.u16[1] = 0xffff;
}
void main()
{
v_blank_in();
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
/* set the color mode to 5bits per channel, 1024 colors */
vdp2.reg.RAMCTL = RAMCTL__CRMD__RGB_5BIT_1024
| RAMCTL__VRAMD | RAMCTL__VRBMD;
vdp2.reg.VRSIZE = 0;
/* enable display of NBG0 */
vdp2.reg.BGON = BGON__N0ON | BGON__N0TPON;
/* set character format for NBG0 to palettized 16 color
set enable "cell format" for NBG0
set character size for NBG0 to 1x1 cell */
vdp2.reg.CHCTLA = CHCTLA__N0CHCN__16_COLOR
| CHCTLA__N0BMEN__CELL_FORMAT
| CHCTLA__N0CHSZ__1x1_CELL;
/* plane size */
vdp2.reg.PLSZ = PLSZ__N0PLSZ__1x1;
/* map plane offset
1-word: value of bit 6-0 * 0x2000
2-word: value of bit 5-0 * 0x4000
*/
constexpr int plane_a = 1;
constexpr int plane_a_offset = plane_a * 0x4000;
constexpr int page_size = 64 * 64 * 2; // N0PNB__1WORD (16-bit)
constexpr int plane_size = page_size * 1;
vdp2.reg.CYCA0 = 0x0F44F99F;
vdp2.reg.CYCA1 = 0x0F44F99F;
vdp2.reg.CYCB0 = 0x0F44F99F;
vdp2.reg.CYCB1 = 0x0F44F99F;
vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6
vdp2.reg.MPABN0 = MPABN0__N0MPB(plane_a) | MPABN0__N0MPA(plane_a); // bits 5~0
vdp2.reg.MPCDN0 = MPCDN0__N0MPD(plane_a) | MPCDN0__N0MPC(plane_a); // bits 5~0
palette_data();
cell_data();
vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD;
for (int i = 0; i < 64 * 64; i++) {
vdp2.vram.u32[(plane_a_offset / 4) + i] = ' ' - 0x20;
}
const char * test = "conversion from 8";
int ix = 0;
while (*test) {
uint8_t c = *test++;
vdp2.vram.u32[(plane_a_offset / 4) + ix++] = c - 0x20;
}
while (1);
}

View File

@ -1,139 +0,0 @@
#include <stdint.h>
#include "vdp2.h"
#include "../common/vdp2_func.hpp"
#include "font/hp_100lx_4bit.data.h"
void cell_data()
{
const uint32_t * start = reinterpret_cast<uint32_t *>(&_binary_font_hp_100lx_4bit_data_start);
const int size = reinterpret_cast<uint32_t>(&_binary_font_hp_100lx_4bit_data_size);
// the start of VRAM-A0
for (int i = 0; i < (size / 4); i++) {
vdp2.vram.u32[i] = start[i];
}
}
void palette_data()
{
vdp2.cram.u16[0] = 0x0000;
vdp2.cram.u16[1] = 0xffff;
}
void main()
{
v_blank_in();
// DISP: Please make sure to change this bit from 0 to 1 during V blank.
vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE
| TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320);
/* set the color mode to 5bits per channel, 1024 colors */
vdp2.reg.RAMCTL = RAMCTL__CRMD__RGB_5BIT_1024
| RAMCTL__VRAMD
| RAMCTL__VRBMD
| RAMCTL__RDBSA0__CHARACTER_PATTERN_TABLE // VRAM-A0 0x000000
| RAMCTL__RDBSA1__PATTERN_NAME_TABLE; // VRAM-A1 0x020000
vdp2.reg.VRSIZE = 0;
/* enable display of NBG0 */
vdp2.reg.BGON = BGON__R0ON | BGON__R0TPON;
/* set character format for NBG0 to palettized 16 color
set enable "cell format" for NBG0
set character size for NBG0 to 1x1 cell */
vdp2.reg.CHCTLB = CHCTLB__R0CHCN__16_COLOR
| CHCTLB__R0BMEN__CELL_FORMAT
| CHCTLB__R0CHSZ__1x1_CELL;
/* plane size */
vdp2.reg.PLSZ = PLSZ__RAPLSZ__1x1
| PLSZ__RBPLSZ__1x1;
/* map plane offset
1-word: value of bit 6-0 * 0x2000
2-word: value of bit 5-0 * 0x4000
*/
// plane_a_offset is at the start of VRAM-A1
constexpr int plane_a = 8;
constexpr int plane_a_offset = plane_a * 0x4000;
constexpr int page_size = 64 * 64 * 2; // N0PNB__1WORD (16-bit)
constexpr int plane_size = page_size * 1;
/* cycle pattern table not used for RBG0 ? */
vdp2.reg.CYCA0 = 0x0F44F99F;
vdp2.reg.CYCA1 = 0x0F44F99F;
vdp2.reg.CYCB0 = 0x0F44F99F;
vdp2.reg.CYCB1 = 0x0F44F99F;
vdp2.reg.MPOFR = MPOFR__RAMP(0); // bits 8~6
vdp2.reg.MPABRA = MPABRA__RAMPB(plane_a) | MPABRA__RAMPA(plane_a); // bits 5~0
vdp2.reg.MPCDRA = MPCDRA__RAMPD(plane_a) | MPCDRA__RAMPC(plane_a); // bits 5~0
vdp2.reg.MPEFRA = MPEFRA__RAMPF(plane_a) | MPEFRA__RAMPE(plane_a); // bits 5~0
vdp2.reg.MPGHRA = MPGHRA__RAMPH(plane_a) | MPGHRA__RAMPG(plane_a); // bits 5~0
vdp2.reg.MPIJRA = MPIJRA__RAMPJ(plane_a) | MPIJRA__RAMPI(plane_a); // bits 5~0
vdp2.reg.MPKLRA = MPKLRA__RAMPL(plane_a) | MPKLRA__RAMPK(plane_a); // bits 5~0
vdp2.reg.MPMNRA = MPMNRA__RAMPN(plane_a) | MPMNRA__RAMPM(plane_a); // bits 5~0
vdp2.reg.MPOPRA = MPOPRA__RAMPP(plane_a) | MPOPRA__RAMPO(plane_a); // bits 5~0
vdp2.reg.PNCR = PNCR__R0PNB__2WORD;
vdp2.reg.RPMD = RPMD__ROTATION_PARAMETER_A;
//vdp2.reg.RPRCTL = 0;
vdp2.reg.KTCTL = 0;
vdp2.reg.KTAOF = 0;
vdp2.reg.PRIR = 3;
palette_data();
cell_data();
volatile struct vdp2_rotation_parameter_table * table = (struct vdp2_rotation_parameter_table *)&vdp2.vram.u32[0x4000 / 4];
table->screen_start_coordinate_xst = 0;
table->screen_start_coordinate_yst = 0;
table->screen_start_coordinate_zst = 0;
table->screen_vertical_coordinate_increment_dxst = 0;
table->screen_vertical_coordinate_increment_dyst = (1 << 16);
table->screen_horizontal_coordinate_increment_dx = (1 << 16);
table->screen_horizontal_coordinate_increment_dy = 0;
table->rotation_matrix_parameter_a = (-1 << 16);
table->rotation_matrix_parameter_b = 0;
table->rotation_matrix_parameter_c = 0;
table->rotation_matrix_parameter_d = 0;
table->rotation_matrix_parameter_e = (1 << 16);
table->rotation_matrix_parameter_f = 0;
table->viewpoint_coordinate_px = 0;
table->viewpoint_coordinate_py = 0;
table->viewpoint_coordinate_pz = 0;
table->center_point_coordinate_px = 0;
table->center_point_coordinate_py = 0;
table->center_point_coordinate_pz = 0;
table->horizontal_shift_mx = 0;
table->horizontal_shift_my = 0;
table->scaling_coefficient_kx = (1 << 16);
table->scaling_coefficient_ky = (1 << 16);
vdp2.reg.RPTA = (((uint32_t)table) >> 1) & 0x7ffff;
/* */
for (int i = 0; i < 64 * 64; i++) {
vdp2.vram.u32[(plane_a_offset / 4) + i] = ' ' - 0x20;
}
const char * test = "If sound level changes progressively, volume on 3 bit makes audi";
int ix = 0;
while (*test) {
uint8_t c = *test++;
vdp2.vram.u32[(plane_a_offset / 4) + ix++] = c - 0x20;
}
while (1);
}

170
vec4.hpp
View File

@ -1,170 +0,0 @@
#pragma once
#include "math.hpp"
#include "vec.hpp"
//
// vec4
//
template <typename T>
struct vec<4, T>
{
union {
struct { T x, y, z, w; };
struct { T a, r, g, b; };
};
inline constexpr vec();
inline constexpr vec(T scalar);
inline constexpr vec(T _x, T _y, T _z, T _w);
inline constexpr vec(const vec<3, T>& v);
constexpr inline vec<4, T> operator-() const;
inline constexpr T const& operator[](int i) const;
inline constexpr vec<4, T>& operator=(vec<4, T> const& v);
inline constexpr vec<4, T>& operator+=(vec<4, T> const& v);
inline constexpr vec<4, T>& operator-=(vec<4, T> const& v);
};
template <typename T>
inline constexpr vec<4, T>::vec()
: x(0), y(0), z(0), w(0)
{}
template <typename T>
inline constexpr vec<4, T>::vec(T scalar)
: x(scalar), y(scalar), z(scalar), w(scalar)
{}
template <typename T>
inline constexpr vec<4, T>::vec(T _x, T _y, T _z, T _w)
: x(_x), y(_y), z(_z), w(_w)
{}
template <typename T>
inline constexpr vec<4, T>::vec(const vec<3, T>& v)
: x(v.x), y(v.y), z(v.z), w(1.f)
{}
template <typename T>
constexpr inline vec<4, T> vec<4, T>::operator-() const
{
return vec<4, T>(-x, -y, -z, -w);
}
template <typename T>
inline constexpr T const& vec<4, T>::operator[](int i) const
{
switch(i)
{
default: [[fallthrough]];
case 0: return x;
case 1: return y;
case 2: return z;
case 3: return w;
}
}
template <typename T>
inline constexpr vec<4, T>& vec<4, T>::operator=(vec<4, T> const& v)
{
this->x = static_cast<T>(v.x);
this->y = static_cast<T>(v.y);
this->z = static_cast<T>(v.z);
this->w = static_cast<T>(v.w);
return *this;
}
template <typename T>
inline constexpr vec<4, T>& vec<4, T>::operator+=(vec<4, T> const& v)
{
*this = *this + vec<4, T>(v);
return *this;
}
template <typename T>
inline constexpr vec<4, T>& vec<4, T>::operator-=(vec<4, T> const& v)
{
*this = *this - vec<4, T>(v);
return *this;
}
template <typename T>
inline constexpr vec<4, T> operator+(vec<4, T> const& v1, vec<4, T> const& v2)
{
return vec<4, T>(v1.x + v2.x,
v1.y + v2.y,
v1.z + v2.z,
v1.w + v2.w);
}
template <typename T>
inline constexpr vec<4, T> operator-(vec<4, T> const& v1, vec<4, T> const& v2)
{
return vec<4, T>(v1.x - v2.x,
v1.y - v2.y,
v1.z - v2.z,
v1.w - v2.w);
}
template <typename T>
inline constexpr vec<4, T> operator*(vec<4, T> const& v1, vec<4, T> const& v2)
{
return vec<4, T>(v1.x * v2.x,
v1.y * v2.y,
v1.z * v2.z,
v1.w * v2.w);
}
template <typename T>
inline constexpr vec<4, T> operator*(vec<4, T> const& v1, T const& scalar)
{
return v1 * vec<4, T>(scalar);
}
template <typename T>
inline constexpr vec<4, T> operator*(T const& scalar, vec<4, T> const& v1)
{
return vec<4, T>(scalar) * v1;
}
template <typename T>
inline constexpr vec<4, T> operator/(vec<4, T> const& v1, vec<4, T> const& v2)
{
return vec<4, T>(v1.x / v2.x,
v1.y / v2.y,
v1.z / v2.z,
v1.w / v2.w);
}
template <typename T>
inline constexpr vec<4, T> operator/(vec<4, T> const& v1, T const& scalar)
{
return v1 / vec<4, T>(scalar);
}
template <typename T>
inline constexpr T dot(vec<4, T> const& v1, vec<4, T> const& v2)
{
vec<4, T> tmp(v1 * v2);
return tmp.x + tmp.y + tmp.z + tmp.w;
}
template <typename T>
inline constexpr vec<4, T> functor1(T (&func) (T const& x), vec<4, T> const& v)
{
return vec<4, T>(func(v.x), func(v.y), func(v.z), func(v.w));
}
template <typename T, typename U>
inline constexpr vec<4, U> functor1(U (&func) (T const& x), vec<4, T> const& v)
{
return vec<4, U>(func(v.x), func(v.y), func(v.z), func(v.w));
}
template <typename T>
inline constexpr T magnitude(vec<4, T> const& v)
{
return sqrt(dot(v, v));
}