Skip to content

Commit 1ee16ba

Browse files
gamemasterplcrasky
authored andcommitted
Add DSO examples and tests
1 parent bf02942 commit 1ee16ba

39 files changed

+1351
-5
lines changed

Diff for: examples/Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ EXAMPLES += eepromfstest
66
EXAMPLES += mixertest
77
EXAMPLES += cpaktest
88
EXAMPLES += cpak-utest
9+
EXAMPLES += overlays
910
EXAMPLES += rdpqdemo
1011
EXAMPLES += rspqdemo
1112
EXAMPLES += spritemap

Diff for: examples/overlays/Makefile

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
all: actor scene
2+
3+
.PHONY: clean
4+
clean:
5+
$(MAKE) -C actor clean
6+
$(MAKE) -C scene clean
7+
8+
.PHONY: actor
9+
actor:
10+
$(MAKE) -C actor
11+
12+
.PHONY: scene
13+
scene:
14+
$(MAKE) -C scene

Diff for: examples/overlays/actor/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
filesystem*/

Diff for: examples/overlays/actor/Makefile

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
BUILD_DIR=build
2+
include $(N64_INST)/include/n64.mk
3+
4+
main_SRC = overlays_actor.c
5+
6+
circle_SRC = circle.c
7+
triangle_SRC = triangle.c
8+
n64brew_SRC = n64brew.c
9+
10+
assets_png = $(wildcard assets/*.png)
11+
assets_conv = $(addprefix filesystem/,$(notdir $(assets_png:%.png=%.sprite)))
12+
13+
all: overlays_actor.z64
14+
15+
MAIN_ELF_EXTERNS := $(BUILD_DIR)/overlays_actor.externs
16+
DSO_MODULES = circle.dso triangle.dso n64brew.dso
17+
DSO_LIST = $(addprefix filesystem/, $(DSO_MODULES))
18+
19+
filesystem/%.sprite: assets/%.png
20+
@mkdir -p $(dir $@)
21+
@echo " [SPRITE] $@"
22+
@$(N64_MKSPRITE) -f RGBA16 --compress -o "$(dir $@)" "$<"
23+
24+
$(BUILD_DIR)/overlays_actor.dfs: $(assets_conv) $(DSO_LIST)
25+
$(BUILD_DIR)/overlays_actor.elf: $(main_SRC:%.c=$(BUILD_DIR)/%.o) $(MAIN_ELF_EXTERNS)
26+
$(MAIN_ELF_EXTERNS): $(DSO_LIST)
27+
filesystem/circle.dso: $(circle_SRC:%.c=$(BUILD_DIR)/%.o)
28+
filesystem/triangle.dso: $(triangle_SRC:%.c=$(BUILD_DIR)/%.o)
29+
filesystem/n64brew.dso: $(n64brew_SRC:%.c=$(BUILD_DIR)/%.o)
30+
31+
overlays_actor.z64: N64_ROM_TITLE="Actor Overlay Demo"
32+
overlays_actor.z64: $(BUILD_DIR)/overlays_actor.dfs $(BUILD_DIR)/overlays_actor.msym
33+
34+
$(BUILD_DIR)/overlays_actor.msym: $(BUILD_DIR)/overlays_actor.elf
35+
36+
clean:
37+
rm -rf $(BUILD_DIR) filesystem $(DSO_LIST) overlays_actor.z64
38+
39+
-include $(wildcard $(BUILD_DIR)/*.d)
40+
41+
.PHONY: all clean

Diff for: examples/overlays/actor/actor.h

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#ifndef __ACTOR_H
2+
#define __ACTOR_H
3+
4+
#include <libdragon.h>
5+
#include <stdbool.h>
6+
7+
struct actor_s;
8+
9+
typedef void (*init_func_t)(struct actor_s *);
10+
typedef bool (*update_func_t)(struct actor_s *, struct controller_data);
11+
12+
typedef struct actor_s {
13+
void *ovl_handle;
14+
sprite_t *sprite;
15+
update_func_t update;
16+
float x;
17+
float y;
18+
float x_scale;
19+
float y_scale;
20+
float angle;
21+
bool visible;
22+
} actor_t;
23+
24+
typedef struct actor_class_s {
25+
size_t instance_size;
26+
init_func_t init;
27+
update_func_t update;
28+
} actor_class_t;
29+
30+
#endif

Diff for: examples/overlays/actor/assets/circle.png

539 Bytes
Loading

Diff for: examples/overlays/actor/assets/n64brew.png

6.05 KB
Loading

Diff for: examples/overlays/actor/assets/triangle.png

333 Bytes
Loading

Diff for: examples/overlays/actor/circle.c

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#include "actor.h"
2+
3+
#define SPAWN_DURATION 1500
4+
#define FLICKER_DURATION 120
5+
6+
typedef struct circle_actor_s {
7+
actor_t actor;
8+
int num_ticks;
9+
float home_x;
10+
float home_y;
11+
float vel_x;
12+
float vel_y;
13+
} circle_actor_t;
14+
15+
static void init(actor_t *actor)
16+
{
17+
circle_actor_t *this = (circle_actor_t *)actor;
18+
this->home_x = actor->x;
19+
this->home_y = actor->y;
20+
this->vel_x = 2.0f;
21+
this->vel_y = 2.0f;
22+
}
23+
24+
static void apply_accel(float *pos, float *origin_pos, float *vel, float accel)
25+
{
26+
//Accelerate towards origin
27+
if(*pos > *origin_pos) {
28+
*vel -= accel;
29+
} else {
30+
*vel += accel;
31+
}
32+
*pos += *vel;
33+
}
34+
35+
static bool update(actor_t *actor, struct controller_data pressed_keys)
36+
{
37+
circle_actor_t *this = (circle_actor_t *)actor;
38+
apply_accel(&actor->x, &this->home_x, &this->vel_x, 0.2f);
39+
apply_accel(&actor->y, &this->home_y, &this->vel_y, 0.1f);
40+
//Despawn after existing for too long
41+
if(++this->num_ticks > SPAWN_DURATION) {
42+
return false;
43+
}
44+
//Fast forward to flickering when pressing B
45+
if(pressed_keys.c[0].B) {
46+
this->num_ticks = SPAWN_DURATION-FLICKER_DURATION;
47+
}
48+
if(this->num_ticks > SPAWN_DURATION-FLICKER_DURATION) {
49+
//Do flicker when running out of time
50+
actor->visible = !actor->visible;
51+
}
52+
return true;
53+
}
54+
55+
actor_class_t actor_class = { sizeof(circle_actor_t), init, update };

Diff for: examples/overlays/actor/n64brew.c

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#include "actor.h"
2+
#include <math.h>
3+
4+
#define SPAWN_DURATION 1500
5+
#define FLICKER_DURATION 120
6+
#define MAX_ROTATION 0.7f
7+
8+
typedef struct n64brew_actor_s {
9+
actor_t actor;
10+
float angle_vel;
11+
int num_ticks;
12+
} n64brew_actor_t;
13+
14+
static void init(actor_t *actor)
15+
{
16+
n64brew_actor_t *this = (n64brew_actor_t *)actor;
17+
this->angle_vel = 0.025f;
18+
}
19+
20+
static void do_rotation(n64brew_actor_t *this)
21+
{
22+
this->actor.angle += this->angle_vel;
23+
if(this->actor.angle > MAX_ROTATION) {
24+
this->angle_vel = -this->angle_vel;
25+
this->actor.angle = MAX_ROTATION;
26+
}
27+
if(this->actor.angle < -MAX_ROTATION) {
28+
this->angle_vel = -this->angle_vel;
29+
this->actor.angle = -MAX_ROTATION;
30+
}
31+
this->actor.x_scale = this->actor.y_scale = cos(this->actor.angle);
32+
}
33+
34+
static void do_crash()
35+
{
36+
debugf((char *)0x1);
37+
}
38+
39+
static bool update(actor_t *actor, struct controller_data pressed_keys)
40+
{
41+
n64brew_actor_t *this = (n64brew_actor_t *)actor;
42+
do_rotation(this);
43+
if(pressed_keys.c[0].C_right) {
44+
do_crash();
45+
}
46+
//Despawn after existing for too long
47+
if(++this->num_ticks > SPAWN_DURATION) {
48+
return false;
49+
}
50+
//Fast forward to flickering when pressing C-up
51+
if(pressed_keys.c[0].C_up) {
52+
this->num_ticks = SPAWN_DURATION-FLICKER_DURATION;
53+
}
54+
if(this->num_ticks > SPAWN_DURATION-FLICKER_DURATION) {
55+
//Do flicker when running out of time
56+
actor->visible = !actor->visible;
57+
}
58+
return true;
59+
}
60+
61+
actor_class_t actor_class = { sizeof(n64brew_actor_t), init, update };

Diff for: examples/overlays/actor/overlays_actor.c

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#include <libdragon.h>
2+
#include <stdlib.h>
3+
#include "actor.h"
4+
5+
#define MAX_ACTORS 24
6+
#define MAX_ACTOR_TYPES 3
7+
8+
typedef struct actor_info_s {
9+
const char *name;
10+
const char *sprite_path;
11+
const char *ovl_path;
12+
} actor_info_t;
13+
14+
static actor_info_t actor_info[MAX_ACTOR_TYPES] = {
15+
{ "circle", "rom:/circle.sprite", "rom:/circle.dso" },
16+
{ "triangle", "rom:/triangle.sprite", "rom:/triangle.dso" },
17+
{ "n64brew", "rom:/n64brew.sprite", "rom:/n64brew.dso" },
18+
};
19+
20+
static actor_t *actors[MAX_ACTORS];
21+
22+
static int find_free_actor()
23+
{
24+
//Search for free actor slot
25+
for(int i=0; i<MAX_ACTORS; i++) {
26+
if(!actors[i]) {
27+
//Found free actor slot
28+
return i;
29+
}
30+
}
31+
//Return sentinel value if no free actor slot exists
32+
return -1;
33+
}
34+
35+
static void create_actor(int type, float x, float y)
36+
{
37+
if(type < MAX_ACTOR_TYPES) {
38+
void *ovl_handle;
39+
actor_class_t *class;
40+
//Try to allocate actor
41+
int slot = find_free_actor();
42+
if(slot == -1) {
43+
//Return if impossible
44+
return;
45+
}
46+
ovl_handle = dlopen(actor_info[type].ovl_path, RTLD_LOCAL);
47+
class = dlsym(ovl_handle, "actor_class");
48+
assertf(class, "Failed to find actor class for actor %s", actor_info[type].name);
49+
actors[slot] = calloc(1, class->instance_size); //Allocate actor instance
50+
//Setup actor global properties
51+
actors[slot]->ovl_handle = ovl_handle;
52+
actors[slot]->update = class->update;
53+
//Setup sprite graphics
54+
actors[slot]->sprite = sprite_load(actor_info[type].sprite_path);
55+
actors[slot]->x = x;
56+
actors[slot]->y = y;
57+
actors[slot]->x_scale = actors[slot]->y_scale = 1.0f;
58+
actors[slot]->visible = true;
59+
class->init(actors[slot]);
60+
}
61+
}
62+
63+
static void draw_actors()
64+
{
65+
rdpq_mode_blender(RDPQ_BLENDER_MULTIPLY);
66+
for(int i=0; i<MAX_ACTORS; i++) {
67+
if(actors[i] && actors[i]->visible) {
68+
//Blit sprite surface to screen
69+
surface_t surf = sprite_get_pixels(actors[i]->sprite);
70+
rdpq_tex_blit(&surf, actors[i]->x, actors[i]->y, &(rdpq_blitparms_t){
71+
.cx = surf.width/2, .cy = surf.height/2,
72+
.scale_x = actors[i]->x_scale, .scale_y = actors[i]->y_scale,
73+
.theta = actors[i]->angle
74+
});
75+
}
76+
}
77+
}
78+
79+
static void update_actors(struct controller_data keys)
80+
{
81+
for(int i=0; i<MAX_ACTORS; i++) {
82+
if(actors[i]) {
83+
if(!actors[i]->update(actors[i], keys)) {
84+
//Free up actor resources
85+
dlclose(actors[i]->ovl_handle);
86+
sprite_free(actors[i]->sprite);
87+
//Free actor instance
88+
free(actors[i]);
89+
actors[i] = NULL;
90+
}
91+
}
92+
}
93+
}
94+
95+
int main()
96+
{
97+
float scr_width;
98+
float scr_height;
99+
//Init debug log
100+
debug_init_isviewer();
101+
debug_init_usblog();
102+
//Init rendering
103+
display_init(RESOLUTION_320x240, DEPTH_16_BPP, 3, GAMMA_NONE, FILTERS_RESAMPLE);
104+
rdpq_init();
105+
rdpq_debug_start();
106+
scr_width = display_get_width();
107+
scr_height = display_get_height();
108+
//Init miscellaneous system
109+
dfs_init(DFS_DEFAULT_LOCATION);
110+
controller_init();
111+
//Setup scene
112+
create_actor(2, scr_width/2, scr_height/2);
113+
while(1) {
114+
surface_t *disp;
115+
//Update controller
116+
controller_scan();
117+
struct controller_data keys = get_keys_down();
118+
//Do actor spawning
119+
if(keys.c[0].A) {
120+
//Spawn a random actor somewhere in the middle 80% of the screen
121+
float pos_x = (((float)rand()/RAND_MAX)*(scr_width*0.8f))+(scr_width*0.1f);
122+
float pos_y = (((float)rand()/RAND_MAX)*(scr_height*0.8f))+(scr_height*0.1f);
123+
create_actor(rand()%MAX_ACTOR_TYPES, pos_x, pos_y);
124+
}
125+
//Update actors
126+
update_actors(keys);
127+
//Clear display
128+
disp = display_get();
129+
rdpq_attach_clear(disp, NULL);
130+
//Render actors
131+
rdpq_set_mode_standard();
132+
draw_actors();
133+
//Finish frame
134+
rdpq_detach_show();
135+
}
136+
}

0 commit comments

Comments
 (0)