Browse Source

add debug flags and menu

Thomas B 1 month ago
parent
commit
9a59268c5d
10 changed files with 218 additions and 26 deletions
  1. 18
    12
      src/game.c
  2. 1
    0
      src/game.h
  3. 28
    0
      src/input.c
  4. 4
    0
      src/input.h
  5. 65
    13
      src/main.c
  6. 53
    0
      src/main.h
  7. 25
    0
      src/maps.c
  8. 1
    0
      src/maps.h
  9. 22
    0
      src/obj.c
  10. 1
    1
      src/score.ba0.c

+ 18
- 12
src/game.c View File

@@ -22,12 +22,14 @@
22 22
 #include <rand.h>
23 23
 #include <stdint.h>
24 24
 
25
+#include "asm/types.h"
25 26
 #include "gb/gb.h"
26 27
 #include "maps.h"
27 28
 #include "obj.h"
28 29
 #include "sprites.h"
29 30
 #include "sound.h"
30 31
 #include "input.h"
32
+#include "main.h"
31 33
 #include "game.h"
32 34
 
33 35
 enum ACCELERATION {
@@ -41,7 +43,7 @@ enum ACCELERATION {
41 43
 #define POWER_OFFSET_Y 16
42 44
 #define PAUSE_BLINK_FRAMES 32
43 45
 
44
-static uint8_t pause_screen(void) {
46
+static uint8_t pause_screen(void) NONBANKED {
45 47
     uint8_t n = 0;
46 48
 
47 49
     while (1) {
@@ -182,10 +184,10 @@ int32_t game(void) NONBANKED {
182 184
 
183 185
                 case ROT_45:
184 186
                     spd_y -= SPEED_INC;
185
-                    if (spd_y < -SPEED_MAX_ACC) spd_y = -SPEED_MAX_ACC;
187
+                    if (spd_y < -SPEED_MAX_ACC_DIAG) spd_y += SPEED_DEC;
186 188
                     acc |= ACC_Y;
187 189
                     spd_x += SPEED_INC;
188
-                    if (spd_x > SPEED_MAX_ACC) spd_x = SPEED_MAX_ACC;
190
+                    if (spd_x > SPEED_MAX_ACC_DIAG) spd_x -= SPEED_DEC;
189 191
                     acc |= ACC_X;
190 192
                     break;
191 193
 
@@ -197,10 +199,10 @@ int32_t game(void) NONBANKED {
197 199
 
198 200
                 case ROT_135:
199 201
                     spd_x += SPEED_INC;
200
-                    if (spd_x > SPEED_MAX_ACC) spd_x = SPEED_MAX_ACC;
202
+                    if (spd_x > SPEED_MAX_ACC_DIAG) spd_x -= SPEED_DEC;
201 203
                     acc |= ACC_X;
202 204
                     spd_y += SPEED_INC;
203
-                    if (spd_y > SPEED_MAX_ACC) spd_y = SPEED_MAX_ACC;
205
+                    if (spd_y > SPEED_MAX_ACC_DIAG) spd_y -= SPEED_DEC;
204 206
                     acc |= ACC_Y;
205 207
                     break;
206 208
 
@@ -212,10 +214,10 @@ int32_t game(void) NONBANKED {
212 214
 
213 215
                 case ROT_225:
214 216
                     spd_y += SPEED_INC;
215
-                    if (spd_y > SPEED_MAX_ACC) spd_y = SPEED_MAX_ACC;
217
+                    if (spd_y > SPEED_MAX_ACC_DIAG) spd_y -= SPEED_DEC;
216 218
                     acc |= ACC_Y;
217 219
                     spd_x -= SPEED_INC;
218
-                    if (spd_x < -SPEED_MAX_ACC) spd_x = -SPEED_MAX_ACC;
220
+                    if (spd_x < -SPEED_MAX_ACC_DIAG) spd_x += SPEED_DEC;
219 221
                     acc |= ACC_X;
220 222
                     break;
221 223
 
@@ -227,10 +229,10 @@ int32_t game(void) NONBANKED {
227 229
 
228 230
                 case ROT_315:
229 231
                     spd_x -= SPEED_INC;
230
-                    if (spd_x < -SPEED_MAX_ACC) spd_x = -SPEED_MAX_ACC;
232
+                    if (spd_x < -SPEED_MAX_ACC_DIAG) spd_x += SPEED_DEC;
231 233
                     acc |= ACC_X;
232 234
                     spd_y -= SPEED_INC;
233
-                    if (spd_y < -SPEED_MAX_ACC) spd_y = -SPEED_MAX_ACC;
235
+                    if (spd_y < -SPEED_MAX_ACC_DIAG) spd_y += SPEED_DEC;
234 236
                     acc |= ACC_Y;
235 237
                     break;
236 238
 
@@ -321,9 +323,9 @@ int32_t game(void) NONBANKED {
321 323
 
322 324
         uint8_t hiwater = SPR_NUM_START;
323 325
 
324
-#ifdef DEBUG
325
-        spr_draw(SPR_DEBUG, FLIP_NONE, 0, 0, 0, &hiwater);
326
-#endif
326
+        if (debug_flags & DBG_MARKER) {
327
+            spr_draw(SPR_DEBUG, FLIP_NONE, 0, 0, 0, &hiwater);
328
+        }
327 329
 
328 330
         if (redraw) {
329 331
             spr_ship(rot, acc & (ACC_X | ACC_Y), &hiwater);
@@ -335,6 +337,10 @@ int32_t game(void) NONBANKED {
335 337
         int32_t prev_score = score;
336 338
         int16_t damage = obj_do(&spd_x, &spd_y, &score, &hiwater);
337 339
         if (damage > 0) {
340
+            if (debug_flags & DBG_GOD_MODE) {
341
+                damage = 0;
342
+            }
343
+
338 344
             if (health > damage) {
339 345
                 health -= damage;
340 346
             } else if (health <= damage) {

+ 1
- 0
src/game.h View File

@@ -26,6 +26,7 @@
26 26
 #define SPEED_DEC 1
27 27
 
28 28
 #define SPEED_MAX_ACC 23
29
+#define SPEED_MAX_ACC_DIAG 16
29 30
 #define SPEED_MAX_IDLE 16
30 31
 
31 32
 #define POS_SCALE_OBJS 5

+ 28
- 0
src/input.c View File

@@ -23,10 +23,34 @@
23 23
 
24 24
 static uint8_t joyp = 0;
25 25
 static uint8_t old_joyp = 0;
26
+static int8_t debug_cnt = 0;
27
+
28
+BANKREF(input)
29
+
30
+static const uint8_t key_debug_sequence[] = {
31
+    J_UP, J_UP, J_DOWN, J_DOWN,
32
+    J_LEFT, J_RIGHT, J_LEFT, J_RIGHT,
33
+    J_B, J_A, /* J_START */
34
+};
35
+
36
+#define DEBUG_SEQUENCE_COUNT (sizeof(key_debug_sequence) / sizeof(key_debug_sequence[0]))
26 37
 
27 38
 void key_read(void) NONBANKED {
28 39
     old_joyp = joyp;
29 40
     joyp = joypad();
41
+
42
+    SWITCH_ROM(BANK(input));
43
+    if (debug_cnt < DEBUG_SEQUENCE_COUNT) {
44
+        if (key_pressed(key_debug_sequence[debug_cnt])) {
45
+            debug_cnt++;
46
+        } else if (key_pressed(0xFF)) {
47
+            debug_cnt = 0;
48
+        }
49
+    } else {
50
+        if (key_pressed(0xFF ^ J_START)) {
51
+            debug_cnt = 0;
52
+        }
53
+    }
30 54
 }
31 55
 
32 56
 uint8_t key_down(uint8_t key) NONBANKED {
@@ -36,3 +60,7 @@ uint8_t key_down(uint8_t key) NONBANKED {
36 60
 uint8_t key_pressed(uint8_t key) NONBANKED {
37 61
     return (joyp ^ old_joyp) & joyp & key;
38 62
 }
63
+
64
+int8_t key_debug(void) NONBANKED {
65
+    return DEBUG_SEQUENCE_COUNT - debug_cnt;
66
+}

+ 4
- 0
src/input.h View File

@@ -26,4 +26,8 @@ void key_read(void);
26 26
 uint8_t key_down(uint8_t key);
27 27
 uint8_t key_pressed(uint8_t key);
28 28
 
29
+int8_t key_debug(void);
30
+
31
+BANKREF_EXTERN(input)
32
+
29 33
 #endif // __INPUT_H__

+ 65
- 13
src/main.c View File

@@ -20,10 +20,8 @@
20 20
  * See <http://www.gnu.org/licenses/>.
21 21
  */
22 22
 
23
-#include <gbdk/platform.h>
24 23
 #include <gbdk/metasprites.h>
25 24
 #include <rand.h>
26
-#include <stdint.h>
27 25
 
28 26
 #include "asm/types.h"
29 27
 #include "gb/gb.h"
@@ -36,6 +34,23 @@
36 34
 #include "score.h"
37 35
 #include "sgb_border.h"
38 36
 #include "border_sgb.h"
37
+#include "main.h"
38
+
39
+#ifdef DEBUG
40
+enum debug_flag debug_flags = DBG_MENU;
41
+#else
42
+enum debug_flag debug_flags = 0;
43
+#endif
44
+
45
+uint8_t debug_menu_index = 0;
46
+
47
+BANKREF(main)
48
+
49
+const struct debug_entry debug_entries[DEBUG_ENTRY_COUNT] = {
50
+    { .name = "menu", .flag = DBG_MENU },
51
+    { .name = "marker", .flag = DBG_MARKER },
52
+    { .name = "invuln", .flag = DBG_GOD_MODE },
53
+};
39 54
 
40 55
 static void highscore(uint8_t is_black) NONBANKED {
41 56
     HIDE_WIN;
@@ -85,16 +100,22 @@ static void about_screen(void) NONBANKED {
85 100
 static void splash_win(void) NONBANKED {
86 101
     HIDE_WIN;
87 102
 
88
-    // initially show the top 1 scores
89
-    int32_t low = score_lowest(0).score;
90
-    int32_t high = score_highest(0).score;
103
+    if (debug_flags & DBG_MENU) {
104
+        win_debug();
105
+        move_win(MINWNDPOSX, MINWNDPOSY);
106
+    } else {
107
+        // initially show the top 1 scores
108
+        int32_t low = score_lowest(0).score;
109
+        int32_t high = score_highest(0).score;
110
+
111
+        // only show on splash if they fit
112
+        if ((low >= -99999) && (high <= 99999)) {
113
+            win_splash_draw(-low, high);
114
+        }
91 115
 
92
-    // only show on splash if they fit
93
-    if ((low >= -99999) && (high <= 99999)) {
94
-        win_splash_draw(-low, high);
116
+        move_win(MINWNDPOSX, MINWNDPOSY + DEVICE_SCREEN_PX_HEIGHT - 16);
95 117
     }
96 118
 
97
-    move_win(MINWNDPOSX, MINWNDPOSY + DEVICE_SCREEN_PX_HEIGHT - 16);
98 119
     SHOW_WIN;
99 120
 }
100 121
 
@@ -130,19 +151,50 @@ static void splash(void) NONBANKED {
130 151
         } else if (key_pressed(J_SELECT)) {
131 152
             about_screen();
132 153
             splash_win();
133
-        } else if (key_pressed(0xFF)) {
134
-            break;
154
+        } else if (key_pressed(J_START)) {
155
+            if ((key_debug() == 0) && (!(debug_flags & DBG_MENU))) {
156
+                debug_flags |= DBG_MENU;
157
+                splash_win();
158
+            } else {
159
+                break;
160
+            }
161
+        } else {
162
+            if (debug_flags & DBG_MENU) {
163
+                if (key_pressed(J_UP)) {
164
+                    if (debug_menu_index > 0) {
165
+                        debug_menu_index--;
166
+                    } else {
167
+                        debug_menu_index = DEBUG_ENTRY_COUNT - 1;
168
+                    }
169
+                    splash_win();
170
+                } else if (key_pressed(J_DOWN)) {
171
+                    if (debug_menu_index < (DEBUG_ENTRY_COUNT - 1)) {
172
+                        debug_menu_index++;
173
+                    } else {
174
+                        debug_menu_index = 0;
175
+                    }
176
+                    splash_win();
177
+                } else if (key_pressed(J_A)) {
178
+                    SWITCH_ROM(BANK(main));
179
+                    debug_flags ^= debug_entries[debug_menu_index].flag;
180
+                    splash_win();
181
+                }
182
+            }
135 183
         }
136 184
 
137 185
         uint8_t hiwater = SPR_NUM_START;
138
-        obj_draw(&hiwater);
186
+
187
+        if (!(debug_flags & DBG_MENU)) {
188
+            obj_draw(&hiwater);
189
+        }
190
+
139 191
         hide_sprites_range(hiwater, MAX_HARDWARE_SPRITES);
140 192
 
141 193
         vsync();
142 194
     }
143 195
 }
144 196
 
145
-uint16_t ask_name(int32_t score) NONBANKED {
197
+static uint16_t ask_name(int32_t score) NONBANKED {
146 198
     disable_interrupts();
147 199
     DISPLAY_OFF;
148 200
     map_title();

+ 53
- 0
src/main.h View File

@@ -0,0 +1,53 @@
1
+/*
2
+ * main.h
3
+ * Duality
4
+ *
5
+ * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
+ *
7
+ * Based on examples from gbdk-2020:
8
+ * https://github.com/gbdk-2020/gbdk-2020/blob/develop/gbdk-lib/examples/gb/rand/rand.c
9
+ *
10
+ * This program is free software: you can redistribute it and/or modify
11
+ * it under the terms of the GNU General Public License as published by
12
+ * the Free Software Foundation, either version 3 of the License, or
13
+ * (at your option) any later version.
14
+ *
15
+ * This program is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
+ * GNU General Public License for more details.
19
+ *
20
+ * See <http://www.gnu.org/licenses/>.
21
+ */
22
+
23
+#ifndef __MAIN_H__
24
+#define __MAIN_H__
25
+
26
+#include <gbdk/platform.h>
27
+#include <stdint.h>
28
+
29
+enum debug_flag {
30
+    DBG_MENU = (1 << 0),
31
+    DBG_MARKER = (1 << 1),
32
+    DBG_GOD_MODE = (1 << 2),
33
+
34
+    DBG_FLAG_COUNT = 2
35
+};
36
+
37
+#define DEBUG_ENTRY_NAME_LEN 8
38
+
39
+struct debug_entry {
40
+    char name[DEBUG_ENTRY_NAME_LEN + 1];
41
+    enum debug_flag flag;
42
+};
43
+
44
+BANKREF_EXTERN(main)
45
+
46
+extern enum debug_flag debug_flags;
47
+extern uint8_t debug_menu_index;
48
+
49
+#define DEBUG_ENTRY_COUNT 3
50
+
51
+extern const struct debug_entry debug_entries[DEBUG_ENTRY_COUNT];
52
+
53
+#endif // __MAIN_H__

+ 25
- 0
src/maps.c View File

@@ -26,6 +26,7 @@
26 26
 #include "numbers_fnt.h"
27 27
 #include "text_fnt.h"
28 28
 #include "git.h"
29
+#include "main.h"
29 30
 #include "maps.h"
30 31
 
31 32
 #define MAX_DIGITS 7
@@ -249,6 +250,30 @@ void win_about(void) NONBANKED {
249 250
     str(__TIME__, 4, 16, 0);
250 251
 }
251 252
 
253
+void win_debug(void) NONBANKED {
254
+    set_win_based(0, 0,
255
+                  title_map_WIDTH / title_map_TILE_W, title_map_HEIGHT / title_map_TILE_H,
256
+                  title_map_map, 0, BANK(title_map), title_map_MAP_ATTRIBUTES, BANK(title_map));
257
+
258
+    // TODO paging when more options added
259
+
260
+    str_center("Debug Menu", 0, 0);
261
+
262
+    char name_buff[DEBUG_ENTRY_NAME_LEN + 2 + 1] = {0};
263
+    for (uint8_t i = 0; (i < DEBUG_ENTRY_COUNT) && (i < 7); i++) {
264
+        SWITCH_ROM(BANK(main));
265
+        strncpy(name_buff, debug_entries[i].name, DEBUG_ENTRY_NAME_LEN + 1);
266
+
267
+        uint8_t n_len = strlen(name_buff);
268
+        name_buff[n_len] = ' ';
269
+        name_buff[n_len + 1] = (debug_flags & debug_entries[i].flag) ? '1' : '0';
270
+        name_buff[n_len + 2] = '\0';
271
+        n_len += 2;
272
+
273
+        str(name_buff, (LINE_WIDTH - n_len) * 2, (i * 2) + 3, (debug_menu_index == i) ? 1 : 0);
274
+    }
275
+}
276
+
252 277
 void win_name(int32_t score) NONBANKED {
253 278
     set_win_based(0, 0,
254 279
                   title_map_WIDTH / title_map_TILE_W, title_map_HEIGHT / title_map_TILE_H,

+ 1
- 0
src/maps.h View File

@@ -31,6 +31,7 @@ void win_splash_draw(int32_t lowest, int32_t highest);
31 31
 void win_score_clear(uint8_t is_black);
32 32
 void win_score_draw(struct scores score, uint8_t off, uint8_t is_black);
33 33
 void win_about(void);
34
+void win_debug(void);
34 35
 void win_name(int32_t score);
35 36
 void win_name_draw(uint16_t name, uint8_t is_black, uint8_t pos);
36 37
 uint8_t win_game_draw(int32_t score);

+ 22
- 0
src/obj.c View File

@@ -71,6 +71,8 @@
71 71
 #define SCORE_SMALL 5
72 72
 #define SCORE_LARGE 10
73 73
 
74
+#define DESPAWN_RANGE (250 << POS_SCALE_OBJS)
75
+
74 76
 struct obj {
75 77
     uint8_t active;
76 78
     enum SPRITES sprite;
@@ -144,6 +146,11 @@ int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *
144 146
         // handle collision
145 147
         switch (objs[i].sprite) {
146 148
             case SPR_DARK:
149
+                if ((abs_off_x >= DESPAWN_RANGE) || (abs_off_y >= DESPAWN_RANGE)) {
150
+                    // TODO find new (random) position
151
+                    //objs[i].active = 0;
152
+                }
153
+
147 154
                 if ((abs_off_x <= GRAVITY_RANGE) && (abs_off_y <= GRAVITY_RANGE)) {
148 155
                     if (objs[i].off_x > 0) {
149 156
                         *spd_off_x += (GRAVITY_RANGE - objs[i].off_x) >> GRAVITY_SHIFT;
@@ -163,6 +170,11 @@ int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *
163 170
                 break;
164 171
 
165 172
             case SPR_LIGHT:
173
+                if ((abs_off_x >= DESPAWN_RANGE) || (abs_off_y >= DESPAWN_RANGE)) {
174
+                    // TODO find new (random) position
175
+                    //objs[i].active = 0;
176
+                }
177
+
166 178
                 if ((abs_off_x <= GRAVITY_RANGE) && (abs_off_y <= GRAVITY_RANGE)) {
167 179
                     if (objs[i].off_x > 0) {
168 180
                         *spd_off_x -= (GRAVITY_RANGE - objs[i].off_x) >> GRAVITY_SHIFT;
@@ -182,6 +194,11 @@ int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *
182 194
                 break;
183 195
 
184 196
             case SPR_SHOT_DARK:
197
+                if ((abs_off_x >= DESPAWN_RANGE) || (abs_off_y >= DESPAWN_RANGE)) {
198
+                    // TODO find new (random) position
199
+                    //objs[i].active = 0;
200
+                }
201
+
185 202
                 if ((abs_off_x <= PICKUP_SMALL_RANGE) && (abs_off_y <= PICKUP_SMALL_RANGE)) {
186 203
                     (*score) -= SCORE_SMALL;
187 204
                     objs[i].active = 0;
@@ -189,6 +206,11 @@ int16_t obj_do(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score, uint8_t *
189 206
                 break;
190 207
 
191 208
             case SPR_SHOT_LIGHT:
209
+                if ((abs_off_x >= DESPAWN_RANGE) || (abs_off_y >= DESPAWN_RANGE)) {
210
+                    // TODO find new (random) position
211
+                    //objs[i].active = 0;
212
+                }
213
+
192 214
                 if ((abs_off_x <= PICKUP_SMALL_RANGE) && (abs_off_y <= PICKUP_SMALL_RANGE)) {
193 215
                     (*score) += SCORE_SMALL;
194 216
                     objs[i].active = 0;

+ 1
- 1
src/score.ba0.c View File

@@ -30,7 +30,7 @@ BANKREF(score)
30 30
 
31 31
 #define NAME(a, b, c) (((uint16_t)(a - 'a') << 10) | ((uint16_t)(b - 'a') << 5) | (uint16_t)(c - 'a'))
32 32
 
33
-const struct scores initial_scores[SCORE_NUM * 2] = {
33
+static const struct scores initial_scores[SCORE_NUM * 2] = {
34 34
     //{ .name = NAME('a', 'd', 'z'), .score = 10000 },
35 35
     //{ .name = NAME('c', 'a', 'n'), .score = 7500 },
36 36
     //{ .name = NAME('i', 'm', 'y'), .score = 5000 },

Loading…
Cancel
Save