Jump to content
Omegamatrix

Harmony and 7800 detection

Recommended Posts

Nukey wrote a cool little routine to detect if the console being played is a 7800 or 2600. With that information you can make the color/B&W switch on a 2600 work as a pause, and have the pause also work on a 7800.

 

 

This routine fails with a Harmony cart, and all the hacks that have been built with it will no longer work. What I'm hoping is the Harmony bios can be adjusted to first run the 7800 detection routine. If it detects a 7800 then maybe it can set the TIA ram back to the known state it is in on 7800's once a game is selected. Then everything would work again.

 

 

Even better would be to copy the 128 bits of TIA ram into the Harmony before they ever get cleared, and fill them back in once a game is selected. That would help some old era games that depend on various TIA locations for random seeds, and not the INTIM register.

 

 

Can it be done? Is it possible??

Share this post


Link to post
Share on other sites

I doubt this will be possible. The Yin-Yang you see before a game get's started is drawn by a RAM kernel and there are hardly any bytes free there. The game is directly started from this RAM kernel.

 

IIRC the auto detection checks some of those RAM bytes and those are requires by the RAM kernel. One could minimize this kernel (less or no graphics etc.), but I doubt we want to go this way.

Share this post


Link to post
Share on other sites

Thomas, does your program trash every single ram location? If it is possible to leave just 2 ram locations alone then 7800 detection could still be done after the jump is made to the game. The bytes don't need to be consecutive either. Any ram location should do, but some would be more ideal then others. Somewhere in the middle would be good.

 

 

initial TIA ram in a 7800:

 

80: A9 00 AA 85 01 95 03 E8 E0 2A D0 F9 85 02 A9 04

90: EA 30 23 A2 04 CA 10 FD 9A 8D 10 01 20 CB 04 20

A0: CB 04 85 11 85 1B 85 1C 85 0F EA 85 02 A9 00 EA

B0: 30 04 24 03 30 09 A9 02 85 09 8D 12 F1 D0 1E 24

C0: 02 30 0C A9 02 85 06 8D 18 F1 8D 60 F4 D0 0E 85

D0: 2C A9 08 85 1B 20 CB 04 EA 24 02 30 D9 A9 FD 85

E0: 08 6C FC FF EA FF FF FF FF FF FF FF FF FF FF FF

F0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

 

 

Nukey is the one that used the 7800 detection most, and he checked ram locations $D0 and $D1. Those seemed like good places to me too (because of the values in them). All the $FF values might be a little sketchy as $FF is a commonly used value.

Share this post


Link to post
Share on other sites

I just checked the code and there might be a few bytes free. $D0/$D1 are not easy to utilize (4 extra bytes), but $80/$82, $a0/$a1, $a8/$a9 or bytes at the end are possible with just two extra bytes.

Share this post


Link to post
Share on other sites

I know the odds are low, but are any bytes in Harmony and 7800 startup RAM the same?

40% for one byte, 16% for two. :)

Share this post


Link to post
Share on other sites

Why not have the Harmony detect the 7800 (in a future update of course) and set a byte of free RAM accordingly?

Edited by Wickeycolumbus

Share this post


Link to post
Share on other sites

I just checked the code and there might be a few bytes free. $D0/$D1 are not easy to utilize (4 extra bytes), but $80/$82, $a0/$a1, $a8/$a9 or bytes at the end are possible with just two extra bytes.

This is good news! $A0/$A1 seems like a good choice to me. Otherwise:

 

$80 << #$A9 - a lot of games have their frame counter here, so you already know it will scroll through #$A9 at some point. That's no good!

$81 << #$00 - this is a common value so it has a higher probability of being left from before... no good!

 

$A0 << #$CB - seems like a reasonable choice if any

$A1 << #$04 - could be more problematic, lots of small counters scroll 0-7

 

$A8 << #$85 - seems like a reasonable choice if any

$A9 << #$0F - this also is more problematic, as a small counter could also be 0-15

 

$FE << #$FF - Busy register... the stack pointer writes the return address over this so you have a higher chance of being #$FF. That's no good!

$FF << #$FF - same as above, but you also have a greater chance of being #$FF as it could be the high pointer for a return addresss.

 

 

All in all I say go with $A0/$A1 (if it needs to consecutive), or $A0 and $A8 if it doesn't need to be consecutive. What do you say Thomas/Batari?

 

 

 

Why not have the Harmony detect the 7800 (in a future update of course) and set a byte of free RAM accordingly?

 

The problem is the hack has to be blind to the Harmony. It has to detect the 7800 whether the game is on a burned eprom or on the Harmony Cartridge. The most ideal thing to happen for a user like me is that the Harmony works some magic, detects the 7800, and rewrites all those exact values back in at the moment the game is loaded. Since that is not feasible the way the Harmony is set up, the next best thing is to leave a couple of known registers alone. Any less then 2 would be too risky IMHO.

