Jump to content
IGNORED

A Programming CHALLENGE


Andrew Davie

Recommended Posts

That I was planning to do, but the others tests result in a better image.

Obviously it can be made using 1 scanline resolution, but would be painful to convert by hand.

This is the left upper corner of the image only, and this is a macaw, not a parrot :

I like the way you think. ;)

 

What I like about this method is that it's very simple and each line could have 3 unique colors. More colors could also possible depending on the line. You have 21 cycles between VBLANK writes, or 19 cycles if one the colors does not have bit 1 set for enabling VBLANK again. I did a test today to see where color writes to the background would take place:

 

  lda  #$44
  ldx  #$86
  ldy  #$2A
  sta  VBLANK
  sta  COLUBK
  stx  COLUBK
  sty  COLUBK
  sta  COLUBK
  stx  COLUBK
  sty  COLUBK
  sta  COLUBK
  sty  VBLANK
post-7074-0-19047300-1382211062_thumb.png
I think it would be good to line up M1 to block one. That way you could have 4 unique colored blocks right at the beginning of the line before a repeats would occur on block 5 (the background color updates 1 pixel too late to change block 5 in time). You still have the option of expanding M1 to 8 pixels to cover both block 1 and 2. You could also use playfiled priority and have M1 appear as block 2 only. Finally you still have the option to move right 2 blocks with a regular HMOVE and HMM1 set to right 8. A cycle 74 hmove could move the M1 back 8 pixels or more. Since VBLANK is enabled before and after the picture you don't see the HMOVE comb as the border is all the same "blacker then black" color.
I would like to see how 3 unique colors looks per line first though. It is by far the easiest to implement.
Link to comment
Share on other sites

I wrote a kernel that can support 3 unique colors per line, and has 18 blocks across each row which are 4 pixels each. It's a 4 line looped kernel so adding new values are no problem, as long as the picture height is divisible by 4, and it is 18 pixels across:

 

post-7074-0-09312900-1382250284_thumb.png

 

ParrotKernel.zip

 

Basically I hacked Tjoppen's utility to just output 3 colors. I didn't include the hacked utility in the zip since I did a lot of editing with excel afterwards. C is not my strong suite, but I'm going to see if I can just get the utility to spit out all the values I need tomorrow if time permits. I still think the image can be a lot better. When the pic is small it looks great, larger no...

  • Like 12
Link to comment
Share on other sites

I just had a brief look at Tjoppen's code. The conversion has two major flaws:

  1. It only converts line by line. So it doesn't use the chance to dither colors vertically or to correct color errors of previous pixels.
  2. The color distance is calculated using RGB. This does not match the human eye's color perception. For better results, the Lab color space should be used.

The latter should be an easy fix.The linked Wikipedia article mentions advanced methods which should fix flaws in CIE76. But it misses DIN99 (German only) which is much easier to implement.

For the fix 1. there are a lot of options. E.g. one could define a sliding window of a few scanlines which then form the base for a new pixel which combines multiple colors vertically.

Edited by Thomas Jentzsch
Link to comment
Share on other sites

If anyone else wants to different images with the kernel I built then here is how I packed the data for the tables:

.

.

