Jump to content
IGNORED

Turning Adventure into an 8k game...


Nukey Shay

Recommended Posts

I recieved a couple requests for info on this already...so I'll just post the files that I used.

 

Adventure was easy to double...since all of the display routines are right in the first 256 bytes of the program. So all that needed to be done was grab those routines and paste them into a new assembly...along with any GFX...and the Curr and Info tables pertaining to them. Then they can be completely removed from the main code...cutting it down in size to just over 2k 8) The free area in the display bank is well over 2k.

 

At the top of each file, a bankswitch instruction is placed in to jump back and forth between the display and the main program.

 

 

Compiling the roms...

They must be done independantly...and the 4k binaries pasted together to create the 8k rom. What you'll need to do is compile the first part with the -s switch added (so Dasm will create an equate table for you that can be added to the second part). I dunno any other way of doing it, but it's not that much of a pain. Instructions...

 

Step 1:

dasm ad1.asm -f3 -seq.txt -o1

This command will compile the first half of the game. All of the addresses where each graphics object "lives" in the first bank will be put into a seperate text file called eq.txt, and the binary will simply be called "1"

 

Step 2:

Open that eq.txt file. You'll see all of the labels that were used in the first assembly (equates)...as well as every address where those labels compiled to. You'll need to copy every label/address identifying GFX tables, and paste that info to the top of the second assembly file. You'll see labels for ram locations ® and program lines as well...these do not need to be transferred. Just the GFX tags. Once pasted, insert an "= $" before each address, and then save it. Open the second assembly and look at the top for an example.

 

Step 3:

Now that the second assembly "knows" where everything is, you can just compile it to create the 2nd 4k binary...

 

dasm ad2.asm -f3 -o2

 

 

 

Now you have both 4k binaries...and you can join them together...

 

copy /b 1+2 adhack.bin

 

This copy command uses the binary mode to combine both files (1 and 2) into a new file (adhack.bin). Once combined, you can open and run it using any 2600 emulator :)

 

 

Things to be aware of...

Make sure that your screen GFX bitmaps do not cross page boundries if you add additional ones...or you'll end up with small pixel "skews" on some of them (because it will take 1 cycle longer for the kernal to access them). This problem had me stumped for awhile until I got wise

These days, I try to make sure that all data never crosses pages. When assembling, I just add ORG tags for each page and fill them up...working my way from $FF00 to lower addresses. When Dasm reports that I go over, I just remove the number of bytes that it says and put them higher up in the assembly file...and then try again. Fortunately, the map data lines do not matter if they cross a page (so you can have up to 64 screens in the original optimized code).

 

The assembly files below have a few ORG tags added to avoid page crossing. These can be removed as you fill in memory...but it's a good idea to keep the very last one (so that Dasm will warn you if you go over the 4k limit for that bank). All of the memory between ORG tags has not been exhausted completely.

 

Adding rooms to the program is a cinch...just copy/past an existing line in the room data matrix found near the end of the 2nd assembly, alter the variables, and voila...a new room has just been added! The current code allows for a maximum of 64 rooms, but the program can be altered slightly to allow for more than that. The new rooms will not be accessable until the room link data is altered to "point" to them. 5 additional rooms are added for an example (the "Custom" rooms).

 

Adding objects, castles, dragons, etc. is more complex. You'll need to reorganize the ram used by the existing objects to insert free ram to hold the values used by the added ones. All dragons and castle gates, for example, must be sequential ram locations in memory...and the last object must be the "null" sprite.

Added objects will require 3 bytes of ram each...the room number and X/Y locations. Added castle gates will require 1 byte of ram (to hold the state it's in)...and added dragons will require 5 bytes of ram (3 bytes like objects, plus variables to hold it's state and movement). The bat requires 7 bytes...the same as the above plus 1 byte to hold the object that the bat is carrying and 1 byte to indicate how long it's been holding it.

Of course, the routines will need to be altered to handle new gates, dragons, or bat. Other objects require very little changes (aside from any special coding to handle their functions).

Of course, any additional game sprites will need bitmap data added to the first assembly...and any changes to the first assembly must be followed by copying the equates to the second assembly.

 

Free ram: locations $E7 to $F7 are unused by the original game (17 bytes). These can be used immediately in any way that you want. An additional 2 bytes can be reclaimed by changing the routines that include the "Temp" location $D8 and the input counter $E6.

8k_adventure_assemblies.zip

Link to comment
Share on other sites

  • 4 months later...

'Course...you already know about sharing data between multiple tables. In this version, I shared a couple more bytes of ram memory too (for a total of 22 free - $E5 to $FA). All the variables have been tagged, and all of the object-specific constants as well...so adding objects should be easy enough for even novice users to pick up on. I moved all object ram past everything else. Be sure to read the comments...and take note about how many bytes of ram each type of object requires.

adventure_8k.zip

Link to comment
Share on other sites

BTW very small JMP's or conditional branches that are always taken can be replaced with a BIT opcode ($24 to skip 1 byte, $2C to skip 2 bytes). Here's another one that was missed before...

 

DealWithLeft_2:

      CPX    #PlayerRoom   ;Are we dealling with the ball?          ;2

      BEQ    DealWithLeft_3;If so Branch.                           ;2

      LDA    #$9A          ;Set new X coordinate for the others.    ;2

      JMP    DealWithLeft_4;                                        ;3



DealWithLeft_3:

      LDA    #$9E          ;Set new X coordinate for the ball.      ;2



DealWithLeft_4:

 

...can be replaced with...

 

DealWithLeft_2:

      CPX    #PlayerRoom   ;Are we dealling with the ball?          ;2

      BEQ    DealWithLeft_3;If so Branch.                           ;2

      LDA    #$9A          ;Set new X coordinate for the others.    ;2

      .byte $2C            ;using BIT to skip ahead 2 bytes         ;4



DealWithLeft_3:

      LDA    #$9E          ;Set new X coordinate for the ball.      ;2



DealWithLeft_4:

 

That saved 2 bytes.

