Browse Source

more multiplayer preparations, packet tx rx

Thomas B 1 month ago
parent
commit
082923aca8
5 changed files with 160 additions and 53 deletions
  1. 2
    2
      Makefile
  2. 14
    4
      src/game.c
  3. 5
    0
      src/game.h
  4. 138
    46
      src/multiplayer.c
  5. 1
    1
      src/multiplayer.h

+ 2
- 2
Makefile View File

@@ -48,8 +48,8 @@ PNGA := $(GBDK_HOME)/bin/png2asset
48 48
 ROMU := $(GBDK_HOME)/bin/romusage
49 49
 GB_EMU := gearboy
50 50
 SGB_EMU := sameboy
51
-BGB_EMU := wine ~/bin/bgb/bgb.exe
52
-GBE_EMU := wine ~/bin/gbe/gbe_plus_qt.exe
51
+BGB_EMU := ~/bin/bgb/bgb.exe
52
+GBE_EMU := ~/bin/gbe/gbe_plus_qt.exe
53 53
 FLASHER := flashgbx
54 54
 
55 55
 LCCFLAGS := -Wa-l -Wl-m -Wp-MMD -Wf--opt-code-speed

+ 14
- 4
src/game.c View File

@@ -138,6 +138,19 @@ static void show_explosion(uint16_t power) NONBANKED {
138 138
     }
139 139
 }
140 140
 
