Jump to content
IGNORED

Adventure: Odyssey (New Adventure Hack)


EarthQuake

Recommended Posts

This is my first post, so I would like to say "Hi" to everyone.

 

Yesterday, I discovered these forums, and thus discovered that ATARI ROM images could be decompiled and reassembled. Since I have absolutely no grasp on Assembly machine language, I've been using a tool called Bithacker to change various aspects of the game Adventure:

 

 

[*]The three consecutive screens just outside the yellow castle have been modified to allow variation of gameplay.

 

[*]There is now a shortcut into the blue maze.

 

[*]The blue maze has been modified to acommodate the new entrance.

 

[*]The sword has been changed to more resemble (IMO) a sword and not an arrow or spear (it also faces an appropriate direction).

 

[*]I added a cross to the castle gates as decoration, and so you would get a sense of the gate raising.

 

[*]The white castle's interior has been drastically renovated for simplicity and so that you can view the inmost screen without a bridge.

 

[*]The candle halo has been rounded off for aesthetics, but also reduces the range of vision in the catacombs and dungeons.

 

All of this has been done from scratch using Bithacker. The ROM was never disassembled.

 

Plans on a future release:

 

 

[*]Adding a black dragon that roams on all skill levels. It will gaurd nothing but the chalice, and is as fast and responsive in attack as Rhindle.

 

[*]Adding a slim chance (1 in 144 or so) that in Skill 3, the vertical barriers will be placed at different spots. This is an old bug that I would like to make a feature.

 

[*]Further modifying the blue maze so that in the screen right above the original entry screen, the two small openings will be removed.

 

[*]Further modifying the white castle so that there is a horizontal line spanning across the top two screens.

 

If anyone can shed light on how I can do either of the first two points above with ease, then please share. Also, if anyone knows any other tricks or hacks with bithacker to change behaviors of the game, also share :) (Btw, I already know about the noclipping hack)

This is my first attempt at any hack, so don't be overly destructive if I've done something that everyone else has done :(

 

Questions? comments? Ask me!

odyssey.zip

Link to comment
Share on other sites

Machine-language coding...the only way. The ram pointers for everything is expected to fall in a given pattern. For example, all the ram pointers for the dragons are grouped together as 15 consecutive bytes...5 bytes each (their horizontal and vertical position, the screen number they are in, the direction that they are moving, and their state -alive, dead, and biting). Fortunately, there is some ram locations that the original game does not use...so the existing ram locations would need to be reorganized to make room for the added dragon (no trouble at all to get it to move following that, since the dragon routine is a loop that handles all of them). In addition, you'd need to add in tables for this new dragon (data lines that hold what it's GFX look like, what objects it guards, etc)...and edit existing ones so that other objects can interact with it (like the bat's...so it can carry it).

 

Look here for the optimized version of Adventure that was commented by Joel Park.

http://atariage.com/forums/viewtopic.php?t=34499

 

That version has 313 bytes free. If more space is needed, you can even turn Adventure into an 8k game...

http://atariage.com/forums/viewtopic.php?t=50191

That has over 4 kbytes of memory free.

 

That's about as close to "English" that they are going to get. For the rest, you are going to have to dive into the maddening realm of assembly programming ;)

 

If you just want to have fun instead of having to learn all that, you could just use one of the 8k hacks that I already did...which added new dragons, a second bat, additional castles, and a lot more rooms...

http://atariage.com/forums/viewtopic.php?t=47783

Link to comment
Share on other sites

Although my thread was not originally intended to ask about how to get started with revamping Adventure, I'm especially thankful that you challenged me to look at the Adventure source.

A few hours into reading through the source and comments, I discovered how to modify some game behaviors by changing hexadecimal values. It's still unknown to me as to where the rest of the values (that almost every line has) comes from, but I think I'm well on my way on uncovering something new.

 

Can I include additional screens by inserting screen definitions after the other screens and adding them to the room table? It seems each screen has a hexidecimal value which is used in the room table to show how it connects to other rooms, where is this number defined?

 

Also, can you elaborate on the following piece of code:

; here we count the unused bytes:

 IF ORIGINAL

   .ds 171, 0

 ELSE

   .ds 271, 0  ; I stopped at 100 extra bytes, you will find a lot more :-)

 ENDIF

I understand you must tell the program how many unused bytes are remaining, but I do not get what I'm supposed to change here in regards to adding or deleting code.

 

Sorry for so many questions, I hope I'm not being too much of a bother. Thanks! :D

