Jump to content
IGNORED

2600 Title Screen question


Recommended Posts

Dear Nukey,

 

In reading the forums I came across a thread from the guy who made adventure plus, (which I bought and enjoyed greatly and inspired me to take on this endeavor). He thanked you for helping him get the 'flicker' out of the title screen room... I created my own title screen in the main number room, by looking at the source code of the original adventure and moving and changing the 'created by WR' message and moving it to that room, but am now experiencing the flicker issue as well... How did you guys pull off the non flicker?

 

Here is another weird thing, when I play this game through an emulator, I start the game, have the flicker on the title screen / number room screen. I go to the same room the game uses as the number screen, in the actual game, which is the upper room in the set of 3 rooms on the right of the maze that takes you to the white castle. Once I've been there, I reset the game, (not the emulator, just reset the adventure game) I'm back at the number room / title screen. My player (dot) is in the room with the numbers AND there is NO FLICKER... WTF? That's weird... I don't know how I stumbled across that, but it happens every time... Go figure... Hope to hear from you soon... HAPPY NEW YEAR!!! Oh PS...

 

 

I did what you said concerning the soundfx for adventure, playing with the settings you told me to and have gotten great results that I am completely happy with. Thanks again so much for the help.

Link to comment
Share on other sites

Hmmm...you know, I never noticed that I was credited for that :lol: It was actually Channel2 that helped him out...you can read that solution here:

http://atariage.com/forums/viewtopic.php?p...p=204064#204064

 

This bug was due to the fact that the invisible surround does not have a starting screen (so it would automatically default to the "zero" screen (i.e. the number room))...and the program would get confused since that additional object would be in a room and it is not supposed to be. If you moved into a dark maze, the problem would correct itself (since the orange "light" object would be left behind once you move into a light screen again).

 

If you are experiencing the problem on every screen even after entering a maze, I'd guess that you need to recheck your changes...and possibly try moving them into other areas if the program is using up too many cycles (if too many instructions happen when the program is trying to draw the screen, it will jump around a bit from running over).

Link to comment
Share on other sites

Exactly...because they were using the original VGR disassembly to add the instructions in (and some of the vectors hadn't been changed to labels yet...Joel completed that). If you work with Joel's optimized source code instead of the binary, it will work fine.

 

If not, here's a binary of the NON-optimised version of what it produces. It's mostly the same as the original, except that b&w support has been taken out. So you have a bit of blank space at the end of it that you can play around with even in a binary editor (pick a spot in the program, JSR to the blank area from there...and move those instructions that were there to the end of your new routine...so they will be executed just like before).

adv_fix.zip

Link to comment
Share on other sites

I'm sorry Nukey, I'm just confused... For starters, I should be able to pull this non flicker trick off with the original adventure game no prob... I'm guessing because of the 4k, not all of the 4k was used, 10kb still exist at the end and I only need to use 4 of those 10 k. So even if I don't used the optimized code or the b/w 'less code doesn't really make a difference right? Please don't get ps'd, I'm a beginner and am just trying to understand the workings of these games.

 

AND don't get me wrong, I am trying to understand how to use distella and dasm. I mean I know how to disassemble and reassemble a game. That's kids play, it's just when I do, I'm still trying to figure out what I'm doing with the code inside... I know how to convert everything pretty much now, another questions I have is...

 

Even if I use the orginal untouched unedited adventure code and it's 10 unused k of info to pull off this non flicker trick, if I have a bunch of code like, fa01 fa02 fa03 and I want to 'stick in at the beginning' 4 lines of code and shift all the other code down, how the heck do you do that?

 

Later! - I'll be at the pc all night, so if you wanna chat lemme know... - D

Link to comment
Share on other sites

That's the whole basis of using source code. Really, all machine-language programs are working with hard addresses. You probably know that in Basic, you can number a program by 10's or so...and if you forget something...you can add it back in later (like throw in line #15 between 10 and 20). You don't have to worry about moving all the program instructions around in memory...the computer does it all for you. So if you had a hundred-line Basic program and you added a line way up top, the computer would shift all the following lines around in memory (as well as the string variables, etc.).

Not true with machine language. It expects that all the instructions are in their proper locations. If your program lines occupied addresses $F100 to $F200 for example, how would you go about adding instructions at $F180? There are byte values already sitting there. So if you pushed that forward to squeeze in some additional instructions...what do you suppose is going to happen when the program line JMP $F190 is executed? Sure, it's going to jump to a routine at $F190...but hold on a second...you pushed all that forward a bit to squeeze in those instructions. The program lines that used to be at $F190 are now at $F194...but the instruction that is doing the jump is still expecting that it is at $F190. So the program will not be jumping to the correct routine. The same goes for data tables. The program Adventure expects that tables are in a specific location. And if you add instructions into the code, all those numbers will need to be changed, so the program can find everything it needs.

This is where the source code bridges the gap between hard coding and abstract. You can simply call the addresses by labels. There is no need to figure out what is going to be at address $F190. You just fill in the instructions, using labels to jump to routines and signify data tables...and the assembler does the rest. So if you added a bit of code to one of the routines, the assembler will read through it and assign the jump label an address as soon as the rest of the program is compiled on the first pass (i.e. it just sticks a placeholder there instead of an actual memory address). Once that is finished, the assembler goes back over the program and changes all the placeholders to hard addresses on the second/third passes.

So this avoids any problems concerning "actual" addresses...because you aren't using any (besides the ones that tell the assembler what address to begin at...this is read as ORG in the assembly file, and the Ram addresses).

 

Long story short...if you add something into a binary, you need to subtract something else to sqeeze it in (at roughly the same memory location). This is what makes hacking instructions into a binary pretty challenging. Using the source code is far easier.

 

But anyway...if you have unused areas of Rom...this can be useful as well. So if you had the routine that reads:

$F100 STA VSYNC,X

$F103 DEX

$F104 BMI $F180

$F106 JSR $F230

$F109 JSR $F2A0

...and you want to add in those two instructions just after the BMI, HOW would you do it? Well, Adventure has some UNUSED bytes Waaaay at the end of it (at addresses $FFEF to $FFF9). So if you really wanted to, you could change the jump instruction at $F106 to jump to this unused space...and then hack in those instructions at the unused space, and then return back to the program :) Like so:

 

$F100 STA VSYNC,X

$F103 DEX

$F104 BMI $F180

$F106 JSR $FFEF ;this is now jumping to the unused area

$F109 JSR $F2A0

.

.

$FFEF LDA #$14 ;these are the two lines...

$FFF1 STA $D9 ;....that you needed to add

$FFF3 JSR $F230 ;now do the instruction that you moved

$FFF6 RTS ;...from $F106 and return back there

 

Don't pay any attention to the actual numbers I used...I was too lazy to look up the real ones that exist in the original binary of Adventure. But do you see how instructions can be squeezed in? You just change a few bytes to be a JSR to an unused portion of memory, and jump over there to do your routine. But you still need to keep an eye on the register and status values BEFORE you jump to your routine patch...and make sure that whatever the patch does will not conflict with what it was trying to do when the program first jumped to the patch.

 

I'm rambling...but I hope that I'm making sense. You can save yourself all these headaches just by using the source code instead...and let Dasm worry about the actual numbers used. ;)