Link to comment
Share on other sites

Here's something that I'm not too sure about...but Z26 doesn't have a problem with...

 

;Preform VSYNC

DoVSYNC:

      LDX    INTIM              ;Get Timer Output                             ;4

      BNE    DoVSYNC            ;Wait for Time-Out                            ;2

      LDA    #$02               ;                                             ;2

      STA    WSYNC              ;Wait for horizonal blank.                    ;3

      STA    VBLANK             ;Start Vertical Blanking.                     ;3

      STA    WSYNC              ;Wait for horizonal blank.                    ;3
;       STA    WSYNC              ;Wait for horizonal blank.                    ;3
;       STA    WSYNC              ;Wait for horizonal blank.                    ;3

      STA    VSYNC              ;Start verticle sync.                         ;3

      STA    WSYNC              ;Wait for horizonal blank.                    ;3

      STA    WSYNC              ;Wait for horizonal blank.                    ;3

      STA    WSYNC              ;Wait for horizonal blank.                    ;3

      STX    VSYNC              ;End Vertical sync.                           ;3
;       LDA    #$2A               ;Set clock interval to                        ;2

      LDA    #$2C               ;Set clock interval to                        ;2



      STA    TIM64T             ;Countdown next frame.                        ;4

      RTS                       ;                                             ;6

 

Eliminating 2 WSYNC's there allows INTIM to be bumped up twice. That might help for those rumbles.

post-222-1095252699_thumb.jpg

Link to comment
Share on other sites

I'm finding a lot of unnecessary branches and jumps (like ones that go directly to an RTS instruction...why waste 3 bytes with a JMP just to go to a one-byte RTS?). In addition, some routines can be cleaned up by editing the order in which checks are done...like this for the surround...

 

Surround_2:

      LDA    PlayerRoom         ;Get the Current Room.                        ;3

      STA    SurroundR          ;And store as the Invisible Surrounds.        ;3

      LDA    PlayerY            ;Get the Ball's Y Coordinate.                 ;3

      CLC                       ;                                             ;2

      ADC    #$0E               ;Adjust for Surround.                         ;2

      STA    SurroundR+2        ;      and store as surround's Y coordinate.  ;3

      LDA    PlayerX            ;Get the Ball's X Coordinate.                 ;3

      SEC                       ;                                             ;2

      SBC    #$0E               ;Adjust for Surround,                         ;2

      BPL    Surround_4         ;00 to 7F OK                                  ;2

      CMP    #$F0               ;Is it close to the right edge?               ;2

      BCC    Surround_3         ;Branch if not.                               ;2

      LDA    #$01               ;Flick surround to the                        ;2

      .byte  $2C                ; opcode for BIT.w (Skip next 2 bytes)        ;4

Surround_3:

      LDA    #$7F               ;If higher than $7F, keep boundry on the right;2

Surround_4:

      STA    SurroundR+1        ;      and store as surround's X coordinate.  ;3

      RTS                       ;                                             ;6

 

Dealing with the vertical location first trims out the reloading of the X postion when doing the compare...and allows the program just to fall through when saving it (there's 4 bytes). Altering the right-side comparison to deal with only negative values gets rid of an extra comparison and use a BIT opcode to branch (saving 4 more). In addition, the program will no longer give a "hint" about what is on the other side of the screen (using $81 was just a little too high...$7F works better).

Link to comment
Share on other sites

Hi EarthQuake! I like the freshness of your hack!

 

You'd be surprised at how useful small optimizations are for even 8k. At one point in HA2 I had used up all my free bytes for the second bank, but then I figured out how to bankswitch the randomization routine to the first bank, freeing up more bytes for other things. Also, saving cycle times for 8k Advent is really important because of possible screen jitters...

 

Thanks Nukey for sharing with us your coding talents! :)

Link to comment
Share on other sites

Hi EarthQuake!  I like the freshness of your hack!

 

Thanks, I played your hack as well; it's probably the only adventure hack that I find decent enough to play. All those others are either extremely hard, or extremely incoherent. They just don't make sense half the time. Plus, one gets sick of all the graphics hacks after a while.

The version of Odyssey that you played (or that I assume you played), was put together in one day, might I add, my first day of hacking any Atari ROM. The version I have now (unreleased) is 50% larger and has been tweaked extensively to allow for a balanced, classic experience. I should have something playable by tomorrow.

 

I hope you will play it and love it as well! :)

Link to comment
Share on other sites

The version of Odyssey that you played (or that I assume you played), was put together in one day, might I add, my first day of hacking any Atari ROM. The version I have now (unreleased) is 50% larger and has been tweaked extensively to allow for a balanced, classic experience. I should have something playable by tomorrow.

 

I hope you will play it and love it as well!  :)

Very impressive! I'm looking forward to your updates! Also, thanks for your compliments! :)
Link to comment
Share on other sites

So are these optimizations you are currently making also applicable to the 4k version? Because in my opinion, the 4k source needs the extra bytes more than the 8k version does. I still have 3k left in Odyssey, and that's after adding 40-some room graphics tables.  ;)

 

Yes, the 4k and 8k games are virtually identical as far as coding is concerned (just one stretch of little more than 200 bytes' worth of code was transferred to the 1st bank in the 8k game). The above will work in either version...though you might want to just stick with the 8k build...where you never have to worry about running low on space (unless you're a complete madman like atwwong!). :D Using 8k, you can make all the rooms unique, make the dragons all look different, etc...with no changes to the program code itself (i.e. just editing or adding data lines).

 

 

Current version...$D100 to $D8FF free in bank 1, $F7FB to $FCDD free in bank 2. All the room bitmaps have been unshared (including the castles), and I altered the room descriptions a bit (makes it easy to edit them in the directional matrix). I also edited the routine that calculates the room address (so that up to 128 rooms can be used). This could be changed to 256 rooms if the RoomDiffs routine is killed...but then no differences would exist between game levels. To add rooms, just add a line to the matrix at the end of the file...and then create a bitmap in bank1.

adventure_8k.zip

