Jump to content

Photo

Modify Colour Palette


19 replies to this topic

#1 mamejay OFFLINE  

mamejay

    Chopper Commander

  • 159 posts
  • Location:Melbourne, Australia

Posted Thu Jul 1, 2010 6:44 PM

Hi Guys,

Just a question.
Would it be possible to correct the colour palette of a NTSC game to run correctly on a PAL console?
I have got a harmony cart and NTSC games run awesome. I live in Australia so my console screws up all the colours.
Was playing Kaboom! last night and the NTSC version is so much more fun than the PAL version.

Any ideas? Or would this be just too hard?

#2 Wickeycolumbus OFFLINE  

Wickeycolumbus

    Red Sea Crosser

  • 5,139 posts
  • Location:Michigan

Posted Thu Jul 1, 2010 7:28 PM

You would have to hack the game, there is no simple solution.

#3 SeaGtGruff OFFLINE  

SeaGtGruff

    Quadrunner

  • 5,558 posts
  • Location:Georgia, USA

Posted Thu Jul 1, 2010 8:09 PM

Hi Guys,

Just a question.
Would it be possible to correct the colour palette of a NTSC game to run correctly on a PAL console?
I have got a harmony cart and NTSC games run awesome. I live in Australia so my console screws up all the colours.
Was playing Kaboom! last night and the NTSC version is so much more fun than the PAL version.

Any ideas? Or would this be just too hard?

Are you saying that you have both NTSC and PAL versions of Kaboom!, and you think the NTSC version is more fun? Why is that?

As Vong said, you would need to hack the game. That shouldn't be too difficult. It's easy to map the NTSC color values to their closest equivalent PAL color values, although the color values from the actual PAL version might be slightly different, depending on which color values the programmers chose for the PAL version. The luminance values should be about the same in both palettes, so all you have to do is convert the hue values, which should be more or less as follows:

NTSC $0x = PAL $0x or $1x or $Ex or $Fx
NTSC $1x = PAL $?x (no equivalent)
NTSC $2x = PAL $2x
NTSC $3x = PAL $4x
NTSC $4x = PAL $6x
NTSC $5x = PAL $8x
NTSC $6x = PAL $Ax
NTSC $7x = PAL $Cx
NTSC $8x = PAL $Dx
NTSC $9x = PAL $Bx
NTSC $Ax = PAL $9x
NTSC $Bx = PAL $7x
NTSC $Cx = PAL $5x
NTSC $Dx = PAL $3x
NTSC $Ex = PAL $?x (no equivalent)
NTSC $Fx = PAL $?x (no equivalent)

The problem areas are NTSC hues $1x, $Ex, and $Fx, because in the PAL palette those hue values produce shades of gray, the same as hue $0x. I think about the best you can do is triple-up on PAL hue $2x, and double-up on PAL hue $3x, as follows:

NTSC $0x = PAL $0x
NTSC $1x = PAL $2x <--
NTSC $2x = PAL $2x
NTSC $3x = PAL $4x
NTSC $4x = PAL $6x
NTSC $5x = PAL $8x
NTSC $6x = PAL $Ax
NTSC $7x = PAL $Cx
NTSC $8x = PAL $Dx
NTSC $9x = PAL $Bx
NTSC $Ax = PAL $9x
NTSC $Bx = PAL $7x
NTSC $Cx = PAL $5x
NTSC $Dx = PAL $3x
NTSC $Ex = PAL $3x <--
NTSC $Fx = PAL $2x <--

The hardest part about hacking the colors in the NTSC version would be finding all the places in the code where you need to change the color values.

Michael

#4 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,666 posts
  • Location:The land of Gorch

Posted Thu Jul 1, 2010 8:42 PM

Are you saying that you have both NTSC and PAL versions of Kaboom!, and you think the NTSC version is more fun? Why is that?


Aside from the color value differences and delay values given to the timer, the NTSC and PAL versions are identical. The program and data in Kaboom! does not shift around at all between versions...so an alternate method would be to take the PAL version and change the TWO bytes that hold the timer values using any bit hacking program.

Addr: NTSC - PAL
F2E7: 21 - 3D
F394: 30 - 4F


This effectively creates a PAL60 version from the 50hz PAL version. You could also use DOS debug to do that...

debug KaboomP.bin {Return}
c 3e7 {Return}
21 {space} {Return}
c 494 {Return}
30 {space} {Return}
w {Return}
q {Return}




Topic:

