Jump to content
IGNORED

Hacking NTSC ROMS to create PAL60 versions


davyK

Recommended Posts

I posted a while ago in the main thread area about PAL60 ROMS I was able to create from high quality disassemblies. I did this by taking an NTSC version of a game and changing the colour (color?) values to their PAL equivalents. Fairly straight forward even for a beginner like me (I can "read" and even write a bit 6502 and have a very rudimentary knowledge of 2600 architecture)

 

I've run out of assemblies to use (pretty quickly) and I thought that maybe using the Stella debugger would be a good way of doing this (as opposed to tackling a disassembly of my own which I think is a step up too much at my current level of 2600 knowledge).

 

Essentially I am thinking of trapping writes to $06, $07, $08 and $09 and examing the code in the disassembly window to try and figure out where the colour data is coming from.

 

Is this a sensible approach?

 

I have looked at the Space Invaders ROM and it's proving tricky to see where the colour values are coming from. I can see the values being set up in the zero page area ($DE and thereabouts) and have managed to see the effects of changing them during the creation of the frame but unfortunately they keep getting reset to the original values at the start of the each frame. It's proving a mite tricky to see exactly where the colour values are coming from. I'm prepared to hang tough and stick at it but is Space Invaders a tricky one to start with?

 

Have a trapwrite at $DE which fires at the start around the beginning of a frame and there's this little lot preceeding it !! Have attempted to add comments.....

 

$f99c:LDA SWCHB ; checking color/bw? (bit 3?)

AND #$08 ; isolating last 4 bits / 2nd nybble?

TAY ; copy to Y reg

BEQ $f9a6 ; skip next instruction if b&w selected?

LDA #$f8 ; what is this doing? Guessing color value being set here

$f9a6: ORA #$07 ; some bit manipulation here in 2nd nybble.performing an OR operation A=1111 1000 (F8) OR 0000 0111 (07) = 1111 1111 ....?????????!!!!!!!

STA $ee; save the resulting value

LDX #$F8 ; load a literal value

LDA $fcff, y -;colour table starts at fcff?

EOR $c7 ;some magic happening here

AND $ee ; ...and here!!!!

STA $e5,X ; trap write to $DE fires here

 

 

EDIT : Just noticed the newbie dev area and should have posted this there - apologies.....

Edited by davyK
Link to comment
Share on other sites

I'd suggest both. Use DiStella to get a static analysis, to have something on paper/in a file for you study. Once you work through that and need more information, use the debugger in Stella (which is still DiStella anyway). The benefit being that is it dynamic, and you can track accesses and make changes on-the-fly.

Link to comment
Share on other sites

thanks for the responses guys.....

 

re the screensaver comment - thought I was analysing a running game when I posted that code - maybe I wasn't. WIll have a go at using DiStella and get back to it.

 

I had an issue with using DiStella some time ago and gave up on it - kept getting an error message - something about it not being able to load the bin file - will have another go!

Edited by davyK
Link to comment
Share on other sites

Wow - got Distella going and it seems to have done a good job splitting the data and code.

 

As a matter of fact it looks like the colour table DOES start at $FCFF - although it isn't as straightforward as the colour values are scattered a bit from that memory location

 

 

;LFCFF: .byte $0F,$0E,$0F,$00,$02,$00,$04,$02,$34,$52,$CC,$F6,$14,$0F,$00,$E2 ; NTSC colours

LFCFF: .byte $0F,$0E,$0F,$00,$02,$00,$04,$02,$42,$82,$5C,$26,$24,$0F,$00,$32 ; PAL colours for PAL60

 

 