Link to comment
Share on other sites

I'm more interested in adding new objects like dragons, porticullises, keys, etc... Is there any chance in the near future that you could write some descriptive tutorials/guides on how to add these?

 

With the growing size of my world map, I'm starting to fear that the difficulty will go down, because the dragons have more places to roam around, leaving fewer chances they will meet the player. Another dragon would balance this offset. :wink:

Link to comment
Share on other sites

Sure. Keys/castles can be added by squeezing in 4 bytes of ram into the varible table. Let's call the new one the red castle...with a red key. First look at the ram assignments at the top...

 

;object variables...

SurroundR     =  $B1;(3 bytes)

DotR          =  $B4;(3 bytes)


;all dragons must be consecutive

RDragonR      =  $B7;(5 bytes)

YDragonR      =  $BC;(5 bytes)

GDragonR      =  $C1;(5 bytes)



MagnetR       =  $C6;(3 bytes)

SwordR        =  $C9;(3 bytes)

ChaliseR      =  $CC;(3 bytes)

BridgeR       =  $CF;(3 bytes)


;all keys must be consecutive

YKeyR         =  $D2;(3 bytes)

WKeyR         =  $D5;(3 bytes)

BKeyR         =  $D8;(3 bytes)


;all gates must be consecutive

YGateR        =  $DB

WGateR        =  $DC

BGateR        =  $DD



BatR          =  $DE;(7 bytes)

 

First, you'll need to add 2 variables...1 for the key (example: RKeyR), and the gate it opens (RGateR). Add them below the existing sets of keys/gates...

 

;object variables...

SurroundR     =  $B1;(3 bytes)

DotR          =  $B4;(3 bytes)


;all dragons must be consecutive

RDragonR      =  $B7;(5 bytes)

YDragonR      =  $BC;(5 bytes)

GDragonR      =  $C1;(5 bytes)



MagnetR       =  $C6;(3 bytes)

SwordR        =  $C9;(3 bytes)

ChaliseR      =  $CC;(3 bytes)

BridgeR       =  $CF;(3 bytes)


;all keys must be consecutive

YKeyR         =  $D2;(3 bytes)

WKeyR         =  $D5;(3 bytes)

BKeyR         =  $D8;(3 bytes)

RKeyR


;all gates must be consecutive

YGateR        =  $DB

WGateR        =  $DC

BGateR        =  $DD

RGateR



BatR          =  $DE;(7 bytes)

 

Next, you'll have to assign ram locations to those variables. Start at the first line that has changed (the key in this example), and begin correcting the ram locations downward. Ram location $DB in this case would belong to the Red key (not the yellow gate)...and just follow it downward. Since keys use 3 bytes of ram, the gate would begin at the ram location 3 bytes later...

 

;object variables...

SurroundR     =  $B1;(3 bytes)

DotR          =  $B4;(3 bytes)


;all dragons must be consecutive

RDragonR      =  $B7;(5 bytes)

YDragonR      =  $BC;(5 bytes)

GDragonR      =  $C1;(5 bytes)



MagnetR       =  $C6;(3 bytes)

SwordR        =  $C9;(3 bytes)

ChaliseR      =  $CC;(3 bytes)

BridgeR       =  $CF;(3 bytes)


;all keys must be consecutive

YKeyR         =  $D2;(3 bytes)

WKeyR         =  $D5;(3 bytes)

BKeyR         =  $D8;(3 bytes)

RKeyR         =  $DB;(3 bytes...i.e. $DB, $DC, and $DD)


;all gates must be consecutive

YGateR        =  $DE

WGateR        =  $DF

BGateR        =  $E0

RGateR        =  $E1



BatR          =  $E2;(7 bytes)

 

 

The program also needs to know where it's offset in the matrix will be...and the set of "constants" just below this area will need them added. Here's the original...

 

;constants...


;Object numbers:
;these are used to calculate the offsets of the object table

SurroundNumber =  SurroundData - Objects;($00)

YGateNumber    =  YGateData - Objects   ;($08)

WGateNumber    =  WGateData - Objects   ;($10)

BGateNumber    =  BGateData - Objects   ;($18)

AuthorNumber   =  AuthorData - Objects  ;($20)

NumberNumber   =  NumberData - Objects  ;($28)

RDragonNumber  =  RDragonData - Objects ;($30)

YDragonNumber  =  YDragonData - Objects ;($38)

GDragonNumber  =  GDragonData - Objects ;($40)

SwordNumber    =  SwordData - Objects   ;($48)

BridgeNumber   =  BridgeData - Objects  ;($50)

YKeyNumber     =  YKeyData - Objects    ;($58)

WKeyNumber     =  WKeyData - Objects    ;($60)

BKeyNumber     =  BKeyData - Objects    ;($68)

BatNumber      =  BatData - Objects     ;($70)

DotNumber      =  DotData - Objects     ;($78)

ChaliseNumber  =  ChaliseData - Objects ;($80)

MagnetNumber   =  MagnetData - Objects  ;($88)

NullNumber     =  NullData - Objects    ;($90)

 

...and here's where they've been added...taking care that they are inserted at the proper positions...

 

;constants...


;Object numbers:
;these are used to calculate the offsets of the object table

SurroundNumber =  SurroundData - Objects;($00)

YGateNumber    =  YGateData - Objects   ;($08)

WGateNumber    =  WGateData - Objects   ;($10)

BGateNumber    =  BGateData - Objects   ;($18)

RGateNumber    =  RGateData - Objects   ;<- new gate

AuthorNumber   =  AuthorData - Objects  ;($20)

NumberNumber   =  NumberData - Objects  ;($28)

RDragonNumber  =  RDragonData - Objects ;($30)

YDragonNumber  =  YDragonData - Objects ;($38)

GDragonNumber  =  GDragonData - Objects ;($40)

SwordNumber    =  SwordData - Objects   ;($48)

BridgeNumber   =  BridgeData - Objects  ;($50)

YKeyNumber     =  YKeyData - Objects    ;($58)