Link to comment
Share on other sites

All that line does is fill up the remaining area of memory with zeros. You don't really need it at all. As long as the lower ORG statement is still there to keep the start vector in place, you can just comment out those lines (add a semicolon to the beginning of each line)...

 

Commenting them out using semicolons...

; here we count the unused bytes: 
;  IF ORIGINAL 
;    .ds 171, 0 
;  ELSE 
;    .ds 271, 0  ; I stopped at 100 extra bytes, you will find a lot more :-) 
;  ENDIF 

 

If that is not done and you add in more code, Dasm will report that you ran out of memory.

 

Adding rooms is simple. Just copy an existing line in the room matrix, paste it to the bottom of the matrix, and change the variables (like which GFX to use, map directions, etc.). As long as a room "points" to the added room in it's directional info, you can reach it. The rooms stop at $1E...so the new room would be numbered $1F (and upward if you add more rooms). 64 rooms is the maximum number of them (numbered $00 to $3F). By hacking the game routine slightly in the 8k builds, I had made the upper limit be 128 rooms (numbered $00 to $7F). Because the program uses the high bit to determine if a room has differences in each game selection, it's not possible to number them $80 or upward.

 

Note: when compiling the game, you should change the ORIGINAL = 1 line near the top to ORIGINAL = 0...this will take advantage of all the program optimizations. And don't forget to fix the red dragon...

 

This part...

MoveRedDragon: 

      LDA    #<RedDragMatrix 

      LDA    #$03

 

...should read...

MoveRedDragon: 

      LDA    #<RedDragMatrix 

      LDY    #$03

Link to comment
Share on other sites

Note: when compiling the game, you should change the ORIGINAL = 1 line near the top to ORIGINAL = 0...this will take advantage of all the program optimizations. And don't forget to fix the red dragon...

 

Wow, thanks greatly, I would have never noticed that.

 

One thing, when I asked how to add rooms I should have been more specific. I want to add different layouts and connect to them via original rooms. I want to do this so I can remove the sharing between rooms, so that when I edit one room it doesn't affect another somewhere else in the level.

 

Can I just add a definition:

 

;Side Corridor

SideCorridor:

      .byte $F0,$FF,$0F         ;XXXXXXXXXXXXXXXX        RRRRRRRRRRRRRRRR

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $F0,$FF,$0F         ;XXXXXXXXXXXXXXXX        RRRRRRRRRRRRRRRR

 

like that, and refer to it when I copy/paste an existing line in the room matrix? Sorry if I'm using the wrong terminology :roll:

Link to comment
Share on other sites

BTW the hex value of the room is really just the value of where that data is in the matrix itself. You'll see that the lowest line in the matrix reads like so...

 

       .byte <BelowYellowCastle,>BelowYellowCastle,  $66,$0A,$21,$06,$01,$06,$03     ;1E; Name Room                              Purple

 

That room is the special signature screen...and since it's the 31st room listed in the matrix, it's hex value is $1E. If you wanted to add a room, you could do it like this...

 

 

First, add in GFX for the new room. This part can be skipped if you are reusing GFX from one of the previous rooms. But here's how you add one. Just add in a table of bytes...

 

;32nd room (room $1F)

CustomRoom1:

      .byte $F0,$FF,$FF;XXXXXXXXXXXXXXXXXXXXRRRRRRRRRRRRRRRRRRRR

      .byte $30,$00,$00;XX                                    RR

      .byte $30,$00,$00;XX                                    RR

      .byte $F0,$FF,$FF;XXXXXXXXXXXXXXXXXXXXRRRRRRRRRRRRRRRRRRRR

      .byte $30,$00,$00;XX                                    RR

      .byte $30,$00,$00;XX                                    RR

      .byte $F0,$FF,$0F;XXXXXXXXXXXXXXXX        RRRRRRRRRRRRRRRR

There's the GFX for a new room, that has a long wall in the middle of the screen (the upper portion can only be reached by the bridge).

 

Now you'll need to add it to the matrix...so paste a new line below the "name" room definition

       .byte <CustomRoom1,>CustomRoom1,  $00,$00,$21,$1F,$1F,$1E,$1F;Custom Room $1F - Black

 

In the data...the first 2 bytes point to the GFX (the address of CusomRoom1 in this example). The next 2 bytes are the color of the room...in color mode and in B&W mode. The next value $21 is the "control" value...which determines how the GFX are to be displayed, whether the room has barriers, and if the room includes the invisible surround. And the last 4 bytes are the directional info...which is the room number of where you will end up when exiting this room (up, right, down, left).

 