;                                 4  5  6  7                ---> PF0 bits
;                                 |  |  |  |
;   0                             |  |  |  |  7  6  5  4  3 ---> PF1 bits
;   |                             |  |  |  |  |  |  |  |  |
;   |  0  1  2  3  4  5  6  7     |  |  |  |  |  |  |  |  | ---> PF2 bits
;   |  |  |  |  |  |  |  |  |     |  |  |  |  |  |  |  |  |
;
;   1  2  3  4  5  6  7  8  9    10 11 12 13 14 15 16 17 18 -----> BLOCK number
;
;   |  |  |  |  |  |  |  |  |     |  |  |  |  |  |  |  |  |
;   7  6  5  4  3  2  1  0  |     |  |  |  |  |  |  |  |  | ---> GRP0 bits
;                           |     |  |  |  |  |  |  |  |  |
;                           1     |  |  |  |  |  |  |  |  | ---> ENAM0 bit
;                                 |  |  |  |  |  |  |  |  |
;                                 7  6  5  4  3  2  1  0  | ---> GRP1 bits
;                                                         |
;                                                         1 ---> ENAM1 bit
;
;--------------------------------------
; mapping for playfield tables
;--------------------------------------
;
;       PF0 & ENAM1
;   7  6  5  4  3  2  1  0
;   |  |  |  |  x  x  |  x
;   |  |  |  |        |
;  13 12 11 10        |    ---> BLOCK number
;                    18    ---> BLOCK number (for player blocks, used by ENAM1)
;
;       PF1 & ENAM0
;   7  6  5  4  3  2  1  0
;   |  |  |  |  |  x  |  |
;   |  |  |  |  |     |  |
;  14 15 16 17 18     |  1 ---> BLOCK number
;                     9    ---> BLOCK number (for player blocks, used by ENAM0)
;
;       PF2
;   7  6  5  4  3  2  1  0
;   |  |  |  |  |  |  |  |
;   |  |  |  |  |  |  |  |
;   9  8  7  6  5  4  3  2  ---> BLOCK number
;
;--------------------------------------
; mapping for player tables
;--------------------------------------
;
;       GRP0
;   7  6  5  4  3  2  1  0
;   |  |  |  |  |  |  |  |
;   |  |  |  |  |  |  |  |
;   1  2  3  4  5  6  7  8  ---> BLOCK number
;
;       GRP1
;   7  6  5  4  3  2  1  0
;   |  |  |  |  |  |  |  |
;   |  |  |  |  |  |  |  |
;  10 11 12 13 14 15 16 17  ---> BLOCK number

.

.

.

Basically every line has three unique colors. This requires three color tables, one for the players & missiles, one for the playfield, and one for the background. The blocks are then displayed by writing to the PFx, GRPx, and ENAMx registers. By definition the background blocks are whatever the playfield, players, and missiles are not covering up, thus the background "blocks" needs no table.

 

Each table has an entry for one scanline. In my rom I made each table 200 bytes long for 200 scanlines. The height of the image must be divisible by 4, and if yours is not then you can pad the tables with a few blank scanlines (values of 0) to get it to run. The tables are flipped upside down too, but any programmer for the 2600 is used to that.

Link to comment
Share on other sites

Top effort OmegaMatrix :) Didn't know you could toggle VBLANK like that

Now unroll the loop, throw some SAX:es in there for extra colors and maybe use the extra cycles for the ball (forming a 19th pixel).

I agree that ultimately, the whole thing would be best optimized by having every line unrolled. I like the idea of loading immediate values. The picture in post #51 shows the earliest places where new writes would take effect with pre-loaded A, X, and Y. You could delaying a cycle here and there to change different blocks. There is still the option to use JSR to get 2 more colors for free in addition to pre-loaded A, X, Y, and SAX. Just have the stack pointer aligned to the color registers. BRK is also an option, especially if you have multiple banks to get multiple break addresses. BRK is a little more limited though. In the roms from post #5 I am using JSR, and using BRK is shown here.

 

 

For right now I'm going to see how far I can take 3 colors, because this kernel is easy to implement for a general purpose program, and might be re-used elsewhere.

Link to comment
Share on other sites

Top effort OmegaMatrix :) Didn't know you could toggle VBLANK like that

 

My original 2-color 48 pixel kernel (developed in 2010 for Stay Frosty 2) used to use VBLANK like that. There was a problem with toggling VBLANK though, it's often noticeable on a real display.

post-3056-0-44824200-1382299575_thumb.jpg

 

It can be made to look OK by adjusting the brightness, but there's no guarantee the end-user would do so.

post-3056-0-68356900-1382299671_thumb.jpg

 

  • Like 1
Link to comment
Share on other sites

Personally, so far I like Nathan's chrono color Parrot best. So, regardless whether or not this fits with the Wikipedia article I wanted to give this a shot as well.

 

An obvious way to try to improve on that would be not to use the same eight source colors for the whole image (left), but instead to vary them per line. So instead of using (1,0,0), (0,1,0), (0,0,1) as primary colors I used (red_max,0,0), (green_max,0,0), (blue_max,0,0), where the maximum values are determined for each line (middle). This results in some stripping where the color distribution changes. One thing that can be done about that is to low-pass filter the line palettes so that they only change gradually (right).

 