WKeyNumber     =  WKeyData - Objects    ;($60)

BKeyNumber     =  BKeyData - Objects    ;($68)

RKeyNumber     =  RKeyData - Objects    ;<- new key

BatNumber      =  BatData - Objects     ;($70)

DotNumber      =  DotData - Objects     ;($78)

ChaliseNumber  =  ChaliseData - Objects ;($80)

MagnetNumber   =  MagnetData - Objects  ;($88)

NullNumber     =  NullData - Objects    ;($90)

 

If you noticed...there are 2 varibles up there that we haven't defined yet (RGateData and RKeyData). I'll get to those in a minute. You don't need to change the ($numbers) after the comments...those were only there to detail what they were originally :)

 

Just below this area, you'll need to tell the program how many gates there are now...and that line looks like this:

 

Gates          =  $02;# of castle gates - 1

 

That line will now be:

 

Gates          =  $03;# of castle gates - 1

 

OK...now scroll all the way down to the area tagged "Objects". This is the object matrix...and everything in the game has a group of 8 bytes dedicated to it...

 

Objects:
;NOTE: SurroundData must be listed first, NullData last.

SurroundData:     ;<-these "Data" tags used up top to define "Number" constants
;Offset 0 : Low byte object information (moveable stuff)
;Offset 1 : High byte object information (moveable stuff)
;Offset 2 : Low byte to object's current state
;Offset 3 : High byte to object's current state
;Offset 4 : Low byte list of states
;Offset 5 : High byte list of states
;Offset 6 : Color (if odd, object is to Flash)
;Offset 7 : Size of object ($00 = small, $07 = large)

Store1:

      .byte <SurroundR                ;#0 Invisible Surround Offsets

Store2:

      .byte >SurroundR                ;1

Store3:

      .byte <SurroundCurr             ;2 Current state location

Store4:

      .byte >SurroundCurr             ;3

Store5:

      .byte <SurroundStates           ;4 list of states location

Store6:

      .byte >SurroundStates           ;5

Store7:

      .byte $28                       ;6 color (Orange)

Store8:

      .byte $07                       ;7 size (Large)



YGateData:

      .word PortInfo1,YGateR,PortStates

      .byte $00,$00;Yellow castle Gate #$01  Yellow, Small



WGateData:

      .word PortInfo2,WGateR,PortStates

      .byte $00,$00;White castle Gate  #$02  White, Small



BGateData:

      .word PortInfo3,BGateR,PortStates

      .byte $00,$00;Black castle Gate  #$03  Black, Small



AuthorData:

      .word AuthorInfo,AuthorCurr,AuthorStates

      .byte $CB,$00;Author Signature   #$04  Flash, Small



NumberData:

      .word NumberInfo,Level,NumberStates

      .byte $C8,$00;Number token       #$05  Green, Small



RDragonData:

      .word RDragonR,RDragonR+4,DragonStates

      .byte $36,$00;Red Dragon         #$06  Red, Small



YDragonData:

      .word YDragonR,YDragonR+4,DragonStates

      .byte $1A,$00;Yellow Dragon      #$07  Yellow, Small



GDragonData:

      .word GDragonR,GDragonR+4,DragonStates

      .byte $C8,$00;Green Dragon       #$08  Green, Small



SwordData:

      .word SwordR,SwordCurr,SwordStates

      .byte $1A,$00;Sword              #$09  Yellow, Small



BridgeData:

      .word BridgeR,BridgeCurr,BridgeStates

      .byte $66,$07;Bridge             #$0A  Purple, Large



YKeyData:

      .word YKeyR,KeyCurr,KeyStates

      .byte $1A,$00;Yellow Key         #$0B  Yellow, Small



WKeyData:

      .word WKeyR,KeyCurr,KeyStates

      .byte $0E,$00;White Key          #$0C  White, Small



BKeyData:

      .word BKeyR,KeyCurr,KeyStates

      .byte $00,$00;Black Key          #$0D  Black, Small



BatData:

      .word BatR,BatR+4,BatStates

      .byte $00,$00;Bat                #$0E  Black, Small



DotData:

      .word DotR,DotCurr,DotStates

      .byte $08,$00;Dot                #$0F  Grey, Small



ChaliseData:

      .word ChaliseR,ChalliseCurr,ChalliseStates

      .byte $CB,$00;Chalise            #$10  Flash, Small



MagnetData:

      .word MagnetR,MagnetCurr,MagnetStates

      .byte $00,$00;Magnet             #$11  Black, Small



NullData:

      .word NullR,NullCurr,NullStates

      .byte $00,$00;Null object        #$12  Black, Small

 

Just as before, add the new key below the existing ones, and the new gate below it's existing ones. You can just use a copy/paste/edit to do this...but be sure to change the variables in the .word lines. If you want to, you can edit the color and size as well...

 

Objects:
;NOTE: SurroundData must be listed first, NullData last.

SurroundData:     ;<-these "Data" tags used up top to define "Number" constants
;Offset 0 : Low byte object information (moveable stuff)
;Offset 1 : High byte object information (moveable stuff)
;Offset 2 : Low byte to object's current state
;Offset 3 : High byte to object's current state
;Offset 4 : Low byte list of states
;Offset 5 : High byte list of states
;Offset 6 : Color (if odd, object is to Flash)
;Offset 7 : Size of object ($00 = small, $07 = large)

Store1:

      .byte <SurroundR                ;#0 Invisible Surround Offsets

Store2:

      .byte >SurroundR                ;1

Store3:

      .byte <SurroundCurr             ;2 Current state location

Store4:

      .byte >SurroundCurr             ;3

Store5:

      .byte <SurroundStates           ;4 list of states location

Store6:

      .byte >SurroundStates           ;5

Store7:

      .byte $28                       ;6 color (Orange)

Store8:

      .byte $07                       ;7 size (Large)



YGateData:

      .word PortInfo1,YGateR,PortStates

      .byte $00,$00;Yellow castle Gate #$01  Yellow, Small



