Browse Source

add continue / save-game feature

Thomas B 2 weeks ago
parent
commit
bc8b857641
16 changed files with 420 additions and 379 deletions
  1. BIN
      data/sfx_damage.wav
  2. BIN
      data/sfx_heal.wav
  3. 0
    8
      docs/index.html
  4. 2
    0
      src/config.ba0.c
  5. 23
    11
      src/config.h
  6. 116
    183
      src/game.c
  7. 17
    7
      src/game.h
  8. 72
    8
      src/main.c
  9. 5
    5
      src/map_data.h
  10. 95
    139
      src/obj.c
  11. 55
    3
      src/obj.h
  12. 8
    0
      src/strings.c
  13. 4
    0
      src/strings.h
  14. 6
    7
      src/timer.c
  15. 16
    8
      src/window.c
  16. 1
    0
      src/window.h

BIN
data/sfx_damage.wav View File


BIN
data/sfx_heal.wav View File


+ 0
- 8
docs/index.html View File

157
                 2: {},
157
                 2: {},
158
                 3: {}
158
                 3: {}
159
             };
159
             };
160
-            EJS_onGameStart = function(e) {
161
-                setTimeout(function() {
162
-                    window.EJS_emulator.gameManager.simulateInput(0, 3, 1);
163
-                    setTimeout(function() {
164
-                        window.EJS_emulator.gameManager.simulateInput(0, 3, 0);
165
-                    }, 42);
166
-                }, 420);
167
-            };
168
             EJS_startButtonName = "Start Duality";
160
             EJS_startButtonName = "Start Duality";
169
         </script>
161
         </script>
170
         <script src="https://cdn.emulatorjs.org/stable/data/loader.js"></script>
162
         <script src="https://cdn.emulatorjs.org/stable/data/loader.js"></script>

+ 2
- 0
src/config.ba0.c View File

65
         mem.config.dmg_bg_inv = 1;
65
         mem.config.dmg_bg_inv = 1;
66
 
66
 
67
         score_reset();
67
         score_reset();
68
+
69
+        mem.state.in_progress = 0;
68
     }
70
     }
69
 }
71
 }
70
 
72
 

+ 23
- 11
src/config.h View File

23
 #include <gbdk/platform.h>
23
 #include <gbdk/platform.h>
24
 #include <stdint.h>
24
 #include <stdint.h>
25
 
25
 
26
+#include "game.h"
26
 #include "score.h"
27
 #include "score.h"
28
+#include "obj.h"
27
 
29
 
28
 enum debug_flag {
30
 enum debug_flag {
29
     DBG_NONE = 0,
31
     DBG_NONE = 0,
30
 
32
 
31
-    DBG_MENU        = (1 << 0),
32
-    DBG_MARKER      = (1 << 1),
33
-    DBG_GOD_MODE    = (1 << 2),
34
-    DBG_NO_OBJ      = (1 << 3),
35
-    DBG_NO_FUEL     = (1 << 4),
36
-    DBG_FAST        = (1 << 5),
37
-    DBG_SHOW_FPS    = (1 << 6),
38
-    DBG_SHOW_FRAMES = (1 << 7),
39
-    DBG_SHOW_TIMER  = (1 << 8),
40
-    DBG_SHOW_STACK  = (1 << 9),
33
+    DBG_MENU        = (1U << 0),
34
+    DBG_MARKER      = (1U << 1),
35
+    DBG_GOD_MODE    = (1U << 2),
36
+    DBG_NO_OBJ      = (1U << 3),
37
+    DBG_NO_FUEL     = (1U << 4),
38
+    DBG_FAST        = (1U << 5),
39
+    DBG_SHOW_FPS    = (1U << 6),
40
+    DBG_SHOW_FRAMES = (1U << 7),
41
+    DBG_SHOW_TIMER  = (1U << 8),
42
+    DBG_SHOW_STACK  = (1U << 9),
41
 };
43
 };
42
 
44
 
43
 #define DBG_OUT_ON (DBG_SHOW_FPS | DBG_SHOW_FRAMES | DBG_SHOW_TIMER | DBG_SHOW_STACK)
45
 #define DBG_OUT_ON (DBG_SHOW_FPS | DBG_SHOW_FRAMES | DBG_SHOW_TIMER | DBG_SHOW_STACK)
44
 
46
 
45
 struct config {
47
 struct config {
46
     enum debug_flag debug_flags;
48
     enum debug_flag debug_flags;
49
+
47
     //uint8_t sfx_vol;
50
     //uint8_t sfx_vol;
48
     uint8_t music_vol;
51
     uint8_t music_vol;
49
     uint8_t game_bg;
52
     uint8_t game_bg;
50
     uint8_t dmg_bg_inv;
53
     uint8_t dmg_bg_inv;
51
 };
54
 };
52
 
55
 
56
+struct state {
57
+    uint8_t in_progress;
58
+    struct game_state state_game;
59
+    struct obj_state state_obj;
60
+};
61
+
53
 void conf_init(void) BANKED;
62
 void conf_init(void) BANKED;
54
 void conf_write_crc(void) BANKED;
63
 void conf_write_crc(void) BANKED;
55
 
64
 
58
 struct config_mem {
67
 struct config_mem {
59
     struct config config;
68
     struct config config;
60
     struct scores scores[SCORE_NUM * 2];
69
     struct scores scores[SCORE_NUM * 2];
70
+    struct state state;
61
 
71
 
62
     uint32_t crc; // needs to be last
72
     uint32_t crc; // needs to be last
63
 };
73
 };
64
 
74
 
65
 extern struct config_mem mem;
75
 extern struct config_mem mem;
76
+
77
+#define conf_get()    (&mem.config)
66
 #define conf_scores() (mem.scores)
78
 #define conf_scores() (mem.scores)
67
-#define conf_get() (&mem.config)
79
+#define conf_state()  (&mem.state)
68
 
80
 
69
 #endif // __CONFIG_H__
81
 #endif // __CONFIG_H__

+ 116
- 183
src/game.c View File

18
  */
18
  */
19
 
19
 
20
 #include <gbdk/metasprites.h>
20
 #include <gbdk/metasprites.h>
21
+#include <string.h>
21
 #include <rand.h>
22
 #include <rand.h>
22
 #include <stdint.h>
23
 #include <stdint.h>
23
 
24
 
45
 #define SPEED_INC 1
46
 #define SPEED_INC 1
46
 #define SPEED_DEC 1
47
 #define SPEED_DEC 1
47
 
48
 
48
-#define SPEED_MAX_ACC 23
49
-#define SPEED_MAX_ACC_DIAG 16
50
-#define SPEED_MAX_ACC_D_LO 9
51
-#define SPEED_MAX_ACC_D_HI 21
52
 #define SPEED_MAX_IDLE 16
49
 #define SPEED_MAX_IDLE 16
53
 #define SPEED_MAX_DBG 256
50
 #define SPEED_MAX_DBG 256
54
 
51
 
60
 
57
 
61
 BANKREF(game)
58
 BANKREF(game)
62
 
59
 
60
+const int8_t table_shot_offsets[ROT_INVALID * 2] = {
61
+    0,                 -SHIP_OFF,         // 0.0
62
+    SHIP_OFF / 2 - 1,  -SHIP_OFF / 2 - 4, // 22.5
63
+    SHIP_OFF / 2 + 3,  -SHIP_OFF / 2 - 2, // 45.0
64
+    SHIP_OFF / 2 + 5,  -SHIP_OFF / 2 + 2, // 67.5
65
+    SHIP_OFF,          0,                 // 90.0
66
+    SHIP_OFF / 2 + 5,  SHIP_OFF / 2 + 0,  // 112.5
67
+    SHIP_OFF / 2 + 3,  SHIP_OFF / 2 + 2,  // 135.0
68
+    SHIP_OFF / 2 + 1,  SHIP_OFF / 2 + 4,  // 157.5
69
+    0,                 SHIP_OFF,          // 180.0
70
+    -SHIP_OFF / 2 + 2, SHIP_OFF / 2 + 3,  // 202.5
71
+    -SHIP_OFF / 2 - 3, SHIP_OFF / 2 + 2,  // 225.0
72
+    -SHIP_OFF / 2 - 5, SHIP_OFF / 2 - 1,  // 247.5
73
+    -SHIP_OFF,         0,                 // 270.0
74
+    -SHIP_OFF / 2 - 2, -SHIP_OFF / 2 + 2, // 292.5
75
+    -SHIP_OFF / 2 - 3, -SHIP_OFF / 2 - 2, // 315.0
76
+    -SHIP_OFF / 2 + 1, -SHIP_OFF / 2 - 4, // 337.5
77
+};
78
+
63
 enum ACCELERATION {
79
 enum ACCELERATION {
64
-    ACC_X = 1,
65
-    ACC_Y = 2,
66
-    ACC_R = 4,
80
+    ACC_X = (1U << 1),
81
+    ACC_Y = (1U << 2),
82
+    ACC_R = (1U << 3),
67
 };
83
 };
68
 
84
 
69
-static int16_t spd_x = 0, spd_y = 0;
70
-static enum SPRITE_ROT rot = 0;
71
-static enum ACCELERATION acc = 0;
72
-static uint16_t health = HEALTH_MAX;
73
-static uint16_t power = POWER_MAX;
74
-static int32_t score = 0;
75
-static uint16_t frame_count = 0;
76
 static uint8_t fps_count = 0;
85
 static uint8_t fps_count = 0;
77
 static uint16_t prev_fps_start = 0;
86
 static uint16_t prev_fps_start = 0;
78
-static uint8_t prev_fps = 0;
87
+
88
+struct game_state game_state;
89
+uint16_t frame_count = 0;
90
+uint8_t game_fps = 0;
79
 
91
 
80
 static void calc_fps(void) {
92
 static void calc_fps(void) {
81
     frame_count++;
93
     frame_count++;
83
     uint16_t diff = timer_get() - prev_fps_start;
95
     uint16_t diff = timer_get() - prev_fps_start;
84
     if (diff >= TIMER_HZ) {
96
     if (diff >= TIMER_HZ) {
85
         prev_fps_start = timer_get();
97
         prev_fps_start = timer_get();
86
-        prev_fps = fps_count;
98
+        game_fps = fps_count;
87
         fps_count = 0;
99
         fps_count = 0;
88
     }
100
     }
89
 }
101
 }