As mentioned, there are only 2 color hues that remain unchanged between palettes ($0x and $2x). There is no quick way of altering them to an alternate color set unless you already know which bytes hold the color data (unless you could use the shortcut mentioned above...which only works if the majority of the program is unchanged between versions). Depending on what game it is, color values may not be easily altered...since a program may depend on a specific bitpattern that a color value uses. In addition, the color table itself may be shared with other data that depend on specific values. The only way to know for sure is through disassembly. This is the color value conversion table I use...

$0x (unchanged)
$1x {no equalivant}
$2x (unchanged)
$3x -> $4x
$4x -> $6x
$5x -> $8x
$6x -> $Ax
$7x -> $Cx
$8x -> $Dx
$9x -> $Bx
$Ax -> $9x
$Bx -> $7x
$Cx -> $5x
$Dx -> $3x
$Ex {no equalivant}
$Fx {no equalivant}

Notice how the color value increases by +$20 in the PAL table until it reaches the middle...when it switches to subtracting by -$20? That could allow for some programming shortcuts to be used if a program arrives at a particular color value through logic instead of using a table.

Edited by Nukey Shay, Thu Jul 1, 2010 8:44 PM.


#5 mamejay OFFLINE  

mamejay

    Chopper Commander

  • Topic Starter
  • 159 posts
  • Location:Melbourne, Australia

Posted Thu Jul 1, 2010 9:21 PM

Thanks Nukey,

That is what I am looking for. Running it at 60Hz

Now all I need is to work out how to hack the damn thing. Google here I come.

#6 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,666 posts
  • Location:The land of Gorch

Posted Thu Jul 1, 2010 9:28 PM

Hacked below...

Attached Files



#7 mamejay OFFLINE  

mamejay

    Chopper Commander

  • Topic Starter
  • 159 posts
  • Location:Melbourne, Australia

Posted Thu Jul 1, 2010 9:32 PM

Your a legend!!!
just on a side note I tried using the debug command as you specified and got errors.

Anyway I will copy this game to my Harmony cart and see if its all working.

Thanks so much for that!


Also would this be the same for the rest of the PAL games? Could a batch file be used to do this to a PAL roms folder?

#8 SeaGtGruff OFFLINE  

SeaGtGruff

    Quadrunner

  • 5,558 posts
  • Location:Georgia, USA

Posted Thu Jul 1, 2010 9:59 PM

Aside from the color value differences and delay values given to the timer, the NTSC and PAL versions are identical.

The CCE and Activision versions (both of which are NTSC) have numerous bytes that are different. Are those differences strictly from the company name display at the bottom of the screen, or are there other differences?

And why are there 2K, 4K, 8K, and 16K versions of the ROMs?

Depending on what game it is, color values may not be easily altered...since a program may depend on a specific bitpattern that a color value uses. In addition, the color table itself may be shared with other data that depend on specific values. The only way to know for sure is through disassembly.

Excellent point!

Notice how the color value increases by +$20 in the PAL table until it reaches the middle...when it switches to subtracting by -$20? That could allow for some programming shortcuts to be used if a program arrives at a particular color value through logic instead of using a table.

Another astute comment!

I used the MS-DOS FC command with the 2K Activision versions-- NTSC and PAL-- and got the following results:

Comparing files Kaboom! (Paddle) (1981) (Activision, Larry Kaplan, David Crane) (AG-010, AG-010-04).bin and KABOOM! - SCHNELLER ALS DER KNALL (PADDLE) (1981) (ACTIVISION, LARRY KAPLAN, DAVID CRANE - ARIOLA) (EAG-010, PAG-010 - 711 010-720) (PAL).BIN

000002AA: 88 B6 * <--
000002E7: 21 3D *** <--
00000394: 30 4F *** <--
00000654: 3A 4A
00000655: 3A 4A
00000656: 3A 4A
00000665: 38 48
00000666: 3A 4A
00000667: 3A 4A
00000668: 3A 4A
00000669: 3A 4A
0000066A: 3A 4A
0000066B: 38 48
0000066F: 14 24
00000670: 12 22
00000671: 10 20
00000673: D4 54 *
00000674: 1A 2A
00000675: 42 62
00000682: 4E 6E
00000683: 4E 6E
00000684: 4E 6E
00000685: 12 22
00000686: 12 22
00000687: 14 24
00000688: 14 24
00000689: 16 26
0000068A: 16 26
0000068B: 88 B6 * <--
0000068C: 16 26
0000068D: 88 B8 *
0000068E: 88 B8 *
0000068F: 88 B8 *
00000690: 88 B8 *
00000691: 88 B8 *
00000692: 88 B8 *
00000693: 88 B8 *
00000694: 88 B8 *
00000695: 12 22
00000696: 12 22
00000697: 14 24
00000698: 14 24
00000699: 16 26
0000069A: 16 26
0000069B: 88 B6 * <--
0000069C: 16 26
0000069D: 88 B8 *
0000069E: 88 B8 *
0000069F: 88 B8 *
000006A0: 88 B8 *
000006A1: 88 B8 *
000006A2: 88 B8 *
000006A3: 88 B8 *
000006A4: 88 B8 *
000006A5: 12 22
000006A6: 12 22
000006A7: 14 24
000006A8: 14 24
000006A9: 16 26
000006AA: 16 26
000006AB: 88 B6 * <--
000006AC: 16 26
000006AD: 88 B8 *
000006AE: 88 B8 *
000006AF: 88 B8 *
000006B0: 88 B8 *
000006B1: 88 B8 *
000006B2: 88 B8 *
000006B3: 88 B8 *
000006B4: 88 B8 *