WGateData:

      .word PortInfo2,WGateR,PortStates

      .byte $00,$00;White castle Gate  #$02  White, Small



BGateData:

      .word PortInfo3,BGateR,PortStates

      .byte $00,$00;Black castle Gate  #$03  Black, Small



RGateData:

      .word PortInfo3,RGateR,PortStates

      .byte $00,$00;Red castle Gate    #$03  Black, Small



AuthorData:

      .word AuthorInfo,AuthorCurr,AuthorStates

      .byte $CB,$00;Author Signature   #$04  Flash, Small



NumberData:

      .word NumberInfo,Level,NumberStates

      .byte $C8,$00;Number token       #$05  Green, Small



RDragonData:

      .word RDragonR,RDragonR+4,DragonStates

      .byte $36,$00;Red Dragon         #$06  Red, Small



YDragonData:

      .word YDragonR,YDragonR+4,DragonStates

      .byte $1A,$00;Yellow Dragon      #$07  Yellow, Small



GDragonData:

      .word GDragonR,GDragonR+4,DragonStates

      .byte $C8,$00;Green Dragon       #$08  Green, Small



SwordData:

      .word SwordR,SwordCurr,SwordStates

      .byte $1A,$00;Sword              #$09  Yellow, Small



BridgeData:

      .word BridgeR,BridgeCurr,BridgeStates

      .byte $66,$07;Bridge             #$0A  Purple, Large



YKeyData:

      .word YKeyR,KeyCurr,KeyStates

      .byte $1A,$00;Yellow Key         #$0B  Yellow, Small



WKeyData:

      .word WKeyR,KeyCurr,KeyStates

      .byte $0E,$00;White Key          #$0C  White, Small



BKeyData:

      .word BKeyR,KeyCurr,KeyStates

      .byte $00,$00;Black Key          #$0D  Black, Small



RKeyData:

      .word RKeyR,KeyCurr,KeyStates

      .byte $36,$00;Red Key            #$0D  red, Small
;($36 = the color red)



BatData:

      .word BatR,BatR+4,BatStates

      .byte $00,$00;Bat                #$0E  Black, Small



DotData:

      .word DotR,DotCurr,DotStates

      .byte $08,$00;Dot                #$0F  Grey, Small



ChaliseData:

      .word ChaliseR,ChalliseCurr,ChalliseStates

      .byte $CB,$00;Chalise            #$10  Flash, Small



MagnetData:

      .word MagnetR,MagnetCurr,MagnetStates

      .byte $00,$00;Magnet             #$11  Black, Small



NullData:

      .word NullR,NullCurr,NullStates

      .byte $00,$00;Null object        #$12  Black, Small

 

Almost done...now we just need to edit the randomization routine to include it...and then the key can optionally be added to the bat and dragon matrixes (so the bat can pick it up or the dragons can guard/fear it). And the magnet matrix as well (so it can attract it). Part 2 coming up...

Link to comment
Share on other sites

Sorry to interupt, but FYI:

 

Here's something that I'm not too sure about...but Z26 doesn't have a problem with...

 

;Preform VSYNC

DoVSYNC:

      LDX    INTIM              ;Get Timer Output                             ;4

      BNE    DoVSYNC            ;Wait for Time-Out                            ;2

      LDA    #$02               ;                                             ;2

      STA    WSYNC              ;Wait for horizonal blank.                    ;3

      STA    VBLANK             ;Start Vertical Blanking.                     ;3

      STA    WSYNC              ;Wait for horizonal blank.                    ;3
;       STA    WSYNC              ;Wait for horizonal blank.                    ;3
;       STA    WSYNC              ;Wait for horizonal blank.                    ;3

      STA    VSYNC              ;Start verticle sync.                         ;3

      STA    WSYNC              ;Wait for horizonal blank.                    ;3

      STA    WSYNC              ;Wait for horizonal blank.                    ;3

      STA    WSYNC              ;Wait for horizonal blank.                    ;3

      STX    VSYNC              ;End Vertical sync.                           ;3
;       LDA    #$2A               ;Set clock interval to                        ;2

      LDA    #$2C               ;Set clock interval to                        ;2



      STA    TIM64T             ;Countdown next frame.                        ;4

      RTS                       ;                                             ;6

 

Eliminating 2 WSYNC's there allows INTIM to be bumped up twice.  That might help for those rumbles.

WOW!!! This seems to remove all my rumble/jitter/screen flipping problems from my hack, uhm..., I mean my hack of your hack! :D I guess I may have to remove the mysterious earthquake (not EarthQuake ;) ) references in the manual... (cheap way to get out of jitter problem) Works with StellaX too!

 

(unless you're a complete madman like atwwong!).   :D
Agreed!!! Bwah-ha-ha-*cough*cough*gasp...

 

Now back to your regularily scheduled hack session... :)

Link to comment
Share on other sites

Here's the original object location chart...

;Game1Objects and Game2Objects must hold the same number of bytes
;Object locations (room and coordinate) for game 01.

Game1Objects:

      .byte $15,$51,$12           ;Black dot (Room, X, Y)

      .byte $0E,$50,$20,$00,$00   ;Red Dragon (Room, X, Y, Movement, State)

      .byte $01,$50,$20,$00,$00   ;Yellow Dragon (Room, X, Y, Movement, State)

      .byte $1D,$50,$20,$00,$00   ;Green Dragon (Room, X, Y, Movement, State)

      .byte $1B,$80,$20           ;Magnet (Room,X,Y)

      .byte $12,$20,$20           ;Sword (Room,X,Y)

      .byte $1C,$30,$20           ;Challise (Room,X,Y)

      .byte $04,$29,$37           ;Bridge (Room,X,Y)

      .byte $11,$20,$40           ;Yellow Key (Room,X,Y)

      .byte $0E,$20,$40           ;White Key (Room,X,Y)

      .byte $1D,$20,$40           ;Black Key (Room,X,Y)

      .byte $1C                   ;Portcullis State

      .byte $1C                   ;Portcullis State

      .byte $1C                   ;Portcullis State

      .byte $1A,$20,$20,$00,$00   ;Bat (Room, X, Y, Movement, State)

      .byte $78,$00               ;Bat (Carrying, Fed-Up)


