rotating bowser

This commit is contained in:
Zack Buhman 2024-08-31 12:59:45 -05:00
parent 4dd7a033ac
commit 9e6cd43860
12 changed files with 583 additions and 48 deletions

View File

@ -13,7 +13,9 @@ MAIN_OBJ = \
start.o \
main.o \
res/player.data.o \
res/player.data.pal.o
res/player.data.pal.o \
res/bowser.data.o \
res/bowser.data.pal.o
main.elf: $(MAIN_OBJ)

View File

@ -1,4 +1,5 @@
io_registers = 0x04000000;
palette_ram = 0x05000000;
bg_vram = 0x06000000;
obj_vram = 0x06400000;
oam = 0x07000000;

50
bg.h
View File

@ -4,43 +4,53 @@
#define static_assert _Static_assert
union screen_block {
union bg_screen_block {
uint8_t u8[0x800 / 1];
uint16_t u16[0x800 / 2];
uint32_t u32[0x800 / 4];
};
static_assert((sizeof (union screen_block)) == 0x800);
static_assert((sizeof (union bg_screen_block)) == 0x800);
struct screen_offset {
union screen_block block[32];
struct bg_screen_offset {
union bg_screen_block block[32];
};
static_assert((sizeof (struct screen_offset)) == 0x10000);
static_assert((sizeof (struct bg_screen_offset)) == 0x10000);
struct screen_data {
struct screen_offset offset[8];
struct bg_screen_data {
struct bg_screen_offset offset[8];
};
static_assert((sizeof (struct screen_data)) == 0x80000);
static_assert((sizeof (struct bg_screen_data)) == 0x80000);
union character_block {
uint16_t u8[0x4000 / 2];
uint16_t u16[0x4000 / 2];
uint32_t u32[0x4000 / 4];
union bg_character {
uint8_t u8[32 / 1];
uint16_t u16[32 / 2];
uint32_t u32[32 / 4];
};
static_assert((sizeof (union character_block)) == 0x4000);
static_assert((sizeof (union bg_character)) == 32);
struct character_offset {
union character_block block[4]; // is actually 16
union bg_character_block {
union bg_character character[0x4000 / (sizeof (union bg_character))];
union {
uint8_t u8[0x4000 / 1];
uint16_t u16[0x4000 / 2];
uint32_t u32[0x4000 / 4];
};
};
static_assert((sizeof (union bg_character_block)) == 0x4000);
struct bg_character_offset {
union bg_character_block block[4]; // is actually 16
};
struct character_data {
struct character_offset offset[8];
struct bg_character_data {
struct bg_character_offset offset[8];
};
static_assert((sizeof (struct character_data)) == 0x80000);
static_assert((sizeof (struct bg_character_data)) == 0x80000);
struct bg {
union {
struct screen_data screen;
struct character_data character;
struct bg_screen_data screen;
struct bg_character_data character;
};
};
static_assert((sizeof (struct bg)) == 0x80000);

View File

@ -11,6 +11,7 @@ CFLAGS += -Wno-array-bounds
CFLAGS += -Wno-error=maybe-uninitialized
CFLAGS += -Wno-error=unused-but-set-variable
CFLAGS += -Wno-error=unused-variable
CFLAGS += -Wno-aggressive-loop-optimizations
CXXFLAGS += -fno-exceptions -fno-non-call-exceptions -fno-rtti -fno-threadsafe-statics

521
main.c
View File

@ -2,24 +2,402 @@
#include "bits.h"
#include "bg.h"
#include "palette.h"
#include "obj.h"
#include "oam.h"
#include "res/player.h"
#include "res/player.pal.h"
#include "res/bowser.h"
#include "res/bowser.pal.h"
static inline uint16_t rgb555(const uint8_t * buf)
static inline uint16_t rgb565(const uint8_t * buf)
{
uint8_t r = buf[0] >> 3;
uint8_t g = buf[1] >> 3;
uint8_t g_l = (buf[1] >> 2) & 1;
uint8_t b = buf[2] >> 3;
return (b << 10) | (g << 5) | (r << 0);
return (g_l << 15) | (b << 10) | (g << 5) | (r << 0);
}
struct sign_v {
char sign;
uint8_t v;
};
struct sign_v cos_table[360] = {
{0, 255},
{0, 254},
{0, 254},
{0, 254},
{0, 254},
{0, 254},
{0, 253},
{0, 253},
{0, 252},
{0, 251},
{0, 251},
{0, 250},
{0, 249},
{0, 248},
{0, 247},
{0, 246},
{0, 245},
{0, 243},
{0, 242},
{0, 241},
{0, 239},
{0, 238},
{0, 236},
{0, 234},
{0, 232},
{0, 231},
{0, 229},
{0, 227},
{0, 225},
{0, 223},
{0, 220},
{0, 218},
{0, 216},
{0, 213},
{0, 211},
{0, 208},
{0, 206},
{0, 203},
{0, 200},
{0, 198},
{0, 195},
{0, 192},
{0, 189},
{0, 186},
{0, 183},
{0, 180},
{0, 177},
{0, 173},
{0, 170},
{0, 167},
{0, 163},
{0, 160},
{0, 156},
{0, 153},
{0, 149},
{0, 146},
{0, 142},
{0, 138},
{0, 135},
{0, 131},
{0, 127},
{0, 123},
{0, 119},
{0, 115},
{0, 111},
{0, 107},
{0, 103},
{0, 99},
{0, 95},
{0, 91},
{0, 87},
{0, 83},
{0, 78},
{0, 74},
{0, 70},
{0, 65},
{0, 61},
{0, 57},
{0, 53},
{0, 48},
{0, 44},
{0, 39},
{0, 35},
{0, 31},
{0, 26},
{0, 22},
{0, 17},
{0, 13},
{0, 8},
{0, 4},
{0, 0},
{1, 4},
{1, 8},
{1, 13},
{1, 17},
{1, 22},
{1, 26},
{1, 31},
{1, 35},
{1, 39},
{1, 44},
{1, 48},
{1, 53},
{1, 57},
{1, 61},
{1, 65},
{1, 70},
{1, 74},
{1, 78},
{1, 83},
{1, 87},
{1, 91},
{1, 95},
{1, 99},
{1, 103},
{1, 107},
{1, 111},
{1, 115},
{1, 119},
{1, 123},
{1, 127},
{1, 131},
{1, 135},
{1, 138},
{1, 142},
{1, 146},
{1, 149},
{1, 153},
{1, 156},
{1, 160},
{1, 163},
{1, 167},
{1, 170},
{1, 173},
{1, 177},
{1, 180},
{1, 183},
{1, 186},
{1, 189},
{1, 192},
{1, 195},
{1, 198},
{1, 200},
{1, 203},
{1, 206},
{1, 208},
{1, 211},
{1, 213},
{1, 216},
{1, 218},
{1, 220},
{1, 223},
{1, 225},
{1, 227},
{1, 229},
{1, 231},
{1, 232},
{1, 234},
{1, 236},
{1, 238},
{1, 239},
{1, 241},
{1, 242},
{1, 243},
{1, 245},
{1, 246},
{1, 247},
{1, 248},
{1, 249},
{1, 250},
{1, 251},
{1, 251},
{1, 252},
{1, 253},
{1, 253},
{1, 254},
{1, 254},
{1, 254},
{1, 254},
{1, 254},
{1, 255},
{1, 254},
{1, 254},
{1, 254},
{1, 254},
{1, 254},
{1, 253},
{1, 253},
{1, 252},
{1, 251},
{1, 251},
{1, 250},
{1, 249},
{1, 248},
{1, 247},
{1, 246},
{1, 245},
{1, 243},
{1, 242},
{1, 241},
{1, 239},
{1, 238},
{1, 236},
{1, 234},
{1, 232},
{1, 231},
{1, 229},
{1, 227},
{1, 225},
{1, 223},
{1, 220},
{1, 218},
{1, 216},
{1, 213},
{1, 211},
{1, 208},
{1, 206},
{1, 203},
{1, 200},
{1, 198},
{1, 195},
{1, 192},
{1, 189},
{1, 186},
{1, 183},
{1, 180},
{1, 177},
{1, 173},
{1, 170},
{1, 167},
{1, 163},
{1, 160},
{1, 156},
{1, 153},
{1, 149},
{1, 146},
{1, 142},
{1, 138},
{1, 135},
{1, 131},
{1, 127},
{1, 123},
{1, 119},
{1, 115},
{1, 111},
{1, 107},
{1, 103},
{1, 99},
{1, 95},
{1, 91},
{1, 87},
{1, 83},
{1, 78},
{1, 74},
{1, 70},
{1, 65},
{1, 61},
{1, 57},
{1, 53},
{1, 48},
{1, 44},
{1, 39},
{1, 35},
{1, 31},
{1, 26},
{1, 22},
{1, 17},
{1, 13},
{1, 8},
{1, 4},
{1, 0},
{0, 4},
{0, 8},
{0, 13},
{0, 17},
{0, 22},
{0, 26},
{0, 31},
{0, 35},
{0, 39},
{0, 44},
{0, 48},
{0, 53},
{0, 57},
{0, 61},
{0, 65},
{0, 70},
{0, 74},
{0, 78},
{0, 83},
{0, 87},
{0, 91},
{0, 95},
{0, 99},
{0, 103},
{0, 107},
{0, 111},
{0, 115},
{0, 119},
{0, 123},
{0, 127},
{0, 131},
{0, 135},
{0, 138},
{0, 142},
{0, 146},
{0, 149},
{0, 153},
{0, 156},
{0, 160},
{0, 163},
{0, 167},
{0, 170},
{0, 173},
{0, 177},
{0, 180},
{0, 183},
{0, 186},
{0, 189},
{0, 192},
{0, 195},
{0, 198},
{0, 200},
{0, 203},
{0, 206},
{0, 208},
{0, 211},
{0, 213},
{0, 216},
{0, 218},
{0, 220},
{0, 223},
{0, 225},
{0, 227},
{0, 229},
{0, 231},
{0, 232},
{0, 234},
{0, 236},
{0, 238},
{0, 239},
{0, 241},
{0, 242},
{0, 243},
{0, 245},
{0, 246},
{0, 247},
{0, 248},
{0, 249},
{0, 250},
{0, 251},
{0, 251},
{0, 252},
{0, 253},
{0, 253},
{0, 254},
{0, 254},
{0, 254},
{0, 254},
{0, 254}
};
void main()
{
// 2d graphics engine A BG
io_registers.a.VRAMCNT = (1 << 31) | (1 << 24);
io_registers.a.WVRAMCNT = 0;
// 2d graphics engine B OBJ
io_registers.a.VRAM_HI_CNT = (1 << 15) | (0b10 << 8);
io_registers.a.DISPCNT = 0
| DISPCNT__bg_screen_base_offset(0)
| DISPCNT__bg_character_base_offset(0)
@ -37,29 +415,41 @@ void main()
| BG0CNT__priority(0)
;
io_registers.b.DISPCNT = 0
| DISPCNT__display_mode__graphics_display
| DISPCNT__obj__enable
| DISPCNT__character_obj_mapping_mode__1d_mapping
;
uint32_t pal_size = (uint32_t)&_binary_res_player_data_pal_size;
const uint8_t * pal = (const uint8_t *)&_binary_res_player_data_pal_start;
// palette ram
for (int i = 0; i < 15; i++) {
palette_ram.a.bg.palette[0].color[i] = rgb555(&pal[i * 3]);
palette_ram.a.bg.palette[0].color[i] = rgb565(&pal[i * 3]);
}
uint32_t b_pal_size = (uint32_t)&_binary_res_bowser_data_pal_size;
const uint8_t * b_pal = (const uint8_t *)&_binary_res_bowser_data_pal_start;
// bowser palette ram
for (int i = 0; i < 16; i++) {
palette_ram.b.obj.palette[0].color[i] = rgb565(&b_pal[i * 3]);
}
const uint8_t * data = (const uint8_t *)&_binary_res_player_data_start;
for (int y = 0; y < 48; y++) {
uint8_t a = data[y * 8 + 0];
uint8_t b = data[y * 8 + 1];
uint8_t c = data[y * 8 + 2];
uint8_t d = data[y * 8 + 3];
uint8_t e = data[y * 8 + 4];
uint8_t f = data[y * 8 + 5];
uint8_t g = data[y * 8 + 6];
uint8_t h = data[y * 8 + 7];
uint8_t a = data[y * 8 + 7];
uint8_t b = data[y * 8 + 6];
uint8_t c = data[y * 8 + 5];
uint8_t d = data[y * 8 + 4];
uint8_t e = data[y * 8 + 3];
uint8_t f = data[y * 8 + 2];
uint8_t g = data[y * 8 + 1];
uint8_t h = data[y * 8 + 0];
bg_vram.a.character.offset[0].block[0].u32[y] = 0
bg_vram.a.character.offset[0].block[0].character[0].u32[y] = 0
| (a << 28)
| (b << 24)
| (c << 20)
@ -73,12 +463,101 @@ void main()
for (int i = 0; i < 32 * 32; i++) {
bg_vram.a.screen.offset[0].block[31].u16[i] = 30;
}
bg_vram.a.screen.offset[0].block[31].u16[32 * 0] = 3;
bg_vram.a.screen.offset[0].block[31].u16[32 * 1] = 4;
bg_vram.a.screen.offset[0].block[31].u16[32 * 2] = 5;
bg_vram.a.screen.offset[0].block[31].u16[32 * 0 + 1] = 0;
bg_vram.a.screen.offset[0].block[31].u16[32 * 1 + 1] = 1;
bg_vram.a.screen.offset[0].block[31].u16[32 * 2 + 1] = 2;
bg_vram.a.screen.offset[0].block[31].u16[32 * 0] = 0;
bg_vram.a.screen.offset[0].block[31].u16[32 * 1] = 1;
bg_vram.a.screen.offset[0].block[31].u16[32 * 2] = 2;
bg_vram.a.screen.offset[0].block[31].u16[32 * 0 + 1] = 3;
bg_vram.a.screen.offset[0].block[31].u16[32 * 1 + 1] = 4;
bg_vram.a.screen.offset[0].block[31].u16[32 * 2 + 1] = 5;
while (1);
const uint8_t * b_data = (const uint8_t *)&_binary_res_bowser_data_start;
for (int c_y = 0; c_y < 8; c_y++) {
for (int c_x = 0; c_x < 8; c_x++) {
for (int y = 0; y < 8; y++) {
int abs_y = c_y * 8 + y;
int abs_x = c_x * 8;
int origin = abs_y * 64 + abs_x;
uint8_t a = b_data[origin + 7];
uint8_t b = b_data[origin + 6];
uint8_t c = b_data[origin + 5];
uint8_t d = b_data[origin + 4];
uint8_t e = b_data[origin + 3];
uint8_t f = b_data[origin + 2];
uint8_t g = b_data[origin + 1];
uint8_t h = b_data[origin + 0];
obj_vram.b.character[c_y * 8 + c_x].u32[y] = 0
| (a << 28)
| (b << 24)
| (c << 20)
| (d << 16)
| (e << 12)
| (f << 8)
| (g << 4)
| (h << 0);
}
}
}
oam.b.obj[0].attr[0] = 0
| OBJ_ATTRIBUTE_0__obj_shape__square
| OBJ_ATTRIBUTE_0__color_mode__16_color_mode
| OBJ_ATTRIBUTE_0__obj_mode__normal
| OBJ_ATTRIBUTE_0__double_size__disable
| OBJ_ATTRIBUTE_0__affine_transformation__enable
//| OBJ_ATTRIBUTE_0__affine_transformation__disable
| OBJ_ATTRIBUTE_0__y_coordinate(15)
;
oam.b.obj[0].attr[1] = 0
| OBJ_ATTRIBUTE_1__obj_size(0b11) // 64x64
| OBJ_ATTRIBUTE_1__x_coordinate(20)
| OBJ_ATTRIBUTE_1__affine_transformation_parameter(0)
;
oam.b.obj[0].attr[2] = 0
| OBJ_ATTRIBUTE_2__display_priority(0)
| OBJ_ATTRIBUTE_2__character_name(0)
;
/*
dx (reference distance in x-direction for same line) =
(1/α)cosθ
dy (reference distance in y-direction for same line) =
- (1/β)sinθ
dmx (reference distance in x-direction for next line) =
(1/α)sinθ
dmy (reference distance in y-direction for next line) =
(1/β)cosθ
*/
int theta = 0;
while (1) {
struct sign_v cos = cos_table[theta];
int sin_theta = theta + 90;
if (sin_theta >= 360) sin_theta -= 360;
struct sign_v sin = cos_table[sin_theta];
// dx
oam.b.param[0].pa = cos.sign ? cos.v : -cos.v;
// dmx
oam.b.param[0].pb = sin.sign ? sin.v : -sin.v;
// dy
oam.b.param[0].pc = sin.sign ? -sin.v : sin.v;
// dmy
oam.b.param[0].pd = cos.sign ? cos.v : -cos.v;
theta += 1;
if (theta >= 360) {
theta = 0;
}
while (io_registers.a.VCOUNT != 262);
while (io_registers.a.VCOUNT != 0);
}
}

12
oam.h
View File

@ -3,13 +3,13 @@
#define static_assert _Static_assert
struct obj {
struct oam_obj {
volatile uint16_t attr[3];
volatile uint16_t _0;
};
static_assert((sizeof (struct obj)) == 8);
static_assert((sizeof (struct oam_obj)) == 8);
struct param {
struct oam_param {
volatile uint16_t _0[3];
volatile uint16_t pa;
volatile uint16_t _1[3];
@ -19,11 +19,11 @@ struct param {
volatile uint16_t _3[3];
volatile uint16_t pd;
};
static_assert((sizeof (struct param)) == 32);
static_assert((sizeof (struct oam_param)) == 32);
union oam {
struct obj obj[128];
struct param param[32];
struct oam_obj obj[128];
struct oam_param param[32];
};
static_assert((sizeof (union oam)) == 0x400);

32
obj.h Normal file
View File

@ -0,0 +1,32 @@
#pragma once
#include <stdint.h>
#define static_assert _Static_assert
union obj_character {
uint8_t u8[32 / 1];
uint16_t u16[32 / 2];
uint32_t u32[32 / 4];
};
static_assert((sizeof (union obj_character)) == 32);
union obj {
union obj_character character[1024];
union {
uint8_t u8[0x8000 / 1];
uint16_t u16[0x8000 / 2];
uint32_t u32[0x8000 / 4];
};
};
static_assert((sizeof (union obj)) == 0x8000);
struct obj_vram {
union obj a;
uint8_t _pad[0x200000 - (sizeof (union obj))];
union obj b;
};
static_assert((offsetof (struct obj_vram, a)) == 0);
static_assert((offsetof (struct obj_vram, b)) == 0x200000);
extern struct obj_vram obj_vram __asm("obj_vram");

BIN
res/bowser.data Normal file

Binary file not shown.

BIN
res/bowser.data.pal Normal file

Binary file not shown.

5
res/bowser.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
extern uint32_t _binary_res_bowser_data_start __asm("_binary_res_bowser_data_start");
extern uint32_t _binary_res_bowser_data_end __asm("_binary_res_bowser_data_end");
extern uint32_t _binary_res_bowser_data_size __asm("_binary_res_bowser_data_size");

5
res/bowser.pal.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
extern uint32_t _binary_res_bowser_data_pal_start __asm("_binary_res_bowser_data_pal_start");
extern uint32_t _binary_res_bowser_data_pal_end __asm("_binary_res_bowser_data_pal_end");
extern uint32_t _binary_res_bowser_data_pal_size __asm("_binary_res_bowser_data_pal_size");

BIN
res/bowser.xcf Normal file

Binary file not shown.