It was easy by using the Scan+1 button in Stella to step down to the object (e.g. invader, cannon, shelter etc.) and look at the TIA colour values and then spot the byte in the disassembly. With a bit of trial and error (and randomterrain's colour converter) I've been able to create a PAL60 version of Space Invaders pretty damn quickly!!

 

It is less satisfying not using the debugger to trace the code and fully understand how those colour values end up in the colour registers but hey - life is too short - at least I now know the memory locations which means I can now go back through the code and trapread against those locations to see how it works..

 

Thanks again....looks like my Harmony cart is going to be busy letting me play PAL60 games on my PAL woody!

Edited by davyK
Link to comment
Share on other sites

Wow - got Distella going and it seems to have done a good job splitting the data and code.

 

As a matter of fact it looks like the colour table DOES start at $FCFF - although it isn't as straightforward as the colour values are scattered a bit from that memory location

 

 

;LFCFF: .byte $0F,$0E,$0F,$00,$02,$00,$04,$02,$34,$52,$CC,$F6,$14,$0F,$00,$E2 ; NTSC colours

LFCFF: .byte $0F,$0E,$0F,$00,$02,$00,$04,$02,$42,$82,$5C,$26,$24,$0F,$00,$32 ; PAL colours for PAL60

 

 

It was easy by using the Scan+1 button in Stella to step down to the object (e.g. invader, cannon, shelter etc.) and look at the TIA colour values and then spot the byte in the disassembly. With a bit of trial and error (and randomterrain's colour converter) I've been able to create a PAL60 version of Space Invaders pretty damn quickly!!

 

It is less satisfying not using the debugger to trace the code and fully understand how those colour values end up in the colour registers but hey - life is too short - at least I now know the memory locations which means I can now go back through the code and trapread against those locations to see how it works..

 

Thanks again....looks like my Harmony cart is going to be busy letting me play PAL60 games on my PAL woody!

 

I often use Stella to find colors. You can set "traps" like Thomas eluded too, or increment like scanline like you said.

 

Another thing you might want to try is jumping multiple scanlines. Type something like "scanline #20" in the prompt window tab to advance 20 scanlines for example. Using the "Scan +1" button or typing in "scanline #20" are both handy because you have the ability to go back! to the left of the "scanline +1" button is the rewind button which allows you to step back. Very handy!

 

 

So yeah, once you notice a color change, hit rewind and then use "scan +1" or "step" to hone in on the spot exactly.

Edited by Omegamatrix
Link to comment
Share on other sites

I often use Stella to find colors. You can set "traps" like Thomas eluded too, or increment like scanline like you said.

 

Another thing you might want to try is jumping multiple scanlines. Type something like "scanline #20" in the prompt window tab to advance 20 scanlines for example. Using the "Scan +1" button or typing in "scanline #20" are both handy because you have the ability to go back! to the left of the "scanline +1" button is the rewind button which allows you to step back. Very handy!

 

 

So yeah, once you notice a color change, hit rewind and then use "scan +1" or "step" to hone in on the spot exactly.

 

Also, Alt-l is a key combo for advancing by one scanline :) As are Alt-s for 'step+1' and Alt-f for 'frame+1'.

Link to comment
Share on other sites

cool - was getting RSI from clicking Scan+1 !!!!!

 

I'm doing Atlantis at the minute - quite a colourful game and doing stepping through quite a few scans as you would imagine!! The zoom feature and the TIA viewer of the debugger is brilliant for this sort of thing too.

 

I've got the playfield, guns and the twirling emplacements done (not to mention the escaping saucer at the end of the game and the fading playfield colours during the end game sequence). It's looking really good so far - and again - a big improvement over PAL50 - not so much with speed as the PAL version doesn't feel noticeably slower - but more the look of the game - just bigger and clearer.

Edited by davyK
Link to comment
Share on other sites

Finished Atlantis - took a bit longer than I thought but it does have a lot of colour lookups - that Imagic trademark!!

 

 

Booting it up on the actual hardware and there is a speed boost - hadn't noticed it earlier - not as noticable as with some games - but it is there.

 

Will post in the PAL60 ROMS thread. WIll only post here again if I hit a wall!!

 

Thanks for the help and hints guys,,,

 

Here's the disassembly - I have commented the changes I made for colours which might give someone a start if they want to do a proper disassembly of this...

http://www.davykelly...lantisPAL60.asm

 

 

Going through this I am starting to learn how these games are put together and how cleverly this game uses the player objects (well - at least its clever to me!! Clever in that it is totally designed around the limitations of the hardware). I can now see why the game looks like it does (e.g. how only the 2 player objects are used to generate the entire display of ships, guns and enemy targets, why the side guns are on different levels etc ) and how the 2 player objects pushed together are used to create the larger features like the domed palace etc.

Edited by davyK
Link to comment
Share on other sites

There are several misunderstandings in your original post. I'll list your original lines in bold and try to explain what is actaully going on.

 

 

 

$f99c:LDA SWCHB ; checking color/bw? (bit 3?)

AND #$08 ; isolating last 4 bits / 2nd nybble?

No...it's isolating bit 3 only. Bit 3 in SWCHB reveals what state the color switch is in. Instead of reading the line as "AND #$08" (hex), you should read it as "AND #%00001000" (binary). Notice how that specific bit is singled out now? After execution of this instruction, the accumulator will hold a value of 8 (binary %00001000) if the switch was set on color, or zero if it was set on B&W.

 

TAY ; copy to Y reg

The Y register is going to be used later as an offset to read values from the palette table.

 

 

BEQ $f9a6 ; skip next instruction if b&w selected?

LDA #$f8 ; what is this doing? Guessing color value being set here

$f9a6: ORA #$07 ; some bit manipulation here in 2nd nybble.performing an OR operation A=1111 1000 (F8) OR 0000 0111 (07) = 1111 1111 ....?????????!!!!!!!

STA $ee; save the resulting value

 

The program is now setting up a "bit mask". What this does is set a "parameter" of sorts to define which bits are used in either of the 2 palettes. If B&W was set (a=0), the branch is taken right to the ORA instruction (0 ORA #%00000111 = #%00000111). If the branch was not taken, the accumulator is givin a different starting value first (#%11111000 ORA #%00000111 = #%11111111).

 

By now you might be asking why is a mask being set up since the values in the table have no upper bits set for the B&W section (and hence, no need to strip them away). The values are not used directly. Bits are flipped when the screensaver is active. More on this in a minute...

 

 

LDX #$F8 ; load a literal value

 

More exactly, this sets up the loop counter for the 8 values. Y is already occupied holding the table offset (8 or 0), and the accumulator is going to be swapping the values. After each iteration, the value of X is increased until it rolls to zero (i.e. 8 passes though the loop to get all the values for that palette).

 

 

LDA $fcff, y -;colour table starts at fcff?

EOR $c7 ;some magic happening here

AND $ee ; ...and here!!!!

STA $e5,X ; trap write to $DE fires here

 

This is the upper portion of the loop. The ingame color values are read from table $fcff using the Y offset - the initial 8 values are the B&W palette, and the next 8 are for the color palette. The following EOR flips bits if the screensaver is active (i.e. if ram $c7 contains -any- non-zero value)...and the next AND strips away the upper nybble if the game is using the B&W palette (because the preceding EOR may have changed them. Non-greyscale values can look funky on a B&W television). The game colors are then updated starting at ram $DE ($E5 + $F8 = $1DE).

 

The lower portion of the loop (not mentioned in your post) increases the Y index and X index...and branches back if zero hasn't been reached yet (via BMI).

Edited by Nukey Shay
Link to comment
Share on other sites

BTW be aware that PAL60 versions of some NTSC games already exist. The hack I did of Atlantis allows the player to select between the original or the more-challenging "Atlantis 2" games 8)

/plug

 

But you can find disassemblies too if you choose to create your own...to help in your search for color values.

 

Also...it may be difficult in certian games to alter color values which are also used for logic decisions within the program (such as the ship color in Gravitar, IIRC). Some program lines may need to be altered if you want a true 1:1 PAL conversion. But even then, a few color hues are beyond reach - yellow being the most common of them. Sunsets often require you to add an additional color table, since PAL does not follow the color spectrum sequentially.

Link to comment
Share on other sites

Many thanks - lots for me to chew on there....I do have basic knowledge of looping and masking , and using indexed addressing for processing arrays of bytes so I can usually follow that OK - I guess its my rustiness of 6502 and my newbie status re the architecture. I suppose there are some standard techniques that I need to learn to recognise as I gain experience...

 

Getting back to thinking about binary operations takes a while too - its been a long time since I did anything in that field.

 

I kind of accept some ports won't be exactly the same re colour - to be honest once you see it running on a CRT the occasional slightly different hue won't be that much of a big deal with many games....

 

Those mighmare scenarios where values are being used for colours and boundary conditions in decisions I'll leave for another day!!! Will also keep a lookout for work already done....hadn't thought about the Atlantis 2 ROM - will look your hack up - thanks again.

Edited by davyK
Link to comment
Share on other sites

It's usually not much of a problem if you can't change such colors IIRC. Having a different color ship in Gravitar wouldn't raise many eyebrows, for example...and in most cases where such code appears, the game is already abstract enough that precise colors don't matter much (like Spider Fighter).

 

Some artistic license is needed where there is no corresponding color in the PAL palette. Those are yellow ($1x), greenish-gold ($Ex), and yellowish-gold ($Fx). Crackpots ended up looking a bit muddy in PAL :P

Link to comment
Share on other sites

  • 2 weeks later...

Had a break from this but back at it.

 

Started on Breakout but hit a wall - see what I did there? :)

 