Except for the six places where I put arrows, the rest of the bytes that differ have the same lo nibbles, and differ only in the hi nibbles. It's clear from comparing the hi nibbles that these are the color values. Except for the places where I put a single asterisk, the color transformations are what I would have expected. They chose to convert NTSC hue $8x to PAL hue $Bx instead of $Dx, and to convert NTSC hue $Dx to PAL hue $5x instead of $3x. And there are four places where they converted NTSC color $88 to PAL $B6 instead of $B8. I guess they thought it looked better that way.

The other two differences-- where I put three asterisks-- are the timing values you mentioned.

I think it's interesting that the color table from $F685 through $F694 is repeated at $F695 through $F6A4, and again at $F6A5 through $F6B4. I realize that's for the three buckets of water, but if I'd been programming it, I probably would have tried to reuse the same color table for all three buckets. On the other hand, I can see the elegance of just putting three copies of the color table one after the other like that. They would have saved 32 bytes by reusing a single color table, but I wonder how many bytes it would have taken to reset the index back to the beginning of the table? Of course, they fit everything into 2K as it was, so I guess there was no need to try to squeeze it down more.

Michael

#9 SeaGtGruff OFFLINE  

SeaGtGruff

    Quadrunner

  • 5,558 posts
  • Location:Georgia, USA

Posted Thu Jul 1, 2010 10:02 PM

Also would this be the same for the rest of the PAL games? Could a batch file be used to do this to a PAL roms folder?

There might possibly be other differences, and the *locations* of the timer values would certainly be different in other games, so I doubt if it would be feasible to try to make a batch file.

Michael

#10 Omegamatrix OFFLINE  

Omegamatrix

    Quadrunner

  • 6,125 posts
  • Location:Canada

Posted Thu Jul 1, 2010 10:17 PM

The CCE and Activision versions (both of which are NTSC) have numerous bytes that are different. Are those differences strictly from the company name display at the bottom of the screen, or are there other differences?

And why are there 2K, 4K, 8K, and 16K versions of the ROMs?


The difference is that the CCE version has a CCE logo hacked in where the Activision logo was. All versions above 2K are overdumps.

#11 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,666 posts
  • Location:The land of Gorch

Posted Fri Jul 2, 2010 9:24 AM

As far as reusing the color table for buckets is concerned, there might not have been enough time to reset the pointer in the display the way that it is written (can't recall offhand). But it doesn't really matter, since the program fit into 2k already ;)

#12 mamejay OFFLINE  

mamejay

    Chopper Commander

  • Topic Starter
  • 159 posts
  • Location:Melbourne, Australia

Posted Thu Jul 8, 2010 10:33 PM

Hey nukey,

Any chance of changing the timings on a few more PAL games :):)
Would love Pitfall! and Pitfall!2.

Or can you point me in the right direction to high level steps to doing this myself? Like apps I need to disassemble the BIN file. What to look for in the code. APP to reassemble the bin file.

#13 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,666 posts
  • Location:The land of Gorch

Posted Fri Jul 9, 2010 4:37 AM

Any chance of changing the timings on a few more PAL games :):)
Would love Pitfall! and Pitfall!2.

Fortunately, PAL versions of both already exist, so all that is needed is to alter the timer values to create PAL60 versions from PAL. By looking at the NTSC versions, that provides the values they used.
A commandline binary compare can be done which reveals all of the bytes that differ between versions...which can be useful if code or data tables don't shift around:
fc /b {name of first binary} {name of second binary} > {name of text file}

Much of the time, the timer and color values are the only things that change between versions. Occasionally, however, there may be other changes present. That FC command above reveals everything.

In Pitfall!, for example, the only changed bytes you are interested in are at $x59C and $x695. Everything else relates to color data.

