// Scanline control byte (SCB) accessors. // // Each scanline holds one uint8_t SCB value in range 0..15 selecting // which of the 16 palettes that scanline uses at display time. #include #include #include "joey/palette.h" #include "surfaceInternal.h" // ----- Public API (alphabetical) ----- uint8_t scbGet(const SurfaceT *s, uint16_t line) { if (s == NULL || line >= SURFACE_HEIGHT) { return 0; } return s->scb[line]; } void scbSet(SurfaceT *s, uint16_t line, uint8_t paletteIndex) { if (s == NULL || line >= SURFACE_HEIGHT) { return; } if (paletteIndex >= SURFACE_PALETTE_COUNT) { return; } s->scb[line] = paletteIndex; if (s == stageGet()) { gStageScbDirty = true; } } void scbSetRange(SurfaceT *s, uint16_t firstLine, uint16_t lastLine, uint8_t paletteIndex) { uint16_t line; uint16_t last; if (s == NULL) { return; } if (paletteIndex >= SURFACE_PALETTE_COUNT) { return; } if (firstLine >= SURFACE_HEIGHT) { return; } last = lastLine; if (last >= SURFACE_HEIGHT) { last = SURFACE_HEIGHT - 1; } if (last < firstLine) { return; } // memset is far cheaper than the per-iter loop on ORCA-C with -b // (scb is uint8_t, sizeof(uint8_t)==1, so the call form below is // exact). On IIgs ORCA-C lowers small fixed-size memsets to MVP / // PEI tricks; on Amiga/ST/DOS it uses libc memset which is // already vectorized. Either way, much tighter than the C loop. (void)line; memset(&s->scb[firstLine], paletteIndex, (size_t)(last - firstLine + 1)); if (s == stageGet()) { gStageScbDirty = true; } }