|
|
@ -73,6 +73,12 @@ static Glyph glyphs_add(Glyph a, Glyph b) { |
|
|
|
return indexed_glyphs[(ia + ib) % Glyphs_index_max]; |
|
|
|
} |
|
|
|
|
|
|
|
static inline bool glyph_is_lowercase(Glyph g) { return g & (1 << 5); } |
|
|
|
//static inline bool glyph_is_uppercase(Glyph g) { return (g & (1 << 5)) == 0; }
|
|
|
|
static inline Glyph glyph_lowered_unsafe(Glyph g) { |
|
|
|
return (Glyph)(g | (1 << 5)); |
|
|
|
} |
|
|
|
|
|
|
|
ORCA_PURE static bool oper_has_neighboring_bang(Glyph const* gbuf, Usz h, Usz w, |
|
|
|
Usz y, Usz x) { |
|
|
|
Glyph const* gp = gbuf + w * y + x; |
|
|
@ -136,34 +142,6 @@ static ORCA_FORCE_NO_INLINE U8 midi_velocity_of(Glyph g) { |
|
|
|
return (U8)(n * 5 - 3); |
|
|
|
} |
|
|
|
|
|
|
|
ORCA_FORCE_NO_INLINE |
|
|
|
static void oper_movement_phase0(Gbuffer gbuf, Mbuffer mbuf, Usz const height, |
|
|
|
Usz const width, Usz const y, Usz const x, |
|
|
|
Mark const cell_flags, |
|
|
|
Glyph const uppercase_char, |
|
|
|
Glyph const actual_char, Isz const delta_y, |
|
|
|
Isz const delta_x) { |
|
|
|
if (cell_flags & (Mark_flag_lock | Mark_flag_sleep)) |
|
|
|
return; |
|
|
|
if ((actual_char != uppercase_char) && |
|
|
|
!oper_has_neighboring_bang(gbuf, height, width, y, x)) |
|
|
|
return; |
|
|
|
Isz y0 = (Isz)y + delta_y; |
|
|
|
Isz x0 = (Isz)x + delta_x; |
|
|
|
if (y0 >= (Isz)height || x0 >= (Isz)width || y0 < 0 || x0 < 0) { |
|
|
|
gbuf[y * width + x] = '*'; |
|
|
|
return; |
|
|
|
} |
|
|
|
Glyph* restrict g_at_dest = gbuf + (Usz)y0 * width + (Usz)x0; |
|
|
|
if (*g_at_dest == '.') { |
|
|
|
*g_at_dest = actual_char; |
|
|
|
gbuf[y * width + x] = '.'; |
|
|
|
mbuf[(Usz)y0 * width + (Usz)x0] |= Mark_flag_sleep; |
|
|
|
} else { |
|
|
|
gbuf[y * width + x] = '*'; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
typedef struct { |
|
|
|
Bank* bank; |
|
|
|
Usz bank_size; |
|
|
@ -279,13 +257,13 @@ Usz usz_clamp(Usz val, Usz min, Usz max) { |
|
|
|
(void)cell_flags; \ |
|
|
|
(void)This_oper_char; |
|
|
|
|
|
|
|
#define OPER_PHASE_SPEC ORCA_FORCE_NO_INLINE static |
|
|
|
#define OPER_FUNCTION_ATTRIBS ORCA_FORCE_NO_INLINE static void |
|
|
|
|
|
|
|
#define BEGIN_UNIQUE_OPERATOR(_oper_name) \ |
|
|
|
OPER_PHASE_SPEC void oper_behavior_##_oper_name(OPER_PHASE_COMMON_ARGS) { \ |
|
|
|
OPER_FUNCTION_ATTRIBS oper_behavior_##_oper_name(OPER_PHASE_COMMON_ARGS) { \ |
|
|
|
OPER_IGNORE_COMMON_ARGS() |
|
|
|
#define BEGIN_OPERATOR(_oper_name) \ |
|
|
|
OPER_PHASE_SPEC void oper_behavior_##_oper_name(OPER_PHASE_COMMON_ARGS) { \ |
|
|
|
OPER_FUNCTION_ATTRIBS oper_behavior_##_oper_name(OPER_PHASE_COMMON_ARGS) { \ |
|
|
|
OPER_IGNORE_COMMON_ARGS() \ |
|
|
|
enum { Uppercase_oper_char = Orca_oper_upper_char_##_oper_name }; \ |
|
|
|
(void)Uppercase_oper_char; |
|
|
@ -404,6 +382,47 @@ ORCA_DECLARE_OPERATORS(ORCA_SOLO_OPERATORS, ORCA_DUAL_OPERATORS, |
|
|
|
'N' : case 'n' : case 'E' : case 'e' : case 'S' : case 's' : case 'W' \ |
|
|
|
: case 'w' |
|
|
|
|
|
|
|
OPER_FUNCTION_ATTRIBS oper_behavior_movement(OPER_PHASE_COMMON_ARGS) { |
|
|
|
OPER_IGNORE_COMMON_ARGS() |
|
|
|
if (cell_flags & (Mark_flag_lock | Mark_flag_sleep)) |
|
|
|
return; |
|
|
|
if (glyph_is_lowercase(This_oper_char) && |
|
|
|
!oper_has_neighboring_bang(gbuffer, height, width, y, x)) |
|
|
|
return; |
|
|
|
|
|
|
|
Isz delta_y, delta_x; |
|
|
|
|
|
|
|
switch (glyph_lowered_unsafe(This_oper_char)) { |
|
|
|
#define EXPAND_MOV_CASE(_glyph_upper, _glyph_lower, _oper_name, _delta_y, \ |
|
|
|
_delta_x) \ |
|
|
|
case _glyph_lower: \ |
|
|
|
delta_y = _delta_y; \ |
|
|
|
delta_x = _delta_x; \ |
|
|
|
break; |
|
|
|
ORCA_MOVEMENT_OPERATORS(EXPAND_MOV_CASE) |
|
|
|
#undef ExPAND_MOV_CASE |
|
|
|
default: |
|
|
|
// could cause strict aliasing problem, maybe
|
|
|
|
delta_y = 0; |
|
|
|
delta_x = 0; |
|
|
|
break; |
|
|
|
} |
|
|
|
Isz y0 = (Isz)y + delta_y; |
|
|
|
Isz x0 = (Isz)x + delta_x; |
|
|
|
if (y0 >= (Isz)height || x0 >= (Isz)width || y0 < 0 || x0 < 0) { |
|
|
|
gbuffer[y * width + x] = '*'; |
|
|
|
return; |
|
|
|
} |
|
|
|
Glyph* restrict g_at_dest = gbuffer + (Usz)y0 * width + (Usz)x0; |
|
|
|
if (*g_at_dest == '.') { |
|
|
|
*g_at_dest = This_oper_char; |
|
|
|
gbuffer[y * width + x] = '.'; |
|
|
|
mbuffer[(Usz)y0 * width + (Usz)x0] |= Mark_flag_sleep; |
|
|
|
} else { |
|
|
|
gbuffer[y * width + x] = '*'; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
BEGIN_UNIQUE_OPERATOR(keys) |
|
|
|
BEGIN_ACTIVE_PORTS |
|
|
|
PORT(0, 1, IN); |
|
|
@ -1072,10 +1091,7 @@ END_OPERATOR |
|
|
|
#define SIM_EXPAND_MOVM_PHASE_0(_upper_oper_char, _lower_oper_char, \ |
|
|
|
_oper_name, _delta_y, _delta_x) \ |
|
|
|
case _upper_oper_char: \ |
|
|
|
case _lower_oper_char: \ |
|
|
|
oper_movement_phase0(gbuf, mbuf, height, width, iy, ix, cell_flags, \ |
|
|
|
_upper_oper_char, glyph_char, _delta_y, _delta_x); \ |
|
|
|
break; |
|
|
|
case _lower_oper_char: |
|
|
|
|
|
|
|
void orca_run(Gbuffer gbuf, Mbuffer mbuf, Usz height, Usz width, |
|
|
|
Usz tick_number, Bank* bank, Oevent_list* oevent_list, |
|
|
@ -1103,7 +1119,11 @@ void orca_run(Gbuffer gbuf, Mbuffer mbuf, Usz height, Usz width, |
|
|
|
switch (glyph_char) { |
|
|
|
ORCA_SOLO_OPERATORS(SIM_EXPAND_SOLO_PHASE_0) |
|
|
|
ORCA_DUAL_OPERATORS(SIM_EXPAND_DUAL_PHASE_0) |
|
|
|
|
|
|
|
ORCA_MOVEMENT_OPERATORS(SIM_EXPAND_MOVM_PHASE_0) |
|
|
|
oper_behavior_movement(gbuf, mbuf, height, width, iy, ix, tick_number, |
|
|
|
&extras, cell_flags, glyph_char); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|