However...in Pitfall 2, there are scanline comparison values mixed in with color data...so those need to be seperated when using different timing.

I made PAL60 versions of both below.
NOTE: Harry's white face is normal in PAL...I don't know if that can be fixed at all (that's how it is in the original PAL game).


Or can you point me in the right direction to high level steps to doing this myself? Like apps I need to disassemble the BIN file.

Distella. Common commandline usage is:
distella -pafs {name of binary} > {name of disassembly}

A sometimes-optional step is to examine the disassembly to collect address ranges of program instructions vs. data, and use that info to create a configuration file and disassemble a second time using it:
distella -pafsc{name of config file} {name of binary} > {name of disassembly}

Depending on the complexity of the program, that optional step may be the only way of seperating program instructions from data correctly. Distella tries to figure out stuff on it's own, but there are some cases when it cannot. Unconditional branching and indirect-jumping are two such examples. Data tables following unconditional branches would be misinterpreted as program instructions (resulting in a lot of gibberish in the disassembly), while instructions at indirect-jump destinations would be missed entirely and misinterpreted as data (unless those destinations are also reached conventionally). Destinations are also arrived at via bankswitching in some games, and again those sections would be missed by Distella. The latter issue has the additional problem where Distella would not be able to "know" the bankswitching scheme used for the game...which is why no binaries larger than the natively-addressable 4k will be handled. Those would need to be split into the banked parts and disassembled seperately with .cfg files to help guide Distella.
Also, any addresses broken up by the program and stored as high byte/low byte vectors would need to be edited and relabelled by hand if you wish the relevant disassembled code or data to be relocatable (to add sprites or program code).



What to look for in the code.

Usually just values stored to the hardware timers (TIMxT). Values stored to COLUxx color registers too, unless you've already got a 50hz PAL version to look at (where the colors have already been corrected).
Take warning that not all programs rely on the hardware timers to build a stable display...it's just usually the most-efficient way of doing so (so the programmer isn't constantly rechecking "worst-case scenarios" in the program). And color values may be impossible to switch between palettes if those values are aquired through logic instead of an actual data table or values. Consider a case involving bitpattern %00011000 - that's a nice centered block for sprite data. If a program also used it as a color (yellow) in NTSC, that yellow color would be impossible to edit without changing the sprite data too. In such a case, the program lines that says "oh by the way, use that bitpattern as a color" would need to be edited and new lines inserted to handle the PAL exception.


APP to reassemble the bin file.

Dasm. Common commandline usage for VCS programs is:
Dasm {name of disassembly} -f3 -o{name of new binary}

Attached Files


Edited by Nukey Shay, Fri Jul 9, 2010 5:23 AM.


#14 mamejay OFFLINE  

mamejay

    Chopper Commander

  • Topic Starter
  • 159 posts
  • Location:Melbourne, Australia

Posted Fri Jul 9, 2010 8:10 AM

Once again you have come through with the goods. I tried looking at some of the comparisons and code and it is just over my head at the moment.

In Pitfall!, for example, the only changed bytes you are interested in are at $x59C and $x695. Everything else relates to color data.


not sure how you worked that one out. i can see those values when i do a FC on the NTSC and Pal files but I can see a lot of differences.

#15 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,666 posts
  • Location:The land of Gorch

Posted Fri Jul 9, 2010 11:12 AM