Anyhow - found the brick colour values easily - but if I change ANY of the values the paddle movement gets broken - must be the colour values being used in the logic for the paddle control - will leave that for another day!!

 

Moved onto Keystone Kapers which is a LOT better in NTSC due to the speed. Have it nearly done but did hit a gotcha.

 

The NTSC colour value for the escalator is #C0 in NTSC - I need to use #50 for the PAL60 version but when I change this the game crashes....

 

code is

 

LDA #$50 ; used to be C0

BMI LF883

 

Getting better at this lark - noticed of course that C0 will set the negative bit but the new value #50 won't - so the easy fix was changing the BMI to a BPL....quite pleased with myself...

 

Just the radar display and some of the objects (ball, plane, radios) to do and I'm done.

Edited by davyK
  • Like 1
Link to comment
Share on other sites

The NTSC colour value for the escalator is #C0 in NTSC - I need to use #50 for the PAL60 version but when I change this the game crashes....

 

code is

 

LDA #$50 ; used to be C0

BMI LF883

 

Getting better at this lark - noticed of course that C0 will set the negative bit but the new value #50 won't - so the easy fix was changing the BMI to a BPL....quite pleased with myself...

 

It's good that you are understanding the language more now. You could also have used BNE in this case, either way this bit of code is meant to always branch.

 

 