Link to comment
Share on other sites

OHHHHHHHHH MYYYYYYYYYYYYYYYYYYYYY GGOOOOOOOOOOOOOODDDDDDDDDDDDDDDDDDDDDD IIIIIIIIIITTTTTTTTTTTTTTTTT WWOOOOOOOOOOOOOOOORRRRRRRRRRRRRRRKKKKKKKKKKKKKKKEEEEEEEEEEEEEDDDDDDDDDDDDDDDD!!!!!!!!!!!!!!!! ARRRRRRRRRGGGGGGGGGGGGGHHHHHHHHH!!!!!!!!!!!!!!!

 

Not that I had any doubt in your coding, I just can't believe I transcribed it right... After I used distella to make a source code, I made the changes I think are right, and then when I used dasm to reassemble it, I noticed that the size of the cart went up to 5K... I forgot to go and delete the 6 k of stuff and bring it back down to 4096. So I did that and pushed it through the emulator and voila! IT WORKED!!!!!!!!!

 

I'm still in denial though... Could you check what I did down below and let me know that I did everything right...?

 

I started by going to this address and then went down to the JSR LFFEF (which was originally JSR LF371) and changed it to the following:

 

LF2FB: STA VSYNC,X

DEX

BMI LF2FB

JSR LFFEF

JSR LF3D3

 

Then I went down to this section:

 

 

LFF4C: .byte $07,$F8,$FB,$C8,$00,$F1,$FA,$00,$00,$00,$FB,$FB,$C9,$00,$F1,$FA

.byte $00,$00,$00,$FE,$FB,$CA,$00,$F1,$FA,$00,$00,$00,$E8,$FD,$EB,$FD

.byte $EC,$FD,$98,$00,$00,$02,$FE,$DD,$00,$05,$FE,$CB,$00,$00,$A4,$00

.byte $A8,$00,$2E,$FD,$00,$0E,$00,$A9,$00,$AD,$00,$2E,$FD,$00,$06,$00

.byte $AE,$00,$B2,$00,$2E,$FD,$00,$00,$00,$B6,$00,$78,$FD,$79,$FD,$18