post-27536-0-30301000-1382299329.pngpost-27536-0-10186600-1382299339.pngpost-27536-0-15304300-1382299345.png

 

With additional dithering we get:

 

post-27536-0-47891800-1382299311.pngpost-27536-0-13260700-1382299317.pngpost-27536-0-95751400-1382299322.png

 

The stripping (middle) is not so apparent anymore. When you compare the 8-color image on the left with the line-colored imaged on the right you can see that the right one is a little less noisy and the red part in the center has less yellow sparkles.

 

When the colors are separated into red/green/blue lines we get:

 

post-27536-0-33227000-1382299352.png

 

And if this is converted to Stella NTSC colors and run in the emulator we get:

 

post-27536-0-54457900-1382299376_thumb.png

 

When using a CIELAB color space instead of RGB for Stella color conversion it looks like this:

 

post-27536-0-90382000-1382299367_thumb.png

 

This shows a greater variation in line colors, but it is also more reddish. I'm not sure if it looks better or not. When you run the binary, you can switch between the RGB and LAB versions with the left button.

ParrotDemo.bin

ParrotDemo.zip

Link to comment
Share on other sites

 

My original 2-color 48 pixel kernel (developed in 2010 for Stay Frosty 2) used to use VBLANK like that. There was a problem with toggling VBLANK though, it's often noticeable on a real display.

attachicon.gifpost-3056-129142479655.jpg

 

It can be made to look OK by adjusting the brightness, but there's no guarantee the end-user would do so.

attachicon.gifpost-3056-129142478662.jpg

 

That's right. Then we developed the technique of using the missiles to mask the color changes instead, with the advantage of being able to have any color background.

 

 

Here's the second version I did:

 

48_bits_2_colors(v2).zip

 

post-7074-0-85857700-1382301291_thumb.png

 

I still think the original idea of using VBLANK was quite clever though. :) In the parrot rom I posted VBLANK surrounds the entire image as a border so you don't see any horizontal lines.

Link to comment
Share on other sites

Thanks, I was looking for that, but couldn't find it!

The missiles were used in the original version, they hid the colored background for the time needed to update VLBANK. batari made the suggestion:

Maybe this would work: set the playfield red and change the background color. Right after the critical section, hit VBLANK and hit it again beforehand. PF0=PF2=0. PF1=$FF. For the multicolored section, PF is copied, for the single-color, PF is reflected. I'm not sure if the timing will work or if I'm also missing something here as well. If the timing is a bit off, perhaps the missiles could be strategically placed at the left and right side of the graphic to hide late or early VBLANK hits.

Link to comment
Share on other sites

I wrote a kernel that can support 3 unique colors per line, and has 18 blocks across each row which are 4 pixels each. It's a 4 line looped kernel so adding new values are no problem, as long as the picture height is divisible by 4, and it is 18 pixels across:

 

attachicon.gifParrotKernel(InStella).png

 

attachicon.gifParrotKernel.zip

 

Basically I hacked Tjoppen's utility to just output 3 colors. I didn't include the hacked utility in the zip since I did a lot of editing with excel afterwards. C is not my strong suite, but I'm going to see if I can just get the utility to spit out all the values I need tomorrow if time permits. I still think the image can be a lot better. When the pic is small it looks great, larger no...

Working a bit further on this one. Still doing all calculations based on RGB (so there is room for improvement), but now combining two lines.

 

The correct colors are now calculated for the merged color of current and the last line. The error is based on the three colors of the last line and the currently tested three colors.

 

I hope you like it.

 

Besides doing the calculations using CIELAB I have a different idea for combining the lines (and of course we could combine more than 2 lines). Not sure if this idea will look better.

post-45-0-70497700-1382480348_thumb.png

Edited by Thomas Jentzsch
Link to comment
Share on other sites

Working a bit further on this one. Still doing all calculations based on RGB (so there is room for improvement), but now combining two lines.

 