90
 
102
 
91
-uint8_t game_get_fps(void) BANKED {
92
-    return prev_fps;
93
-}
94
-
95
-uint16_t game_get_framecount(void) BANKED {
96
-    return frame_count;
97
-}
98
-
99
 static uint8_t pause_screen(void) {
103
 static uint8_t pause_screen(void) {
100
     snd_music_off();
104
     snd_music_off();
101
     snd_note_off();
105
     snd_note_off();
118
         hide_sprites_range(hiwater, MAX_HARDWARE_SPRITES);
122
         hide_sprites_range(hiwater, MAX_HARDWARE_SPRITES);
119
 
123
 
120
         if ((_cpu == CGB_TYPE) && (conf_get()->debug_flags & DBG_OUT_ON)) {
124
         if ((_cpu == CGB_TYPE) && (conf_get()->debug_flags & DBG_OUT_ON)) {
121
-            uint8_t x_off = win_game_draw(score, 0);
122
-            move_win(MINWNDPOSX + DEVICE_SCREEN_PX_WIDTH - x_off, MINWNDPOSY + DEVICE_SCREEN_PX_HEIGHT - 16);
125
+            uint8_t x_off = win_game_draw(game_state.score, 0);
126
+            move_win(MINWNDPOSX + DEVICE_SCREEN_PX_WIDTH - x_off,
127
+                     MINWNDPOSY + DEVICE_SCREEN_PX_HEIGHT - 16);
123
         }
128
         }
124
 
129
 
125
         calc_fps();
130
         calc_fps();
182
 }
187
 }
183
 
188
 
184
 void game_get_mp_state(void) BANKED {
189
 void game_get_mp_state(void) BANKED {
185
-    static struct mp_player_state state;
190
+    static struct mp_player_state mps;
186
 
191
 
187
     // TODO pass own pos to mp
192
     // TODO pass own pos to mp
188
 
193
 
189
     // TODO scale?
194
     // TODO scale?
190
-    state.spd_x = spd_x;
191
-    state.spd_y = spd_y;
195
+    mps.spd_x = game_state.spd_x;
196
+    mps.spd_y = game_state.spd_y;
192
 
197
 
193
-    state.rot = rot;
194
-    mp_new_state(&state);
198
+    mps.rot = game_state.rot;
199
+    mp_new_state(&mps);
195
 }
200
 }
196
 
201
 