FC reports them. So all you need to do is look at a Distella disassembly (or from Stella's debugger) for what actually exists at those addresses. As shown below, even a rough disassembly that Distella made without any .cfg file shows that the values in question are stored to timer register TIM64T.

NTSC...
LF59B: LDA    #$20    ;2 <- address $x59C
       LDX    #$82    ;2
       STA    WSYNC   ;3
       STA    TIM64T  ;4
LF68E: STY    $87     ;3
       ASL    $87     ;5
       STA    $88     ;3
       LDA    #$2F    ;2 <- address $x695
       STA    WSYNC   ;3
       STA    TIM64T  ;4

PAL...
LF59B: LDA    #$3C    ;2 <- address $x59C
       LDX    #$82    ;2
       STA    WSYNC   ;3
       STA    TIM64T  ;4
LF68E: STY    $87     ;3
       ASL    $87     ;5
       STA    $88     ;3
       LDA    #$4F    ;2 <- address $x695
       STA    WSYNC   ;3
       STA    TIM64T  ;4

If you look at the other differences reported, you'll see that the values from those addresses are either being directly stored to color registers, or are in data tables.

#16 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,666 posts
  • Location:The land of Gorch

Posted Sun Jul 11, 2010 1:50 AM

Update:
Fixed harry's white face in PAL and PAL60 Pitfall 2 :)

Are the PAL values $0E in the actual cartridge?

;       .byte $0E ; |    XXX | $63CD
;       .byte $0E ; |    XXX | $63CE
;       .byte $0E ; |    XXX | $63CF
;correction...
       .byte $6A ; | XX XXX | $63CD
       .byte $6A ; | XX XXX | $63CE
       .byte $6A ; | XX XXX | $63CF

Attached Files



#17 mamejay OFFLINE  

mamejay

    Chopper Commander

  • Topic Starter
  • 159 posts
  • Location:Melbourne, Australia

Posted Mon Jul 12, 2010 10:11 PM

Update:
Fixed harry's white face in PAL and PAL60 Pitfall 2 :)

Are the PAL values $0E in the actual cartridge?

;       .byte $0E ; |    XXX | $63CD
;       .byte $0E ; |    XXX | $63CE
;       .byte $0E ; |    XXX | $63CF
;correction...
       .byte $6A ; | XX XXX | $63CD
       .byte $6A ; | XX XXX | $63CE
       .byte $6A ; | XX XXX | $63CF



Thanks so much for that!!

Hey I attempt to compile a PAL 60 Dragster. I decompiled both the PAL and NTSC versions and looked for the TIM64T value and modified the LDA value on the Pal version to match the NTSC version. It sort of worked. In Stella it would run but on my Harmony cart the screen kept scrolling. There was 2 x TIM64T entries and I change both of these. I do not have the exact code that I changed as i am on my work laptop at the moment. Will publish the values I changed once I get home.

I would love to be able to do this all my favorite games. Kaboom! is so much faster and so much harder.

#18 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,666 posts
  • Location:The land of Gorch

Posted Tue Jul 13, 2010 1:42 AM

Dragster features shifting code, not just timer adjustments.

2 of the NOPs present in NTSC (@$x027-8) were removed for PAL. This was done so that a STA WSYNC instruction could be added just above the first TIM64T store. Also, the VBLANK store was moved from above VSYNC in NTSC to just below the first TIM64T store in PAL.


For this game, it would have been simpler to just change the color values in the NTSC version to create PAL60...which avoids the shifting code problem totally. There's only 4 bytes that change from NTSC to create PAL60 from it:
;NTSC...
       .byte $88 ; |X   X   | $F6CC
       .byte $CC ; |XX  XX  | $F6CD
       .byte $D8 ; |XX XX   | $F6CE
       .byte $46 ; | X   XX | $F6CF

;PAL...
       .byte $B8 ; |X XXX   | $F6CC
       .byte $3C ; |  XXXX  | $F6CD
       .byte $58 ; | X XX   | $F6CE
       .byte $66 ; | XX  XX | $F6CF

EDIT: when you see lots of color-unrelated changes between versions, you should look at disassemblies of both (side-by-side) to see how those changes occurred...then decide which is more work: to change the timing in PAL, or to change the color values in NTSC.

Edited by Nukey Shay, Tue Jul 13, 2010 1:43 AM.


#19 mamejay OFFLINE  

mamejay

    Chopper Commander

  • Topic Starter
  • 159 posts
  • Location:Melbourne, Australia

Posted Tue Jul 13, 2010 2:27 AM

I think I did it. Attached is my attempt. The colours look correct on my PAL 2600.
not sure how you worked out what the colour value code was. i just started searching through the code and found a string with the values you posted.

Attached Files



#20 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,666 posts
  • Location:The land of Gorch

Posted Tue Jul 13, 2010 3:00 AM

not sure how you worked out what the colour value code was.

Explained above. Since code-shifting was present between versions, I took the NTSC version disassembly and looked at it side-by-side with the PAL version disassembly...editing it to match along the way by adding IF-THEN statements. After assembling a new NTSC-to-PAL binary from it, I did an FC binary compare against the actual PAL binary...and it revealed the only changes left over that were not related to code-shifting - the timer values and color table. The process sounds complicated but only took about 15 minutes or so.

On retrospect, it would have been easier to look for where color stores get their values from...but I wanted to be sure to catch all changes. Looking at either disassembly, you'll see that every store to a COLUxx register is getting it's value from a ram location ($86-$8C). Searching for ram location $86 reveals this routine:

LF016: ldx    #$06    ;2
LF018: lda    LF6CA,X ;4 get color value
       eor    $84     ;3 (scramble for screensaver)
       and    $85     ;3 (adjust for B&W)
       sta    $86,X   ;4 store to ram
       dex            ;2
       bpl    LF018   ;2 loop until done

Thus, table LF6CA is the only place color values exist in the game.




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users