Now that a room has been added...it will still be unaccessable until you edit the existing map to include it (at least one room must have the new room number $1F in it's directional values). As an example, let's just hack the signature room, so that when moving UP from it, it will now place you in the new room. Change the first directional value (Up) in the "name room" line to be $1F...

       .byte <BelowYellowCastle,>BelowYellowCastle,  $66,$0A,$21,$1F,$01,$06,$03     ;1E; Name Room                              Purple

 

There ya go.

Link to comment
Share on other sites

Can I just add a definition:

 

;Side Corridor

SideCorridor:

      .byte $F0,$FF,$0F         ;XXXXXXXXXXXXXXXX        RRRRRRRRRRRRRRRR

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $F0,$FF,$0F         ;XXXXXXXXXXXXXXXX        RRRRRRRRRRRRRRRR

 

like that, and refer to it when I copy/paste an existing line in the room matrix? Sorry if I'm using the wrong terminology   :roll:

 

Yep. One other bug that crops up is when a room's definition table crosses over a "page" in memory. You'll get little pixel skews on the screen when this happens. The way to avoid it is to insure that the room's data table does NOT cross a page. It's kind of hard to explain, and the bug isn't serious...so I won't go into it (those other threads do anyway).

 

To save memory in the original game, you'll see that a number of rooms have this "sharing" going on. Just copy/paste the lines that are shared if you wish to "unshare" them.

Link to comment
Share on other sites

An example of unsharing....

 

original...

;Left of Name Room

LeftOfName:

      .byte $F0,$FF,$FF;XXXXXXXXXXXXXXXXXXRRRRRRRRRRRRRRRRRR

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00


;Below Yellow Castle

BelowYellowCastle:

      .byte $F0,$FF,$0F;XXXXXXXXXXXXXX        RRRRRRRRRRRRRR   **Line Shared With Above Room ----^

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $F0,$FF,$FF;XXXXXXXXXXXXXXXXXXRRRRRRRRRRRRRRRRRR

 

 

unshared...

;Left of Name Room

LeftOfName:

      .byte $F0,$FF,$FF;XXXXXXXXXXXXXXXXXXRRRRRRRRRRRRRRRRRR

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $F0,$FF,$0F;XXXXXXXXXXXXXX        RRRRRRRRRRRRRR


;Below Yellow Castle

BelowYellowCastle:

      .byte $F0,$FF,$0F;XXXXXXXXXXXXXX        RRRRRRRRRRRRRR

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $00,$00,$00

      .byte $F0,$FF,$FF;XXXXXXXXXXXXXXXXXXRRRRRRRRRRRRRRRRRR

Link to comment
Share on other sites

Yep...that's the glitches I was referring to. Try using more ORG statements in the code...and fill up the memory between them so that no data crosses pages. The room index table is the largest one...and it WILL cross a page, so I'd leave that one last (keep the table just before the vectors...just before that ORG $FFFA line). Also to insure that the game will be playable on a Supercharger, you'll need to keep $FFF8 and $FFF9 unused.

Example...


ORG $FA00


;256 bytes of data here



ORG $FB00


;256 bytes of data here



ORG $FC00


;256 bytes of data here



ORG $FD00


;256 bytes of data here



ORG $FE00


;506 bytes of data here...with the room index crossing the page at $FF00



ORG $FFF8

      .word 0,0,START,0

 

Paste that onto the very end of the assembly...and start filling them in. Grab tables one-by-one and insert them between the ORG's...so that nothing crosses a page. If all the room definitions are unshared, you can fit 12 of them in a single page (21 bytes each...with 4 bytes left over). There are a few data tables that are only 4 bytes long to take up the slack.

Link to comment
Share on other sites

Not quite sure what you want me to do.

 

I need to take all the code and move it between the ORG statements? And there needs to be exactly 256 bytes between each one? What if there is less than 256 bytes? How am I supposed to know how many bytes a line takes up?

 

Ugh, sorry if all this sounds "newbish", but I was first introduced to all this yesterday. :P

 

I wonder why this hasn't already been done before they released this "optimized" code...

Link to comment
Share on other sites

Not quite sure what you want me to do.

 

I need to take all the code and move it between the ORG statements?

Not coded instructions...just the data only (all of those .byte lines).

 

 

 

And there needs to be exactly 256 bytes between each one?

That's what you would shoot for.

 

 

 

What if there is less than 256 bytes?

It would still compile and run normally. The goal is to pack 256 bytes' worth of data between each page so that all of the free memory can be better spent in the program area...and that all instructions that load the data use consistant amounts of cycle time (when reading a bit of data from a table that crosses a page, the instruction will take 1 cycle longer to complete. That's how come the pixel skews...that 1 cycle is the cause).

 

 

 

