[Maintenance] [th05] Minimize #includes for the shot type translation units

Since a few annoying alignment bytes suggested more translation units
than previously expected, using many small headers has proved to be
better than one big shared TH04/TH05 header file. Or should we *really*
pepper the code with lots of `#pragma codestring`? 😛

And in case we have multiple translation units which all #include the
same set of headers, we'll just go with situational shared headers,
using a common prefix.

Part of P0062, funded by Touhou Patch Center.
This commit is contained in:
nmlgc 2019-12-20 20:06:42 +01:00
parent c5b07b746e
commit 765eae82e8
11 changed files with 157 additions and 155 deletions

View File

@ -1,2 +1,7 @@
uint16_t pascal near randring1_next16(void);
uint16_t pascal near randring1_next16_and(uint16_t mask);
inline char randring_angle(char random_range, char offset)
{
return randring1_next16_and(random_range) + offset;
}

12
th04/math/motion.hpp Normal file
View File

@ -0,0 +1,12 @@
typedef struct {
SPPoint cur;
SPPoint prev;
SPPoint velocity;
void init(float screen_x, float screen_y) {
cur.x = screen_x;
prev.x = screen_x;
cur.y = screen_y;
prev.y = screen_y;
}
} motion_t;

52
th04/player/shot.hpp Normal file
View File

@ -0,0 +1,52 @@
// Sets [velocity] to a vector with the given [angle] and a 12-pixel length.
//
// TH05 also insists on setting shot_t::angle via a ridiculous out-of-bounds
// access, and therefore *must* be called with [velocity] pointing inside a
// shot_t structure!
SPPoint pascal near shot_velocity_set(
SPPoint near* velocity, unsigned char angle
);
struct shot_t {
char flag;
char age;
motion_t pos;
// The displayed sprite changes between this one and
// [patnum_base + 1] every two frames.
#if GAME == 5
char patnum_base;
char type;
#else
int patnum_base;
#endif
char damage;
char angle; // Unused in TH04
void from_option_l(float offset = 0.0f) {
this->pos.cur.x -= PLAYER_OPTION_DISTANCE + offset;
}
void from_option_r(float offset = 0.0f) {
this->pos.cur.x += PLAYER_OPTION_DISTANCE + offset;
}
void set_option_sprite() {
this->patnum_base = 22;
}
void set_option_sprite_and_damage(char damage) {
set_option_sprite();
this->damage = damage;
}
void set_random_angle_forwards(char random_range = 15, char offset = 184) {
shot_velocity_set(
(SPPoint near*)&this->pos.velocity,
randring_angle(random_range, offset)
);
}
};
// Searches and returns the next free shot slot, or NULL if there are no more
// free ones.
shot_t near* pascal near shots_add(void);

View File

