git.y1.nz

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.