;Object locations (room and coordinate) for Games 02 and 03.

Game2Objects:

      .byte $15,$51,$12           ;Black Dot (Room,X,Y)

      .byte $14,$50,$20,$A0,$00   ;Red Dragon (Room,X,Y,Movement,State)

      .byte $19,$50,$20,$A0,$00   ;Yellow Dragon (Room,X,Y,Movement,State)

      .byte $04,$50,$20,$A0,$00   ;Green Dragon (Room,X,Y,Movement,State)

      .byte $0E,$80,$20           ;Magnet (Room,X,Y)

      .byte $11,$20,$20           ;Sword (Room,X,Y)

      .byte $14,$30,$20           ;Chalise (Room,X,Y)

      .byte $0B,$40,$40           ;Bridge (Room,X,Y)

      .byte $09,$20,$40           ;Yellow Key (Room,X,Y)

      .byte $06,$20,$40           ;White Key (Room,X,Y)

      .byte $19,$20,$40           ;Black Key (Room,X,Y)

      .byte $1C                   ;Portcullis State

      .byte $1C                   ;Portcullis State

      .byte $1C                   ;Portcullis State

      .byte $02,$20,$20,$90,$00   ;Bat (Room,X,Y,Movement,State)

      .byte $78,$00               ;Bat (Carrying, Fed-Up)

You'll need to add in a line for the red key (giving it any value you want for where it begins), and the gate (which just uses a static value of $1C to indicate that it is locked) to both of these tables. Again...right at the proper spots. All of these byte values are placed in the ram table in exactly the order shown, so it must match up to your ram assignments perfectly...

 

;Game1Objects and Game2Objects must hold the same number of bytes
;Object locations (room and coordinate) for game 01.

Game1Objects:

      .byte $15,$51,$12           ;Black dot (Room, X, Y)

      .byte $0E,$50,$20,$00,$00   ;Red Dragon (Room, X, Y, Movement, State)

      .byte $01,$50,$20,$00,$00   ;Yellow Dragon (Room, X, Y, Movement, State)

      .byte $1D,$50,$20,$00,$00   ;Green Dragon (Room, X, Y, Movement, State)

      .byte $1B,$80,$20           ;Magnet (Room,X,Y)

      .byte $12,$20,$20           ;Sword (Room,X,Y)

      .byte $1C,$30,$20           ;Challise (Room,X,Y)

      .byte $04,$29,$37           ;Bridge (Room,X,Y)

      .byte $11,$20,$40           ;Yellow Key (Room,X,Y)

      .byte $0E,$20,$40           ;White Key (Room,X,Y)

      .byte $1D,$20,$40           ;Black Key (Room,X,Y)

      .byte $02,$20,$40           ;Red Key (Room,X,Y)<-added

      .byte $1C                   ;Portcullis State

      .byte $1C                   ;Portcullis State

      .byte $1C                   ;Portcullis State

      .byte $1C                   ;Portcullis State <-added

      .byte $1A,$20,$20,$00,$00   ;Bat (Room, X, Y, Movement, State)

      .byte $78,$00               ;Bat (Carrying, Fed-Up)


;Object locations (room and coordinate) for Games 02 and 03.

Game2Objects:

      .byte $15,$51,$12           ;Black Dot (Room,X,Y)

      .byte $14,$50,$20,$A0,$00   ;Red Dragon (Room,X,Y,Movement,State)

      .byte $19,$50,$20,$A0,$00   ;Yellow Dragon (Room,X,Y,Movement,State)

      .byte $04,$50,$20,$A0,$00   ;Green Dragon (Room,X,Y,Movement,State)

      .byte $0E,$80,$20           ;Magnet (Room,X,Y)

      .byte $11,$20,$20           ;Sword (Room,X,Y)

      .byte $14,$30,$20           ;Chalise (Room,X,Y)

      .byte $0B,$40,$40           ;Bridge (Room,X,Y)

      .byte $09,$20,$40           ;Yellow Key (Room,X,Y)

      .byte $06,$20,$40           ;White Key (Room,X,Y)

      .byte $02,$20,$40           ;Red Key (Room,X,Y) <-added

      .byte $1C                   ;Portcullis State

      .byte $1C                   ;Portcullis State

      .byte $1C                   ;Portcullis State

      .byte $1C                   ;Portcullis State <-added

      .byte $02,$20,$20,$90,$00   ;Bat (Room,X,Y,Movement,State)

      .byte $78,$00               ;Bat (Carrying, Fed-Up)

 

I just had it begin below the yellow castle in both. Next, you'll need to add the key to the randomization routine's table used in game 3...

 

;Room Bounds Data.
;Ex. the chalise at location &B9 can only
;     exist in rooms 13-1A for level 3.

Loc_1:

      .byte ChaliseR              ;

Loc_2:

      .byte $13                   ;Chalise

Loc_3:

      .byte $1A                   ;

      .byte RDragonR,$01,$1D      ;Red Dragon

      .byte YDragonR,$01,$1D      ;Yellow Dragon

      .byte GDragonR,$01,$1D      ;Green Dragon

      .byte SwordR,$01,$1D        ;Sword

      .byte BridgeR,$01,$1D       ;Bridge

      .byte YKeyR,$01,$1D         ;Yellow Key

      .byte WKeyR,$01,$16         ;White Key

      .byte BKeyR,$01,$12         ;Black Key

      .byte RKeyR,$01,$12         ;Red Key <-added

      .byte BatR,$01,$1D          ;Bat

      .byte MagnetR,$01,$1D       ;Magnet

Loc_4:

      .byte <Game1Objects                   ;objects game 01.

Loc_5:

      .byte >Game1Objects                   ;      --continued.

      .byte <Game2Objects,>Game2Objects     ;objects game 02.

      .byte <Game2Objects,>Game2Objects     ;objects game 03.

 