Share this post


Link to post
Share on other sites

And finally the code at the heart of it all, this time modified to use $A0/$A1.

 

 

START:
   sei
   ldx    $A0               ; test for 7800
   cpx    #$CB
   bne    .not7800
   ldx    $A1
   cpx    #$04
   bne    .not7800
   sec                      ; 7800 detected
   .byte  $04               ; illegal NOP, skip 1 byte
.not7800:
   clc                      ; 2600 detected
   .byte  $0C               ; illegal NOP, skip 2 bytes
RESET:
   lsr    consoleType       ; move previous 2600/7800 detection into carry
   cld
   ldx    #0
   txa
.loopClear:
   dex
   txs
   pha
   bne    .loopClear
   rol    consoleType       ; move 7800 detection into bit 0

Share this post


Link to post
Share on other sites

And finally the code at the heart of it all, this time modified to use $A0/$A1.

 

 

START:
   sei
   ldx    $A0               ; test for 7800
   cpx    #$CB
   bne    .not7800
   ldx    $A1
   cpx    #$04
   bne    .not7800
   sec                      ; 7800 detected
   .byte  $04               ; illegal NOP, skip 1 byte
.not7800:
   clc                      ; 2600 detected
   .byte  $0C               ; illegal NOP, skip 2 bytes
RESET:
   lsr    consoleType       ; move previous 2600/7800 detection into carry
   cld
   ldx    #0
   txa
.loopClear:
   dex
   txs
   pha
   bne    .loopClear
   rol    consoleType       ; move 7800 detection into bit 0

 

You can save a couple of bytes (and complication) by doing this :)

 

 

START:
   sei
   ldy    #0
   ldx    $A0               ; test for 7800
   cpx    #$CB
   bne    RESET
   ldx    $A1
   cpx    #$04
   bne    RESET

   iny                      

RESET:

   cld
   ldx    #0
   txa
.loopClear:
   dex
   txs
   pha
   bne    .loopClear
  
   sty    consoleType

Share this post


Link to post
Share on other sites

Are $A0 and $A1 to be the new standard? It doesn't matter to me which ones are used for detecting...I just picked $D0 and $D1 because they were in the middle of user ram (a higher probablilty of being used uniquely by any given game). The same is true for most "middle of the road" ram.

Share this post


Link to post
Share on other sites

You can save a couple of bytes (and complication) by doing this :)

 

 

Wickey, that code doesn't preserve the 2600/7800 flag when the player hits the Reset switch. That's the purpose of the 2nd illegal NOP is to jump over the instruction that pushes the old flag in the carry. But you could save a byte by taking out the 2nd illegal NOP, and doing the "LSR consoleType" before you jump to the RESET. I wanted to show how the whole code works here though, so I'm doing the 2nd illegal NOP in the example. :)

Share this post


Link to post
Share on other sites

Are $A0 and $A1 to be the new standard? It doesn't matter to me which ones are used for detecting...I just picked $D0 and $D1 because they were in the middle of user ram (a higher probablilty of being used uniquely by any given game). The same is true for most "middle of the road" ram.

I guess that is what we are trying to hammer out here. I have no idea what the Cuttle Cart 2 does (never owned one), but I know the Krok cart will detect the 7800 in single image mode. Multi-image on the Krok might be the same story of all the ram getting trashed, but I think we can all agree here that the Harmony is the choice of the future, and whatever we decide here we probably will stick with in the future.

Share this post


Link to post
Share on other sites

You can save a couple of bytes (and complication) by doing this :)

 

 

Wickey, that code doesn't preserve the 2600/7800 flag when the player hits the Reset switch. That's the purpose of the 2nd illegal NOP is to jump over the instruction that pushes the old flag in the carry. But you could save a byte by taking out the 2nd illegal NOP, and doing the "LSR consoleType" before you jump to the RESET. I wanted to show how the whole code works here though, so I'm doing the 2nd illegal NOP in the example. :)

 

Ah, I didn't realize that you were clearing RAM every time the Reset switch was pressed.

Share this post


Link to post
Share on other sites

I'm still at the Vegas airport waiting for my flight home, but I thought I'd post what I have for Harmony RAM on startup (I think this is the latest, but I may be wrong.)

 

So far I only spot one byte ($CD, value $D0) which is the same, ignoring the $FF of course. If anyone sees another, let me know.

 

80: 1C 16 3F 1F 07 03 16 04 3C 7E 5F 3F 03 05 00 00

90: 3C 7E FB B0 F2 20 00 00 3C 78 F4 F0 F0 D0 60 00

