Browse Source

add ROM autobanking and store highscores in banked RAM.

Thomas B 1 month ago
parent
commit
1f8001e4e8
13 changed files with 265 additions and 100 deletions
  1. 6
    4
      Makefile
  2. 3
    3
      src/game.c
  3. 3
    3
      src/input.c
  4. 12
    8
      src/main.c
  5. 17
    12
      src/maps.c
  6. 5
    5
      src/obj.c
  7. 149
    0
      src/score.ba0.c
  8. 0
    32
      src/score.c
  9. 8
    3
      src/score.h
  10. 2
    2
      src/sound.c
  11. 50
    25
      src/sprite_data.c
  12. 1
    0
      src/sprite_data.h
  13. 9
    3
      src/sprites.c

+ 6
- 4
Makefile View File

@@ -39,7 +39,8 @@ GB_EMU := gearboy
39 39
 
40 40
 LCCFLAGS := -Wa-l -Wl-m -Wp-MMD
41 41
 LCCFLAGS += -I$(BUILD_DIR)/$(DATA_DIR)
42
-LCCFLAGS += -Wm"-yn Duality" -Wm-yc
42
+LCCFLAGS += -Wm"-yn Duality" -Wm-yt0x1A -Wm-yoA -Wm-ya16 -Wm-yc
43
+LCCFLAGS += -autobank -Wb-ext=.rel -Wb-v -Wf-bo255
43 44
 
44 45
 EMUFLAGS := $(BIN)
45 46
 
@@ -94,12 +95,13 @@ $(BUILD_DIR)/$(DATA_DIR)/%.c $(BUILD_DIR)/$(DATA_DIR)/%.h: $(DATA_DIR)/%.png
94 95
 
95 96
 $(BUILD_DIR)/%.o: %.c $(SPRITES)
96 97
 	@mkdir -p $(@D)
97
-	@echo Compiling $<
98
-	@$(LCC) $(LCCFLAGS) -c -o $@ $<
98
+	@echo Compiling Code $<
99
+	$(eval BAFLAG = $(shell echo "$<" | sed -n 's/.*\.ba\([0-9]\+\).*/\-Wf-ba\1/p'))
100
+	@$(LCC) $(LCCFLAGS) $(BAFLAG) -c -o $@ $<
99 101
 
100 102
 $(BUILD_DIR)/%.o: $(BUILD_DIR)/%.c $(SPRITES)
101 103
 	@mkdir -p $(@D)
102
-	@echo Compiling $<
104
+	@echo Compiling Asset $<
103 105
 	@$(LCC) $(LCCFLAGS) -c -o $@ $<
104 106
 
105 107
 $(BUILD_DIR)/%.o: %.s $(SPRITES)

+ 3
- 3
src/game.c View File