The first value is it's ram location (RKeyR)...the second value is the lowest room number that it is allowed to appear at...and the last value is the highest room number. The program includes these to limit the chance that an object will appear at an inaccessable area right from the start.

 

That takes care of the key. I'll get to including it in the magnet. bat, and dragon matrixes later. Right now, we need to assign the key to the castle gate...so scroll down to the PostOffsets...etc...tables. Sorry about that, but the lines in the version posted above were missed :lol: I forgot to edit the values to be the "Number" labels instead. Here's what they SHOULD be...

 

;Portcullis #1, #2, #3

PortOffsets:

    .byte YGateNumber,WGateNumber,BGateNumber


;Keys #1, #2, #3  (Yellow, White, Black)

KeyOffsets:

    .byte YKeyNumber,WKeyNumber,BKeyNumber


;Castle Entry Rooms (Yellow, White, Black)

EntryRoomOffsets:

    .byte $12,$1A,$1B


;Castle Rooms (Yellow, White, Black)

CastleRoomOffsets:

    .byte $11,$0F,$10

 

The first set of data is the object numbers for all of the gates. The next set is for the keys, the 3rd set is for what room you'll go to when entering a gate, and the last set is for what screen the gates will be at. Here's the one including the new gate/key....

 

;Portcullis #1, #2, #3

PortOffsets:

    .byte YGateNumber,WGateNumber,BGateNumber,RGateNumber


;Keys #1, #2, #3  (Yellow, White, Black)

KeyOffsets:

    .byte YKeyNumber,WKeyNumber,BKeyNumber,RKeyNumber


;Castle Entry Rooms (Yellow, White, Black)

EntryRoomOffsets:

    .byte $12,$1A,$1B,$20


;Castle Rooms (Yellow, White, Black)

CastleRoomOffsets:

    .byte $11,$0F,$10,$1F

 

I just used the as-yet undefined custom rooms $1F and $20 as the castle and inside. So scroll all the way up to bank 1 and edit their bitmaps. Room1F to look like a castle (copy/paste if you wish)...and Room20 to whatever you want it's inside to look like.

 

This would now be ready to compile as far as Dasm is concerned...but you still can't REACH those rooms unless you edit the room matrix first. Way down at the bottom of the file. Just edit the lines for Room1F and Room20...which look like this currently...

 

       .byte <Room1F,>Room1F,$66,$21,$00,$00,$00,$00               ;Red castle

      .byte <Room20,>Room20,$66,$21,$00,$00,$00,$00               ;inside the red castle

 

You'll need to edit the last 4 bytes of each to indicate where the game should put you when you exit the room. For castle entrypoints, the program will automatically put you outside the castle when exiting...so the values for room $20 can be all $20 if you want. But room $1F is going to need to "point" to at least 1 of the existing rooms...and that room to $1F (so you can get to/from it when playing the game). Optionally, you can edit the color of each room...plus the GFX control value next to it (a breakdown of what bits do what is listed at the top of the matrix). Just keep the GFX control byte at $21 if you are unsure about what it does (which would be a normal reversed, lighted room with no panels).

 

Next...adding the key to the other character's matrixes...

Link to comment
Share on other sites