A0: 3C 7E FF FF FF FF 7E 3C B5 80 85 5B B5 A0 85 5C

B0: CA 85 42 85 42 10 F1 4A 85 41 A2 80 A9 9E E8 E8

C0: 87 BB A9 98 87 A9 A0 F6 98 E9 7D 69 03 D0 05 2C

D0: 82 02 30 20 2A 0A 85 42 85 40 88 D0 EB A0 06 84

E0: 41 A9 0A 85 46 49 B8 85 47 E0 9E D0 04 46 DE 85

F0: E2 BA D0 B4 18 6C FC FF 85 5B 86 60 86 61 88 A9

Share this post


Link to post
Share on other sites

It looks like just 3 locations are the same:

 

$B8 << #$85

$CD << #$D0

$F7 << #$FF

No too big surprise, both are pretty often used opcodes (sta zp, bne).

 

Also, how does this help 7800 detection? We cannot change these bytes when Harmony detects a 2600. We HAVE TO use at least one NEW byte.

Share this post


Link to post
Share on other sites

Also, how does this help 7800 detection? We cannot change these bytes when Harmony detects a 2600. We HAVE TO use at least one NEW byte.

 

 

I don't know, but I figured Batari had some sort of plan.

Share this post


Link to post
Share on other sites

Best option of course would be to use the existing spots $D0/$D1. We would need 3-4 bytes for that.

 

I start to think that might be doable.

Share this post


Link to post
Share on other sites

Using $D0/$D1 means we need to change two bytes. If we already know at least one byte is the same, we only need to change one. It's going to be tough to pull off either way, but one byte might be easier to squeeze in.

Share this post


Link to post
Share on other sites

All this talk of 1 or 2 bytes...how much space is available in the Harmony bios? I never saw the program.

 

Why can't you just use a console detect when powering up Harmony, then copy the full list of 7800 ram (or scrambled 2600 ram) back when booting a cart image? You could also throw in a random value for INTIM. :?

Share this post


Link to post
Share on other sites

All this talk of 1 or 2 bytes...how much space is available in the Harmony bios? I never saw the program.

 

Why can't you just use a console detect when powering up Harmony, then copy the full list of 7800 ram (or scrambled 2600 ram) back when booting a cart image? You could also throw in a random value for INTIM. :?

That's because the loaded game is started from RAM. There is a loop (which displays the Yin-Yang) and checks a register if the game has been loaded. If that's the case, the loop is exited and code jumps to the address of start vector which can be found at the end of the loaded ROM.

 

So the RAM is pretty much full at this moment.

Share this post


Link to post
Share on other sites

There is a loop (which displays the Yin-Yang) and checks a register if the game has been loaded.

 

 

This register... is it a hard-wired address or a variable ram address that could be changed? If it is a ram location maybe the address could be changed depending on whether the Harmony is on a 7800 or 2600.

 

The trick is the absolute address has to match the 7800 code if a 7800 is detected, and not match it otherwise (easier).

 

 

So:

1. Harmony boots up and runs the 7800 detection code.

2. Depending on whether the console is 7800/2600 a different address is chosen to for the register that is checked to see if the game is ready or not.

3. The code for the Yin-Yang gets loaded into TIA ram. In that code the register that gets checked will have an absolute address that either matches 7800 TIA data or not.

 

 

Anyhow maybe the idea can be re-used for stuff other than the address of this one particular register. Write a ram code that is slightly different to have some data at locations that match the 7800. Use the old one otherwise. The detection code is run at the beginning, and the appropriate ram code would be loaded in. As long as some data matches the 7800 data when you want it to, you're good.

 

 

If this idea can be done, it'd be better not to use the existing or previously released ram codes as the one for matching a 7800 cart. This is because many people already have that bios in the Harmony's, and unless they upgrade it will falsely detect a 7800.

Share this post


Link to post
Share on other sites

Having said all that though, the most desirable option is still finding the bytes to free $D0/$D1. I'm assuming here that none of the previous bios versions matched the 7800 data at $D0/$D1. May the force be with you Thomas, and the illegal opcodes!!

 

 

Also, I did check the Krok in multi-image mode, and it failed the 7800 detection routine. I have no idea about the CC2, but if it has a menu screen then it'll probably be the same story.

Share this post


Link to post
Share on other sites

That's exactly why I wanted to know how much programming space is available (i.e. when it's NOT executing the ram loader). What cannot be done by optimizing the loader can be done by redundancy in the program that creates the loader in ram. And what about giving the bios an even-numbered MSB for the origin? 2600 games cannot use even-numbered banks so there is no conflict there (dunno if the 7800 uses all 4k chunks).

 

Is there an assembly file for the bios to look at?

Share this post


Link to post
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.

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...