141
+void game_get_mp_state(void) NONBANKED {
142
+    // TODO pass own pos to mp
143
+    //mp_new_state();
144
+}
145
+
146
+void game_set_mp_player2(struct mp_player_state *state) NONBANKED {
147
+    // TODO update p2 pos
148
+}
149
+
150
+void game_set_mp_shot(struct mp_shot_state *state) NONBANKED {
151
+    // TODO add shot
152
+}
153
+
141 154
 int32_t game(enum GAME_MODE mode) NONBANKED {
142 155
     snd_music_off();
143 156
     snd_note_off();
@@ -180,10 +193,7 @@ int32_t game(enum GAME_MODE mode) NONBANKED {
180 193
         key_read();
181 194
 
182 195
         if (mode != GM_SINGLE) {
183
-            if (mp_handle()) {
184
-                // TODO
185
-                //mp_new_state();
186
-            }
196
+            mp_handle();
187 197
         }
188 198
 
189 199
         enum ACCELERATION acc = 0;

+ 5
- 0
src/game.h View File

@@ -21,6 +21,7 @@
21 21
 #define __GAME_H__
22 22
 
23 23
 #include <stdint.h>
24
+#include "multiplayer.h"
24 25
 
25 26
 #define HEALTH_MAX 0x1FF
26 27
 #define HEALTH_SHIFT 1
@@ -33,6 +34,10 @@ enum GAME_MODE {
33 34
     GM_MULTI,
34 35
 };
35 36
 
37
+void game_get_mp_state(void);
38
+void game_set_mp_player2(struct mp_player_state *state);
39
+void game_set_mp_shot(struct mp_shot_state *state);
40
+
36 41
 int32_t game(enum GAME_MODE mode);
37 42
 
38 43
 #endif // __GAME_H__

+ 138
- 46
src/multiplayer.c View File

@@ -17,6 +17,8 @@
17 17
  * See <http://www.gnu.org/licenses/>.
18 18
  */
19 19
 
20
+#include <gbdk/emu_debug.h>
21
+
20 22
 #include "game.h"
21 23
 #include "timer.h"
22 24
 #include "multiplayer.h"
@@ -24,7 +26,8 @@
24 26
 #define MASTER_HELLO 0x42
25 27
 #define SLAVE_HELLO 0x23
26 28
 
27
-#define RETRANSMIT_TIME 200
29
+#define RETRANSMIT_TIME_HELLO 200
30
+#define RETRANSMIT_TIME_GAME 10
28 31
 
29 32
 #define PKT_TYPE_PLAYER 0x00
30 33
 #define PKT_TYPE_SHOT 0x01
@@ -38,12 +41,9 @@ struct mp_packet {
38 41
     union {
39 42
         struct mp_player_state player;
40 43
         struct mp_shot_state shot;
41
-    } data;
44
+    };
42 45
 };
43 46
 
44
-#define PKT_SIZE_PLAYER (sizeof(struct mp_player_state) + sizeof(struct mp_header))
45
-#define PKT_SIZE_SHOT (sizeof(struct mp_shot_state) + sizeof(struct mp_header))
46
-
47 47
 enum mp_state {
48 48
     MP_M_SEND = 0,
49 49
     MP_M_WAIT = 1,
@@ -58,14 +58,10 @@ static enum mp_state state = 0;
58 58
 static uint16_t next_t = 0;
59 59
 static uint8_t our_turn = 0;
60 60
 
61
-static uint8_t *data = NULL;
62
-static uint8_t remaining = 0;
63
-
64
-static uint8_t rx_buff[sizeof(struct mp_packet)] = {0};
65
-static uint8_t rx_len = 0;
66
-
67 61
 uint8_t mp_connection_status = 0;
68 62
 
63
+static void mp_game_init(void);
64
+
69 65
 static inline void Tx(uint8_t x) {
70 66
     SB_REG = x;
71 67
     SC_REG = SIOF_XFER_START | SIOF_CLOCK_INT;
@@ -76,23 +72,19 @@ static inline void Rx(uint8_t x) {
76 72
     SC_REG = SIOF_XFER_START | SIOF_CLOCK_EXT;
77 73
 }
78 74
 
79
-static inline void tx_rx(uint8_t x) {
80
-    our_turn ? Tx(x) : Rx(x);
81
-}
82
-
83
-static inline void transmit(struct mp_packet *pkt) {
84
-
85
-}
86
-
87 75
 static inline uint8_t transmitting(void) {
88 76
     return SC_REG & SIOF_XFER_START;
89 77
 }
90 78
 
79
+// ----------------------------------------------------------------------------
80
+// Initial Handshake
81
+// ----------------------------------------------------------------------------
82
+
91 83
 uint8_t mp_master_ready(void) BANKED {
92 84
     switch (state) {
93 85
         case MP_M_SEND:
94 86
             Tx(MASTER_HELLO);
95
-            next_t = timer_get() + RETRANSMIT_TIME;
87
+            next_t = timer_get() + RETRANSMIT_TIME_HELLO;
96 88
             mp_connection_status++;
97 89
             state = MP_M_WAIT;
98 90
             break;
@@ -101,7 +93,7 @@ uint8_t mp_master_ready(void) BANKED {
101 93
             if (!transmitting()) {
102 94
                 if (SB_REG == SLAVE_HELLO) {
103 95
                     Rx(SLAVE_HELLO);
104
-                    next_t = timer_get() + RETRANSMIT_TIME;
96
+                    next_t = timer_get() + RETRANSMIT_TIME_HELLO;
105 97
                     mp_connection_status++;
106 98
                     state = MP_M_REPLY;
107 99
                 }
@@ -134,11 +126,8 @@ uint8_t mp_master_ready(void) BANKED {
134 126
 
135 127
 void mp_master_start(void) BANKED {
136 128
     our_turn = 1;
137
-    remaining = 0;
138
-    next_t = timer_get() + RETRANSMIT_TIME;
139
-
129
+    mp_game_init();
140 130
     game(GM_MULTI);
141
-
142 131
     state = 0;
143 132
 }
144 133
 
@@ -146,7 +135,7 @@ uint8_t mp_slave_ready(void) BANKED {
146 135
     switch (state) {
147 136
         case MP_S_START:
148 137
             Rx(SLAVE_HELLO);
149
-            next_t = timer_get() + RETRANSMIT_TIME;
138
+            next_t = timer_get() + RETRANSMIT_TIME_HELLO;
150 139
             mp_connection_status++;
151 140
             state = MP_S_WAIT;
152 141
             break;
@@ -155,7 +144,7 @@ uint8_t mp_slave_ready(void) BANKED {
155 144
             if (!transmitting()) {
156 145
                 if (SB_REG == MASTER_HELLO) {
157 146
                     Tx(MASTER_HELLO);
158
-                    next_t = timer_get() + RETRANSMIT_TIME;
147
+                    next_t = timer_get() + RETRANSMIT_TIME_HELLO;
159 148
                     mp_connection_status++;
160 149
                     state = MP_S_REPLY;
161 150
                 } else {
@@ -188,36 +177,139 @@ uint8_t mp_slave_ready(void) BANKED {
188 177
 
189 178
 void mp_slave_start(void) BANKED {
190 179
     our_turn = 0;
191
-    remaining = 0;
192
-    next_t = timer_get() + RETRANSMIT_TIME;
193
-
180
+    mp_game_init();
194 181
     game(GM_MULTI);
195
-
196 182
     state = 0;
197 183
 }
198 184
 
199
-uint8_t mp_handle(void) BANKED {
200
-    if ((our_turn) && (timer_get() >= next_t) && data && (remaining > 0)) {
201
-        if (rx_len < sizeof(struct mp_packet)) {
202
-            rx_buff[rx_len++] = SB_REG;
203
-        }
204
-        tx_rx(*(data++));
205
-        remaining--;
206
-    } else if ((!our_turn) && (!transmitting()) && data && (remaining > 0)) {
207
-        if (rx_len < sizeof(struct mp_packet)) {
208
-            rx_buff[rx_len++] = SB_REG;
185
+// ----------------------------------------------------------------------------
186
+// Game Runtime
187
+// ----------------------------------------------------------------------------
188
+
189
+#define QUEUE_LEN 5
190
+
191
+static struct mp_packet queue[QUEUE_LEN];
192
+static uint8_t q_head = 0;
193
+static uint8_t q_tail = 0;
194
+static uint8_t q_full = 0;
195
+static uint8_t byte_pos = 0;
196
+
197
+static uint8_t q_len(void) {
198
+    if (q_head == q_tail) {
199
+        if (q_full) {
200
+            return QUEUE_LEN;
201
+        } else {
202
+            return 0;
209 203
         }
210
-        tx_rx(*(data++));
211
-        remaining--;
204
+    } else if (q_head > q_tail) {
205
+        return q_head - q_tail;
206
+    } else {
207
+        return QUEUE_LEN - q_tail + q_head;
212 208
     }
209
+}
213 210
 
214
-    return our_turn && (remaining == 0);
211
+static inline void q_inc_head(void) {
212
+    if (q_full && (++q_tail == QUEUE_LEN)) {
213
+        q_tail = 0;
214
+    }
215
+    if (++q_head == QUEUE_LEN) {
216
+        q_head = 0;
217
+    }
218
+    q_full = (q_head == q_tail);
219
+}
220
+
221
+static inline void q_inc_tail(void) {
222
+    q_tail++;
223
+    if (q_tail >= QUEUE_LEN) {
224
+        q_tail = 0;
225
+    }
226
+}
227
+
228
+static void mp_game_init(void) {
229
+    q_head = 0;
230
+    q_tail = 0;
231
+    q_full = 0;
232
+    byte_pos = sizeof(struct mp_packet); // immediately query packet from game
233
+    next_t = timer_get() + RETRANSMIT_TIME_GAME;
234
+}
235
+
236
+static inline void handle_rx(struct mp_packet *pkt) {
237
+    switch (pkt->header.type) {
238
+        case PKT_TYPE_PLAYER:
239
+            game_set_mp_player2(&pkt->player);
240
+            break;
241
+
242
+        case PKT_TYPE_SHOT:
243
+            game_set_mp_shot(&pkt->shot);
244
+            break;
245
+
246
+        default:
247
+#ifdef DEBUG
248
+            EMU_printf("%s: unknown type %hx\n", __func__, (uint8_t)pkt->header.type);
249
+#endif // DEBUG
250
+            break;
251
+    }
252
+}
253
+
254
+static inline void tx_rx(uint8_t x) {
255
+    our_turn ? Tx(x) : Rx(x);
256
+    next_t = timer_get() + RETRANSMIT_TIME_GAME;
257
+}
258
+
259
+void mp_handle(void) BANKED {
260
+    // ensure we always have something in the queue
261
+    if ((q_len() == 0) && (byte_pos >= sizeof(struct mp_packet))) {
262
+        game_get_mp_state();
263
+    }
264
+
265
+    if (byte_pos < sizeof(struct mp_packet)) {
266
+        if ((our_turn && (timer_get() >= next_t)) || ((!our_turn) && (!transmitting()))) {
267
+            uint8_t to_send = ((uint8_t *)(&queue[q_tail]))[byte_pos];
268
+            ((uint8_t *)(&queue[q_tail]))[byte_pos] = SB_REG;
269
+            tx_rx(to_send);
270
+
271
+            byte_pos++;
272
+            if (byte_pos >= sizeof(struct mp_packet)) {
273
+                handle_rx(&queue[q_tail]);
274
+                q_inc_tail();
275
+                if (q_len() > 0) {
276
+                    byte_pos = 0; // keep going
277
+                }
278
+            }
279
+
280
+            our_turn = our_turn ? 0 : 1;
281
+        }
282
+    }
215 283
 }
216 284
 
217 285
 void mp_new_state(struct mp_player_state *state) BANKED {
218
-    // TODO
286
+#ifdef DEBUG
287
+    if (q_full) {
288
+        EMU_printf("%s: queue overflow\n", __func__);
289
+    }
290
+#endif // DEBUG
291
+
292
+    queue[q_head].header.type = PKT_TYPE_PLAYER;
293
+    queue[q_head].player = *state;
294
+    q_inc_head();
295
+
296
+    if ((q_len() == 1) && (byte_pos >= sizeof(struct mp_packet))) {
297
+        byte_pos = 0; // start transmitting
298
+    }
219 299
 }
220 300
 
221 301
 void mp_add_shot(struct mp_shot_state *state) BANKED {
222
-    // TODO
302
+#ifdef DEBUG
303
+    if (q_full) {
304
+        EMU_printf("%s: queue overflow\n", __func__);
305
+    }
306
+#endif // DEBUG
307
+
308
+    queue[q_head].header.type = PKT_TYPE_SHOT;
309
+    queue[q_head].shot = *state;
310
+    q_inc_head();
311
+
312
+    if ((q_len() == 1) && (byte_pos >= sizeof(struct mp_packet))) {
313
+        byte_pos = 0; // start transmitting
314
+    }
223 315
 }

+ 1
- 1
src/multiplayer.h View File

@@ -42,7 +42,7 @@ void mp_master_start(void) BANKED;
42 42
 uint8_t mp_slave_ready(void) BANKED;
43 43
 void mp_slave_start(void) BANKED;
44 44
 
45
-uint8_t mp_handle(void) BANKED;
45
+void mp_handle(void) BANKED;
46 46
 
47 47
 void mp_new_state(struct mp_player_state *state) BANKED;
48 48
 void mp_add_shot(struct mp_shot_state *state) BANKED;

Loading…
Cancel
Save