Here's the dragon matrixes. Any value listed BEFORE themselves will be "feared"...and any value listed AFTER themselves will be guarded. Kind of funny...but the dragon isn't really "trying" to eat you...it just wants to guard you! (but then the program makes it "bite" as soon as it reaches you). Here's the original...you'll notice that I left a few bytes at the end of each (though this wasn't really necessary, since most of the game tables can cross pages without indident)...

;all must be on 1 page
;if an object is listed befor the dragon, it is "feared"
;if an object is listed after the dragon, it is "guarded"
;extra bytes can be used to add more objects to guard or fear...be sure to end with $00
;Red Dragon Object Matrix

RedDragMatrix:

      .byte SwordR,RDragonR       ;Sword, Red Dragon

      .byte RDragonR,PlayerRoom   ;Red Dragon, Ball

      .byte RDragonR,ChaliseR     ;Red Dragon, Chalise

      .byte RDragonR,WKeyR        ;Red Dragon, White Key

      .byte $00                   ;matrix end
;extra bytes

      .byte $00

      .byte $00

      .byte $00

      .byte $00


;Yellow Dragon's Object Matrix

YelDragMatrix:

      .byte SwordR,YDragonR       ;Sword, Yellow Dragon

      .byte YKeyR,YDragonR        ;Yellow Key, Yellow Dragon

      .byte YDragonR,PlayerRoom   ;Yellow Dragon, Ball

      .byte YDragonR,ChaliseR     ;Yellow Dragon, Chalise

      .byte $00                   ;matrix end
;extra bytes

      .byte $00

      .byte $00

      .byte $00

      .byte $00


;Green Dragon's Object Matrix

GreenDragonMatrix:

      .byte SwordR,GDragonR       ;Sword, Green Dragon

      .byte GDragonR,PlayerRoom   ;Green Dragon, Ball

      .byte GDragonR,ChaliseR     ;Green Dragon Chalise

      .byte GDragonR,BridgeR      ;Green Dragon, Bridge

      .byte GDragonR,MagnetR      ;Green Dragon, Magnet

      .byte GDragonR,BKeyR        ;Green Dragon, Black Key

      .byte $00                   ;matrix end

 

Let's make the red dragon fear it...and the yellow dragon guard it...

;all must be on 1 page
;if an object is listed befor the dragon, it is "feared"
;if an object is listed after the dragon, it is "guarded"
;extra bytes can be used to add more objects to guard or fear...be sure to end with $00
;Red Dragon Object Matrix

RedDragMatrix:

      .byte RKeyR,RDragonR        ;Red Key, Red Dragon

      .byte SwordR,RDragonR       ;Sword, Red Dragon

      .byte RDragonR,PlayerRoom   ;Red Dragon, Ball

      .byte RDragonR,ChaliseR     ;Red Dragon, Chalise

      .byte RDragonR,WKeyR        ;Red Dragon, White Key

      .byte $00                   ;matrix end


;Yellow Dragon's Object Matrix

YelDragMatrix:

      .byte SwordR,YDragonR       ;Sword, Yellow Dragon

      .byte YKeyR,YDragonR        ;Yellow Key, Yellow Dragon

      .byte YDragonR,PlayerRoom   ;Yellow Dragon, Ball

      .byte YDragonR,ChaliseR     ;Yellow Dragon, Chalise

      .byte YDragonR,RKeyR        ;Yellow Dragon, Red key

      .byte $00                   ;matrix end


;Green Dragon's Object Matrix

GreenDragonMatrix:

      .byte SwordR,GDragonR       ;Sword, Green Dragon

      .byte GDragonR,PlayerRoom   ;Green Dragon, Ball

      .byte GDragonR,ChaliseR     ;Green Dragon Chalise

      .byte GDragonR,BridgeR      ;Green Dragon, Bridge

      .byte GDragonR,MagnetR      ;Green Dragon, Magnet

      .byte GDragonR,BKeyR        ;Green Dragon, Black Key

      .byte $00                   ;matrix end

 

 

 

 

And now the bat...let's have it "like" the key more than all the others...

;Bat Object Matrix.

BatMatrix:

      .byte BatR,ChaliseR         ;Bat,Chalise

      .byte BatR,SwordR           ;Bat,Sword

      .byte BatR,BridgeR          ;Bat,Bridge

      .byte BatR,RKeyR            ;Bat,Red Key <-added

      .byte BatR,YKeyR            ;Bat,Yellow Key

      .byte BatR,WKeyR            ;Bat,White Key

      .byte BatR,BKeyR            ;Bat,Black Key

      .byte BatR,RDragonR         ;Bat,Red Dragon

      .byte BatR,YDragonR         ;Bat,Yellow Dragon

      .byte BatR,GDragonR         ;Bat,Green Dragon

      .byte BatR,MagnetR          ;Bat,Magnet

      .byte $00                   ;matrix end

 

 

 

 

 

And the magnet...let's have it "attract" the key last...

;Magnet Object Matrix.

MagnetMatrix:

      .byte YKeyR,MagnetR         ;Yellow Key, Magnet

      .byte WKeyR,MagnetR         ;White Key, Magnet

      .byte BKeyR,MagnetR         ;Black Key, Magnet

      .byte SwordR,MagnetR        ;Sword, Magnet

      .byte BridgeR,MagnetR       ;Bridge, Magnet

      .byte ChaliseR,MagnetR      ;Chalise, Magnet

      .byte RKeyR,MagnetR         ;Red Key, Magnet <-added

      .byte $00                   ;matrix end

 

 

And that's all. Now adding dragons or bats...that's really more involved!

Link to comment
Share on other sites

Oops...something I forgot is that the gate would need to be told to appear independantly from all the other ones :lol:

Edit the "RKeyData" line to indicate a unique set...just change PortInfo3 to PortInfo4...

RGateData:

      .word PortInfo4,RGateR,PortStates

      .byte $00,$00 ;Red castle Gate    #$03  Red, Small

[code]

 

 

 

...and then add in a table for PortInfo4...

 

 

 

[code]

;Object Data

;Offset 0 : Room number of object.

;Offset 1 : X Coordinate of object.

;Offset 2 : Y Coordinate of object.

 

;Object #1 : Portcullis

PortInfo1:

      .byte $11,$4D,$31          ;Room 11, (4D, 31)

;Object #2 : Portcullis

PortInfo2:

      .byte $0F,$4D,$31          ;Room 0F, (4D, 31)

;Object #3 : Portcullis

PortInfo3:

      .byte $10,$4D,$31          ;Room 10, (4D, 31

 

;added for the red key's gate

;Object #4 : Portcullis

PortInfo4:

      .byte $1F,$4D,$31          ;Room 10, (4D, 31

 

 

 

Note how the first byte in it points at the new castle room $1F.

 

Also...since the program is now dealing with 4 gates instead of just 3, there is a possibility of running low on cycle time (causing some jitters mentioned by atwwong). That's a bit more involved too (programming changes)...so I won't cross that bridge unless you want to give this a try. But just eliminating those 2 WSYNC's and changing the next value might buy you enough cycles to get away with adding just 1 with no probs :)

Link to comment
Share on other sites

All that code break the thread? :lol:

 

Let's try this again...

 

PortInfo4...


RGateData:

      .word PortInfo4,RGateR,PortStates

      .byte $00,$00;Red castle Gate    #$03  Red, Small

 

 

 

...and then add in a table for PortInfo4...

;Object Data
;Offset 0 : Room number of object.
;Offset 1 : X Coordinate of object.
;Offset 2 : Y Coordinate of object.


;Object #1 : Portcullis

PortInfo1:

      .byte $11,$4D,$31         ;Room 11, (4D, 31)
;Object #2 : Portcullis

PortInfo2:

      .byte $0F,$4D,$31         ;Room 0F, (4D, 31)
;Object #3 : Portcullis

PortInfo3:

      .byte $10,$4D,$31         ;Room 10, (4D, 31


;added for the red key's gate
;Object #4 : Portcullis

PortInfo4:

      .byte $1F,$4D,$31         ;Room 10, (4D, 31

Link to comment
Share on other sites

;RoomData

...
;Offset 5 : Room Above
;Offset 6 : Room Right
;Offset 7 : Room Down
;Offset 8 : Room Left

 

This is wrong. It should read:

 

;RoomData

...
;Offset 5 : Room Above
;Offset 6 : Room Left
;Offset 7 : Room Down
;Offset 8 : Room Right

 

Unless I'm just reading it backwards... :P

 

Nope...the last byte (offset8) is pointing left. Two bytes before that one is pointing to the right (offset6). As an example, take a look at room $02 (below the yellow castle). The last byte $01 indicates the room below the blue maze...off to the left.

 

Thanks for pointing it out tho...because it was incorrect in this 8k listing :)

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