gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-lib/examples/cross-platform/large_map/src/large_map.c
1 #include <stdint.h>
2
3 #include <gbdk/platform.h>
4
5 #include "res/bigmap.h"
6 #define bigmap_mapWidth (bigmap_WIDTH/bigmap_TILE_W)
7 #define bigmap_mapHeight (bigmap_HEIGHT/bigmap_TILE_H)
8
9 #define camera_max_y ((bigmap_mapHeight - DEVICE_SCREEN_HEIGHT) * 8)
10 #define camera_max_x ((bigmap_mapWidth - DEVICE_SCREEN_WIDTH) * 8)
11
12 #define WRAP_SCROLL_Y(y) ((y) % (DEVICE_SCREEN_BUFFER_HEIGHT * 8))
13
14 // For systems where screen buffer height is equal to screen height, adjust Y-scroll 4 pixels down to partly hide artifacts in NTSC overscan
15 #if DEVICE_SCREEN_BUFFER_HEIGHT == DEVICE_SCREEN_HEIGHT
16 #define SCROLL_Y_OFFSET 4
17 #else
18 #define SCROLL_Y_OFFSET 0
19 #endif
20
21 #if defined(SEGA)
22 // The "compatibility" function set_bkg_submap (=set_tile_submap_compat)
23 // expect maps with only 1-byte-per-tile, only containing either a tile
24 // index or an attribute.
25 // But png2asset can only produce 2-byte-per-tile maps where both tile index
26 // and attribute are consecutive when the -map_attributes parameter is used.
27 // To work around this, we redefine those functions for SMS/GG only, so
28 // they work like this:
29 // * Use set_tile_submap for tile indices, to read/write both bytes of map
30 // * Make set_submap_attributes a no-op, as attributes were already set
31 #define set_submap_indices(x, y, w, h, map, map_w) set_tile_submap(x, y, w, h, map, map_w)
32 #define set_submap_attributes(x, y, w, h, map, map_w)
33 #else
34 #define set_submap_indices(x, y, w, h, map, map_w) set_bkg_submap(x, y, w, h, map, map_w)
35 #define set_submap_attributes(x, y, w, h, map, map_w) set_bkg_submap_attributes(x, y, w, h, map, map_w)
36 #endif
37
38 #define MIN(A,B) ((A)<(B)?(A):(B))
39
40 uint8_t joy;
41
42 // current and old positions of the camera in pixels
43 uint16_t camera_x, camera_y, old_camera_x, old_camera_y;
44 // current and old position of the map in tiles
45 uint8_t map_pos_x, map_pos_y, old_map_pos_x, old_map_pos_y;
46 // redraw flag, indicates that camera position was changed
47 uint8_t redraw;
48
49 inline uint8_t update_column_left(uint8_t map_pos_x)
50 {
51 #if (DEVICE_SCREEN_BUFFER_WIDTH == DEVICE_SCREEN_WIDTH)
52 return map_pos_x + 1;
53 #else
54 return map_pos_x;
55 #endif
56 }
57
58 inline uint8_t update_column_right(uint8_t map_pos_x)
59 {
60 return map_pos_x + DEVICE_SCREEN_WIDTH;
61 }
62
63 inline uint8_t update_row_top(uint8_t map_pos_y)
64 {
65 #if (DEVICE_SCREEN_BUFFER_HEIGHT == DEVICE_SCREEN_HEIGHT)
66 return map_pos_y + 1;
67 #else
68 return map_pos_y;
69 #endif
70 }
71
72 inline uint8_t update_row_bottom(uint8_t map_pos_y)
73 {
74 return map_pos_y + DEVICE_SCREEN_HEIGHT;
75 }
76
77 void set_camera(void)
78 {
79 // update hardware scroll position
80 move_bkg(camera_x, WRAP_SCROLL_Y(camera_y + SCROLL_Y_OFFSET));
81 // up or down
82 map_pos_y = (uint8_t)(camera_y >> 3u);
83 if (map_pos_y != old_map_pos_y)
84 {
85 if (camera_y < old_camera_y)
86 {
87 set_submap_indices(
88 map_pos_x,
89 update_row_top(map_pos_y),
90 MIN(DEVICE_SCREEN_WIDTH + 1, bigmap_mapWidth-map_pos_x),
91 1,
92 bigmap_map,
93 bigmap_mapWidth);
94 set_submap_attributes(
95 map_pos_x,
96 update_row_top(map_pos_y),
97 MIN(DEVICE_SCREEN_WIDTH + 1, bigmap_mapWidth-map_pos_x),
98 1,
99 bigmap_map_attributes,
100 bigmap_mapWidth);
101 }
102 else
103 {
104 if ((bigmap_mapHeight - DEVICE_SCREEN_HEIGHT) > map_pos_y)
105 {
106 set_submap_indices(
107 map_pos_x,
108 update_row_bottom(map_pos_y),
109 MIN(DEVICE_SCREEN_WIDTH + 1, bigmap_mapWidth-map_pos_x),
110 1,
111 bigmap_map,
112 bigmap_mapWidth);
113 set_submap_attributes(
114 map_pos_x,
115 update_row_bottom(map_pos_y),
116 MIN(DEVICE_SCREEN_WIDTH + 1, bigmap_mapWidth-map_pos_x),
117 1,
118 bigmap_map_attributes,
119 bigmap_mapWidth);
120 }
121 }
122 old_map_pos_y = map_pos_y;
123 }
124 // left or right
125 map_pos_x = (uint8_t)(camera_x >> 3u);
126 if (map_pos_x != old_map_pos_x)
127 {
128 if (camera_x < old_camera_x)
129 {
130 set_submap_indices(
131 update_column_left(map_pos_x),
132 map_pos_y,
133 1,
134 MIN(DEVICE_SCREEN_HEIGHT + 1, bigmap_mapHeight - map_pos_y),
135 bigmap_map,
136 bigmap_mapWidth);
137 set_submap_attributes(
138 update_column_left(map_pos_x),
139 map_pos_y,
140 1,
141 MIN(DEVICE_SCREEN_HEIGHT + 1, bigmap_mapHeight - map_pos_y),
142 bigmap_map_attributes,
143 bigmap_mapWidth);
144 }
145 else
146 {
147 if ((bigmap_mapWidth - DEVICE_SCREEN_WIDTH) > map_pos_x)
148 {
149 set_submap_indices(
150 update_column_right(map_pos_x),
151 map_pos_y,
152 1,
153 MIN(DEVICE_SCREEN_HEIGHT + 1, bigmap_mapHeight - map_pos_y),
154 bigmap_map,
155 bigmap_mapWidth);
156 set_submap_attributes(
157 update_column_right(map_pos_x),
158 map_pos_y,
159 1,
160 MIN(DEVICE_SCREEN_HEIGHT + 1, bigmap_mapHeight - map_pos_y),
161 bigmap_map_attributes,
162 bigmap_mapWidth);
163 }
164 }
165 old_map_pos_x = map_pos_x;
166 }
167 // set old camera position to current camera position
168 old_camera_x = camera_x, old_camera_y = camera_y;
169 }
170
171
172 void init_camera(uint8_t x, uint8_t y) {
173
174 // Set up tile data
175 set_native_tile_data(0, bigmap_TILE_COUNT, bigmap_tiles);
176
177 // Set up color palettes
178 #if defined(SEGA)
179 __WRITE_VDP_REG(VDP_R2, R2_MAP_0x3800);
180 __WRITE_VDP_REG(VDP_R5, R5_SAT_0x3F00);
181 set_palette(0, bigmap_PALETTE_COUNT, bigmap_palettes);
182 #elif defined(GAMEBOY)
183 if (_cpu == CGB_TYPE) {
184 set_bkg_palette(BKGF_CGB_PAL0, bigmap_PALETTE_COUNT, bigmap_palettes);
185 }
186 #elif defined(NINTENDO_NES)
187 set_bkg_palette(0, bigmap_PALETTE_COUNT, bigmap_palettes);
188 #endif
189
190
191 // Initial camera position in pixels set here.
192 camera_x = x;
193 camera_y = y;
194 // Enforce map limits on initial camera position
195 if (camera_x > camera_max_x) camera_x = camera_max_x;
196 if (camera_y > camera_max_y) camera_y = camera_max_y;
197 old_camera_x = camera_x; old_camera_y = camera_y;
198
199 map_pos_x = camera_x >> 3;
200 map_pos_y = camera_y >> 3;
201 old_map_pos_x = old_map_pos_y = 255;
202 move_bkg(camera_x, WRAP_SCROLL_Y(camera_y + SCROLL_Y_OFFSET));
203
204 // Draw the initial map view for the whole screen
205 set_submap_indices(
206 map_pos_x,
207 map_pos_y,
208 MIN(DEVICE_SCREEN_WIDTH + 1u, bigmap_mapWidth - map_pos_x),
209 MIN(DEVICE_SCREEN_HEIGHT + 1u, bigmap_mapHeight - map_pos_y),
210 bigmap_map,
211 bigmap_mapWidth);
212
213 set_submap_attributes(
214 map_pos_x,
215 map_pos_y,
216 MIN(DEVICE_SCREEN_WIDTH + 1u, bigmap_mapWidth - map_pos_x),
217 MIN(DEVICE_SCREEN_HEIGHT + 1u, bigmap_mapHeight - map_pos_y),
218 bigmap_map_attributes,
219 bigmap_mapWidth);
220
221 redraw = FALSE;
222
223 move_bkg(camera_x, WRAP_SCROLL_Y(camera_y + SCROLL_Y_OFFSET));
224 #if DEVICE_SCREEN_BUFFER_WIDTH == DEVICE_SCREEN_WIDTH
225 // On platforms where screen buffer has no more space than physical screen,
226 // the next map column will be written to the leftmost screen column.
227 // So we blank the leftmost column to hide visual artifacts where possible.
228 HIDE_LEFT_COLUMN;
229 #endif
230 }
231
232 void main(void){
233 DISPLAY_OFF;
234 init_camera(0, 0);
235
236 SHOW_BKG;
237 DISPLAY_ON;
238 while (TRUE) {
239 joy = joypad();
240 // up or down
241 if (joy & J_UP) {
242 if (camera_y) {
243 camera_y--;
244 redraw = TRUE;
245 }
246 } else if (joy & J_DOWN) {
247 if (camera_y < camera_max_y) {
248 camera_y++;
249 redraw = TRUE;
250 }
251 }
252 // left or right
253 if (joy & J_LEFT) {
254 if (camera_x) {
255 camera_x--;
256 redraw = TRUE;
257 }
258 } else if (joy & J_RIGHT) {
259 if (camera_x < camera_max_x) {
260 camera_x++;
261 redraw = TRUE;
262 }
263 }
264 if (redraw) {
265 vsync();
266 set_camera();
267 redraw = FALSE;
268 } else vsync();
269 }
270 }
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.