Mirai's Miscellaneous Misadventures

M55 / core / displays.c

1/* license: AGPLv3 or later */
2/* copyright 2024 zamfofex */
3/* note: a lot of this file assumes C99 division rules */
4/* note: is this worthwhile fixing? */
5
6#include "../mimimi.h"
7
8void mimimi_camera_stamp(struct mimimi_image *target, struct mimimi_position *camera, int x, int y, int z, struct mimimi_image *source)
9{
10	z += 8;
11	if (z <= 0) return;
12	
13	x -= camera->x;
14	x = mimimi_div_up(x, z);
15	x += target->width / 2;
16	
17	y -= camera->y;
18	y = mimimi_div_up(y, z);
19	y += target->height / 2;
20	
21	mimimi_stamp(target, x, y, source);
22}
23
24static void mimimi_sprite_jumping(struct mimimi_image *image, struct mimimi_sprite *sprite)
25{
26	static struct mimimi_pose pose0 = {0};
27	static struct mimimi_pose poses[2] = {0};
28	
29	int slant;
30	int n;
31	int dx, dy;
32	int y_angle;
33	
34	n = sprite->direction == 1 ? 1 : -1;
35	
36	dx = sprite->physics.dx * -n;
37	dy = sprite->physics.dy;
38	
39	if (dx < 0) dx = 0;
40	if (dx > 8191) dx = 8191;
41	
42	dy += 8192;
43	if (dy < 0) dy = 0;
44	if (dy > 16383) dy = 16383;
45	
46	slant = 64 * dx / 8192 * n;
47	y_angle = 64 + (20 + 20 * dx / 8192) * n;
48	
49	poses[0] = pose0;
50	poses[1] = pose0;
51	
52	poses[0].layers[0].y_angle = y_angle;
53	poses[0].layers[0].slant = -slant * 2;
54	poses[0].layers[1].slant = slant * 2;
55	poses[0].layers[4].slant = -slant / 2;
56	poses[0].layers[5].slant = -slant / 2;
57	
58	poses[1].layers[0].y_angle = y_angle;
59	poses[1].layers[2].slant = -slant * 2;
60	poses[1].layers[3].slant = -slant * 2;
61	poses[1].layers[4].slant = slant * 2;
62	poses[1].layers[5].slant = slant * 2;
63	
64	poses[0].x = image->width / 2;
65	poses[0].y = image->height - 15;
66	poses[1].x = image->width / 2;
67	poses[1].y = image->height - 15;
68	
69	mimimi_interpolate(poses, poses + 1, dy, 16384);
70	mimimi_pose(image, sprite->model, poses);
71}
72
73static void mimimi_sprite_walking(struct mimimi_image *image, struct mimimi_sprite *sprite)
74{
75	static struct mimimi_pose pose0 = {0};
76	static struct mimimi_pose poses[2] = {0};
77	
78	int slant, y_angle;
79	int intent;
80	int n;
81	int dx;
82	struct mimimi_pose *a, *b;
83	int i;
84	int y;
85	
86	n = sprite->direction == 1 ? 1 : -1;
87	
88	dx = sprite->physics.dx * -n;
89	if (dx < 0) dx = 0;
90	if (dx > 8191) dx = 8191;
91	
92	intent = dx / 16;
93	slant = intent * n;
94	y_angle = 64 + (20 + 20 * dx / 8192) * n;
95	
96	poses[0] = pose0;
97	poses[1] = pose0;
98	
99	poses[0].layers[0].y_angle = y_angle;
100	poses[1].layers[0].y_angle = y_angle;
101	
102	poses[0].layers[0].slant = -slant / 8;
103	poses[1].layers[0].slant = -slant / 8;
104	
105	poses[0].layers[1].slant = slant / 8;
106	poses[1].layers[1].slant = slant / 8;
107	
108	poses[1].layers[4].slant = slant / 2;
109	poses[0].layers[4].slant = -slant / 3;
110	poses[1].layers[8].slant = -slant / 8;
111	poses[0].layers[8].slant = -slant / 16;
112	
113	poses[0].layers[5].slant = slant / 2;
114	poses[1].layers[5].slant = -slant / 4;
115	poses[0].layers[9].slant = -slant / 8;
116	poses[1].layers[9].slant = -slant / 16;
117	
118	poses[0].layers[2].slant = slant / 6;
119	poses[1].layers[2].slant = -slant / 2;
120	poses[0].layers[6].slant = slant / 6;
121	poses[1].layers[6].slant = slant / 2;
122	poses[1].layers[6].y = intent / 128;
123	
124	poses[1].layers[3].slant = slant / 6;
125	poses[0].layers[3].slant = -slant / 2;
126	poses[1].layers[7].slant = slant / 6;
127	poses[0].layers[7].slant = slant / 2;
128	poses[0].layers[7].y = intent / 128;
129	
130	sprite->animation_time += dx / 512;
131	
132	/* do not assume 'char' is eight bits */
133	sprite->animation_time &= 0xFF;
134	
135	if (sprite->animation_time < 128) {
136		a = poses;
137		b = poses + 1;
138		i = sprite->animation_time;
139	}
140	else {
141		a = poses + 1;
142		b = poses;
143		i = sprite->animation_time - 128;
144	}
145	
146	y = sprite->landing_time * dx / 0x8000;
147	
148	a->layers[8].y = 128 + mimimi_sine[sprite->animation_time * 8];
149	a->layers[8].y *= intent;
150	a->layers[8].y /= 0x8000;
151	a->layers[8].y += y;
152	b->layers[8].y = a->layers[8].y;
153	
154	a->layers[9].y = 128 - mimimi_sine[sprite->animation_time * 8];
155	a->layers[9].y *= intent;
156	a->layers[9].y /= 0x8000;
157	a->layers[9].y += y;
158	b->layers[9].y = a->layers[9].y;
159	
160	poses[0].layers[0].y = 128 + mimimi_cosine[i * 16];
161	poses[0].layers[0].y *= intent * (16 - sprite->landing_time);
162	poses[0].layers[0].y /= 0x8000 * 16;
163	poses[0].layers[0].y -= y;
164	poses[1].layers[0].y = poses[0].layers[0].y;
165	
166	a->x = image->width / 2;
167	a->y = image->height - 15;
168	b->x = a->x;
169	b->y = a->y;
170	
171	mimimi_interpolate(a, b, i, 128);
172	mimimi_pose(image, sprite->model, a);
173}
174
175void mimimi_display_tick(struct mimimi_image *target, struct mimimi_sprite *sprite, struct mimimi_position *camera)
176{
177	static unsigned char colors[24 * 48];
178	
179	struct mimimi_physics *physics;
180	struct mimimi_walk *walk;
181	struct mimimi_image image;
182	int x, y;
183	int trail;
184	
185	physics = &sprite->physics;
186	walk = &sprite->walk;
187	
188	image.width = 24;
189	image.height = 48;
190	image.colors = colors;
191	
192	for (y = 0 ; y < image.height ; y++) {
193		for (x = 0 ; x < image.width ; x++) {
194			colors[x + y * image.width] = 0;
195		}
196	}
197	
198	if (walk->direction != 0) sprite->direction = walk->direction;
199	
200	if (physics->airborne != 0) {
201		sprite->landing_time = 16;
202	}
203	else {
204		if (sprite->landing_time > 0) sprite->landing_time--;
205	}
206	
207	if (physics->airborne == 0) mimimi_sprite_walking(&image, sprite);
208	else mimimi_sprite_jumping(&image, sprite);
209	
210	trail = sprite->trail;
211	sprite->trailing_y = mimimi_div(sprite->trailing_y * trail, 256);
212	sprite->trailing_y += mimimi_div(sprite->position.y * (256 - trail), 256);
213	sprite->trail = trail / 2;
214	
215	mimimi_camera_stamp(target, camera, sprite->position.x - image.width * 4, sprite->trailing_y - image.height * 8 + 32, 0, &image);
216}
217
218void mimimi_background_tick(struct mimimi_background *background, struct mimimi_image *image, struct mimimi_position *camera, struct mimimi_position *offset)
219{
220	mimimi_camera_stamp(image, camera, background->x + offset->x, background->y + offset->y, background->z, &background->image);
221}