.byte $06,$00,$BC,$00,$D7,$FC,$D8,$FC,$02,$02,$07,$BF,$00,$FC,$FC,$FD

.byte $FC,$0E,$06,$00,$C2,$00,$FC,$FC,$FD,$FC,$0E,$0E,$00,$C5,$00,$FC

.byte $FC,$FD,$FC,$0E,$00,$00,$CB,$00,$CF,$00,$14,$FD,$06,$00,$00,$A1

.byte $00,$82,$FD,$83,$FD,$08,$08,$00,$B9,$00,$EF,$FD,$F0,$FD,$CB,$06

.byte $00,$B3,$00,$0E,$FE,$0F,$FE,$F4,$06,$00,$BC,$00,$FD,$FD,$FE,$FD

.byte $00,$00,$00,$00

 

I left the above code alone, but cut off the section where the empty bytes started and entered the following:

 

LFFEF: LDA #$14

LFFF1: STA $D9

LFFF3: JSR LF371

LFFF5: RTS

LFFF6: .byte $00,$00,$00,$F0,$00,$F0

.byte $00,$F0

 

Notice I made the JSR back to LF371 because that's what was at the top originally at L2F2B and then added the end of the code at the end... Please tell me I did all this right, even know the game plays fine and the title screen works, seems too good to be true! THANKS NUKEYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY! - Daryl

Link to comment
Share on other sites

Yep, you did it right. I forgot to mention that you need to take out 8 of those $00's listed at $FFEF (because that is how many bytes that little routine consists of). Keep in mind that this is kind of a last-ditch effort at hacking game code...because other things can go wrong when doing things this way (like using too many machine cycles). And it ends up making your program look like spagetti :P Anyway, glad it worked for ya. :D

 

Did you notice that huge mass of data at LFF4C? That's not just a bunch of bytes...there are some vectors and pointers in there that Distella did not translate correctly (that can cause problems later if you try to use Dasm to compile it again if you add opcodes before that point...because it won't know where those pointers ended up). Something else that can go wrong when using Distella is when a game uses the indirect JMP. The way that works is that 2 bytes in Ram hold the ADDRESS that the program jumps to (so you may not even see a value in the Rom code itself). And since Distella doesn't "know" that this is a jump destination that it should attach a label to, it won't translate the data that follows into opcodes (similar to what happened above). If you want to see an extreme example of this, try disassembling Alien (the thing is nearly ALL indirect jumps). Indirect loads (like LDA ($nn),y) will cause this to happen as well...since that is grabbing data from a point defined in Ram (i.e. again, no instruction is specifically loading the data from an address that Distella can "see"...so the reference point remains unlabelled in the disassembly it produces).

I think you can see how much of a chore it is to reverse-engineer a little 4k game like Adventure into something you can read ;)

Link to comment
Share on other sites

Hmmm...you know, I never noticed that I was credited for that  It was actually Channel2 that helped him out...you can read that solution here:  

 

Just thought I'd mention this....When I submitted the text for that page to Albert the first time, I did accidently credit you instead of Channel 2. I sent several follow up emails asking Albert to correct it that same day, and he never did. :ponder: Oh well.

 

AM

Link to comment
Share on other sites

Hmmm...you know, I never noticed that I was credited for that  It was actually Channel2 that helped him out...you can read that solution here:  

 

Just thought I'd mention this....When I submitted the text for that page to Albert the first time, I did accidently credit you instead of Channel 2. I sent several follow up emails asking Albert to correct it that same day, and he never did. :ponder: Oh well.

 

Sorry for not changing that earlier, I just updated the Hacks page as well as the entry in the store so they both say "Channel 2" instead of Nukey.

 

..Al

Link to comment
Share on other sites

Haha...no, we were just joking. There's no money to be made in programming! :lol:

 

BTW I messed up a bit when describing that patch method. If you are replacing a JSR instruction to jump to your own routine, you could change the last part of the patch routine to be a JMP instruction instead of a JSR...like this:

 

$F300 JSR LFFEF ;jump to our patch (same as before)

.

.

LFFEF:

LDA #$14

STA $D9

JMP LF371 ;Using a JMP accomplishes the same thing as a JSR/RTS combo

 

When the RTS is encountered in the routine at LF371, it will return all the way back to $F303. This trims out one byte...since the RTS isn't needed in the patch. If you wanted to hunt disassemblies for bytes that you can save, this combo is one that sometimes appears (Note: However, if the RTS instruction has a label attached to it, you can't remove it...since another instruction is jumping to it). Look around in the optimized assembly file for other examples of instructions that are not needed...look at the IF ORIGINAL lines that have no matching ELSE routines.

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