@ -8,26 +8,8 @@
/// Math
/// ----
#include "th03/math/subpixel.hpp"
typedef struct {
SPPoint cur;
SPPoint prev;
SPPoint velocity;
void init(float screen_x, float screen_y) {
cur.x = screen_x;
prev.x = screen_x;
cur.y = screen_y;
prev.y = screen_y;
}
} motion_t;
#include "th04/math/motion.hpp"
#include "th03/math/randring.h"
inline char randring_angle(char random_range, char offset)
{
return randring1_next16_and(random_range) + offset;
}
/// ----
/// Rank
@ -52,62 +34,6 @@ int pascal far select_for_rank(
/// Player
/// ------
#include "th04/player/player.h"
// Shots
// -----
// Sets [velocity] to a vector with the given [angle] and a 12-pixel length.
//
// TH05 also insists on setting shot_t::angle via a ridiculous out-of-bounds
// access, and therefore *must* be called with [velocity] pointing inside a
// shot_t structure!
SPPoint pascal near shot_velocity_set(
SPPoint near* velocity, unsigned char angle
);
struct shot_t {
char flag;
char age;
motion_t pos;
// The displayed sprite changes between this one and
// [patnum_base + 1] every two frames.
#if GAME == 5
char patnum_base;
char type;
#else
int patnum_base;
#endif
char damage;
char angle; // Unused in TH04
void from_option_l(float offset = 0.0f) {
this->pos.cur.x -= PLAYER_OPTION_DISTANCE + offset;
}
void from_option_r(float offset = 0.0f) {
this->pos.cur.x += PLAYER_OPTION_DISTANCE + offset;
}
void set_option_sprite() {
this->patnum_base = 22;
}
void set_option_sprite_and_damage(char damage) {
set_option_sprite();
this->damage = damage;
}
void set_random_angle_forwards(char random_range = 15, char offset = 184) {
shot_velocity_set(
(SPPoint near*)&this->pos.velocity,
randring_angle(random_range, offset)
);
}
};
// Searches and returns the next free shot slot, or NULL if there are no more
// free ones.
shot_t near* pascal near shots_add(void);
// -----
/// ------
/// Stages

12
th05/i_shot.hpp Normal file
View File

@ -0,0 +1,12 @@
/* ReC98
* -----
* Shared #includes for the shot type control translation units
*/
#include <stddef.h>
#include "platform.h"
#include "th03/math/subpixel.hpp"
#include "th03/math/randring.h"
#include "th04/math/motion.hpp"
#include "th04/player/player.h"
#include "th05/player/shot.hpp"

View File

@ -6,8 +6,7 @@
#pragma codeseg main_01_TEXT
extern "C" {
#include "th05/th05.hpp"
#include "th05/player/shot.h"
#include "th05/i_shot.hpp"
#define cycle _AL
#define STAR_DISTANCE (16)

View File

@ -6,8 +6,7 @@
#pragma codeseg main_01_TEXT
extern "C" {
#include "th05/th05.hpp"
#include "th05/player/shot.h"
#include "th05/i_shot.hpp"
#define cycle _AL
void pascal near shot_mima_l2(void)

View File

@ -6,7 +6,7 @@
#pragma codeseg main_01_TEXT
extern "C" {
#include "th05/th05.hpp"
#include "th05/i_shot.hpp"
#define cycle _AL
#define YUUKA_INNER_L4 \

View File

@ -1,17 +0,0 @@
// We *really* want to fit those on a line...
#define OPT_L shot->from_option_l()
#define OPT_R shot->from_option_r()
#define MISSILE_L shot->type = ST_MISSILE_LEFT
#define MISSILE_R shot->type = ST_MISSILE_RIGHT
#define MISSILE_S shot->type = ST_MISSILE_STRAIGHT
#define VELOCITY_X(screen_x) shot->pos.velocity.x = screen_x;
#define VELOCITY_Y(screen_y) shot->pos.velocity.y = screen_y;
#define VELOCITY_XY(screen_x, screen_y) \
VELOCITY_X(screen_x); \
VELOCITY_Y(screen_y);
#define VELOCITY_YX(screen_y, screen_x) \
VELOCITY_Y(screen_y); \
VELOCITY_X(screen_x);

72
th05/player/shot.hpp Normal file
View File

@ -0,0 +1,72 @@
#include "th04/player/shot.hpp"
// Shot types
#define ST_NORMAL 0
#define ST_HOMING 1
#define ST_MISSILE_LEFT 2
#define ST_MISSILE_RIGHT 3
#define ST_MISSILE_STRAIGHT 4
// Shot cycle bitflags
#define SC_1X 0x8 // Triggered 1× per cycle
#define SC_2X 0x2 // Triggered 2× per cycle
#define SC_3X 0x1 // Triggered 3× per cycle
#define SC_6X 0x4 // Triggered 6× per cycle
// Returns the current shot cycle, and prepares everything for more shots
// being added.
char pascal near shot_cycle_init(void);
// Common per-iteration data for shot type control functions.
// (Yeah, code generation mandated additions to [i] to be wrapped into
// functions, so why not bundle all of the rather intricate shot handling
// stuff as well.)
struct ShotAddIterator {
unsigned char angle;
unsigned char i;
ShotAddIterator(unsigned char count)
: i(count) {
}
void add_secondary(unsigned char n) {
i += n;
}
unsigned char next(void) {
return i -= 1;
}
};
// Requires [cycle] to be defined in some way. (It's _AL in the original game,
// and I didn't want to pollute the namespace)
#define SHOT_FUNC_INIT(count, primary_cycle, secondary_cycle, secondary_offset_expr) \
shot_t near *shot; \
ShotAddIterator sai(count); \
\
cycle = shot_cycle_init(); \
if((cycle & (primary_cycle | secondary_cycle)) == 0) { \
return; \
} \
if(cycle & secondary_cycle) { \
sai.secondary_offset_expr; \
}
// -----
// We *really* want to fit those on a line...
#define OPT_L shot->from_option_l()
#define OPT_R shot->from_option_r()
#define MISSILE_L shot->type = ST_MISSILE_LEFT
#define MISSILE_R shot->type = ST_MISSILE_RIGHT
#define MISSILE_S shot->type = ST_MISSILE_STRAIGHT
#define VELOCITY_X(screen_x) shot->pos.velocity.x = screen_x;
#define VELOCITY_Y(screen_y) shot->pos.velocity.y = screen_y;
#define VELOCITY_XY(screen_x, screen_y) \
VELOCITY_X(screen_x); \
VELOCITY_Y(screen_y);
#define VELOCITY_YX(screen_y, screen_x) \
VELOCITY_Y(screen_y); \
VELOCITY_X(screen_x);

View File

@ -11,64 +11,6 @@
bb_seg_t pascal near bb_load(const char far *fn);
/// -------
/// Player
/// ------
// Shots
// -----
// Shot types
#define ST_NORMAL 0
#define ST_HOMING 1
#define ST_MISSILE_LEFT 2
#define ST_MISSILE_RIGHT 3
#define ST_MISSILE_STRAIGHT 4
// Shot cycle bitflags
#define SC_1X 0x8 // Triggered 1× per cycle
#define SC_2X 0x2 // Triggered 2× per cycle
#define SC_3X 0x1 // Triggered 3× per cycle
#define SC_6X 0x4 // Triggered 6× per cycle
// Returns the current shot cycle, and prepares everything for more shots
// being added.
char pascal near shot_cycle_init(void);
// Common per-iteration data for shot type control functions.
// (Yeah, code generation mandated additions to [i] to be wrapped into
// functions, so why not bundle all of the rather intricate shot handling
// stuff as well.)
struct ShotAddIterator {
unsigned char angle;
unsigned char i;
ShotAddIterator(unsigned char count)
: i(count) {
}
void add_secondary(unsigned char n) {
i += n;
}
unsigned char next(void) {
return i -= 1;
}
};
// Requires [cycle] to be defined in some way. (It's _AL in the original game,
// and I didn't want to pollute the namespace)
#define SHOT_FUNC_INIT(count, primary_cycle, secondary_cycle, secondary_offset_expr) \
shot_t near *shot; \
ShotAddIterator sai(count); \
\
cycle = shot_cycle_init(); \
if((cycle & (primary_cycle | secondary_cycle)) == 0) { \
return; \
} \
if(cycle & secondary_cycle) { \
sai.secondary_offset_expr; \
}
// -----
/// ------
/// Stages
/// ------
void pascal near stage2_update(void);