shithub: orca

Download patch

ref: 5578e46dce7b516ea5288ebf4c7cdf9562203c47
parent: fc2322e323d6dcc00fa413c8afc9de177c9652dc
author: cancel <cancel@cancel.fm>
date: Sat Dec 29 12:13:30 EST 2018

Cleanup movement operator dispatch

--- a/sim.c
+++ b/sim.c
@@ -73,6 +73,12 @@
   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 @@
   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 @@
   (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 @@
   '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 @@
 #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 @@
       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;
       }
     }
   }