@@ -39,7 +39,7 @@ enum ACCELERATION {
39 39
 #define HEALTH_OFFSET_Y -16
40 40
 #define POWER_OFFSET_Y 16
41 41
 
42
-static void status(uint8_t health, uint8_t power, uint8_t *hiwater) {
42
+static void status(uint8_t health, uint8_t power, uint8_t *hiwater) NONBANKED {
43 43
     if (health > 0) {
44 44
         switch (health >> 6) {
45 45
             case 3:
@@ -75,7 +75,7 @@ static void status(uint8_t health, uint8_t power, uint8_t *hiwater) {
75 75
     }
76 76
 }
77 77
 
78
-int32_t game(void) {
78
+int32_t game(void) NONBANKED {
79 79
     disable_interrupts();
80 80
     DISPLAY_OFF;
81 81
     map_game();
@@ -104,7 +104,7 @@ int32_t game(void) {
104 104
     obj_add(SPR_SHOT_DARK, -32, -32, 0, 0);
105 105
 
106 106
     win_game_draw(score);
107
-    move_win(MINWNDPOSX + 0, MINWNDPOSY + DEVICE_SCREEN_PX_HEIGHT - 16);
107
+    move_win(MINWNDPOSX, MINWNDPOSY + DEVICE_SCREEN_PX_HEIGHT - 16);
108 108
 
109 109
     SHOW_WIN;
110 110
     DISPLAY_ON;

+ 3
- 3
src/input.c View File

@@ -24,15 +24,15 @@
24 24
 static uint8_t joyp = 0;
25 25
 static uint8_t old_joyp = 0;
26 26
 
27
-void key_read(void) {
27
+void key_read(void) NONBANKED {
28 28
     old_joyp = joyp;
29 29
     joyp = joypad();
30 30
 }
31 31
 
32
-uint8_t key_down(uint8_t key) {
32
+uint8_t key_down(uint8_t key) NONBANKED {
33 33
     return joyp & key;
34 34
 }
35 35
 
36
-uint8_t key_pressed(uint8_t key) {
36
+uint8_t key_pressed(uint8_t key) NONBANKED {
37 37
     return (joyp ^ old_joyp) & joyp & key;
38 38
 }

+ 12
- 8
src/main.c View File

@@ -32,14 +32,14 @@
32 32
 #include "game.h"
33 33
 #include "score.h"
34 34
 
35
-static void highscore(uint8_t is_black) {
35
+static void highscore(uint8_t is_black) NONBANKED {
36 36
     HIDE_WIN;
37 37
 
38 38
     hide_sprites_range(SPR_NUM_START, MAX_HARDWARE_SPRITES);
39 39
     win_score_clear();
40 40
 
41 41
     for (uint8_t i = 0; i < SCORE_NUM; i++) {
42
-        int32_t score = is_black ? -score_lowest(i) : score_highest(i);
42
+        int32_t score = is_black ? -score_lowest(i).score : score_highest(i).score;
43 43
         win_score_draw(score, i, is_black);
44 44
     }
45 45
 
@@ -57,12 +57,12 @@ static void highscore(uint8_t is_black) {
57 57
     }
58 58
 }
59 59
 
60
-static void splash_win(void) {
60
+static void splash_win(void) NONBANKED {
61 61
     HIDE_WIN;
62 62
 
63 63
     // initially show the top 1 scores
64
-    int32_t low = score_lowest(0);
65
-    int32_t high = score_highest(0);
64
+    int32_t low = score_lowest(0).score;
65
+    int32_t high = score_highest(0).score;
66 66
 
67 67
     // only show on splash if they fit
68 68
     if ((low >= -99999) && (high <= 99999)) {
@@ -73,7 +73,7 @@ static void splash_win(void) {
73 73
     SHOW_WIN;
74 74
 }
75 75
 
76
-static void splash(void) {
76
+static void splash(void) NONBANKED {
77 77
     disable_interrupts();
78 78
     DISPLAY_OFF;
79 79
     map_title();
@@ -111,7 +111,7 @@ static void splash(void) {
111 111
     }
112 112
 }
113 113
 
114
-void main(void) {
114
+void main(void) NONBANKED {
115 115
     spr_init();
116 116
     snd_init();
117 117
     win_init();
@@ -125,7 +125,11 @@ void main(void) {
125 125
 
126 126
     while (1) {
127 127
         int32_t score = game();
128
-        score_add(score);
128
+
129
+        // TODO ask for name of player
130
+        struct scores s = { .name = 0x00, .score = score };
131
+        score_add(s);
132
+
129 133
         splash();
130 134
     }
131 135
 }

+ 17
- 12
src/maps.c View File

@@ -45,35 +45,39 @@ const palette_color_t num_pal_inv[4] = {
45 45
     RGB8(  0,  0,  0), RGB8(  0,  0,  0), RGB8(248,252,248), RGB8(  0,  0,  0)
46 46
 };
47 47
 
48
-void map_title(void) {
48
+void map_title(void) NONBANKED {
49
+    SWITCH_ROM(BANK(title_map));
49 50
     set_bkg_palette(OAMF_CGB_PAL0, title_map_PALETTE_COUNT, title_map_palettes);
50 51
     set_bkg_data(0, title_map_TILE_COUNT, title_map_tiles);
51 52
     set_bkg_attributes(0, 0, title_map_MAP_ATTRIBUTES_WIDTH, title_map_MAP_ATTRIBUTES_HEIGHT, title_map_MAP_ATTRIBUTES);
52 53
     set_bkg_tiles(0, 0, title_map_WIDTH / title_map_TILE_W, title_map_HEIGHT / title_map_TILE_H, title_map_map);
53 54
 }
54 55
 
55
-void map_game(void) {
56
+void map_game(void) NONBANKED {
57
+    SWITCH_ROM(BANK(bg_map));
56 58
     set_bkg_palette(OAMF_CGB_PAL0, bg_map_PALETTE_COUNT, bg_map_palettes);
57 59
     set_bkg_data(0, bg_map_TILE_COUNT, bg_map_tiles);
58 60
     set_bkg_attributes(0, 0, bg_map_MAP_ATTRIBUTES_WIDTH, bg_map_MAP_ATTRIBUTES_HEIGHT, bg_map_MAP_ATTRIBUTES);
59 61
     set_bkg_tiles(0, 0, bg_map_WIDTH / bg_map_TILE_W, bg_map_HEIGHT / bg_map_TILE_H, bg_map_map);
60 62
 }
61 63
 
62
-void win_init(void) {
64
+void win_init(void) NONBANKED {
65
+    SWITCH_ROM(BANK(numbers));
63 66
     set_bkg_palette(OAMF_CGB_PAL0 + bg_map_PALETTE_COUNT, numbers_PALETTE_COUNT, numbers_palettes);
64 67
     set_bkg_palette(OAMF_CGB_PAL0 + bg_map_PALETTE_COUNT + 1, numbers_PALETTE_COUNT, num_pal_inv);
65 68
     set_win_data(bg_map_TILE_COUNT, numbers_TILE_COUNT, numbers_tiles);
66 69
 }
67 70
 
68 71
 static void set_win_based(uint8_t x, uint8_t y, uint8_t w, uint8_t h,
69
-                          const uint8_t *tiles, uint8_t base_tile, const uint8_t *attributes) {
72
+                          const uint8_t *tiles, uint8_t base_tile, const uint8_t *attributes) NONBANKED {
70 73
     VBK_REG = VBK_ATTRIBUTES;
71 74
     set_win_tiles(x, y, w, h, attributes);
72 75
     VBK_REG = VBK_TILES;
73 76
     set_win_based_tiles(x, y, w, h, tiles, base_tile);
74 77
 }
75 78
 
76
-static void digit(uint8_t val, uint8_t digit, uint8_t x_off, uint8_t y_off, uint8_t is_black) {
79
+static void digit(uint8_t val, uint8_t digit, uint8_t x_off, uint8_t y_off, uint8_t is_black) NONBANKED {
80
+    SWITCH_ROM(BANK(numbers));
77 81
     uint8_t off = val * numbers_WIDTH / numbers_TILE_W;
78 82
 
79 83
     set_win_based(x_off + (digit * numbers_WIDTH / numbers_TILE_W), y_off,
@@ -87,7 +91,7 @@ static void digit(uint8_t val, uint8_t digit, uint8_t x_off, uint8_t y_off, uint
87 91
                   (is_black ? num_attr_2 : num_attr_1) + off);
88 92
 }
89 93
 
90
-static void number(int32_t score, uint8_t x_off, uint8_t y_off, uint8_t is_black) {
94
+static void number(int32_t score, uint8_t x_off, uint8_t y_off, uint8_t is_black) NONBANKED {
91 95
     // TODO can not set numbers larger than int16 max?!
92 96
     //score = 32767 + 1; // wtf?!
93 97
 
@@ -112,14 +116,14 @@ static void number(int32_t score, uint8_t x_off, uint8_t y_off, uint8_t is_black
112 116
     }
113 117
 }
114 118
 
115
-static void fill_win(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t tile, uint8_t attr) {
119
+static void fill_win(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t tile, uint8_t attr) NONBANKED {
116 120
     VBK_REG = VBK_ATTRIBUTES;
117 121
     fill_win_rect(x, y, w, h, attr);
118 122
     VBK_REG = VBK_TILES;
119 123
     fill_win_rect(x, y, w, h, tile);
120 124
 }
121 125
 
122
-void win_splash_draw(int32_t lowest, int32_t highest) {
126
+void win_splash_draw(int32_t lowest, int32_t highest) NONBANKED {
123 127
     // reuse full black and white tiles at 0 and 1 from splash bg
124 128
     fill_win(0, 0, 10, 2, 0, 0x00);
125 129
     fill_win(10, 0, 10, 2, 1, 0x00);
@@ -128,19 +132,20 @@ void win_splash_draw(int32_t lowest, int32_t highest) {
128 132
     number(highest, 0xFE, 0, 0);
129 133
 }
130 134
 
131
-void win_score_clear(void) {
135
+void win_score_clear(void) NONBANKED {
136
+    SWITCH_ROM(BANK(title_map));
132 137
     set_win_based(0, 0,
133 138
                   title_map_WIDTH / title_map_TILE_W, title_map_HEIGHT / title_map_TILE_H,
134 139
                   title_map_map, 0, title_map_MAP_ATTRIBUTES);
135 140
 }
136 141
 
137
-void win_score_draw(int32_t score, uint8_t off, uint8_t is_black) {
142
+void win_score_draw(int32_t score, uint8_t off, uint8_t is_black) NONBANKED {
138 143
     number(off, 1, 4 + off * 3, is_black);
139 144
     number(score, 5, 4 + off * 3, is_black);
140 145
 }
141 146
 
142
-void win_game_draw(int32_t score) {
143
-    fill_win(0, 0, 20, 2, bg_map_TILE_COUNT + numbers_TILE_COUNT, 0x81);
147
+void win_game_draw(int32_t score) NONBANKED {
148
+    fill_win(0, 0, 20, 2, (uint8_t)bg_map_TILE_COUNT + (uint8_t)numbers_TILE_COUNT, 0x81);
144 149
 
145 150
     uint8_t is_black = 0;
146 151
     if (score < 0) {

+ 5
- 5
src/obj.c View File

@@ -73,11 +73,11 @@ struct obj {
73 73
 
74 74
 static struct obj objs[MAX_OBJ];
75 75
 
76
-void obj_init(void) {
76
+void obj_init(void) NONBANKED {
77 77
     memset(objs, 0, sizeof(objs));
78 78
 }
79 79
 
80
-static uint8_t cnt_sprite(enum SPRITES sprite) {
80
+static uint8_t cnt_sprite(enum SPRITES sprite) NONBANKED {
81 81
     uint8_t cnt = 0;
82 82
     for (uint8_t i = 0; i < MAX_OBJ; i++) {
83 83
         if (!objs[i].active) {
@@ -90,7 +90,7 @@ static uint8_t cnt_sprite(enum SPRITES sprite) {
90 90
     return cnt;
91 91
 }
92 92
 
93
-enum OBJ_STATE obj_add(enum SPRITES sprite, int16_t off_x, int16_t off_y, int16_t spd_x, int16_t spd_y) {
93
+enum OBJ_STATE obj_add(enum SPRITES sprite, int16_t off_x, int16_t off_y, int16_t spd_x, int16_t spd_y) NONBANKED {
94 94
     uint8_t obj_cnt = 0xFF;
95 95
     for (uint8_t i = 0; i < MAX_OBJ; i++) {
96 96
         if (!objs[i].active) {
@@ -125,7 +125,7 @@ enum OBJ_STATE obj_add(enum SPRITES sprite, int16_t off_x, int16_t off_y, int16_
125 125
 #define PICKUP_SMALL_RANGE (10 << POS_SCALE_OBJS)
126 126
 #define PICKUP_LARGE_RANGE (16 << POS_SCALE_OBJS)
127 127
 
128
-int16_t obj_act(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score) {
128
+int16_t obj_act(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score) NONBANKED {
129 129
     int16_t damage = 0;
130 130
 
131 131
     for (uint8_t i = 0; i < MAX_OBJ; i++) {
@@ -194,7 +194,7 @@ int16_t obj_act(int16_t *spd_off_x, int16_t *spd_off_y, int32_t *score) {
194 194
     return damage;
195 195
 }
196 196
 
197
-void obj_draw(int16_t spd_x, int16_t spd_y, uint8_t *hiwater) {
197
+void obj_draw(int16_t spd_x, int16_t spd_y, uint8_t *hiwater) NONBANKED {
198 198
     for (uint8_t i = 0; i < MAX_OBJ; i++) {
199 199
         if (!objs[i].active) {
200 200
             continue;

+ 149
- 0
src/score.ba0.c View File

@@ -0,0 +1,149 @@
1
+/*
2
+ * score.ba0.c
3
+ * Duality
4
+ *
5
+ * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * This program is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
+ * GNU General Public License for more details.
16
+ *
17
+ * See <http://www.gnu.org/licenses/>.
18
+ */
19
+
20
+#include <gbdk/platform.h>
21
+
22
+#include "score.h"
23
+
24
+static struct scores scores[SCORE_NUM * 2];
25
+static uint32_t scores_crc;
26
+
27
+static uint16_t convert_name(char a, char b, char c) {
28
+    // convert to lowercase
29
+    if ((a >= 'A') && (a <= 'Z')) a = a - 'A' + 'a';
30
+    if ((b >= 'A') && (b <= 'Z')) b = b - 'A' + 'a';
31
+    if ((c >= 'A') && (c <= 'Z')) c = c - 'A' + 'a';
32
+
33
+    // skip invalid characters
34
+    if ((a < 'a') || (a > 'z')) a = 'x';
35
+    if ((b < 'a') || (b > 'z')) b = 'x';
36
+    if ((c < 'a') || (c > 'z')) c = 'x';
37
+
38
+    // zero offset in alphabet
39
+    a -= 'a';
40
+    b -= 'a';
41
+    c -= 'a';
42
+
43
+    return (a << 10) | (b << 5) | c;
44
+}
45
+
46
+static uint32_t calc_crc(void) NONBANKED {
47
+    const uint8_t *d = (const uint8_t *)scores;
48
+
49
+    uint32_t c = 0xFFFFFFFF;
50
+    for (size_t i = 0; i < sizeof(scores); i++) {
51
+        // adapted from "Hacker's Delight"
52
+        c ^= d[i];
53
+        for (size_t j = 0; j < 8; j++) {
54
+            uint32_t mask = -(c & 1);
55
+            c = (c >> 1) ^ (0xEDB88320 & mask);
56
+        }
57
+    }
58
+
59
+    return ~c;
60
+}
61
+
62
+static uint8_t check_crc(void) NONBANKED {
63
+    return (calc_crc() == scores_crc) ? 1 : 0;
64
+}
65
+
66
+static void score_init(void) NONBANKED {
67
+    // TODO
68
+    scores[0].name = convert_name('a', 'b', 'c');
69
+    scores[0].score = 10000;
70
+
71
+    scores[1].name = convert_name('a', 'b', 'c');
72
+    scores[1].score = 8000;
73
+
74
+    scores[2].name = convert_name('a', 'b', 'c');
75
+    scores[2].score = 6000;
76
+
77
+    scores[3].name = convert_name('a', 'b', 'c');
78
+    scores[3].score = 4000;
79
+
80
+    scores[4].name = convert_name('a', 'b', 'c');
81
+    scores[4].score = 2000;
82
+
83
+    scores[5].name = convert_name('a', 'b', 'c');
84
+    scores[5].score = -2000;
85
+
86
+    scores[6].name = convert_name('a', 'b', 'c');
87
+    scores[6].score = -4000;
88
+
89
+    scores[7].name = convert_name('a', 'b', 'c');
90
+    scores[7].score = -6000;
91
+
92
+    scores[8].name = convert_name('a', 'b', 'c');
93
+    scores[8].score = -8000;
94
+
95
+    scores[9].name = convert_name('a', 'b', 'c');
96
+    scores[9].score = -10000;
97
+
98
+    scores_crc = calc_crc();
99
+}
100
+
101
+void score_add(struct scores score) NONBANKED {
102
+    ENABLE_RAM;
103
+    SWITCH_RAM(0);
104
+
105
+    // initialize score table when data is invalid
106
+    if (!check_crc()) {
107
+        score_init();
108
+    }
109
+
110
+    // TODO
111
+
112
+    DISABLE_RAM;
113
+}
114
+
115
+struct scores score_highest(uint8_t off) NONBANKED {
116
+    ENABLE_RAM;
117
+    SWITCH_RAM(0);
118
+
119
+    // initialize score table when data is invalid
120
+    if (!check_crc()) {
121
+        score_init();
122
+    }
123
+
124
+    if (off >= SCORE_NUM) {
125
+        off = SCORE_NUM - 1;
126
+    }
127
+    struct scores r = scores[off];
128
+
129
+    DISABLE_RAM;
130
+    return r;
131
+}
132
+
133
+struct scores score_lowest(uint8_t off) NONBANKED {
134
+    ENABLE_RAM;
135
+    SWITCH_RAM(0);
136
+
137
+    // initialize score table when data is invalid
138
+    if (!check_crc()) {
139
+        score_init();
140
+    }
141
+
142
+    if (off >= SCORE_NUM) {
143
+        off = SCORE_NUM - 1;
144
+    }
145
+    struct scores r = scores[(SCORE_NUM * 2) - 1 - off];
146
+
147
+    DISABLE_RAM;
148
+    return r;
149
+}

+ 0
- 32
src/score.c View File

@@ -1,32 +0,0 @@
1
-/*
2
- * score.c
3
- * Duality
4
- *
5
- * Copyright (C) 2025 Thomas Buck <thomas@xythobuz.de>
6
- *
7
- * This program is free software: you can redistribute it and/or modify
8
- * it under the terms of the GNU General Public License as published by
9
- * the Free Software Foundation, either version 3 of the License, or
10
- * (at your option) any later version.
11
- *
12
- * This program is distributed in the hope that it will be useful,
13
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
- * GNU General Public License for more details.
16
- *
17
- * See <http://www.gnu.org/licenses/>.
18
- */
19
-
20
-#include "score.h"
21
-
22
-void score_add(int32_t score) {
23
-
24
-}
25
-
26
-int32_t score_highest(uint8_t off) {
27
-    return 8888 - off;
28
-}
29
-
30
-int32_t score_lowest(uint8_t off) {
31
-    return -(9999 - off);
32
-}

+ 8
- 3
src/score.h View File

@@ -24,8 +24,13 @@
24 24
 
25 25
 #define SCORE_NUM 5
26 26
 
27
-void score_add(int32_t score);
28
-int32_t score_highest(uint8_t off);
29
-int32_t score_lowest(uint8_t off);
27
+struct scores {
28
+    uint16_t name;
29
+    int32_t score;
30
+};
31
+
32
+void score_add(struct scores score);
33
+struct scores score_highest(uint8_t off);
34
+struct scores score_lowest(uint8_t off);
30 35
 
31 36
 #endif // __SCORE_H__

+ 2
- 2
src/sound.c View File

@@ -27,7 +27,7 @@
27 27
 
28 28
 #include "sound.h"
29 29
 
30
-void snd_init(void) {
30
+void snd_init(void) NONBANKED {
31 31
     NR52_REG = 0x80; // sound on
32 32
     NR51_REG = 0xFF; // all channels on left and right
33 33
 
@@ -38,7 +38,7 @@ void snd_init(void) {
38 38
 #endif
39 39
 }
40 40
 
41
-void snd_noise(void) {
41
+void snd_noise(void) NONBANKED {
42 42
     NR41_REG = 0x2F; // length timer, higher value is shorter time (up to 0x3F)
43 43
     NR42_REG = 0xF0; // initially full volume, no volume changes over time
44 44
     NR43_REG = 0x11; // frequency distribution

+ 50
- 25
src/sprite_data.c View File

@@ -51,7 +51,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
51 51
         .pa = rockshp_0_palettes,
52 52
         .pa_i = OAMF_CGB_PAL0,
53 53
         .cnt = rockshp_0_TILE_COUNT,
54
-        .off = TILE_NUM_START
54
+        .off = TILE_NUM_START,
55
+        .bank = BANK(rockshp_0),
55 56
     },
56 57
     { // SPR_SHIP_90
57 58
         .ms = rockshp_90_metasprites,
@@ -59,7 +60,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
59 60
         .pa = NULL,
60 61
         .pa_i = OAMF_CGB_PAL0,
61 62
         .cnt = rockshp_90_TILE_COUNT,
62
-        .off = TILE_NUM_START
63
+        .off = TILE_NUM_START,
64
+        .bank = BANK(rockshp_90),
63 65
     },
64 66
     { // SPR_THRUST_0
65 67
         .ms = thrust_0_metasprites,
@@ -67,7 +69,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
67 69
         .pa = thrust_0_palettes,
68 70
         .pa_i = OAMF_CGB_PAL1,
69 71
         .cnt = thrust_0_TILE_COUNT,
70
-        .off = TILE_NUM_START
72
+        .off = TILE_NUM_START,
73
+        .bank = BANK(thrust_0),
71 74
     },
72 75
     { // SPR_THRUST_90
73 76
         .ms = thrust_90_metasprites,
@@ -75,7 +78,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
75 78
         .pa = NULL,
76 79
         .pa_i = OAMF_CGB_PAL1,
77 80
         .cnt = thrust_90_TILE_COUNT,
78
-        .off = TILE_NUM_START
81
+        .off = TILE_NUM_START,
82
+        .bank = BANK(thrust_90),
79 83
     },
80 84
     { // SPR_LIGHT
81 85
         .ms = light_metasprites,
@@ -83,7 +87,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
83 87
         .pa = light_palettes,
84 88
         .pa_i = OAMF_CGB_PAL2,
85 89
         .cnt = light_TILE_COUNT,
86
-        .off = TILE_NUM_START
90
+        .off = TILE_NUM_START,
91
+        .bank = BANK(light),
87 92
     },
88 93
     { // SPR_DARK
89 94
         .ms = dark_metasprites,
@@ -91,7 +96,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
91 96
         .pa = dark_palettes,
92 97
         .pa_i = OAMF_CGB_PAL3,
93 98
         .cnt = dark_TILE_COUNT,
94
-        .off = TILE_NUM_START
99
+        .off = TILE_NUM_START,
100
+        .bank = BANK(dark),
95 101
     },
96 102
     { // SPR_SHOT
97 103
         .ms = shoot_metasprites,
@@ -99,7 +105,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
99 105
         .pa = shoot_palettes,
100 106
         .pa_i = OAMF_CGB_PAL4,
101 107
         .cnt = shoot_TILE_COUNT,
102
-        .off = TILE_NUM_START
108
+        .off = TILE_NUM_START,
109
+        .bank = BANK(shoot),
103 110
     },
104 111
     { // SPR_SHOT_LIGHT
105 112
         .ms = shoot_metasprites,
@@ -107,7 +114,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
107 114
         .pa = NULL,
108 115
         .pa_i = OAMF_CGB_PAL2,
109 116
         .cnt = shoot_TILE_COUNT,
110
-        .off = SPR_SHOT
117
+        .off = SPR_SHOT,
118
+        .bank = BANK(shoot),
111 119
     },
112 120
     { // SPR_SHOT_DARK
113 121
         .ms = shoot_metasprites,
@@ -115,7 +123,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
115 123
         .pa = NULL,
116 124
         .pa_i = OAMF_CGB_PAL3,
117 125
         .cnt = shoot_TILE_COUNT,
118
-        .off = SPR_SHOT
126
+        .off = SPR_SHOT,
127
+        .bank = BANK(shoot),
119 128
     },
120 129
     { // SPR_HEALTH_1
121 130
         .ms = bar_1_metasprites,
@@ -123,7 +132,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
123 132
         .pa = bar_1_palettes,
124 133
         .pa_i = OAMF_CGB_PAL5,
125 134
         .cnt = bar_1_TILE_COUNT,
126
-        .off = TILE_NUM_START
135
+        .off = TILE_NUM_START,
136
+        .bank = BANK(bar_1),
127 137
     },
128 138
     { // SPR_HEALTH_2
129 139
         .ms = bar_2_metasprites,
@@ -131,7 +141,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
131 141
         .pa = NULL,
132 142
         .pa_i = OAMF_CGB_PAL5,
133 143
         .cnt = bar_2_TILE_COUNT,
134
-        .off = TILE_NUM_START
144
+        .off = TILE_NUM_START,
145
+        .bank = BANK(bar_2),
135 146
     },
136 147
     { // SPR_HEALTH_3
137 148
         .ms = bar_3_metasprites,
@@ -139,7 +150,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
139 150
         .pa = NULL,
140 151
         .pa_i = OAMF_CGB_PAL5,
141 152
         .cnt = bar_3_TILE_COUNT,
142
-        .off = TILE_NUM_START
153
+        .off = TILE_NUM_START,
154
+        .bank = BANK(bar_3),
143 155
     },
144 156
     { // SPR_HEALTH_4
145 157
         .ms = bar_4_metasprites,
@@ -147,7 +159,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
147 159
         .pa = NULL,
148 160
         .pa_i = OAMF_CGB_PAL5,
149 161
         .cnt = bar_4_TILE_COUNT,
150
-        .off = TILE_NUM_START
162
+        .off = TILE_NUM_START,
163
+        .bank = BANK(bar_4),
151 164
     },
152 165
     { // SPR_HEALTH_5
153 166
         .ms = bar_5_metasprites,
@@ -155,7 +168,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
155 168
         .pa = NULL,
156 169
         .pa_i = OAMF_CGB_PAL5,
157 170
         .cnt = bar_5_TILE_COUNT,
158
-        .off = TILE_NUM_START
171
+        .off = TILE_NUM_START,
172
+        .bank = BANK(bar_5),
159 173
     },
160 174
     { // SPR_HEALTH_6
161 175
         .ms = bar_6_metasprites,
@@ -163,7 +177,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
163 177
         .pa = NULL,
164 178
         .pa_i = OAMF_CGB_PAL5,
165 179
         .cnt = bar_6_TILE_COUNT,
166
-        .off = TILE_NUM_START
180
+        .off = TILE_NUM_START,
181
+        .bank = BANK(bar_6),
167 182
     },
168 183
     { // SPR_HEALTH_7
169 184
         .ms = bar_7_metasprites,
@@ -171,7 +186,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
171 186
         .pa = NULL,
172 187
         .pa_i = OAMF_CGB_PAL5,
173 188
         .cnt = bar_7_TILE_COUNT,
174
-        .off = TILE_NUM_START
189
+        .off = TILE_NUM_START,
190
+        .bank = BANK(bar_7),
175 191
     },
176 192
     { // SPR_HEALTH_8
177 193
         .ms = bar_8_metasprites,
@@ -179,7 +195,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
179 195
         .pa = NULL,
180 196
         .pa_i = OAMF_CGB_PAL5,
181 197
         .cnt = bar_8_TILE_COUNT,
182
-        .off = TILE_NUM_START
198
+        .off = TILE_NUM_START,
199
+        .bank = BANK(bar_8),
183 200
     },
184 201
     { // SPR_POWER_1
185 202
         .ms = bar_1_metasprites,
@@ -187,7 +204,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
187 204
         .pa = power_palettes,
188 205
         .pa_i = OAMF_CGB_PAL6,
189 206
         .cnt = bar_1_TILE_COUNT,
190
-        .off = SPR_HEALTH_1
207
+        .off = SPR_HEALTH_1,
208
+        .bank = BANK(bar_1),
191 209
     },
192 210
     { // SPR_POWER_2
193 211
         .ms = bar_2_metasprites,
@@ -195,7 +213,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
195 213
         .pa = NULL,
196 214
         .pa_i = OAMF_CGB_PAL6,
197 215
         .cnt = bar_2_TILE_COUNT,
198
-        .off = SPR_HEALTH_2
216
+        .off = SPR_HEALTH_2,
217
+        .bank = BANK(bar_2),
199 218
     },
200 219
     { // SPR_POWER_3
201 220
         .ms = bar_3_metasprites,
@@ -203,7 +222,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
203 222
         .pa = NULL,
204 223
         .pa_i = OAMF_CGB_PAL6,
205 224
         .cnt = bar_3_TILE_COUNT,
206
-        .off = SPR_HEALTH_3
225
+        .off = SPR_HEALTH_3,
226
+        .bank = BANK(bar_3),
207 227
     },
208 228
     { // SPR_POWER_4
209 229
         .ms = bar_4_metasprites,
@@ -211,7 +231,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
211 231
         .pa = NULL,
212 232
         .pa_i = OAMF_CGB_PAL6,
213 233
         .cnt = bar_4_TILE_COUNT,
214
-        .off = SPR_HEALTH_4
234
+        .off = SPR_HEALTH_4,
235
+        .bank = BANK(bar_4),
215 236
     },
216 237
     { // SPR_POWER_5
217 238
         .ms = bar_5_metasprites,
@@ -219,7 +240,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
219 240
         .pa = NULL,
220 241
         .pa_i = OAMF_CGB_PAL6,
221 242
         .cnt = bar_5_TILE_COUNT,
222
-        .off = SPR_HEALTH_5
243
+        .off = SPR_HEALTH_5,
244
+        .bank = BANK(bar_5),
223 245
     },
224 246
     { // SPR_POWER_6
225 247
         .ms = bar_6_metasprites,
@@ -227,7 +249,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
227 249
         .pa = NULL,
228 250
         .pa_i = OAMF_CGB_PAL6,
229 251
         .cnt = bar_6_TILE_COUNT,
230
-        .off = SPR_HEALTH_6
252
+        .off = SPR_HEALTH_6,
253
+        .bank = BANK(bar_6),
231 254
     },
232 255
     { // SPR_POWER_7
233 256
         .ms = bar_7_metasprites,
@@ -235,7 +258,8 @@ struct sprites metasprites[SPRITE_COUNT] = {
235 258
         .pa = NULL,
236 259
         .pa_i = OAMF_CGB_PAL6,
237 260
         .cnt = bar_7_TILE_COUNT,
238
-        .off = SPR_HEALTH_7
261
+        .off = SPR_HEALTH_7,
262
+        .bank = BANK(bar_7),
239 263
     },
240 264
     { // SPR_POWER_8
241 265
         .ms = bar_8_metasprites,
@@ -243,6 +267,7 @@ struct sprites metasprites[SPRITE_COUNT] = {
243 267
         .pa = NULL,
244 268
         .pa_i = OAMF_CGB_PAL6,
245 269
         .cnt = bar_8_TILE_COUNT,
246
-        .off = SPR_HEALTH_8
270
+        .off = SPR_HEALTH_8,
271
+        .bank = BANK(bar_8),
247 272
     }
248 273
 };

+ 1
- 0
src/sprite_data.h View File

@@ -39,6 +39,7 @@ struct sprites {
39 39
     uint8_t pa_i;
40 40
     uint8_t cnt;
41 41
     uint8_t off;
42
+    uint8_t bank;
42 43
 };
43 44
 
44 45
 extern struct sprites metasprites[SPRITE_COUNT];

+ 9
- 3
src/sprites.c View File

@@ -22,9 +22,11 @@
22 22
 
23 23
 #include "sprite_data.h"
24 24
 
25
-void spr_init(void) {
25
+void spr_init(void) NONBANKED {
26 26
     uint8_t off = TILE_NUM_START;
27 27
     for (uint8_t i = 0; i < SPRITE_COUNT; i++) {
28
+        SWITCH_ROM(metasprites[i].bank);
29
+
28 30
         if (metasprites[i].pa != NULL) {
29 31
             set_sprite_palette(metasprites[i].pa_i, 1, metasprites[i].pa);
30 32
         }
@@ -39,7 +41,11 @@ void spr_init(void) {
39 41
     }
40 42
 }
41 43
 
42
-void spr_draw(enum SPRITES sprite, enum SPRITE_FLIP flip, int8_t x_off, int8_t y_off, uint8_t frame, uint8_t *hiwater) {
44
+void spr_draw(enum SPRITES sprite, enum SPRITE_FLIP flip,
45
+              int8_t x_off, int8_t y_off, uint8_t frame,
46
+              uint8_t *hiwater) NONBANKED {
47
+    SWITCH_ROM(metasprites[sprite].bank);
48
+
43 49
     switch (flip) {
44 50
         case FLIP_Y:
45 51
             *hiwater += move_metasprite_flipy(
@@ -76,7 +82,7 @@ void spr_draw(enum SPRITES sprite, enum SPRITE_FLIP flip, int8_t x_off, int8_t y
76 82
     }
77 83
 }
78 84
 
79
-void spr_ship(enum SPRITE_ROT rot, uint8_t moving, uint8_t *hiwater) {
85
+void spr_ship(enum SPRITE_ROT rot, uint8_t moving, uint8_t *hiwater) NONBANKED {
80 86
     switch (rot) {
81 87
         case ROT_0:
82 88
             spr_draw(SPR_SHIP_0, FLIP_NONE, 0, 0, 0, hiwater);

Loading…
Cancel
Save