The correct colors are now calculated for the merged color of current and the last line. The error is based on the three colors of the last line and the currently tested three colors.

 

I hope you like it.

 

Besides doing the calculations using CIELAB I have a different idea for combining the lines (and of course we could combine more than 2 lines). Not sure if this idea will look better.

 

The regular on/off pattern evident in successive scanlines here suggests to me there's a bug in the conversion/calculations.

For example, the rightmost vertical part of the tail, whitish... black/white/black/white/black.... doesn't intuitively feel right.

Or, the parrot body -- red/orange/red/orange. Also, many of the foliage green bits are green/black/green/black. Are you sure your calculations are correct?

Perhaps the algorithm is 'over correcting' and causing oscillation between extremes. Good work, though... getting there!

Link to comment
Share on other sites

Working a bit further on this one. Still doing all calculations based on RGB (so there is room for improvement), but now combining two lines.

 

The correct colors are now calculated for the merged color of current and the last line. The error is based on the three colors of the last line and the currently tested three colors.

 

I hope you like it.

 

Besides doing the calculations using CIELAB I have a different idea for combining the lines (and of course we could combine more than 2 lines). Not sure if this idea will look better.

I've taken a bit of a branch from building the parrot to just working on the utility. I don't get much time in the weekdays, so I just added so stuff to have the bytes print 16 across or on each line. I made this a flag you pass in the command line. I also added a flag for PAL/NTSC. Now I'm working on making the assembly file handle different heights. I've haven't done anything to improve the quantification function yet.

 

 

This weekend I might explore adding more colors per line. This would be an unwound loop of course. ;)

Link to comment
Share on other sites

bird2.png

 

1. original 24 bit image

2. Thomas's conversion

3. original using NTSC palette (from Wikipedia)

4. Omegamatrix's original conversion

 

So, Thomas's image looks washed out to me.

The rightmost image suggests the colours could be better.

I used the PAL palette for my picture posted above, here is the same with NTSC palette.

post-45-0-78809900-1382507387_thumb.png

Link to comment
Share on other sites

 

The regular on/off pattern evident in successive scanlines here suggests to me there's a bug in the conversion/calculations.

For example, the rightmost vertical part of the tail, whitish... black/white/black/white/black.... doesn't intuitively feel right.

Or, the parrot body -- red/orange/red/orange. Also, many of the foliage green bits are green/black/green/black. Are you sure your calculations are correct?

Perhaps the algorithm is 'over correcting' and causing oscillation between extremes. Good work, though... getting there!

I am not sure what is causing this pattern. The calculations are right, but not very sophisticated yet. Since the three colors have to by chosen line by line this might be a normal effect.

 

I will try to improve this tonight. For example I could remember the color error of each pixel of a line and include this error into the next lines pixel color calculation. Or I could combine the two lines with different weights (e.g. 2:1 instead of 1:1). And of course I have to switch to CIELAB.

Link to comment
Share on other sites

I am not sure what is causing this pattern. The calculations are right, but not very sophisticated yet. Since the three colors have to by chosen line by line this might be a normal effect.

 

The *extremely regular* oscillation between green/black on the lower right of the last image you posted... suggests a bug IMHO.

 

You could test this easily enough by creating an image with vertical stripes of colour. See what comes out.

Link to comment
Share on other sites

 

The *extremely regular* oscillation between green/black on the lower right of the last image you posted... suggests a bug IMHO.

I suppose the darkest green is not dark enough, so black is mixed into it. But of course there could be a coding error, though I think the algorithm needs further tweaking.

Edited by Thomas Jentzsch
Link to comment
Share on other sites

Thomas are you going to share your mods to the code/utiliiy? I'd like to play with it but am too lazy to learn how to get it up and running :P

I will post it tonight, after some comments and cleanup. Currently it is an experimental mess with only a few structural improvements over the original. But at least it is C and not Pascal anymore. :)

Link to comment
Share on other sites

It would be really interesting to see a 2-frame version of this, with each frame using the same image but different colours.

That is, interlaced, but in terms of colour. The first frame as above, but perhaps the second frame trying to correct for the errors in the first frame.

Just an idea :) Wonder how it would look.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...