Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variable bit-per-pixel drawing #1099

Merged
merged 3 commits into from
May 26, 2020
Merged

Variable bit-per-pixel drawing #1099

merged 3 commits into from
May 26, 2020

Conversation

ddelemeny
Copy link

This PR introduces a way to draw the spritesheet with different bpp, allowing a more optimized use of the spritesheet memory for graphics that only use a few colors.

blit segment spec:

usage : 
poke4(2*0x03FFC, value)

val  | target memory segment to read
-------------------------- 
0000 | (reserved) 1bpp system graphics // not implemented
0001 | (reserved) 1bpp system font
0010 | 4bpp page 0 BG  // default value
0011 | 4bpp page 0 FG
0100 | 2bpp page 0 BG
0101 | 2bpp page 0 FG
0110 | 2bpp page 1 BG
0111 | 2bpp page 1 FG
1000 | 1bpp page 0 BG
1001 | 1bpp page 0 FG
1010 | 1bpp page 1 BG
1011 | 1bpp page 1 FG
1100 | 1bpp page 2 BG
1101 | 1bpp page 2 FG
1110 | 1bpp page 3 BG
1111 | 1bpp page 3 FG

Pixel stretching

Low-bpp stretches pixels on the X axis when reading the spritesheet.
In 2bpp, the spritesheet becomes twice as large, but stays the same height.

Indexing:

Low bpp stretches indexes on the X axis.
In 2bpp the full index of the rightmost sprite of the first line is 31

In order to preserve compatibility with drawing functions that use total spritesheet indexes (index>255) and prevent reading out of the allowed memory segment, the whole spritesheet wraps around on both vertical and horizontal axis and the segment is interpreted as a translation of the origin of the spritesheet.
Internal access to a tile must specify if they use local indexing (index < 255: map,font, textri with use_map) or total indexing (index < 255 * 2*nbPages: spr)(default)

Lifted indexing limitations

Using the blit segment, map and font can draw from other parts of the spritesheet than their default However, they can't draw from more than 1 segment in the same call, as they still use 8bits indexing.

System sheet and font:

blit segment values 0 and 1 are reserved respectively to implement a 1bpp system spritesheet and to access the 1bpp font sheet.

Font drawing:

In order to preserve compatibility with existing font calls drawing from sprites, BG and FG sheets are swapped in font's interpretation of the blit segment.
The endianness of the system font in memory has been adjusted to read like sprites.

Flags:

fset and fget don't take the blit segment into account, because it would be tedious to keep poking the blit segment to retrieve for flags. The user has to adapt their use of flags if necessary.

Sprite Editor:

The UI has been adjusted to allow edition in different bpp modes and navigation in a larger spritesheet.

Test cart :

https://gist.github.com/ddelemeny/956ae9496a6ce124cc1f43a316b14325

Fixes #1074
- the first nibble of 0x03FFC serves as a register to control the target
of the drawing function.
- spr, map and textri can use variable bpp, font will come later
- tic_tilesheet is used as the representation of a bpp-aware tilesheet window in
memory
Copy link
Owner

@nesbox nesbox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A very cool addition that expands creativity for users without breaking compatibility with the older carts.
The code looks very polished and I'm very happy to approve such a nice feature.
Thank you for your contribution 👍
PS. pls, don't hesitate to add your nickname to the license header in the code :)

@nesbox nesbox merged commit cd5218f into nesbox:master May 26, 2020
@nesbox nesbox added API Issues related to TIC80 API editor: sprites Issues related to sprite editor enhancement Improvement of existing feature or adding something new labels May 26, 2020
@nesbox nesbox added this to the 0.80.0 milestone May 26, 2020
@RobLoach
Copy link
Contributor

🤯 💥

@ddelemeny
Copy link
Author

Thanks for your approval, and thanks a lot for your insight, support and reactivity! I hope this feature will be useful to many :)

@nesbox
Copy link
Owner

nesbox commented May 26, 2020

Could you please update the wiki?
Also, I think I'll add this https://gist.github.com/ddelemeny/956ae9496a6ce124cc1f43a316b14325 to the demo carts

@ddelemeny
Copy link
Author

I'll try to write some documentation for the wiki.

For the demo cart, I borrowed fonts from other carts for which I don't really know the license, including those can be a problem. I can try to come up with something else.

@potato25
Copy link

potato25 commented Jun 1, 2020

i understand how sprites and spritesheet works , I don't understand how flags , map , etc work . Is it possible for someone to write function that when called changes bpp and it reflects over map , fset , fget , textri ,etc ? Just a thought 😄 because it's excessive use of poke4() function 😃 and complex gymnastics

@ddelemeny
Copy link
Author

fset and fget are oblivious to variable bpp because it would definitely be excessive use of poke4. It doesn't really make sense to switch bpp context when the whole operation is just keeping track of a division on an index.

textri without use_map uses stretched coordinates on the X axis, meaning that when you want to draw in 2bpp, you switch to segment 4 (2bpp page 0), and you consider a spritesheet that's 256x256px

map, font, textri with use_map use 8bits locally indexed windows to reference tiles. I means that you always consider a square window of 16x16 tiles indexed from 0 to 257, the segment value tells which page in memory you want to use.

You could theoretically implement a whole game using 2bpp graphics with a single call to poke4, using only one page of memory for map, same with font, stretched coords if you're using textri and have the rest of the extended spritesheet accessed with spr's total indexing.

Reference documentation for the feature is there: Advanced Drawing Techniques, I'll try to improve it with your feedback and bake more examples.

@potato25
Copy link

potato25 commented Jun 1, 2020

i love what you're doing 😄
You would have to tweak the map editor for selecting tiles , because it shows default 4 BPP .
I also Assume that , say for 2 bpp you would call poke4() functions with different values before drawing sprites from different pages ?
TIC-80

@nesbox nesbox removed this from the 0.80.0 milestone Jul 15, 2020
@nesbox nesbox moved this from Done to In progress in current version 0.80-beta Jul 17, 2020
@nesbox nesbox moved this from In progress to Done in current version 0.80-beta Jul 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API Issues related to TIC80 API editor: sprites Issues related to sprite editor enhancement Improvement of existing feature or adding something new
Projects
No open projects
Development

Successfully merging this pull request may close these issues.

None yet

4 participants