How am I supposed to know how many bytes a line takes up?

The bytes are all there...so you could count them if you really wanted to. A better way is to just keep packing data between 2 ORG's until Dasm reports that has gone over when you compile. It will state something like...

 

segment: code fff8 vs. current org: 10008

 

In this case, the ORG statement at the end (ORG $FFF8) has too many bytes preceding it. What you do is take the current value 10008 and subtract the first. Both numbers are in HEX. So $10008 - $FFF8 = $10... which is decimal 16. 16 bytes too many. So in that last page, you'd have to find a table of 16 bytes or more and move it someplace else higher in memory.

It's especially easy to do if you comment out all of the ORG statements except the 2 that you are trying to fill in...then just keep shoving data between them until Dasm reports an error (at which point, you know exactly how many bytes attempted to cross the page). Then grab that number of bytes, move upward, and do the same thing with an ORG that is on the next preceding page in memory :)

 

 

I wonder why this hasn't already been done before they released this "optimized" code...

The purpose of the optimized code was to free up memory...not necessarily move things around so that nothing crosses pages. As you add in bitmaps, data, and code of your own...this would also affect it anyway (for example, the bat's matrix would need to be longer if you add more objects that it is supposed to interact with...the room matrix will be longer if you add rooms).

Link to comment
Share on other sites

I moved most of the tables between the ORG statements, changed the ORIGINAL to 0, and "fixed the red dragon".

 

I get this when compiling with DASM:

 

DASM V2.20.07, Macro Assembler ©1988-2003

segment: INITIAL CODE SEGMENT fa00                    vs current org: fa7f

source.asm (2336): error: Origin Reverse-indexed.

Aborting assembly

 

Did I put the ORG statements in the right place?

 

Assuming that all the remaining tables might not go over 256 bytes, I left them throughout the code and moved just the graphics between the tables.

I know it's not efficient, but I only plan on adding so many rooms.

 

Here is my source code:

source.zip

Link to comment
Share on other sites

Is it okay to leave some tables, mainly the ones that are scattered throughout the code, between F000 and FA00? I remember reading that if the dragon matrices are put on seperate pages, everything will not work right. I figured I could just leave them there as I have not been getting page overflow errors on the F000 page.

 

Also, just out of curiosity, why is there not a page between FE00 and FF00? Of course there isn't an FF00, but why? Theoretically, it would give me 256 more bytes to work with. :wink:

Link to comment
Share on other sites

I didn't number FF00 because that's where I described where the room index was (which does spill over). You don't have to have it there if you don't want to...but no matter what page it resides on, it's going to cross the page (because it's over 256 bytes in length). There's a tag at $FE00 and one at $FFF8...and room for over 500 bytes between them. And the majority of the tables are OK to have cross pages...but as long as I was describing how to fix the room bitmaps so that artifacts disappear, I figured to go the whole 9 yards and describe how to avoid page crossing for anything. And you are correct that there is 127 bytes too many before $FA00...so you just need to shift things around a little bit.

Link to comment
Share on other sites

Nukey Shay, I appreciate you walking me through this, even though I got a bit excited/frustrated and passed over some helpful points you made. I successfully compiled the source (also fixing the red dragon) without any of the artifacts I mentioned.

I did have to comment these lines out for it to compile though:

 


ORG $FFF8

      .word 0,0,START,0

 

Hope it was nothing important. ^_^

I will now start applying the same changes I made in Odyssey to this fresh new slate.

 

Thanks for all your help, Nukey.

 

By the way, you can grab the reorganized source below. The source has been organized in a way so that groups of similar things are together to make it more readable and I've also listed below how many bytes are still available in each page.

 

$F000 to $FA00: Not sure... lol

$FA00 to $FB00: 22 bytes left (I tried)

$FB00 to $FC00: 0 bytes left!

$FC00 to $FD00: 4 bytes left if you add two room gfx definitions

$FD00 to $FE00: 4 bytes left if you add two room gfx definitions

$FE00 to $F888: Exactly 506 bytes used like you said (how strange was that O_o)

newsource.zip

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