I think it would be nice to be able to draw sprites using a lower bit depth palette.
The idea would be to pass a bit_depth parameter to sprite drawing functions that would clamp the palette and read bit_depth bits per pixel from the sprite memory (with appropriately scaled coordinates)
The spirit of this proposal is really a low-level memory trick, which is IMHO completely in the style of a fantasy computer.
PALETTE_MAP section of the memory to locally adapt the palette to their needs. spr, possibly map, remap and textripoke1, poke2, poke3 ? or general poke with bitmaskmap (and textri from map) would be harder to adapt to mixed bit_depth data. remap can helpWhat do you think ?
So, I've been trying to prototype this as an exercise...
https://github.com/ddelemeny/TIC-80/commit/303713a39a33d4fc77d32aea1cfabe028034ccf8 implements a (very unpolished) sspr function with a bit_depth parameter.
Key takeaways:
sspr is pretty straightforward, ~although my version of it does not implement arbitrary bitmap scaling~ (edit: now it does, see comments below) (beyond the scope of this issue, but I didn't want to consider what happens to the tile indexing in lower bit_depth modes).Here's the result, each 4bits pixel value from the spritesheet is interpreted as two 2bits values, effectively doubling the size of the sprite :
x=72
y=24
function TIC()
cls(13)
-- sspr(sx, sy, sw, sh, x, y, colorkey, scale, flip, rotate, bit_depth)
sspr(16,0,32,16,x,y,3,3,0,0,2)
print("Ed... WaRlD...",84,84)
end
-- <TILES>
-- 001:eccccccccc888888caaaaaaaca888888cacccccccacc0ccccacc0ccccacc0ccc
-- 002:ccccceee8888cceeaaaa0cee888a0ceeccca0ccc0cca0c0c0cca0c0c0cca0c0c
-- 003:eccccccccc888888caaaaaaaca888888cacccccccacccccccacc0ccccacc0ccc
-- 004:ccccceee8888cceeaaaa0cee888a0ceeccca0cccccca0c0c0cca0c0c0cca0c0c
-- 017:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec
-- 018:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee
-- 019:cacccccccaaaaaaacaaacaaacaaaaccccaaaaaaac8888888cc000cccecccccec
-- 020:ccca00ccaaaa0ccecaaa0ceeaaaa0ceeaaaa0cee8888ccee000cceeecccceeee
-- </TILES>
-- <PALETTE>
-- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57
-- </PALETTE>

Judging by that image, I think the caption should instead read "PLEASE KILL ME!"
I'd prefer replacing the scale parameter with w and h:
sspr(sx, sy, sw, sh, x, y, colorkey, w, h, flip, rotate, bit_depth)
This would allow the sprite to be scaled freely both horizontally and vertically (with float values allowed, which is a sole purpose of sspr() in PICO-8).
@StinkerB06 I think it's more relevant to #952, but I was going for it anyway : https://github.com/ddelemeny/TIC-80/commit/503fcb9f7572da0f76a475427041ebd29b0e27d0

I preferred keeping dx,dy,dw,dh together in the function signature (as pico-8 does) to keep some coherence in surface coordinates definition between source and dest, but I'm open to counter-arguments on this. Order of arguments is closer to textri than to spr.
https://github.com/ddelemeny/TIC-80/commit/7d82ac9a581667f5b30b9e82e4c7361db920db04 implements drawSurface an optimized version of this _almighty_ drawing function (true coordinates, arbitrary bitmap scaling, bit-depth aware... it just lacks a texture-repeat mode at this point) that could serve as a drawing backend for the other drawing functions of the api (spr, map).
But there's a catch.
The current drawing backend, drawTile, is tightly optimized. I've tried to re-implement the same optimizations except the following :
This means drawSurface is quite fast, but not as fast as drawTile yet.
Using https://tic.computer/play?cart=631 as a naive benchmark on my laptop, I managed to obtain 85% of the performance of drawTile at 1:1 scale (drawSurface can draw 85% of the sprites that drawTile can draw at 30fps), and I lose 40 to 50% of drawTile's performance at scale 3:1.
Fast, but not fast enough. I need to find a way to match the fast paths of drawTile.
Any ideas welcome.
Current progress of the bit_depth feature experiment https://github.com/ddelemeny/TIC-80/commit/ada039a101dc8dcc5b9ec2fa02668f6c00a048ca
Here's the editor working in 2bits mode:

And here's a bit_depth enabled spr drawing the same animated sprite :

Now I need to find a good UI to handle that mode in the sprite editor, right now you can switch between mode 2 and 4 bits with the Ctrl-Tab hotkey (to mimic bank switching)
Edit : Bonus test cartridge for the current implementation.
-- title: TIC80 - 2bit sprite test
-- author: ddelemeny
-- desc: Example for the bit_depth feature
-- script: lua
t=0
x=48
y=48
PALETTE_MAP = 2*0x3FF0
function mapColors(colors)
for i=0,#colors-1 do
poke4(PALETTE_MAP+i,tonumber(string.sub(colors,i+1,i+1),16) or i)
end
end
function TIC()
cls(13)
-- regular spr call
spr(1,x,y,1,3,0,0,2,2)
-- spr in 2bpp mode
spr(2+t%60//30*2,x+54,y,1,3,0,0,2,2,2) -- that last '2' is the bit_depth parameter
-- same with remap
mapColors("F1AB")
spr(2+t%60//30*2,x+108,y,1,3,0,0,2,2,2)
mapColors("0123")
t=t+1
end
-- <TILES>
-- 001:dfffff75f00000f5baaaaac5baaaaac5bffffbcfbfcfcbccbfcfcbccbfcfcbcc
-- 002:dfffff75f00000f5baaaaac5baaaaac5bffffbcfbffffbccbfcfcbccbfcfcbcc
-- 017:bffffbccbaaaaa0fbababac7baefaac5baaaaac5baaaaaf5f0cf0c75dffdff55
-- 018:bffffbccbaaaaa0fbababac7baefaac5baaaaac5baaaaaf5f0cf0c75dffdff55
-- </TILES>
-- <PALETTE>
-- 000:1a1c2c5d275db13e53ef7d57ffcd75a7f07038b76425717929366f3b5dc941a6f673eff7f4f4f494b0c2566c86333c57
-- </PALETTE>
Here's the current state of the sprite editor at https://github.com/ddelemeny/TIC-80/commit/65930f31633f9101a3ded28368ed3b7166e538a2

Some remaining concerns to resolve :
bit_depth be enabled on more functions (map, textri, font) ?bit_depth be enabled in the map editor ? Should it ?config use a low-palette spritesheet ? Should it ?SPRITE FLAGS memory segment is limited. What to do of flags for extra sprite indices in low-palette modes ?MOUSE CURSOR could benefit from low palette, but the interpretation of value in is quite tied to the 4bits mode, is there something doable with this ?drawSurface backend be optimized further ? How do less naive benchmarks compare ?texture-repeat drawing mode I joked about in a previous comment about the _almighty_ drawSurface actually sounds useful and doable. bit_depth everywhere I used it for a more accurate bpp, or less descriptive bit_mode ? Nice work on the UI!!!!
More UI experiments at https://github.com/ddelemeny/TIC-80/commit/7f1cdb5d48a97dcc812a0de89c666f24f8aa15a5 , some prompted by @nesbox's suggestions

Edit update at https://github.com/ddelemeny/TIC-80/commit/6ac8c944e34c8c9377417d30fd7fe22c0317979f :

Progress update:
fset/fget font (see demo below)
Most helpful comment
Judging by that image, I think the caption should instead read "PLEASE KILL ME!"