abse/gameboy-advance

A tscircuit package created by abse.

Version
0.0.45
License
unset
Stars
0

firmware/game-console/dirty_regions.c

#include "dirty_regions.h"
#include <string.h>
/* Compare 16x8 source tiles, combine horizontal runs, then extend equal
 * runs from the previous tile row. Coordinates are half-open. */
unsigned find_dirty_regions(const uint8_t *before, const uint8_t *after, bool force,
                            struct dirty_region *regions) {
    if (force) {
        regions[0] = (struct dirty_region){0, 0, 320, 200};
        return 1;
    }
    unsigned count = 0;
    for (unsigned y = 0; y < 200; y += 8) {
        bool dirty[20] = {0};
        for (unsigned tile = 0; tile < 20; tile++) {
            for (unsigned row = 0; row < 8; row++) {
                unsigned offset = (y + row) * 320 + tile * 16;
                if (memcmp(before + offset, after + offset, 16)) {
                    dirty[tile] = true;
                    break;
                }
            }
        }
        for (unsigned tile = 0; tile < 20;) {
            if (!dirty[tile]) {
                tile++;
                continue;
            }
            unsigned start = tile;
            while (tile < 20 && dirty[tile])
                tile++;
            unsigned merge = count;
            for (unsigned i = 0; i < count; i++)
                if (regions[i].x0 == start * 16 && regions[i].x1 == tile * 16 &&
                    regions[i].y1 == y) {
                    merge = i;
                    break;
                }
            if (merge < count)
                regions[merge].y1 = y + 8;
            else if (count < MAX_DIRTY_REGIONS)
                regions[count++] = (struct dirty_region){start * 16, y, tile * 16, y + 8};
            else {
                regions[0] = (struct dirty_region){0, 0, 320, 200};
                return 1;
            }
        }
    }
    return count;
}