diff --git a/inc/map.h b/inc/map.h index 00212d04..77311bd1 100644 --- a/inc/map.h +++ b/inc/map.h @@ -31,6 +31,41 @@ #include "vdp_tile.h" #include "pal.h" +// forward +typedef struct Map Map; + +/** + * \brief + * Map data update type + */ +typedef enum +{ + ROW_UPDATE, /** tilemap row update **/ + COLUMN_UPDATE /** tilemap column update **/ +} MapUpdateType; + +/** + * \brief + * Map data patch callback.
+ * It's used to modify/patch map data (for destructible blocks for instance) before sending it to VRAM. + * + * \param map + * source Map structure containing map information. + * \param buf + * buffer containing the tilemap data to patch + * \param x + * tile X start update position + * \param y + * tile Y start update position + * \param updateType + * map data update type:
+ * - ROW_UPDATE (tilemap row update)
+ * - COLUMN_UPDATE (tilemap column update)
+ * \param size + * size of the buffer (tilemap width or height depending we are on a row or column update type) + */ +typedef void MapDataPatchCallback(Map *map, u16 *buf, u16 x, u16 y, MapUpdateType updateType, u16 size); + /** * \brief @@ -87,7 +122,6 @@ typedef struct u16* blockRowOffsets; } MapDefinition; - /** * \brief * Map structure containing information for large background/plane update based on #MapDefinition @@ -124,13 +158,17 @@ typedef struct * internal * \param lastYT * internal + * \param hScrollTable + * internal + * \param vScrollTable + * internal * \param prepareMapDataColumnCB * internal * \param prepareMapDataRowCB * internal - * \param hScrollTable + * \param patchMapDataColumnCB * internal - * \param vScrollTable + * \param patchMapDataRowCB * internal * \param getMetaTileCB * internal @@ -161,12 +199,11 @@ typedef struct Map u16 lastYT; u16 hScrollTable[240]; u16 vScrollTable[20]; - void (*prepareMapDataColumnCB)(struct Map *map, u16 *bufCol1, u16 *bufCol2, u16 xm, u16 ym, u16 height); - void (*prepareMapDataRowCB)(struct Map *map, u16 *bufRow1, u16 *bufRow2, u16 xm, u16 ym, u16 width); - void (*patchMapDataColumnCB)(struct Map *map, u16 *buf, u16 x, u16 y, u16 height); - void (*patchMapDataRowCB)(struct Map *map, u16 *buf, u16 x, u16 y, u16 width); - u16 (*getMetaTileCB)(struct Map *map, u16 x, u16 y); - void (*getMetaTilemapRectCB)(struct Map *map, u16 x, u16 y, u16 w, u16 h, u16* dest); + void (*prepareMapDataColumnCB)(Map *map, u16 *bufCol1, u16 *bufCol2, u16 xm, u16 ym, u16 height); + void (*prepareMapDataRowCB)(Map *map, u16 *bufRow1, u16 *bufRow2, u16 xm, u16 ym, u16 width); + MapDataPatchCallback* mapDataPatchCB; + u16 (*getMetaTileCB)(Map *map, u16 x, u16 y); + void (*getMetaTilemapRectCB)(Map *map, u16 x, u16 y, u16 w, u16 h, u16* dest); } Map; @@ -211,7 +248,7 @@ void MAP_release(Map* map); * SYS_doVBlankProcess() in between. * * \param map - * Map structure containing map information. + * source Map structure containing map information. * \param x * view position X we want to scroll on * \param y @@ -225,7 +262,7 @@ void MAP_scrollTo(Map* map, u32 x, u32 y); * Exactly as #MAP_scrollTo(..) except we can force complete map drawing * * \param map - * Map structure containing map information. + * source Map structure containing map information. * \param x * view position X we want to scroll on * \param y @@ -347,6 +384,23 @@ void MAP_getMetaTilemapRect(Map* map, u16 x, u16 y, u16 w, u16 h, u16* dest); */ void MAP_getTilemapRect(Map* map, u16 x, u16 y, u16 w, u16 h, bool column, u16* dest); +/** + * \brief + * Set the callback function to patch tilemap data.
+ * Note that you need to set + *
+ * The method will be called when a new tilemap row / column is ready to be send to the VDP.
+ * You can use this callback to modify the tilemap data before sending it to VRAM.
+ * It can be useful, for instance, to implement destructibles blocks. + * + * \param map + * source Map structure we want to set the patch data callback for. + * \param CB + * Callback to use to patch the new tilemap data (set to NULL by default = no callback).
+ * See declaration of #MapDataPatchCallback to get information about the callback parameters. + */ +void MAP_setDataPatchCallback(Map* map, MapDataPatchCallback *CB); + /** * \brief * Override the system (VDP) plane size for this map (should be called after MAP_create(..))
diff --git a/lib/libmd.a b/lib/libmd.a index ec51375c..41d62470 100644 Binary files a/lib/libmd.a and b/lib/libmd.a differ diff --git a/src/map.c b/src/map.c index 1d14e9a8..bdd740f2 100644 --- a/src/map.c +++ b/src/map.c @@ -193,9 +193,8 @@ Map* NO_INLINE MAP_create(const MapDefinition* mapDef, VDPPlane plane, u16 baseT } } - // patch callbacks - result->patchMapDataColumnCB = NULL; - result->patchMapDataRowCB = NULL; + // patch callback + result->mapDataPatchCB = NULL; return result; } @@ -501,10 +500,10 @@ static void prepareMapDataColumn(Map *map, u16 *bufCol1, u16 *bufCol2, u16 xm, u map->prepareMapDataColumnCB(map, bufCol1, bufCol2, xm, ym, height); // patch data callback set ? - if (map->patchMapDataColumnCB != NULL) + if (map->mapDataPatchCB != NULL) { - map->patchMapDataColumnCB(map, bufCol1, (xm * 2) + 0, ym * 2, height * 2); - map->patchMapDataColumnCB(map, bufCol2, (xm * 2) + 1, ym * 2, height * 2); + map->mapDataPatchCB(map, bufCol1, (xm * 2) + 0, ym * 2, COLUMN_UPDATE, height * 2); + map->mapDataPatchCB(map, bufCol2, (xm * 2) + 1, ym * 2, COLUMN_UPDATE, height * 2); } #ifdef MAP_PROFIL @@ -522,10 +521,10 @@ static void prepareMapDataRow(Map* map, u16 *bufRow1, u16 *bufRow2, u16 xm, u16 map->prepareMapDataRowCB(map, bufRow1, bufRow2, xm, ym, width); // patch data callback set ? - if (map->patchMapDataRowCB != NULL) + if (map->mapDataPatchCB != NULL) { - map->patchMapDataRowCB(map, bufRow1, xm * 2, (ym * 2) + 0, width * 2); - map->patchMapDataRowCB(map, bufRow2, xm * 2, (ym * 2) + 1, width * 2); + map->mapDataPatchCB(map, bufRow1, xm * 2, (ym * 2) + 0, ROW_UPDATE, width * 2); + map->mapDataPatchCB(map, bufRow2, xm * 2, (ym * 2) + 1, ROW_UPDATE, width * 2); } #ifdef MAP_PROFIL @@ -1904,6 +1903,12 @@ static void getMetaTilemapRect_MTI16_BI16(Map* map, u16 x, u16 y, u16 w, u16 h, } +void MAP_setDataPatchCallback(Map* map, MapDataPatchCallback *CB) +{ + map->mapDataPatchCB = CB; +} + + void MAP_overridePlaneSize(Map* map, u16 w, u16 h) { // only 32, 64 or 128 accepted here