197
 void game_set_mp_player2(struct mp_player_state *state) BANKED {
202
 void game_set_mp_player2(struct mp_player_state *state) BANKED {
204
 
209
 
205
 static void get_max_spd(int16_t *max_spd_x, int16_t *max_spd_y) NONBANKED {
210
 static void get_max_spd(int16_t *max_spd_x, int16_t *max_spd_y) NONBANKED {
206
     START_ROM_BANK(BANK(table_speed_move)) {
211
     START_ROM_BANK(BANK(table_speed_move)) {
207
-        *max_spd_x = table_speed_move[(rot * table_speed_move_WIDTH) + 0];
208
-        *max_spd_y = -table_speed_move[(rot * table_speed_move_WIDTH) + 1];
212
+        *max_spd_x = table_speed_move[(game_state.rot * table_speed_move_WIDTH) + 0];
213
+        *max_spd_y = -table_speed_move[(game_state.rot * table_speed_move_WIDTH) + 1];
209
     } END_ROM_BANK;
214
     } END_ROM_BANK;
210
 }
215
 }
211
 
216
 
212
 static void get_shot_spd(int16_t *shot_spd_x, int16_t *shot_spd_y) NONBANKED {
217
 static void get_shot_spd(int16_t *shot_spd_x, int16_t *shot_spd_y) NONBANKED {
213
     START_ROM_BANK(BANK(table_speed_shot)) {
218
     START_ROM_BANK(BANK(table_speed_shot)) {
214
-        *shot_spd_x = table_speed_shot[(rot * table_speed_move_WIDTH) + 0];
215
-        *shot_spd_y = -table_speed_shot[(rot * table_speed_move_WIDTH) + 1];
219
+        *shot_spd_x = table_speed_shot[(game_state.rot * table_speed_move_WIDTH) + 0];
220
+        *shot_spd_y = -table_speed_shot[(game_state.rot * table_speed_move_WIDTH) + 1];
216
     } END_ROM_BANK;
221
     } END_ROM_BANK;
217
 }
222
 }
218
 
223
 
219
-int32_t game(enum GAME_MODE mode) BANKED {
224
+void game_init(void) BANKED {
225
+    game_state.spd_x = 0;
226
+    game_state.spd_y = 0;
227
+    game_state.rot = 0;
228
+    game_state.health = HEALTH_MAX;
229
+    game_state.power = POWER_MAX;
230
+    game_state.score = 0;
231
+    memset(&obj_state, 0, sizeof(struct obj_state));
232
+}
233
+
234
+uint8_t game(enum GAME_MODE mode) BANKED {
220
     snd_music_off();
235
     snd_music_off();
221
     snd_note_off();
236
     snd_note_off();
222
 
237
 
229
     SHOW_SPRITES;
244
     SHOW_SPRITES;
230
     SPRITES_8x8;
245
     SPRITES_8x8;
231
 
246
 
232
-    spd_x = 0;
233
-    spd_y = 0;
234
-    rot = 0;
235
-    health = HEALTH_MAX;
236
-    power = POWER_MAX;
237
-    score = 0;
238
     frame_count = 0;
247
     frame_count = 0;
239
-
240
-    obj_init();
248
+    fps_count = 0;
249
+    prev_fps_start = 0;
241
 
250
 
242
     if (mode == GM_SINGLE) {
251
     if (mode == GM_SINGLE) {
243
         if (!(conf_get()->debug_flags & DBG_NO_OBJ)) {
252
         if (!(conf_get()->debug_flags & DBG_NO_OBJ)) {
245
         }
254
         }
246
     }
255
     }
247
 
256
 
248
-    uint8_t x_off = win_game_draw(score, 1);
249
-    move_win(MINWNDPOSX + DEVICE_SCREEN_PX_WIDTH - x_off, MINWNDPOSY + DEVICE_SCREEN_PX_HEIGHT - 16);
257
+    uint8_t x_off = win_game_draw(game_state.score, 1);
258
+    move_win(MINWNDPOSX + DEVICE_SCREEN_PX_WIDTH - x_off,
259
+             MINWNDPOSY + DEVICE_SCREEN_PX_HEIGHT - 16);
250
 
260
 
251
     SHOW_WIN;
261
     SHOW_WIN;
252
     DISPLAY_ON;
262
     DISPLAY_ON;
254
 
264
 
255
     snd_music(SND_GAME);
265
     snd_music(SND_GAME);
256
 
266
 
267
+    uint8_t return_value = 0xFF;
257
     while(1) {
268
     while(1) {
258
         key_read();
269
         key_read();
259
 
270
 
261
             mp_handle();
272
             mp_handle();
262
         }
273
         }
263
 
274
 
264
-        acc = 0;
265
-        int32_t prev_score = score;
275
+        enum ACCELERATION acc = 0;
276
+        int32_t prev_score = game_state.score;
266
 
277
 
267
         if (key_pressed(J_LEFT)) {
278
         if (key_pressed(J_LEFT)) {
268
-            rot = (rot - 1) & (ROT_INVALID - 1);
279
+            game_state.rot = (game_state.rot - 1) & (ROT_INVALID - 1);
269
             acc |= ACC_R;
280
             acc |= ACC_R;
270
         } else if (key_pressed(J_RIGHT)) {
281
         } else if (key_pressed(J_RIGHT)) {
271
-            rot = (rot + 1) & (ROT_INVALID - 1);
282
+            game_state.rot = (game_state.rot + 1) & (ROT_INVALID - 1);
272
             acc |= ACC_R;
283
             acc |= ACC_R;
273
         }
284
         }
274
 
285
 
275
-        if (key_down(J_A) && (power > 0)) {
286
+        if (key_down(J_A) && (game_state.power > 0)) {
276
             int16_t max_spd_x;
287
             int16_t max_spd_x;
277
             int16_t max_spd_y;
288
             int16_t max_spd_y;
278
             get_max_spd(&max_spd_x, &max_spd_y);
289
             get_max_spd(&max_spd_x, &max_spd_y);
293
 
304
 
294
             if (max_spd_x != 0) {
305
             if (max_spd_x != 0) {
295
                 if (max_spd_x > 0) {
306
                 if (max_spd_x > 0) {
296
-                    spd_x += SPEED_INC;
297
-                    if (spd_x > max_spd_x) {
298
-                        spd_x = max_spd_x;
307
+                    game_state.spd_x += SPEED_INC;
308
+                    if (game_state.spd_x > max_spd_x) {
309
+                        game_state.spd_x = max_spd_x;
299
                     }
310
                     }
300
                 } else {
311
                 } else {
301
-                    spd_x -= SPEED_INC;
302
-                    if (spd_x < max_spd_x) {
303
-                        spd_x = max_spd_x;
312
+                    game_state.spd_x -= SPEED_INC;
313
+                    if (game_state.spd_x < max_spd_x) {
314
+                        game_state.spd_x = max_spd_x;
304
                     }
315
                     }
305
                 }
316
                 }
306
 
317
 
309
 
320
 
310
             if (max_spd_y != 0) {
321
             if (max_spd_y != 0) {
311
                 if (max_spd_y > 0) {
322
                 if (max_spd_y > 0) {
312
-                    spd_y += SPEED_INC;
313
-                    if (spd_y > max_spd_y) {
314
-                        spd_y = max_spd_y;
323
+                    game_state.spd_y += SPEED_INC;
324
+                    if (game_state.spd_y > max_spd_y) {
325
+                        game_state.spd_y = max_spd_y;
315
                     }
326
                     }
316
                 } else {
327
                 } else {
317
-                    spd_y -= SPEED_INC;
318
-                    if (spd_y < max_spd_y) {
319
-                        spd_y = max_spd_y;
328
+                    game_state.spd_y -= SPEED_INC;
329
+                    if (game_state.spd_y < max_spd_y) {
330
+                        game_state.spd_y = max_spd_y;
320
                     }
331
                     }
321
                 }
332
                 }
322
 
333
 
324
             }
335
             }
325
 
336
 
326
             if (!(conf_get()->debug_flags & DBG_NO_FUEL)) {
337
             if (!(conf_get()->debug_flags & DBG_NO_FUEL)) {
327
-                if (power >= POWER_DEC) {
328
-                    power -= POWER_DEC;
338
+                if (game_state.power >= POWER_DEC) {
339
+                    game_state.power -= POWER_DEC;
329
                 } else {
340
                 } else {
330
-                    power = 0;
341
+                    game_state.power = 0;
331
                 }
342
                 }
332
             }
343
             }
333
-        } else if (!key_down(J_A) && (power < POWER_MAX)) {
334
-            if (power <= (POWER_MAX - POWER_INC)) {
335
-                power += POWER_INC;
344
+        } else if (!key_down(J_A) && (game_state.power < POWER_MAX)) {
345
+            if (game_state.power <= (POWER_MAX - POWER_INC)) {
346
+                game_state.power += POWER_INC;
336
             } else {
347
             } else {
337
-                power = POWER_MAX;
348
+                game_state.power = POWER_MAX;
338
             }
349
             }
339
         }
350
         }
340
 
351
 
341
         // adjust speed down when not moving
352
         // adjust speed down when not moving
342
         if (!(acc & ACC_X)) {
353
         if (!(acc & ACC_X)) {
343
-            if (spd_x != 0) {
354
+            if (game_state.spd_x != 0) {
344
                 if (!(conf_get()->debug_flags & DBG_FAST)) {
355
                 if (!(conf_get()->debug_flags & DBG_FAST)) {
345
-                    if (spd_x > SPEED_MAX_IDLE) spd_x -= SPEED_DEC;
346
-                    else if (spd_x < -SPEED_MAX_IDLE) spd_x += SPEED_DEC;
356
+                    if (game_state.spd_x > SPEED_MAX_IDLE) game_state.spd_x -= SPEED_DEC;
357
+                    else if (game_state.spd_x < -SPEED_MAX_IDLE) game_state.spd_x += SPEED_DEC;
347
                 } else {
358
                 } else {
348
-                    spd_x = 0;
359
+                    game_state.spd_x = 0;
349
                 }
360
                 }
350
             }
361
             }
351
         }
362
         }
352
         if (!(acc & ACC_Y)) {
363
         if (!(acc & ACC_Y)) {
353
-            if (spd_y != 0) {
364
+            if (game_state.spd_y != 0) {
354
                 if (!(conf_get()->debug_flags & DBG_FAST)) {
365
                 if (!(conf_get()->debug_flags & DBG_FAST)) {
355
-                    if (spd_y > SPEED_MAX_IDLE) spd_y -= SPEED_DEC;
356
-                    else if (spd_y < -SPEED_MAX_IDLE) spd_y += SPEED_DEC;
366
+                    if (game_state.spd_y > SPEED_MAX_IDLE) game_state.spd_y -= SPEED_DEC;
367
+                    else if (game_state.spd_y < -SPEED_MAX_IDLE) game_state.spd_y += SPEED_DEC;
357
                 } else {
368
                 } else {
358
-                    spd_y = 0;
369
+                    game_state.spd_y = 0;
359
                 }
370
                 }
360
             }
371
             }
361
         }
372
         }
364
             int16_t shot_spd_x;
375
             int16_t shot_spd_x;
365
             int16_t shot_spd_y;
376
             int16_t shot_spd_y;
366
             get_shot_spd(&shot_spd_x, &shot_spd_y);
377
             get_shot_spd(&shot_spd_x, &shot_spd_y);
367
-            shot_spd_x += spd_x;
368
-            shot_spd_y += spd_y;
369
-
370
-            // TODO ugly hard-coded offsets?!
371
-            int16_t shot_pos_x = 0, shot_pos_y = 0;
372
-            switch (rot) {
373
-                case ROT_0:
374
-                    shot_pos_x = 0;
375
-                    shot_pos_y = -SHIP_OFF;
376
-                    break;
377
-
378
-                case ROT_22_5:
379
-                    shot_pos_x = SHIP_OFF / 2 - 1;
380
-                    shot_pos_y = -SHIP_OFF / 2 - 4;
381
-                    break;
382
-
383
-                case ROT_45:
384
-                    shot_pos_x = SHIP_OFF / 2 + 3;
385
-                    shot_pos_y = -SHIP_OFF / 2 - 2;
386
-                    break;
387
-
388
-                case ROT_67_5:
389
-                    shot_pos_x = SHIP_OFF / 2 + 5;
390
-                    shot_pos_y = -SHIP_OFF / 2 + 2;
391
-                    break;
392
-
393
-                case ROT_90:
394
-                    shot_pos_x = SHIP_OFF;
395
-                    shot_pos_y = 0;
396
-                    break;
397
-
398
-                case ROT_112_5:
399
-                    shot_pos_x = SHIP_OFF / 2 + 5;
400
-                    shot_pos_y = SHIP_OFF / 2 + 0;
401
-                    break;
402
-
403
-                case ROT_135:
404
-                    shot_pos_x = SHIP_OFF / 2 + 3;
405
-                    shot_pos_y = SHIP_OFF / 2 + 2;
406
-                    break;
407
-
408
-                case ROT_157_5:
409
-                    shot_pos_x = SHIP_OFF / 2 + 1;
410
-                    shot_pos_y = SHIP_OFF / 2 + 4;
411
-                    break;
412
-
413
-                case ROT_180:
414
-                    shot_pos_x = 0;
415
-                    shot_pos_y = SHIP_OFF;
416
-                    break;
417
-
418
-                case ROT_202_5:
419
-                    shot_pos_x = -SHIP_OFF / 2 + 2;
420
-                    shot_pos_y = SHIP_OFF / 2 + 3;
421
-                    break;
422
-
423
-                case ROT_225:
424
-                    shot_pos_x = -SHIP_OFF / 2 - 3;
425
-                    shot_pos_y = SHIP_OFF / 2 + 2;
426
-                    break;
427
-
428
-                case ROT_247_5:
429
-                    shot_pos_x = -SHIP_OFF / 2 - 5;
430
-                    shot_pos_y = SHIP_OFF / 2 - 1;
431
-                    break;
432
-
433
-                case ROT_270:
434
-                    shot_pos_x = -SHIP_OFF;
435
-                    shot_pos_y = 0;
436
-                    break;
437
-
438
-                case ROT_292_5:
439
-                    shot_pos_x = -SHIP_OFF / 2 - 2;
440
-                    shot_pos_y = -SHIP_OFF / 2 + 2;
441
-                    break;
442
-
443
-                case ROT_315:
444
-                    shot_pos_x = -SHIP_OFF / 2 - 3;
445
-                    shot_pos_y = -SHIP_OFF / 2 - 2;
446
-                    break;
447
-
448
-                case ROT_337_5:
449
-                    shot_pos_x = -SHIP_OFF / 2 + 1;
450
-                    shot_pos_y = -SHIP_OFF / 2 - 4;
451
-                    break;
452
-            }
378
+            shot_spd_x += game_state.spd_x;
379
+            shot_spd_y += game_state.spd_y;
380
+
381
+            int16_t shot_pos_x = table_shot_offsets[(game_state.rot * 2) + 0];
382
+            int16_t shot_pos_y = table_shot_offsets[(game_state.rot * 2) + 1];
453
 
383
 
454
             int8_t ret = obj_add(SPR_SHOT,
384
             int8_t ret = obj_add(SPR_SHOT,
455
                                  shot_pos_x, shot_pos_y,
385
                                  shot_pos_x, shot_pos_y,
459
                 sample_play(SFX_SHOT);
389
                 sample_play(SFX_SHOT);
460
 
390
 
461
                 if (mode == GM_SINGLE) {
391
                 if (mode == GM_SINGLE) {
462
-                    if (score > 0) {
463
-                        score--;
392
+                    if (game_state.score > 0) {
393
+                        game_state.score--;
464
                     }
394
                     }
465
                 } else {
395
                 } else {
466
                     static struct mp_shot_state state;
396
                     static struct mp_shot_state state;
480
 
410
 
481
         if (key_pressed(J_START)) {
411
         if (key_pressed(J_START)) {
482
             if (pause_screen()) {
412
             if (pause_screen()) {
413
+                return_value = 1;
483
                 break;
414
                 break;
484
             }
415
             }
485
 
416
 
491
             map_dbg_reset();
422
             map_dbg_reset();
492
         }
423
         }
493
 
424
 
494
-        map_move(spd_x, spd_y);
425
+        map_move(game_state.spd_x, game_state.spd_y);
495
 
426
 
496
         uint8_t hiwater = SPR_NUM_START;
427
         uint8_t hiwater = SPR_NUM_START;
497
-        status(health >> HEALTH_SHIFT, power >> POWER_SHIFT, &hiwater);
428
+        status(game_state.health >> HEALTH_SHIFT, game_state.power >> POWER_SHIFT, &hiwater);
498
 
429
 
499
         if (conf_get()->debug_flags & DBG_MARKER) {
430
         if (conf_get()->debug_flags & DBG_MARKER) {
500
             spr_draw(SPR_DEBUG, FLIP_NONE, 0, 0, 0, &hiwater);
431
             spr_draw(SPR_DEBUG, FLIP_NONE, 0, 0, 0, &hiwater);
501
             spr_draw(SPR_DEBUG_LARGE, FLIP_NONE, 0, 0, 0, &hiwater);
432
             spr_draw(SPR_DEBUG_LARGE, FLIP_NONE, 0, 0, 0, &hiwater);
502
         }
433
         }
503
 
434
 
504
-        spr_ship(rot, acc & (ACC_X | ACC_Y), &hiwater);
435
+        spr_ship(game_state.rot, acc & (ACC_X | ACC_Y), &hiwater);
505
 
436
 
506
-        int16_t damage = obj_do(&spd_x, &spd_y, &score, &hiwater,
437
+        int16_t damage = obj_do(&game_state.spd_x, &game_state.spd_y, &game_state.score, &hiwater,
507
                                 (conf_get()->debug_flags & DBG_NO_OBJ) ? 1 : 0);
438
                                 (conf_get()->debug_flags & DBG_NO_OBJ) ? 1 : 0);
508
         if (damage > 0) {
439
         if (damage > 0) {
509
             if (conf_get()->debug_flags & DBG_GOD_MODE) {
440
             if (conf_get()->debug_flags & DBG_GOD_MODE) {
510
                 damage = 0;
441
                 damage = 0;
511
             }
442
             }
512
 
443
 
513
-            if (health > damage) {
514
-                health -= damage;
444
+            if (game_state.health > damage) {
445
+                game_state.health -= damage;
515
                 if ((!sample_running()) && (sample_last() != SFX_DAMAGE)) {
446
                 if ((!sample_running()) && (sample_last() != SFX_DAMAGE)) {
516
                     sample_play(SFX_DAMAGE);
447
                     sample_play(SFX_DAMAGE);
517
                 }
448
                 }
518
-            } else if (health <= damage) {
519
-                health = 0;
520
-                show_explosion(power);
449
+            } else if (game_state.health <= damage) {
450
+                game_state.health = 0;
451
+                show_explosion(game_state.power);
452
+                return_value = 0;
521
                 break;
453
                 break;
522
             }
454
             }
523
-        } else if ((damage < 0) && (health < HEALTH_MAX)) {
455
+        } else if ((damage < 0) && (game_state.health < HEALTH_MAX)) {
524
             if ((!sample_running()) && (sample_last() != SFX_HEAL)) {
456
             if ((!sample_running()) && (sample_last() != SFX_HEAL)) {
525
                 sample_play(SFX_HEAL);
457
                 sample_play(SFX_HEAL);
526
             }
458
             }
527
 
459
 
528
-            health += -damage;
529
-            if (health > HEALTH_MAX) {
530
-                health = HEALTH_MAX;
460
+            game_state.health += -damage;
461
+            if (game_state.health > HEALTH_MAX) {
462
+                game_state.health = HEALTH_MAX;
531
             }
463
             }
532
         } else if (damage == 0) {
464
         } else if (damage == 0) {
533
             sample_last_reset();
465
             sample_last_reset();
535
 
467
 
536
         hide_sprites_range(hiwater, MAX_HARDWARE_SPRITES);
468
         hide_sprites_range(hiwater, MAX_HARDWARE_SPRITES);
537
 
469
 
538
-        if ((score != prev_score)
470
+        if ((game_state.score != prev_score)
539
                 || ((_cpu == CGB_TYPE) && (conf_get()->debug_flags & DBG_OUT_ON))) {
471
                 || ((_cpu == CGB_TYPE) && (conf_get()->debug_flags & DBG_OUT_ON))) {
540
-            uint8_t x_off = win_game_draw(score, 0);
541
-            move_win(MINWNDPOSX + DEVICE_SCREEN_PX_WIDTH - x_off, MINWNDPOSY + DEVICE_SCREEN_PX_HEIGHT - 16);
472
+            uint8_t x_off = win_game_draw(game_state.score, 0);
473
+            move_win(MINWNDPOSX + DEVICE_SCREEN_PX_WIDTH - x_off,
474
+                     MINWNDPOSY + DEVICE_SCREEN_PX_HEIGHT - 16);
542
         }
475
         }
543
 
476
 
544
         calc_fps();
477
         calc_fps();
545
         vsync();
478
         vsync();
546
     }
479
     }
547
 
480
 
548
-    return score;
481
+    return return_value;
549
 }
482
 }

+ 17
- 7
src/game.h View File

22
 
22
 
23
 #include <gbdk/platform.h>
23
 #include <gbdk/platform.h>
24
 #include <stdint.h>
24
 #include <stdint.h>
25
+
25
 #include "multiplayer.h"
26
 #include "multiplayer.h"
27
+#include "sprites.h"
26
 
28
 
27
 #define HEALTH_MAX 0x1FF
29
 #define HEALTH_MAX 0x1FF
28
 #define HEALTH_SHIFT 1
30
 #define HEALTH_SHIFT 1
30
 #define SHOT_SPEED 42 //23
32
 #define SHOT_SPEED 42 //23
31
 #define MAX_TRAVEL 64 //128
33
 #define MAX_TRAVEL 64 //128
32
 
34
 
33
-#define SHOT_SPEED_DIAG 30
34
-#define SHOT_SPEED_D_HI 39
35
-#define SHOT_SPEED_D_LO 16
36
-
37
 enum GAME_MODE {
35
 enum GAME_MODE {
38
     GM_SINGLE = 0,
36
     GM_SINGLE = 0,
39
     GM_MULTI,
37
     GM_MULTI,
40
 };
38
 };
41
 
39
 
40
+struct game_state {
41
+    int16_t spd_x;
42
+    int16_t spd_y;
43
+    enum SPRITE_ROT rot;
44
+    uint16_t health;
45
+    uint16_t power;
46
+    int32_t score;
47
+};
48
+
42
 void game_get_mp_state(void) BANKED;
49
 void game_get_mp_state(void) BANKED;
43
 void game_set_mp_player2(struct mp_player_state *state) BANKED;
50
 void game_set_mp_player2(struct mp_player_state *state) BANKED;
44
 void game_set_mp_shot(struct mp_shot_state *state) BANKED;
51
 void game_set_mp_shot(struct mp_shot_state *state) BANKED;
45
 
52
 
46
-uint8_t game_get_fps(void) BANKED;
47
-uint16_t game_get_framecount(void) BANKED;
48
-int32_t game(enum GAME_MODE mode) BANKED;
53
+void game_init(void) BANKED;
54
+uint8_t game(enum GAME_MODE mode) BANKED;
55
+
56
+extern struct game_state game_state;
57
+extern uint16_t frame_count;
58
+extern uint8_t game_fps;
49
 
59
 
50
 BANKREF_EXTERN(game)
60
 BANKREF_EXTERN(game)
51
 
61
 

+ 72
- 8
src/main.c View File

21
  */
21
  */
22
 
22
 
23
 #include <gbdk/metasprites.h>
23
 #include <gbdk/metasprites.h>
24
+#include <string.h>
24
 #include <rand.h>
25
 #include <rand.h>
25
 
26
 
26
 #include "banks.h"
27
 #include "banks.h"
27
 #include "config.h"
28
 #include "config.h"
29
+#include "gb/gb.h"
28
 #include "gb/hardware.h"
30
 #include "gb/hardware.h"
29
 #include "maps.h"
31
 #include "maps.h"
30
 #include "obj.h"
32
 #include "obj.h"
164
 static void conf_screen(void) {
166
 static void conf_screen(void) {
165
     HIDE_WIN;
167
     HIDE_WIN;
166
 
168
 
169
+    uint8_t changed = 0;
167
     debug_menu_index = 0;
170
     debug_menu_index = 0;
168
 
171
 
169
     move_win(MINWNDPOSX, MINWNDPOSY);
172
     move_win(MINWNDPOSX, MINWNDPOSY);
176
         key_read();
179
         key_read();
177
 
180
 
178
         if (key_pressed(J_SELECT)) {
181
         if (key_pressed(J_SELECT)) {
182
+            if (changed) {
183
+                conf_write_crc();
184
+                changed = 0;
185
+            }
179
             about_screen();
186
             about_screen();
180
             break;
187
             break;
181
         } else if (key_pressed(J_UP)) {
188
         } else if (key_pressed(J_UP)) {
204
             } else {
211
             } else {
205
                 *conf_entries[debug_menu_index].var = conf_entries[debug_menu_index].max;
212
                 *conf_entries[debug_menu_index].var = conf_entries[debug_menu_index].max;
206
             }
213
             }
207
-            conf_write_crc();
208
             win_conf();
214
             win_conf();
215
+            changed = 1;
209
         } else if (key_pressed(J_RIGHT)) {
216
         } else if (key_pressed(J_RIGHT)) {
210
             if (*conf_entries[debug_menu_index].var < conf_entries[debug_menu_index].max) {
217
             if (*conf_entries[debug_menu_index].var < conf_entries[debug_menu_index].max) {
211
                 (*conf_entries[debug_menu_index].var)++;
218
                 (*conf_entries[debug_menu_index].var)++;
212
             } else {
219
             } else {
213
                 *conf_entries[debug_menu_index].var = 0;
220
                 *conf_entries[debug_menu_index].var = 0;
214
             }
221
             }
215
-            conf_write_crc();
216
             win_conf();
222
             win_conf();
223
+            changed = 1;
217
         } else if (key_pressed(J_A) || key_pressed(J_B) || key_pressed(J_START)) {
224
         } else if (key_pressed(J_A) || key_pressed(J_B) || key_pressed(J_START)) {
218
             break;
225
             break;
219
         }
226
         }
221
         vsync();
228
         vsync();
222
     }
229
     }
223
 
230
 
231
+    if (changed) {
232
+        conf_write_crc();
233
+    }
234
+
224
     debug_menu_index = 0;
235
     debug_menu_index = 0;
225
 }
236
 }
226
 
237
 
344
     anim_frame = 0;
355
     anim_frame = 0;
345
     anim_state = 0;
356
     anim_state = 0;
346
 
357
 
347
-    obj_init();
358
+    memset(&obj_state, 0, sizeof(struct obj_state));
348
     obj_add(SPR_LIGHT, 42, -42, 0, 0);
359
     obj_add(SPR_LIGHT, 42, -42, 0, 0);
349
     obj_add(SPR_DARK, -42, -42, 0, 0);
360
     obj_add(SPR_DARK, -42, -42, 0, 0);
350
 
361
 
572
     return convert_name(name[0], name[1], name[2]);
583
     return convert_name(name[0], name[1], name[2]);
573
 }
584
 }
574
 
585
 
586
+uint8_t ask_continue(void) BANKED {
587
+    HIDE_WIN;
588
+
589
+    uint8_t r = 0;
590
+
591
+    move_win(MINWNDPOSX, MINWNDPOSY);
592
+    hide_sprites_range(SPR_NUM_START, MAX_HARDWARE_SPRITES);
593
+    win_continue();
594
+
595
+    SHOW_WIN;
596
+
597
+    while (1) {
598
+        key_read();
599
+
600
+        if (key_pressed(J_A)) {
601
+            r = 1;
602
+            break;
603
+        } else if (key_pressed(J_B)) {
604
+            r = 0;
605
+            break;
606
+        }
607
+
608
+        vsync();
609
+    }
610
+
611
+    return r;
612
+}
613
+
575
 static void sgb_init(void) NONBANKED {
614
 static void sgb_init(void) NONBANKED {
576
     // Wait 4 frames
615
     // Wait 4 frames
577
     // For SGB on PAL SNES this delay is required on startup, otherwise borders don't show up
616
     // For SGB on PAL SNES this delay is required on startup, otherwise borders don't show up
607
         cpu_fast();
646
         cpu_fast();
608
     }
647
     }
609
 
648
 
649
+    DISPLAY_OFF;
650
+    map_load(1);
651
+    map_fill(MAP_TITLE, 1);
652
+    SHOW_BKG;
653
+    DISPLAY_ON;
654
+
610
     conf_init();
655
     conf_init();
611
     timer_init();
656
     timer_init();
612
     spr_init();
657
     spr_init();
620
     initarand(seed);
665
     initarand(seed);
621
 
666
 
622
     while (1) {
667
     while (1) {
623
-        int32_t score = game(GM_SINGLE);
668
+        if (conf_state()->in_progress && ask_continue()) {
669
+            game_state = conf_state()->state_game;
670
+            obj_state = conf_state()->state_obj;
671
+        } else {
672
+            game_init();
673
+        }
624
 
674
 
625
-        if ((!(conf_get()->debug_flags)) && (score != 0) && score_ranking(score)) {
626
-            uint16_t name = ask_name(score);
627
-            struct scores s = { .name = name, .score = score };
628
-            score_add(s);
675
+        if (game(GM_SINGLE)) {
676
+            // game was exited via pause menu
677
+            conf_state()->in_progress = 1;
678
+            conf_state()->state_game = game_state;
679
+            conf_state()->state_obj = obj_state;
680
+            conf_write_crc();
681
+        } else {
682
+            // game ended with player death
683
+            conf_state()->in_progress = 0;
684
+            conf_write_crc();
685
+
686
+            if ((!(conf_get()->debug_flags))
687
+                    && (game_state.score != 0)
688
+                    && score_ranking(game_state.score)) {
689
+                uint16_t name = ask_name(game_state.score);
690
+                struct scores s = { .name = name, .score = game_state.score };
691
+                score_add(s);
692
+            }
629
         }
693
         }
630
 
694
 
631
         splash();
695
         splash();

+ 5
- 5
src/map_data.h View File

28
 // background tiles are loaded into VRAM starting at tile number 0
28
 // background tiles are loaded into VRAM starting at tile number 0
29
 #define BG_TILE_NUM_START 0
29
 #define BG_TILE_NUM_START 0
30
 
30
 
31
-#define BG_COPY_NONE 0xFF
31
+#define BG_COPY_NONE 0xFFU
32
 
32
 
33
-#define BG_LOAD_GAME     (0 << 0)
34
-#define BG_LOAD_SPLASH   (1 << 0)
35
-#define BG_LOAD_ALL      (1 << 6)
36
-#define BG_LOAD_GBC_ONLY (1 << 7)
33
+#define BG_LOAD_GAME     (0U << 0)
34
+#define BG_LOAD_SPLASH   (1U << 0)
35
+#define BG_LOAD_ALL      (1U << 6)
36
+#define BG_LOAD_GBC_ONLY (1U << 7)
37
 
37
 
38
 struct maps {
38
 struct maps {
39
     uint8_t width;
39
     uint8_t width;

+ 95
- 139
src/obj.c View File

18
  */
18
  */
19
 
19
 
20
 #include <stdint.h>
20
 #include <stdint.h>
21
-#include <string.h>
22
 #include <stdlib.h>
21
 #include <stdlib.h>
23
 #include <rand.h>
22
 #include <rand.h>
24
 
23
 
27
 #include "sample.h"
26
 #include "sample.h"
28
 #include "obj.h"
27
 #include "obj.h"
29
 
28
 
30
-/*
31
- * sprite budget:
32
- *
33
- * fixed:
34
- * status bars: 8
35
- * ship + thruster: 7
36
- * --> 15 fixed
37
- *
38
- * hardware tiles: 40 - 15 = 25
39
- *
40
- * dynamic:
41
- * shot / small: 1
42
- * expl: 4
43
- * light: 4
44
- * dark: 4
45
- * --> 2x dark & 2x light & 1x expl = 20
46
- * --> 2x shot & 4x small = 6
47
- * --> 20 + 6 = 26
48
- *
49
- * TODO we will sometimes have glitches
50
- * 1 sprite tile too much
51
- */
52
-#define MAX_DARK 2
53
-#define MAX_LIGHT 2
54
-#define MAX_SHOT 2
55
-#define MAX_SHOT_DARK 2
56
-#define MAX_SHOT_LIGHT 2
57
-#define MAX_OBJ ((4 * MAX_DARK) + (4 * MAX_LIGHT) + MAX_SHOT + MAX_SHOT_DARK + MAX_SHOT_LIGHT)
58
-
59
 #define POS_SCALE_OBJS 5
29
 #define POS_SCALE_OBJS 5
60
 #define POS_OBJS_MAX (INT16_MAX >> (8 - POS_SCALE_OBJS))
30
 #define POS_OBJS_MAX (INT16_MAX >> (8 - POS_SCALE_OBJS))
61
 #define POS_OBJS_MIN (-(INT16_MAX >> (8 - POS_SCALE_OBJS)) - 1)
31
 #define POS_OBJS_MIN (-(INT16_MAX >> (8 - POS_SCALE_OBJS)) - 1)
83
 
53
 
84
 #define CHECK_COL_AT_SHOTS
54
 #define CHECK_COL_AT_SHOTS
85
 
55
 
86
-struct obj {
87
-    uint8_t active;
88
-    enum SPRITES sprite;
89
-    int16_t off_x, off_y;
90
-    int16_t spd_x, spd_y;
91
-    uint8_t travel;
92
-    uint8_t frame;
93
-    uint8_t frame_index;
94
-    uint8_t frame_count;
95
-    uint8_t frame_duration;
96
-};
97
-
98
-static struct obj objs[MAX_OBJ];
99
-static uint8_t obj_cnt[SPRITE_COUNT];
56
+struct obj_state obj_state;
100
 
57
 
101
 static const uint8_t obj_max[SPRITE_COUNT] = {
58
 static const uint8_t obj_max[SPRITE_COUNT] = {
102
     1, // SPR_SHIP
59
     1, // SPR_SHIP
113
     1, // SPR_DEBUG_LARGE
70
     1, // SPR_DEBUG_LARGE
114
 };
71
 };
115
 
72
 
116
-void obj_init(void) BANKED {
117
-    memset(objs, 0, sizeof(objs));
118
-    memset(obj_cnt, 0, sizeof(obj_cnt));
119
-}
120
-
121
 static uint8_t is_too_close(int8_t x, int8_t y, int8_t center_dist) {
73
 static uint8_t is_too_close(int8_t x, int8_t y, int8_t center_dist) {
122
     if ((abs(x) < center_dist) && (abs(y) < center_dist)) {
74
     if ((abs(x) < center_dist) && (abs(y) < center_dist)) {
123
         return 1;
75
         return 1;
124
     }
76
     }
125
 
77
 
126
     for (uint8_t i = 0; i < MAX_OBJ; i++) {
78
     for (uint8_t i = 0; i < MAX_OBJ; i++) {
127
-        if (!objs[i].active) {
79
+        if (!obj_state.objs[i].active) {
128
             continue;
80
             continue;
129
         }
81
         }
130
 
82
 
131
-        int dst_x = abs((objs[i].off_x >> POS_SCALE_OBJS) - x);
132
-        int dst_y = abs((objs[i].off_y >> POS_SCALE_OBJS) - y);
83
+        int dst_x = abs((obj_state.objs[i].off_x >> POS_SCALE_OBJS) - x);
84
+        int dst_y = abs((obj_state.objs[i].off_y >> POS_SCALE_OBJS) - y);
133
 
85
 
134
         if ((dst_x < PLACEMENT_DISTANCE) && (dst_y < PLACEMENT_DISTANCE)) {
86
         if ((dst_x < PLACEMENT_DISTANCE) && (dst_y < PLACEMENT_DISTANCE)) {
135
             return 1;
87
             return 1;
153
 }
105
 }
154
 
106
 
155
 static void obj_respawn_type(enum SPRITES spr, int8_t center_dist) {
107
 static void obj_respawn_type(enum SPRITES spr, int8_t center_dist) {
156
-    while (obj_cnt[spr] < obj_max[spr]) {
108
+    while (obj_state.obj_cnt[spr] < obj_max[spr]) {
157
         int8_t x, y;
109
         int8_t x, y;
158
         generate_coords(&x, &y, center_dist);
110
         generate_coords(&x, &y, center_dist);
159
         obj_add(spr, x, y, 0, 0);
111
         obj_add(spr, x, y, 0, 0);
170
 enum OBJ_STATE obj_add(enum SPRITES sprite, int16_t off_x, int16_t off_y, int16_t spd_x, int16_t spd_y) BANKED {
122
 enum OBJ_STATE obj_add(enum SPRITES sprite, int16_t off_x, int16_t off_y, int16_t spd_x, int16_t spd_y) BANKED {
171
     uint8_t next = 0xFF;
123
     uint8_t next = 0xFF;
172
     for (uint8_t i = 0; i < MAX_OBJ; i++) {
124
     for (uint8_t i = 0; i < MAX_OBJ; i++) {
173
-        if (!objs[i].active) {
125
+        if (!obj_state.objs[i].active) {
174
             next = i;
126
             next = i;
175
             break;
127
             break;
176
         }
128
         }
179
         return OBJ_LIST_FULL;
131
         return OBJ_LIST_FULL;
180
     }
132
     }
181
 
133
 
182
-    if (obj_cnt[sprite] >= obj_max[sprite]) {
134
+    if (obj_state.obj_cnt[sprite] >= obj_max[sprite]) {
183
         return OBJ_TYPE_FULL;
135
         return OBJ_TYPE_FULL;
184
     }
136
     }
185
 
137
 
186
-    obj_cnt[sprite]++;
138
+    obj_state.obj_cnt[sprite]++;
187
 
139
 
188
-    objs[next].active = 1;
189
-    objs[next].sprite = sprite;
190
-    objs[next].off_x = off_x << POS_SCALE_OBJS;
191
-    objs[next].off_y = off_y << POS_SCALE_OBJS;
192
-    objs[next].spd_x = spd_x;
193
-    objs[next].spd_y = spd_y;
194
-    objs[next].travel = 0;
195
-    objs[next].frame = 0;
196
-    objs[next].frame_index = 0;
197
-    objs[next].frame_count = 1;
198
-    objs[next].frame_duration = 0;
140
+    obj_state.objs[next].active = 1;
141
+    obj_state.objs[next].sprite = sprite;
142
+    obj_state.objs[next].off_x = off_x << POS_SCALE_OBJS;
143
+    obj_state.objs[next].off_y = off_y << POS_SCALE_OBJS;
144
+    obj_state.objs[next].spd_x = spd_x;
145
+    obj_state.objs[next].spd_y = spd_y;
146
+    obj_state.objs[next].travel = 0;
147
+    obj_state.objs[next].frame = 0;
148
+    obj_state.objs[next].frame_index = 0;
149
+    obj_state.objs[next].frame_count = 1;
150
+    obj_state.objs[next].frame_duration = 0;
199
 
151
 
200
     return OBJ_ADDED;
152
     return OBJ_ADDED;
201
 }
153
 }
202
 
154
 
203
 static uint8_t handle_shot_col(uint8_t shot, uint8_t orb, int32_t *score, uint8_t is_splash) {
155
 static uint8_t handle_shot_col(uint8_t shot, uint8_t orb, int32_t *score, uint8_t is_splash) {
204
-    if ((abs(objs[shot].off_x - objs[orb].off_x) <= SHOT_RANGE)
205
-            && (abs(objs[shot].off_y - objs[orb].off_y) <= SHOT_RANGE)) {
156
+    if ((abs(obj_state.objs[shot].off_x - obj_state.objs[orb].off_x) <= SHOT_RANGE)
157
+            && (abs(obj_state.objs[shot].off_y - obj_state.objs[orb].off_y) <= SHOT_RANGE)) {
206
         sample_play(SFX_EXPL_ORB);
158
         sample_play(SFX_EXPL_ORB);
207
 
159
 
208
-        objs[orb].active = 0;
160
+        obj_state.objs[orb].active = 0;
209
 
161
 
210
-        obj_cnt[objs[shot].sprite]--;
211
-        obj_cnt[objs[orb].sprite]--;
162
+        obj_state.obj_cnt[obj_state.objs[shot].sprite]--;
163
+        obj_state.obj_cnt[obj_state.objs[orb].sprite]--;
212
 
164
 
213
-        objs[shot].sprite = SPR_EXPL;
214
-        objs[shot].travel = 0;
215
-        objs[shot].frame = 0;
216
-        objs[shot].frame_index = 0;
217
-        objs[shot].frame_count = 4;
218
-        objs[shot].frame_duration = 4;
219
-        obj_cnt[SPR_EXPL]++;
165
+        obj_state.objs[shot].sprite = SPR_EXPL;
166
+        obj_state.objs[shot].travel = 0;
167
+        obj_state.objs[shot].frame = 0;
168
+        obj_state.objs[shot].frame_index = 0;
169
+        obj_state.objs[shot].frame_count = 4;
170
+        obj_state.objs[shot].frame_duration = 4;
171
+        obj_state.obj_cnt[SPR_EXPL]++;
220
 
172
 
221
         // move explosion to center of orb instead of shot
173
         // move explosion to center of orb instead of shot
222
-        objs[shot].off_x = objs[orb].off_x;
223
-        objs[shot].off_y = objs[orb].off_y;
174
+        obj_state.objs[shot].off_x = obj_state.objs[orb].off_x;
175
+        obj_state.objs[shot].off_y = obj_state.objs[orb].off_y;
224
 
176
 
225
         // also would look kinda cool with shot speed still applied?
177
         // also would look kinda cool with shot speed still applied?
226
-        objs[shot].spd_x = 0;
227
-        objs[shot].spd_y = 0;
178
+        obj_state.objs[shot].spd_x = 0;
179
+        obj_state.objs[shot].spd_y = 0;
228
 
180
 
229
         if (!is_splash) {
181
         if (!is_splash) {
230
-            obj_respawn_type(objs[orb].sprite, RESPAWN_DISTANCE);
182
+            obj_respawn_type(obj_state.objs[orb].sprite, RESPAWN_DISTANCE);
231
         }
183
         }
232
 
184
 
233
-        if (objs[orb].sprite == SPR_LIGHT) {
185
+        if (obj_state.objs[orb].sprite == SPR_LIGHT) {
234
             (*score) += SCORE_LARGE;
186
             (*score) += SCORE_LARGE;
235
         } else {
187
         } else {
236
             (*score) -= SCORE_LARGE;
188
             (*score) -= SCORE_LARGE;
250
     int16_t spd_y = *spd_off_y;
202
     int16_t spd_y = *spd_off_y;
251
 
203
 
252
     for (uint8_t i = 0; i < MAX_OBJ; i++) {
204
     for (uint8_t i = 0; i < MAX_OBJ; i++) {
253
-        if (!objs[i].active) {
205
+        if (!obj_state.objs[i].active) {
254
             continue;
206
             continue;
255
         }
207
         }
256
 
208
 
257
         // move objects by their speed and compensate for movement of the background / ship
209
         // move objects by their speed and compensate for movement of the background / ship
258
-        objs[i].off_x = objs[i].off_x + objs[i].spd_x - spd_x;
259
-        objs[i].off_y = objs[i].off_y + objs[i].spd_y - spd_y;
210
+        obj_state.objs[i].off_x = obj_state.objs[i].off_x + obj_state.objs[i].spd_x - spd_x;
211
+        obj_state.objs[i].off_y = obj_state.objs[i].off_y + obj_state.objs[i].spd_y - spd_y;
260
 
212
 
261
-        if (objs[i].off_x > POS_OBJS_MAX) {
262
-            objs[i].off_x -= POS_OBJS_MAX - POS_OBJS_MIN + 1;
263
-        } else if (objs[i].off_x < POS_OBJS_MIN) {
264
-            objs[i].off_x += POS_OBJS_MAX - POS_OBJS_MIN + 1;
213
+        if (obj_state.objs[i].off_x > POS_OBJS_MAX) {
214
+            obj_state.objs[i].off_x -= POS_OBJS_MAX - POS_OBJS_MIN + 1;
215
+        } else if (obj_state.objs[i].off_x < POS_OBJS_MIN) {
216
+            obj_state.objs[i].off_x += POS_OBJS_MAX - POS_OBJS_MIN + 1;
265
         }
217
         }
266
-        if (objs[i].off_y > POS_OBJS_MAX) {
267
-            objs[i].off_y -= POS_OBJS_MAX - POS_OBJS_MIN + 1;
268
-        } else if (objs[i].off_y < POS_OBJS_MIN) {
269
-            objs[i].off_y += POS_OBJS_MAX - POS_OBJS_MIN + 1;
218
+        if (obj_state.objs[i].off_y > POS_OBJS_MAX) {
219
+            obj_state.objs[i].off_y -= POS_OBJS_MAX - POS_OBJS_MIN + 1;
220
+        } else if (obj_state.objs[i].off_y < POS_OBJS_MIN) {
221
+            obj_state.objs[i].off_y += POS_OBJS_MAX - POS_OBJS_MIN + 1;
270
         }
222
         }
271
 
223
 
272
         // only update travel time if we're actually moving
224
         // only update travel time if we're actually moving
273
-        if ((objs[i].spd_x != 0) || (objs[i].spd_y != 0)) {
274
-            objs[i].travel += 1;
225
+        if ((obj_state.objs[i].spd_x != 0) || (obj_state.objs[i].spd_y != 0)) {
226
+            obj_state.objs[i].travel += 1;
275
         }
227
         }
276
 
228
 
277
         // remove objects that have traveled for too long
229
         // remove objects that have traveled for too long
278
-        if (objs[i].travel >= MAX_TRAVEL) {
279
-            objs[i].active = 0;
280
-            obj_cnt[objs[i].sprite]--;
230
+        if (obj_state.objs[i].travel >= MAX_TRAVEL) {
231
+            obj_state.objs[i].active = 0;
232
+            obj_state.obj_cnt[obj_state.objs[i].sprite]--;
281
             continue;
233
             continue;
282
         }
234
         }
283
 
235
 
284
-        int abs_off_x = abs(objs[i].off_x);
285
-        int abs_off_y = abs(objs[i].off_y);
236
+        int abs_off_x = abs(obj_state.objs[i].off_x);
237
+        int abs_off_y = abs(obj_state.objs[i].off_y);
286
 
238
 
287
         // handle collision
239
         // handle collision
288
-        switch (objs[i].sprite) {
240
+        switch (obj_state.objs[i].sprite) {
289
             case SPR_DARK:
241
             case SPR_DARK:
290
 #ifdef DESPAWN_RANGE
242
 #ifdef DESPAWN_RANGE
291
                 if ((abs_off_x >= DESPAWN_RANGE) || (abs_off_y >= DESPAWN_RANGE)) {
243
                 if ((abs_off_x >= DESPAWN_RANGE) || (abs_off_y >= DESPAWN_RANGE)) {
296
 #endif // DESPAWN_RANGE
248
 #endif // DESPAWN_RANGE
297
 
249
 
298
                 if ((abs_off_x <= GRAVITY_RANGE) && (abs_off_y <= GRAVITY_RANGE)) {
250
                 if ((abs_off_x <= GRAVITY_RANGE) && (abs_off_y <= GRAVITY_RANGE)) {
299
-                    if (objs[i].off_x > 0) {
300
-                        *spd_off_x += (GRAVITY_RANGE - objs[i].off_x) >> GRAVITY_SHIFT;
301
-                    } else if (objs[i].off_x < 0) {
302
-                        *spd_off_x += (-GRAVITY_RANGE - objs[i].off_x) >> GRAVITY_SHIFT;
251
+                    if (obj_state.objs[i].off_x > 0) {
252
+                        *spd_off_x += (GRAVITY_RANGE - obj_state.objs[i].off_x) >> GRAVITY_SHIFT;
253
+                    } else if (obj_state.objs[i].off_x < 0) {
254
+                        *spd_off_x += (-GRAVITY_RANGE - obj_state.objs[i].off_x) >> GRAVITY_SHIFT;
303
                     }
255
                     }
304
-                    if (objs[i].off_y > 0) {
305
-                        *spd_off_y += (GRAVITY_RANGE - objs[i].off_y) >> GRAVITY_SHIFT;
306
-                    } else if (objs[i].off_y < 0) {
307
-                        *spd_off_y += (-GRAVITY_RANGE - objs[i].off_y) >> GRAVITY_SHIFT;
256
+                    if (obj_state.objs[i].off_y > 0) {
257
+                        *spd_off_y += (GRAVITY_RANGE - obj_state.objs[i].off_y) >> GRAVITY_SHIFT;
258
+                    } else if (obj_state.objs[i].off_y < 0) {
259
+                        *spd_off_y += (-GRAVITY_RANGE - obj_state.objs[i].off_y) >> GRAVITY_SHIFT;
308
                     }
260
                     }
309
                 }
261
                 }
310
 
262
 
335
 #endif // DESPAWN_RANGE
287
 #endif // DESPAWN_RANGE
336
 
288
 
337
                 if ((abs_off_x <= GRAVITY_RANGE) && (abs_off_y <= GRAVITY_RANGE)) {
289
                 if ((abs_off_x <= GRAVITY_RANGE) && (abs_off_y <= GRAVITY_RANGE)) {
338
-                    if (objs[i].off_x > 0) {
339
-                        *spd_off_x -= (GRAVITY_RANGE - objs[i].off_x) >> GRAVITY_SHIFT;
340
-                    } else if (objs[i].off_x < 0) {
341
-                        *spd_off_x -= (-GRAVITY_RANGE - objs[i].off_x) >> GRAVITY_SHIFT;
290
+                    if (obj_state.objs[i].off_x > 0) {
291
+                        *spd_off_x -= (GRAVITY_RANGE - obj_state.objs[i].off_x) >> GRAVITY_SHIFT;
292
+                    } else if (obj_state.objs[i].off_x < 0) {
293
+                        *spd_off_x -= (-GRAVITY_RANGE - obj_state.objs[i].off_x) >> GRAVITY_SHIFT;
342
                     }
294
                     }
343
-                    if (objs[i].off_y > 0) {
344
-                        *spd_off_y -= (GRAVITY_RANGE - objs[i].off_y) >> GRAVITY_SHIFT;
345
-                    } else if (objs[i].off_y < 0) {
346
-                        *spd_off_y -= (-GRAVITY_RANGE - objs[i].off_y) >> GRAVITY_SHIFT;
295
+                    if (obj_state.objs[i].off_y > 0) {
296
+                        *spd_off_y -= (GRAVITY_RANGE - obj_state.objs[i].off_y) >> GRAVITY_SHIFT;
297
+                    } else if (obj_state.objs[i].off_y < 0) {
298
+                        *spd_off_y -= (-GRAVITY_RANGE - obj_state.objs[i].off_y) >> GRAVITY_SHIFT;
347
                     }
299
                     }
348
                 }
300
                 }
349
 
301
 
375
 
327
 
376
                 if ((abs_off_x <= PICKUP_SMALL_RANGE) && (abs_off_y <= PICKUP_SMALL_RANGE)) {
328
                 if ((abs_off_x <= PICKUP_SMALL_RANGE) && (abs_off_y <= PICKUP_SMALL_RANGE)) {
377
                     (*score) -= SCORE_SMALL;
329
                     (*score) -= SCORE_SMALL;
378
-                    objs[i].active = 0;
379
-                    obj_cnt[SPR_SHOT_DARK]--;
330
+                    obj_state.objs[i].active = 0;
331
+                    obj_state.obj_cnt[SPR_SHOT_DARK]--;
380
                     obj_respawn_type(SPR_SHOT_DARK, RESPAWN_DISTANCE);
332
                     obj_respawn_type(SPR_SHOT_DARK, RESPAWN_DISTANCE);
381
                 }
333
                 }
382
                 break;
334
                 break;
392
 
344
 
393
                 if ((abs_off_x <= PICKUP_SMALL_RANGE) && (abs_off_y <= PICKUP_SMALL_RANGE)) {
345
                 if ((abs_off_x <= PICKUP_SMALL_RANGE) && (abs_off_y <= PICKUP_SMALL_RANGE)) {
394
                     (*score) += SCORE_SMALL;
346
                     (*score) += SCORE_SMALL;
395
-                    objs[i].active = 0;
396
-                    obj_cnt[SPR_SHOT_LIGHT]--;
347
+                    obj_state.objs[i].active = 0;
348
+                    obj_state.obj_cnt[SPR_SHOT_LIGHT]--;
397
                     obj_respawn_type(SPR_SHOT_LIGHT, RESPAWN_DISTANCE);
349
                     obj_respawn_type(SPR_SHOT_LIGHT, RESPAWN_DISTANCE);
398
                 }
350
                 }
399
                 break;
351
                 break;
401
 #ifdef CHECK_COL_AT_SHOTS
353
 #ifdef CHECK_COL_AT_SHOTS
402
             case SPR_SHOT:
354
             case SPR_SHOT:
403
                 for (uint8_t orb = 0; orb < MAX_OBJ; orb++) {
355
                 for (uint8_t orb = 0; orb < MAX_OBJ; orb++) {
404
-                    if ((!objs[orb].active)
405
-                            || ((objs[orb].sprite != SPR_LIGHT) && (objs[orb].sprite != SPR_DARK))) {
356
+                    if ((!obj_state.objs[orb].active)
357
+                            || ((obj_state.objs[orb].sprite != SPR_LIGHT)
358
+                                && (obj_state.objs[orb].sprite != SPR_DARK))) {
406
                         continue;
359
                         continue;
407
                     }
360
                     }
408
 
361
 
417
                 break;
370
                 break;
418
         }
371
         }
419
 
372
 
420
-        if (!objs[i].active) {
373
+        if (!obj_state.objs[i].active) {
421
             continue;
374
             continue;
422
         }
375
         }
423
 
376
 
424
-        spr_draw(objs[i].sprite, FLIP_NONE, objs[i].off_x >> POS_SCALE_OBJS, objs[i].off_y >> POS_SCALE_OBJS, objs[i].frame_index, hiwater);
425
-
426
-        objs[i].frame++;
427
-        if (objs[i].frame >= objs[i].frame_duration) {
428
-            objs[i].frame = 0;
429
-            objs[i].frame_index++;
430
-            if (objs[i].frame_index >= objs[i].frame_count) {
431
-                objs[i].frame_index = 0;
432
-
433
-                if (objs[i].sprite == SPR_EXPL) {
434
-                    objs[i].active = 0;
435
-                    obj_cnt[SPR_EXPL]--;
377
+        spr_draw(obj_state.objs[i].sprite, FLIP_NONE,
378
+                 obj_state.objs[i].off_x >> POS_SCALE_OBJS,
379
+                 obj_state.objs[i].off_y >> POS_SCALE_OBJS,
380
+                 obj_state.objs[i].frame_index, hiwater);
381
+
382
+        obj_state.objs[i].frame++;
383
+        if (obj_state.objs[i].frame >= obj_state.objs[i].frame_duration) {
384
+            obj_state.objs[i].frame = 0;
385
+            obj_state.objs[i].frame_index++;
386
+            if (obj_state.objs[i].frame_index >= obj_state.objs[i].frame_count) {
387
+                obj_state.objs[i].frame_index = 0;
388
+
389
+                if (obj_state.objs[i].sprite == SPR_EXPL) {
390
+                    obj_state.objs[i].active = 0;
391
+                    obj_state.obj_cnt[SPR_EXPL]--;
436
                 }
392
                 }
437
             }
393
             }
438
         }
394
         }

+ 55
- 3
src/obj.h View File

25
 
25
 
26
 #include "sprites.h"
26
 #include "sprites.h"
27
 
27
 
28
+/*
29
+ * sprite budget:
30
+ *
31
+ * fixed:
32
+ * status bars: 8
33
+ * ship + thruster: 7
34
+ * --> 15 fixed
35
+ *
36
+ * hardware tiles: 40 - 15 = 25
37
+ *
38
+ * dynamic:
39
+ * shot / small: 1
40
+ * expl: 4
41
+ * light: 4
42
+ * dark: 4
43
+ * --> 2x dark & 2x light & 1x expl = 20
44
+ * --> 2x shot & 4x small = 6
45
+ * --> 20 + 6 = 26
46
+ *
47
+ * TODO we will sometimes have glitches
48
+ * 1 sprite tile too much
49
+ */
50
+#define MAX_DARK 2
51
+#define MAX_LIGHT 2
52
+#define MAX_SHOT 2
53
+#define MAX_SHOT_DARK 2
54
+#define MAX_SHOT_LIGHT 2
55
+#define MAX_OBJ ((4 * MAX_DARK) + (4 * MAX_LIGHT) + MAX_SHOT + MAX_SHOT_DARK + MAX_SHOT_LIGHT)
56
+
57
+struct obj {
58
+    uint8_t active;
59
+    enum SPRITES sprite;
60
+    int16_t off_x, off_y;
61
+    int16_t spd_x, spd_y;
62
+    uint8_t travel;
63
+    uint8_t frame;
64
+    uint8_t frame_index;
65
+    uint8_t frame_count;
66
+    uint8_t frame_duration;
67
+};
68
+
69
+struct obj_state {
70
+    struct obj objs[MAX_OBJ];
71
+    uint8_t obj_cnt[SPRITE_COUNT];
72
+};
73
+
28
 enum OBJ_STATE {
74
 enum OBJ_STATE {
29
     OBJ_ADDED = 0,
75
     OBJ_ADDED = 0,
30
     OBJ_LIST_FULL,
76
     OBJ_LIST_FULL,
31
     OBJ_TYPE_FULL,
77
     OBJ_TYPE_FULL,
32
 };
78
 };
33
 
79
 
34
-void obj_init(void) BANKED;
35
 void obj_spawn(void) BANKED;
80
 void obj_spawn(void) BANKED;
36
-enum OBJ_STATE obj_add(enum SPRITES sprite, int16_t off_x, int16_t off_y, int16_t spd_x, int16_t spd_y) BANKED;
37
-int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *hiwater, uint8_t is_splash) BANKED;
81
+
82
+enum OBJ_STATE obj_add(enum SPRITES sprite,
83
+                       int16_t off_x, int16_t off_y,
84
+                       int16_t spd_x, int16_t spd_y) BANKED;
85
+
86
+int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y,
87
+               int32_t *score, uint8_t *hiwater, uint8_t is_splash) BANKED;
88
+
89
+extern struct obj_state obj_state;
38
 
90
 
39
 #endif // __OBJ_H__
91
 #endif // __OBJ_H__

+ 8
- 0
src/strings.c View File

55
 static const char   string_printf_stack[] = " Stack: 0x%x";
55
 static const char   string_printf_stack[] = " Stack: 0x%x";
56
 static const char     string_printf_fps[] = "   FPS: %hd";
56
 static const char     string_printf_fps[] = "   FPS: %hd";
57
 static const char        string_spinner[] = "/-\\|";
57
 static const char        string_spinner[] = "/-\\|";
58
+static const char        string_game_in[] = "Game in";
59
+static const char       string_progress[] = "Progress";
60
+static const char     string_a_continue[] = "A Continue";
61
+static const char     string_b_new_game[] = "B New Game";
58
 
62
 
59
 static const char * const strings[COUNT_STRINGS] = {
63
 static const char * const strings[COUNT_STRINGS] = {
60
     string_top,            // STR_TOP
64
     string_top,            // STR_TOP
88
     string_printf_stack,   // STR_PRINTF_STACK
92
     string_printf_stack,   // STR_PRINTF_STACK
89
     string_printf_fps,     // STR_PRINTF_FPS
93
     string_printf_fps,     // STR_PRINTF_FPS
90
     string_spinner,        // STR_SPINNER
94
     string_spinner,        // STR_SPINNER
95
+    string_game_in,        // STR_GAME_IN
96
+    string_progress,       // STR_PROGRESS
97
+    string_a_continue,     // STR_A_CONTINUE
98
+    string_b_new_game,     // STR_B_NEW_GAME
91
 };
99
 };
92
 
100
 
93
 #define MAX_STR_LEN 32
101
 #define MAX_STR_LEN 32

+ 4
- 0
src/strings.h View File

54
     STR_PRINTF_STACK,
54
     STR_PRINTF_STACK,
55
     STR_PRINTF_FPS,
55
     STR_PRINTF_FPS,
56
     STR_SPINNER,
56
     STR_SPINNER,
57
+    STR_GAME_IN,
58
+    STR_PROGRESS,
59
+    STR_A_CONTINUE,
60
+    STR_B_NEW_GAME,
57
 
61
 
58
     COUNT_STRINGS
62
     COUNT_STRINGS
59
 };
63
 };

+ 6
- 7
src/timer.c View File

21
 #include "sound.h"
21
 #include "sound.h"
22
 #include "timer.h"
22
 #include "timer.h"
23
 
23
 
24
+#define DMG_TMA_VAL (0x100UL -  64UL) // 16.384kHz /  64 = 256Hz
25
+#define CGB_TMA_VAL (0x100UL - 128UL) // 32.768kHz / 128 = 256Hz
26
+
24
 static uint16_t count = 0;
27
 static uint16_t count = 0;
25
 
28
 
26
 static void timer_isr(void) NONBANKED {
29
 static void timer_isr(void) NONBANKED {
27
     sample_isr();
30
     sample_isr();
28
     snd_play();
31
     snd_play();
29
-    count += 4;
32
+    count++;
30
 }
33
 }
31
 
34
 
32
 void timer_init(void) BANKED {
35
 void timer_init(void) BANKED {
33
     CRITICAL {
36
     CRITICAL {
34
         count = 0;
37
         count = 0;
35
         add_TIM(timer_isr);
38
         add_TIM(timer_isr);
36
-        if (_cpu == CGB_TYPE) {
37
-            TMA_REG = 0x100 - 128; // 32.768kHz / 128 = 256Hz
38
-        } else {
39
-            TMA_REG = 0x100 - 64; // 16.384kHz / 64 = 256Hz
40
-        }
39
+        TMA_REG = (_cpu == CGB_TYPE) ? CGB_TMA_VAL : DMG_TMA_VAL;
41
         TAC_REG = TACF_16KHZ | TACF_START;
40
         TAC_REG = TACF_16KHZ | TACF_START;
42
 
41
 
43
         set_interrupts(TIM_IFLAG | VBL_IFLAG);
42
         set_interrupts(TIM_IFLAG | VBL_IFLAG);
49
     CRITICAL {
48
     CRITICAL {
50
         r = count;
49
         r = count;
51
     }
50
     }
52
-    return r;
51
+    return r << 2;
53
 }
52
 }

+ 16
- 8
src/window.c View File

273
          (pos == 2) ? !is_black : is_black);
273
          (pos == 2) ? !is_black : is_black);
274
 }
274
 }
275
 
275
 
276
+void win_continue(void) BANKED {
277
+    map_fill(MAP_TITLE, 0);
278
+
279
+    str_center(get_string(STR_GAME_IN), 1, 0);
280
+    str_center(get_string(STR_PROGRESS), 3, 0);
281
+
282
+    str_center(get_string(STR_A_CONTINUE), 13, 1);
283
+    str_center(get_string(STR_B_NEW_GAME), 15, 1);
284
+}
285
+
276
 uint8_t win_game_draw(int32_t score, uint8_t initial) BANKED {
286
 uint8_t win_game_draw(int32_t score, uint8_t initial) BANKED {
277
     uint8_t is_black = 0;
287
     uint8_t is_black = 0;
278
     if (score < 0) {
288
     if (score < 0) {
298
 
308
 
299
         if ((conf_get()->debug_flags & DBG_SHOW_FPS) && (y_off < 2)) {
309
         if ((conf_get()->debug_flags & DBG_SHOW_FPS) && (y_off < 2)) {
300
             static uint8_t prev_fps = 0;
310
             static uint8_t prev_fps = 0;
301
-            uint8_t fps = game_get_fps();
302
-            if ((fps != prev_fps) || redraw) {
303
-                prev_fps = fps;
304
-                sprintf(str_buff, get_string(STR_PRINTF_FPS), (uint8_t)fps);
311
+            if ((game_fps != prev_fps) || redraw) {
312
+                prev_fps = game_fps;
313
+                sprintf(str_buff, get_string(STR_PRINTF_FPS), (uint8_t)game_fps);
305
                 str_ascii(str_buff, x_off, y_off, 1);
314
                 str_ascii(str_buff, x_off, y_off, 1);
306
             }
315
             }
307
             y_off++;
316
             y_off++;
309
 
318
 
310
         if ((conf_get()->debug_flags & DBG_SHOW_FRAMES) && (y_off < 2)) {
319
         if ((conf_get()->debug_flags & DBG_SHOW_FRAMES) && (y_off < 2)) {
311
             static uint16_t prev_framecount = 0;
320
             static uint16_t prev_framecount = 0;
312
-            uint16_t framecount = game_get_framecount();
313
-            if ((framecount != prev_framecount) || redraw) {
314
-                prev_framecount = framecount;
315
-                sprintf(str_buff, get_string(STR_PRINTF_FRAMES), (uint16_t)framecount);
321
+            if ((frame_count != prev_framecount) || redraw) {
322
+                prev_framecount = frame_count;
323
+                sprintf(str_buff, get_string(STR_PRINTF_FRAMES), (uint16_t)frame_count);
316
                 str_ascii(str_buff, x_off, y_off, 1);
324
                 str_ascii(str_buff, x_off, y_off, 1);
317
             }
325
             }
318
             y_off++;
326
             y_off++;

+ 1
- 0
src/window.h View File

37
 void win_debug(void) BANKED;
37
 void win_debug(void) BANKED;
38
 void win_name(int32_t score) BANKED;
38
 void win_name(int32_t score) BANKED;
39
 void win_name_draw(uint16_t name, uint8_t is_black, uint8_t pos) BANKED;
39
 void win_name_draw(uint16_t name, uint8_t is_black, uint8_t pos) BANKED;
40
+void win_continue(void) BANKED;
40
 uint8_t win_game_draw(int32_t score, uint8_t initial) BANKED;
41
 uint8_t win_game_draw(int32_t score, uint8_t initial) BANKED;
41
 
42
 
42
 void fill_win(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t tile, uint8_t attr) BANKED;
43
 void fill_win(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t tile, uint8_t attr) BANKED;

Loading…
Cancel
Save