Using an unconditional branch saves one byte over using a JMP. With limited rom space it is desirable to save bytes this way.

Link to comment
Share on other sites

Regarding Breakout...

Could you be more specific about how the paddle reacts when you change the game? Be aware that if you are testing with Stella, you have to reset your control to paddle whenever any changes are made (since the original profile no longer applies). This will need to be done after additional changes, too. You ought to able to alter the colors to anything you want (at least, I did).

Link to comment
Share on other sites

Regarding Breakout...

Could you be more specific about how the paddle reacts when you change the game? Be aware that if you are testing with Stella, you have to reset your control to paddle whenever any changes are made (since the original profile no longer applies). This will need to be done after additional changes, too. You ought to able to alter the colors to anything you want (at least, I did).

 

You'll probably want to set the controls from the commandline in this case, since changing them after every modification gets old 'real fast'. If in Windows, perhaps create a BATCH file to do it. Or in Linux/OSX, a BASH script.

Link to comment
Share on other sites

Regarding Breakout...

Could you be more specific about how the paddle reacts when you change the game? Be aware that if you are testing with Stella, you have to reset your control to paddle whenever any changes are made (since the original profile no longer applies). This will need to be done after additional changes, too. You ought to able to alter the colors to anything you want (at least, I did).

 

 

a - ha!! That's probably what the issue is.....the control just stops working - probably because Stella has defaulted to joystick with the new rom image. Its the first rom I've changed and tested in Stella that doesn't use standard joystick control...

 

When I amended Kaboom! I wasn't using Stella to test the results - just kept copying the rom to the Harmony (which got tedious really fast!). Once I learned about ctrl-F in Stella (after I completed Kaboom!) I started using Stella for testing.

 

I can remember reading about that now but clearly it didn't sink in....you have to get your hands dirty - best way to remember is through experience....

 

Thanks - yet again.

 

Breakout, Super Breakout, Circus and Solar Storm are all in my sights now....

Edited by davyK
Link to comment
Share on other sites

It's good that you are understanding the language more now. You could also have used BNE in this case, either way this bit of code is meant to always branch.

 

 

Using an unconditional branch saves one byte over using a JMP. With limited rom space it is desirable to save bytes this way.

 

yeah - Nukey Shay showed me a trick to save a byte in Demon Attack by changing an absolute jump to a relative jump. All good stuff - hadn't though of BNE - guess it does the same job as long as you know the value in A isn't zero (AND the jump isn't out of range for relative addressing!)

Edited by davyK
Link to comment
Share on other sites

All good stuff - hadn't though of BNE - guess it does the same job as long as you know the value in A isn't zero (AND the jump isn't out of range for relative addressing!)

 

Yep, you got it right. A lot of the time you will see LDA #0, BEQ when a game wants to color something black. In some situations you can save bytes if you see a value of 1 reloaded. i.e.:

 

LDA #0

STA COLUP1

LDA #1

STA CTRLPF

 

In this case you could just use (and save 2 bytes):

 

LDA #1

STA COLUP1

STA CTRLPF

 

Since the lowest bit is ignored by the color registers. If you were doing an unconditional branch off of that LDA #0, then you simply change BEQ to BNE and use LDA #1.

 

The PAL color palette also gives you more options to double up bytes, since $0x, $1x, $Ex, and $Fx are all the same colors.

Edited by Omegamatrix
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...