Hello.
With the understanding that Pico-8 graphics will always use memory location 0x6000-0x7FFF (hexadecimal memory location), then what new resolutions could be added by ZEP without using any additional memory ?
Well, quite a few actually.
(128 x 128 / 2) = 8192
Let's look at the primary resolution which is 128x128 pixels with a maximum of 16-color choices. Now be aware a new palette was found for it so you can change any of these 16-colors to really 32-colors, but you cannot change the TINT, either R G or B of any of them. They are a fixed color set from the 32 shown above. And despite this palette you can only view 16 of them at a time - conventionally.
With "hardware" tweaks you can have more on the screen at a time.
But this article is not going to cover that. Instead it is going to cover what CAN be done with those 0x2000 or 8192-bytes of memory for graphics and where any pixel can be any other colored pixel. This primary resolution uses 2-horizontal pixels to make up one byte.
So the next resolution available would be 64x128 wide-pixels to give you a true 256-colors per pixel.
(64 x 128 x 1) = 8192
Here you can see a much larger palette with long pixels double-size across yet it is also uses a fixed palette, in this case 216-colors derived from 6-shades of red, 6-shades of green, and 6-shades of blue. While it might be possible to use any portion of extended memory to hold a custom palette, that is not covered in this article. Where a single pixel representing a single byte. Still only using 8192-bytes of memory.
(64 x 64 x 2) = 8192
The next resolution from here is 64x64 both wide and tall pixels to give you a true 65536-colors per pixel or 32-shades of red, 64-shades of green, and 32-shades of blue with a single pixel representing in this case =2= bytes of memory. Still only using 8192-bytes of memory.
So we now have more colors. Let's reverse this and get more pixels once again still only using 8192-bytes of memory.
The next resolution is 128 pixels across by 256-pixels down.
(128 x 256 / 4) = 8192
Using the 32-color palette above you are now limited to only showing 4-colors on the screen at a time although in truth you should be able to pick out which of the 32-palette for each of the 4-color slots. Where 4-long pixels represent a single byte. Still only using 8192-bytes of memory.
For wide-screen monitors or cellphones you can have this 256 pixels across by 128-pixels down with no distortion of the actual pixel shape:
(256 x 128 / 4) = 8192
Although you can see quite clearly this breaks the perfect square Cosy™ resolution and may not be feasible to do considering the interface and current display. Yet if it were limited to only appearing for the output of the cart, I think this could be done. Like the resolution above it also only allows 4-colors on the screen at one time. Where 4-pixels represents a single byte. Still only using 8192-bytes of memory.
The last would be one I would really like to see. True 1-bit graphics, black and white.
(256 x 256 / 8) = 8192
This gives you a whopping 256x256 pixels maintaining the square shape and square pixels with the ability to choose from the 32-palette any of the 2-colors available displayed here, default of BLACK (color #0) and WHITE (color #7). Where 8-pixels represent a single byte. Still only using 8192-bytes of memory.
And that's it ! Likely you can see additional ways of cutting up that 8192-bytes of memory for graphics and I think I've only touched the surface of this. Here is hoping @zep will in the future allow for some of these added resolution modes which of course could vary from one cart to the next.
For more information on colors, resolutions, and the hardware they run on, see this WIKIPEDIA comprehensive chart.
https://en.wikipedia.org/wiki/List_of_color_palettes
Hope This Helps !
I don't think older consoles were able to change their resolutions - NES was always stuck at that (searches google) 256 x 240. (You can change PICO-8 screen modes to decrease the resolution, but that's... decreasing the resolution.)
Though it's possible that older consoles had completely arbitrary screen sizes..., which could have been increased if the console could handle it. (not lookin it up lol. but i trust that guess)
There's been exported projects that use up more screens of PICO-8. I couldn't find how it worked, any threads that mentioned it. I swear it existed though! somebody made a 128x64 Jelpi for the web...
I did find this one guy, dw817, on two threads mentioning that Zep liked his cozy space, 128x128, and prolly won't change it. (haven't watched the video but I'll take dw's word for it)
... Oh, wait. /joking around
(Is it because here we're keeping it 1:1? or is it because the memory space is staying the same?)
It is interesting about sacrificing colors for more screen space, or the other way around (though I think that will only get us the secret colors rather than 16-bit color*). Kinda gives Playdate / Gameboy (but the screen's already small enough) vibes.
I think instead of sacrificing color, we could use the new memory space. It already has a bit of graphics remapping stuff going on (big maps!), maybe if it was a secret kinda feature it would be neat.
(tl;dr final thought) But at the end of all this ramble, I think the most PICO-8-y option would be to sacrifice color for screen size. Besides, we already have a lot of color hacks to get us beyond the 16 we were always supposed to have. (And (obviously) we shouldn't expect any more hacks anyway. I feel the extra colors were in PICO-8 from the start?)
(it feels oddly okay to make the screen larger but have less colors. it does feel very reasonable. like... we get less detail, but we can have more detail? something like that. I share your opinion that 256x256 1-bit would be very cool.)
(disappointing thing about exports is that it won't work for 128x128 screens. we'd have to have even crazier tech to figure out if the screen will even work for what we're doing. would we just get stuck in the top left corner?)
*Palette hardware is 16 bytes for the "we're gonna draw 12 as 8" part (draw palette) and 16 bytes for the "we're gonna draw anything 8 on screen as secret shade red" part (screen palette). The hardware is capable, though we only get 127 for the draw palette due to needing transparency. That results in 127 for the screen palette, or maybe 128 if there's a specific transparent color.
Anyway, uh, sorry. Apparently I had a lot of thoughts about this come straight to my head.
Hi @aKidCalledAris:
Thanks for your interest !
And yes, years ago I thought we would only have 128x128 with 16-colors, until I experimented some more and wrote THESE:
https://www.lexaloffle.com/bbs/?tid=45648
https://www.lexaloffle.com/bbs/?tid=42990
https://www.lexaloffle.com/bbs/?tid=47070
So it shows me in theory it should be possible.
As for using the extended memory. I had thought of this but wanted to flesh out 8192-bytes first.
Using memory location 0x8000-0xFFFF however you could easily have true 16-bit (2-byte) color yielding 32-brightness levels for red, 64-brightness levels for green, and 32-brightness levels for blue in a 128x128 pixel field.
(128 x 128 x 2) = 32768 bytes
(32 x 64 x 32) = 65536 colors
Or if you're a mind it could be 40-brightness levels for red, 40-brightness levels for green, and 40-brightness levels for blue.
(40 x 40 x 40) = 64000 colors
Using memory location 0xA000-0xFFFF you can have true 24-bit (3-byte) colors yielding 256-brightness levels for red, 256-brightness levels for green, and 256-brightness levels for blue in a 64x128 pixel field.
(64 x 128 x 3) = 24576
I do not believe there is enough memory for true 24-bit colors and 128x128 screen.
Although one simple solution I made MANY years before this @zep is a single tweak that changes the way pixels are interpreted. It gives you essentially 256-colors for a 128x128 screen still at 8192-bytes, or if you use advanced blending you can have any colors at all.
The method ? This single POKE()
would let you blend colors. So if you plotted WHITE and BLACK in the same square it would visually blend them giving you a perfect GRAY. Plotting another color on top of that would do one of two things.
- Simply blend it with the existing color. The disadvantage is there is no way to clear that pixel until you type CLS() or use method 4, 7, or 8 (seen below).
- Remove the oldest color, make the last color you plotted now the oldest and the new color you are plotted is blended with the single color. In this if you plot BLACK and BLACK you will always remove that pixel color entirely.
PGET() of course would always only retrieve the last color plotted. There would be no way memory could keep track of the blends unless it was coded in a custom array by the cart developer.
function _init() blend=0x12345 -- memory location of blend type=0 poke(blend,type) end --[[ Where TYPE is: 0 = end mode: remove blend plotting, screen will change to normal 16-color 1 = end mode: remove blend plotting, screen will maintain visual blends however 2 = set mode: blend two colors at a time, black and black will reset to black pixel 3 = set mode: add two colors at a time (brighter) (OR), max r255, g255, b255 4 = set mode: subtract two colors at a time (darker) (AND), min r0, g0, b0 5 = set mode: blend colors, no limit 6 = set mode: add colors, no limit, (brighter) (OR), max r255, g255, b255 7 = set mode: subtract colors, no limit, (darker) (AND), min r0, g0, b0 8 = set mode: true red, green, blue, must plot 3x for one pixel, value 0-255 ]]-- |
This POKE() with TYPE 2 would make this cart:
https://www.lexaloffle.com/bbs/?tid=45648
Perfect and have no flicker whatsoever as the colors would truly be blended.
Here is example code for black at the top sweeping to medium blue below:
function _init() cls() blend=0x12345 poke(blend,8) for i=0,127 do line(0,i,127,i,0) line(0,i,127,i,0) line(0,i,127,i,i) end end function _update() end |
There might even could be future commands:
PSETRGB(X, Y, [COL-RED, COL-GREEN, COL-BLUE]) LINERGB(X0, Y0, [X1, Y1, [COL-RED, COL-GREEN, COL-BLUE]]) RECTRGB(X0, Y0, X1, Y1, [COL-RED, COL-GREEN, COL-BLUE]) RECTFILLRGB(X0, Y0, X1, Y1, [COL-RED, COL-GREEN, COL-BLUE]) |
Alternatively, use all 32k bytes to pull off 256x256 with 16color.
I'd be fine with 16-bit color. That's what the Gameboy Advance has (although each color gets 5 bits, rather than Green getting a bonus bit).
(I kinda wanted to make something on the GBA or at least has similar restrictions as the GBA a bit back. I get funny little trivia when I do stuff like that)
[how do you do the line thing]
To pull off blending, you would actually need more than 8192 bytes, since the screen data is stored in 4 bits per pixel, and the screen palette is only 16 different numbers that are associated with specific hardware colors.
So for two colors blended together, we'd have 16384. But for the amount of colors you could get for that, it's an insanely profitable sacrifice. From 16 colors to 240 (16^2 - 16
as it's stupid to mix a color with itself).
This little part is a hard maybe because it might not work with screen data? weird hardware thing.
In the end, I think this is just the sort of thing that's "hey we all love more color and more screen space." in which case maybe we should just move to something else, and impose the restrictions on ourselves.
Hi @aKidCalledAris:
No I was thinking of not storing the graphics in memory at all.
This was an idea I had over 30 years ago where you could have superior graphics on simple computers and use zero memory besides.
Curious, my Dad asked me how this could be done.
I told him it would be a computer that had a resolution of up to 4096x3072 pixels with true 24-bit color. That you could really specify any resolution in it you wanted but 4096x3072 was really tops.
I then explained to do this you can plot pixels on the screen, or lines, or shapes, but you could not read the pixels back.
So ... no actual memory in the computer would be used even for a resolution of 4096x3072 which at the time would've been over 37 megabytes.
This of course meant you could not SAVE a picture of that size. But in this Fantasy computer I described you could have any resolution you wanted so 256x192 2-color B&W was also a possible resolution to set which would only take 6144-bytes.
At the time I thought it was a genius idea. Dad said he wasn't sure how it could be done, how it could be implemented even if you didn't use accessible computer memory.
So ... I think since Pico-8 is a Fantasy Console, it could be done. To have really any resolution you want and use zero bytes of memory for it. Especially for the blending or the 24-bit R G B access.
How do I do the line thing ? Do you mean the page with the fading blue ? I wrote that in Blitz, a different programming language entirely. Definitely not as user-friendly as pico-8 is.
As for my 256-color pictures in Pico-8, they are not perfect. While the Christmas ornament looks pretty good, the snow scene beneath that does flicker a bit.
And yep, in the end these are just some ideas to be tossing around. :)
Both the "blending" idea and the "no memory" idea seem to overlook how raster displays work. They suggest that there's a "screen" that's somehow storing the final image separately from the memory addresses being written to by the program. Sure, a computer (fantasy or otherwise) could make this screen memory inaccessible from the program, but it's still being stored as bits in digital memory. It has to be: something has to remind the raster display once every fraction of a second (at the refresh rate of the display) what color each pixel is. If you want 24-bit color on a 4096x3072 raster display, you must have 36 megabytes of digital memory somewhere in your computer storing the color values (and graphics hardware refreshing the display from that memory and a video connection standard that supports that data rate).
Could you generate the data for each scan line as they're being drawn without storing the full graphical image in memory? Yes! The Atari 2600 did this—and it didn't do it for you, either. You had to write your own program to change the color of the beam as it traveled across the screen. To draw a line, you'd have to calculate whether the beam is "on" the line at any given moment then tell it to turn on. See Racing the Beam by Nick Montfort and Ian Bogost.
Could the display surface itself be a sort of write-only memory for each pixel, at least for a short time? Yes! In a very real sense that's what CRT displays do: the beam excites the phosphor coating to glow a particular way. This lasts for a brief period of time beyond when the beam has moved on to other locations, providing persistence of the image until the next refresh. It's extremely brief, and for a raster display it could not remember patterns in any particular shape. Even after you draw a line, the line will be gone 1/60th of a second later, so something needs to know to draw it again at each pixel location. (Perhaps a particular kind of phosphor persistence could do the "blending" thing you're describing: firing the beam so many times per second produces a particular shade of blue.)
Could the display hardware be modified to draw shapes instead of pixels? Yes! There are vector displays where the beam follows a program-controlled path instead of a raster pattern. Such displays still use a phosphor coating for image persistence, though some such displays use phosphor that can glow for minutes at a time (!). To draw a line, you instruct the beam to move to the beginning of the line, turn on, move to the end of the line, then turn off. Older oscilloscopes, some vintage arcade games (Battlezone, Star Wars), and the beloved Vectrex home console used vector displays.
Could a fantasy console or game engine be architected to hide display memory from the game program? Of course! Many game engines abstract away the pixel display entirely. To draw a line, you might create a line object and add it to the draw list, and the engine takes care of rendering the line to hidden screen memory, perhaps a buffer in a graphics card.
The question for a fantasy console designer would be, what abstraction is most fun and useful for the developer? PICO-8 didn't need to expose its screen buffer as addressable memory, and many games don't even access it. If you're willing to pretend that screen memory "doesn't count," then just ignore it, and you're using no memory at all.
[Please log in to post a comment]