Jump to content

Photo

Defender II Hack Attempt - Trying to find 2 portions of code


20 replies to this topic

#1 rallyrabbit OFFLINE  

rallyrabbit

    Space Invader

  • 21 posts
  • Location:North Carolina (USA)

Posted Fri Apr 5, 2019 2:17 PM

After a week digging I thought I would post.  I disassembled stargate and made some of the improvements from the Defender II hack that was done years ago.  I'm also trying to do a number of other things.  I'm fairly confident I've isolated a handful of portions of the code doing certain things (particularly scoring, graphics are not that hard).

 

What I am trying to find now are two things that I am falling flat on:

1) I am trying to find the routine (supposing it is timer based) that uses multiple graphics to rotate for the enemies.  There are enemies that have 3 graphics each and seem to rotate through on a strict timer interval

2) I am trying to figure out where the mountains are generated to start playing with that as well.  I thought these would be a predetermined set of "graphics too" but I think I am wrong.

 

Putting up the set of assemblies just in case someone can offer some assistance.

Attached Files



#2 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Sat Apr 6, 2019 10:44 PM

1) Do you mean the framecounter?  To speed things along, the game uses 2 variations of the counter ($81) in various routines...$F8 which is the counter divided by 4 and trimmed to values 0-3, and $F9 which is the counter divided by 8 and trimmed to values 0-3:

 

LF1DC: LDX    #$01    ;2
       LDA    $A2     ;3
       BEQ    LF255   ;2
       LDA    $81     ;3
       LSR            ;2
       LSR            ;2
       TAY            ;2
       AND    #$03    ;2
       STA    $F8     ;3
       TYA            ;2
       LSR            ;2
       AND    #$03    ;2
       STA    $F9     ;3

 

Just track down those variables in your disassembly, you can remove them in the routines which they appear in to be able to tell which bit of code does what.  You can edit them right from Stella's debugger, rather than assembling the coded each time.

 

2) Within the display code itself.  You'll find many instances of ENAM1 followed by ENABL.  This is what produces the hills.  The M1 and Ball sprites both start at the same horizontal location.  The missile is given a horizontal motion value 3 pixels left, the ball is given 3 pixels right.  HMOVE is drawn on every scanline, so they move apart as the screen is drawn downward.  Kind of a neat solution to draw Defender's hillside (rather than use a playfield cityscape like the original did).  Not so good if you are looking to change it into something different, tho.



#3 rallyrabbit OFFLINE  

rallyrabbit

    Space Invader

  • Topic Starter
  • 21 posts
  • Location:North Carolina (USA)

Posted Wed Apr 10, 2019 7:11 AM

This was fantastic.  Just that one hint at the top gave me enough information to sort out a good portion of the code.

 

Thanks!



#4 rallyrabbit OFFLINE  

rallyrabbit

    Space Invader

  • Topic Starter
  • 21 posts
  • Location:North Carolina (USA)

Posted Fri Apr 12, 2019 6:03 AM

Ok, I haven't started the cityscape work yet.  Will leave that for last.  I was hoping for some other questions someone might be able to help me figure out.

 

Question 1:

it seems that $F8 and $F9 do different things as far as the frame counter.  Seems that F9 rotates most of the ships like the landers.  F8 rotates other ships (like firebomber) and is also used for some reason on the end of wave screen.  So I can hard code F9 to 0x01 to get the ship images to stop rotating without impact (but not 0x00).  Further, I cannot set F8 to anything other than rotating 0x00 to 0x03 without it affecting the end of wave screen.

 

Less a question and more an observation I guess.

 

Question 2:

Where are the enemy graphics actually loaded?  I can see the bit where the enemy ship index positions are used from 9d and 9e but I cannot tell where it actually loads the base addresses to use with the index registers.  Debugging is really baffling me to try and figure out.

 

Question 3:

This is to do with colors.  So for instance, Lander IMage 1 is FF94 to FF4E.  but the colors defined at FF9E to FFA5 are for the mutant.  And this is similar to other lander images (the other 4).  The mutant is defined alone without colors right after the image and the lander colors themselves are FFD5 to FFDC!  How in the world are the graphics referenced since they don't seem to be uniform addresses spaces away from each other, and especially where the colors definitions are scattered everywhere.  Is there are reference table somewhere i have not found?

 

Cause it's like the bombers are defined differently and the baiters are even more different.

 

Question 4:

Take the lander definition:

;       .byte $92 ; |X  X  X | $FF96 original
;       .byte $54 ; | X X X  | $FF97
;       .byte $54 ; | X X X  | $FF98
;       .byte $7C ; | XXXXX  | $FF99
;       .byte $EE ; |XXX XXX | $FF9A
;       .byte $EE ; |XXX XXX | $FF9B
;       .byte $7C ; | XXXXX  | $FF9C
;       .byte $38 ; |  XXX   | $FF9D
 
This is the defined lander.  If I change line FFD9 to $00 (blank) then the image does not show.  I cannot find a stripping of graphics if the top/bottom defined is not non-zero.
 
 
Maybe I am getting assembly tunnel vision....


#5 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Fri Apr 12, 2019 6:38 AM

Been awhile since I looked at Defender2 (I made the portable version), but did you see the data table $FA3B to $FA98? Looks to be holding the 16 bit addresses of most.

 

EDIT 4/13: current disassembly added

Attached Files


Edited by Nukey Shay, Sat Apr 13, 2019 9:19 PM.


#6 rallyrabbit OFFLINE  

rallyrabbit

    Space Invader

  • Topic Starter
  • 21 posts
  • Location:North Carolina (USA)

Posted Fri Apr 12, 2019 6:55 PM

Been awhile since I looked at Defender2 (I made the portable version), but did you see the data table $FA3B to $FA98? Looks to be holding the 16 bit addresses of most.

 

Yes sir, I saw that referenced in an older post when PacManPlus was working on Defender Arcade.  But thank you for passing it along just in case.

 

That table seems to be reference addresses for "screen" content of the title and end of wave screens.  It doesn't seem to be used for game play, that's why I am a bit baffled at how the these other graphics bits are pulled in



#7 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Fri Apr 12, 2019 7:59 PM

Base addresses appear to be built (in-program) using bits culled from data tables LFB00 and LFB50...the final values take the scanline count of where they should appear onscreen into consideration.  So you might be forced to use a trace file to discover how they arrive at the values.  Everytime I think I see a connection, one or two of the values in the tables throw me off :(

 

Makes sense now why Defender Arcade eliminated characters rather than repurpose them.



#8 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Sat Apr 13, 2019 4:54 PM

LF948:
       .byte $08 ; |    X   | $F948 00
       .byte $0C ; |    XX  | $F949 04
       .byte $08 ; |    X   | $F94A 08
       .byte $0B ; |    X XX| $F94B 0C
       .byte $0F ; |    XXXX| $F94C 10
       .byte $0C ; |    XX  | $F94D 14
       .byte $09 ; |    X  X| $F94E 18
       .byte $09 ; |    X  X| $F94F 1C
       .byte $09 ; |    X  X| $F950 20
       .byte $0F ; |    XXXX| $F951 24 lander page $FF
       .byte $0D ; |    XX X| $F952 28
       .byte $0B ; |    X XX| $F953 2C
       .byte $0A ; |    X X | $F954 30
       .byte $08 ; |    X   | $F955 34
       .byte $08 ; |    X   | $F956 38
       .byte $08 ; |    X   | $F957 3C
       .byte $09 ; |    X  X| $F958 40
       .byte $0D ; |    XX X| $F959 44
       .byte $0D ; |    XX X| $F95A 48
       .byte $08 ; |    X   | $F95B 4C

Above table holds the low nybble of the MSB (the high nybble #$F is added by the kernel).

 

Table LFB00 holds the LSB of objects (grouped in bunches of 4)...which point just beyond the sprite definintions.  The lander pointers are these...

       .byte $9E ; |X  XXXX | $FB24
       .byte $B2 ; |X XX  X | $FB25
       .byte $C7 ; |XX   XXX| $FB26
       .byte $D3 ; |XX X  XX| $FB27

 

Table LFB50 holds the LSB of just beyond the color definitions.  The lander colors:

       .byte $DD ; |XX XXX X| $FB74
       .byte $DD ; |XX XXX X| $FB75
       .byte $DD ; |XX XXX X| $FB76
       .byte $DD ; |XX XXX X| $FB77

 

This matches perfectly for what exists for the lander at page $FF.

 

Table LFA00 holds which animation rate to use.  0=ram_F8, 1=ram_F9.  The lander's is at $FA09.

 

Just need to find the table which defines sprite height.



#9 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Sat Apr 13, 2019 5:20 PM

Nevermind...the kernel just displays bitmap values (going upward in Rom) until a zero is reached.  No size variable.



#10 rallyrabbit OFFLINE  

rallyrabbit

    Space Invader

  • Topic Starter
  • 21 posts
  • Location:North Carolina (USA)

Posted Sat Apr 13, 2019 6:39 PM

In a day where I have been missing with sound, you found the partial nibbles of the MSB and LSB of data areas like this?

 

I gotta ask, what's your angle for investigation, I'm apparently going about this wrong.



#11 rallyrabbit OFFLINE  

rallyrabbit

    Space Invader

  • Topic Starter
  • 21 posts
  • Location:North Carolina (USA)

Posted Sat Apr 13, 2019 6:40 PM

Nevermind...the kernel just displays bitmap values (going upward in Rom) until a zero is reached.  No size variable.

 

I found that the hard way.  I wanted to change some bitmaps but center them, but the bitmaps have to have a non-zero first and the zero based lines last.



#12 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Sat Apr 13, 2019 8:27 PM

I always wondered why the smaller "warp in" bitmap had the hook at the top.  Now we know...it can't be zero for centering.

 

what's your angle for investigation, I'm apparently going about this wrong.

 

Stella is invaluable here.  You can point and click on any image and fill to that point.  The kernel routine will show you the values it's using, so you just need to backtrack through a disassembly file to see where they were saved.  Rinse and repeat for each step of the value involved.  I had a hunch that the large data tables at LFB00/LFB50 were involved in some way (because many of those values matched LSB's where bitmaps and color values were located).  Looking for those 2 tags led me to the routine @$F1C9.  I already knew from stepping through the display kernel that the upper nybble of MSB pointers was done there, So looking for a table that only had low nybbles in the same pattern as object #'s pointed that one out at $F948.  Reading though the routine solved the rest.

 

Kinda haphazard, I know.  Brainiacs like Thomas or Dennis could probably do it all in their heads.



#13 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Sat Apr 13, 2019 8:48 PM

BTW if you are moving things around, take care not to move enemy sprite data below $xx94.  The program subtracts the scanline count of where they should appear onscreen from the LSB's before the kernel is executed (so instructions will run over by a cycle if that value ends up to be less than zero).  The stargate does not move from it's position, so that object is allowed to be a bit lower in memory.  Only color data is allowed to extend right to the end of a page.

 

The player ship and standing humanoids use their own method for display.


Edited by Nukey Shay, Sat Apr 13, 2019 8:53 PM.


#14 rallyrabbit OFFLINE  

rallyrabbit

    Space Invader

  • Topic Starter
  • 21 posts
  • Location:North Carolina (USA)

Posted Wed Apr 17, 2019 2:31 PM

Thank you sir.

 

Before I read this I found that out the hard way.  But given the enemies I am changing, colors schemes, etc.  I saved enough space to fit in where I can add some new code.  I am trying to take a scalpel to the original code to try and maintain the code spacing and image/table areas as well, but I can shift that around if needed too.

 

I got a test cityscape in, looks like garbage but proves out it can be done.  I was trying to port in the CityScape from the original defender, but it needs 12 bytes of RAM free to handle the cityscape area so they can build it and roll it.  I was attempting to find enough free ram to handle it.  I think i've found 8 bytes (2 4 byte contiguous area), but not 12 (at least not twelve where 4 bytes more are contiguous), which offers a new challenge in deciding what to do next.

 

It is moving along, slowly.... much slower than I was anticipating.

 

For you Stella experts.  I don't see it in the doc, the trace back in history is really nice.  Is there a way to set watchpoints on RAM so it breaks when a watchpoint is hit?



#15 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Thu Apr 18, 2019 6:10 AM

I got a test cityscape in, looks like garbage but proves out it can be done.  I was trying to port in the CityScape from the original defender, but it needs 12 bytes of RAM free...

 

...or 1 byte of Ram and 240 bytes of Rom:

 

Ram for the index value (value 0-19), and 3 sets of 20 bytes x 4 lines for each register.  You could cut this to 160 bytes of Rom if you made the first and 4th buildings identical.

 

The main hurdle is creating enough cycle time to handle the changes...24 cycles to update PF from Rom using an index, or 20 cycles if the 1st and 4th buildings look the same.



#16 rallyrabbit OFFLINE  

rallyrabbit

    Space Invader

  • Topic Starter
  • 21 posts
  • Location:North Carolina (USA)

Posted Yesterday, 6:52 AM

Not sure I can cut out that much ROM space and still retain a good amount of gameplay.  Even with cutting out enemies and graphic rotation, I only saved about 100 bytes after compressing everything a bit.  I am still working on more compression though.  This is a lot of trial and error to move, test, move, test, etc.

 

One thing I am unclear on is:

Data FC00 to FCA0 - obviously this is loaded from some major indexing off a base address.  I cannot pinpoint what this block of stuff is actually doing, it all seems to majorly affect gameplay, dimensions, etc.

Data FE22 to FEA7 - seems to be used for the starfield in the background (which I tend to like), but I am surprised at the amount of space needed.

 

Data FCFE to FD8B actually seems to be free....



#17 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Yesterday, 7:40 AM

Lotta opportunities to cut program code here...I'm slowly working though that (without cutting data tables).

 

The data at $FE22 is used to display the player blip in the radar...in addition to the stars.  Uses a large table to reuse the scanline counter as the index.  Look above and below LF348 to see how this is used.

 

$FCFE/FF are unused...but I assumed that the lower portion of page $FD is called when your ship is carrying a humanoid?  Those ship tables are so long because the blanks are used to fill in space when you are high on the screen (that way, no need to mask off or load pointers).


Edited by Nukey Shay, Yesterday, 8:00 AM.


#18 rallyrabbit OFFLINE  

rallyrabbit

    Space Invader

  • Topic Starter
  • 21 posts
  • Location:North Carolina (USA)

Posted Yesterday, 10:16 AM

I've been on this one for 2 days on and off can you tell where these are called up?

 

Person: FD8C-95

Extra Ship: FD96-9B

Ship: FF8C-FF90

Lives: F840-44

 

I am going to feel really silly if they are called up in bank 2.  I've search on MSB, LSB, decrementing and incrementing address off the LSB.  I've scanned through bank 0 too, but not quite as thoroughly.  These are the last bits that I want to move as far as graphics but I cannot do it until I find how they are referenced.



#19 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Today, 2:05 AM

There is no "extra ship" (with the person).  That is the sprite gfx used when catching a humanoid.  Normally, ram $94/$95 (the player ship indirect-y vector) is set to page $FF...displaying a ship without a humanoid below it (that's the one at $FF8C).  When you collide with any sprite, it gets recorded in an array starting at ram $B0.  This is later checked outside the kernel to decide what to do...

       LDX    rA3                     ;3
       DEX                            ;2
LD20B:
       DEX                            ;2
       BMI    LD243                   ;2
       LDA    rB0,X                   ;4
       BPL    LD20B                   ;2 branch if no sprite collisions for this section
       LDY    read+$43,X              ;4
       LDA    r99                     ;3
       SBC    #$05                    ;2
       CMP.wy $E0,Y                   ;4
       BCS    LD243                   ;2
       LDX    read+$22,Y              ;4
       CPX    #$0D                    ;2 check humanoid tag #
  IF INVULNERABLE
       BCC    LD243                   ;2 ignore enemy collisions
  ELSE
       BCC    LD25F                   ;2 branch if any enemy (lower tag # than humanoid)
  ENDIF
       BEQ    LD246                   ;2 branch to catch humanoid
       CPX    #$10                    ;2 Hit stargate?
       BEQ    LD282                   ;2 branch if so
;       CPX    #$10                    ;2 superfluous
       BCS    LD243                   ;2 ignore warp-ins, explosion (higher tag # than stargate
       LDA    #$00                    ;2
       STA    write+$22,Y             ;5
       LDX    rAF                     ;3
       INC    rAF                     ;5
       CLC                            ;2
       LDA    LDE0D,X                 ;4
       JSR    LDC56                   ;6
       LDA    #$D2                    ;2
       STA    r91                     ;3
LD243:
       JMP    LD2F5                   ;3

 

I haven't yet worked out all of that, but the gist is that when a humanoid (tag # $0D) is touched by the ship, the MSB of the ship vector is changed to be page $FD...the ship gfx + humanoid.

 

There's a cheat up above for you :)

 

Not much you can do with those long tables for the ship...the LSB's must remain identical between them.

 

Extra Lives ($F840), Smart Bombs ($F853), and Inviso ($F8DD) are all called by the "print score" subroutine...so those images must reside on the same page as score digits - there's not enough kernel time to change the MSB's!  Other text messages and the logo are displayed outside of active gameplay, so those can be on any page).

 

LF2D9:
       STX    NUSIZ1                  ;3
       STX    VDELP0                  ;3
       STX    VDELP1                  ;3
       LDY    #$06                    ;2 7 scanlines
       LDA    r81                     ;3 frame counter
       ASL                            ;2
       AND    #$F0                    ;2
       ORA    #$14                    ;2 merge flashing score color
       JSR    LF900                   ;6 draw score
;@01
       LDY    r82                     ;3 Ships in reserve
       BNE    LF2F2                   ;2 branch if ships remain
       JMP    LF118                   ;3
LF2F2:
       DEY                            ;2 (do not count current ship)
       LDA    #<LF840                 ;2 reserve ship gfx location
       JSR    LF66B                   ;6 set LSBs
       LDA    #$32                    ;2 reserve ship color
       LDY    #$04                    ;2 5 scanlines
       JSR    LF900                   ;6 draw ships
;@01
       LDY    r83                     ;3 # smart bombs in reserve
       LDA    #<LF853                 ;2 smart bomb gfx location
       JSR    LF66B                   ;6 set LSBs
       LDY    #$02                    ;2 3 scanlines
       LDA    #$FF                    ;2 smart bomb color
       JSR    LF900                   ;6 draw smart bombs remaining
;@01
       LDY    r84                     ;3 # inviso time in reserve
       LDA    #<LF8DD                 ;2 inviso gfx location
       JSR    LF66B                   ;6 set LSBs
       LDY    #$01                    ;2 2 scanlines
       LDA    #$32                    ;2 inviso color
       JSR    LF900                   ;6 draw inviso remaining
;@01


#20 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Today, 2:17 AM

BTW don't go changing the enemy branch to be LD246 (i.e. catch the enemy as a humanoid).

The game will crash if you try to set one too many down on the ground and it oversteps the number of empty humanoid slots to receive it!



#21 Nukey Shay OFFLINE  

Nukey Shay

    Sheik Yerbouti

  • 21,933 posts
  • Location:The land of Gorch

Posted Today, 2:31 AM

More cheats to make testing easier:

 

 
LD1A1:
       LDA    CXM0P                   ;3
       BPL    LD1B5                   ;2 branch if not shot by enemy
  IF IMMUNE
       BMI    LD1B5                   ;2 ignore if shot
  ELSE
       LDA    rAB                     ;3
  ENDIF

 

  IF INFINITE_SHIPS
       DEC    $2E                     ;5
  ELSE
       DEC    r82                     ;5
  ENDIF
LD3EC:

 

;* = $D57D
  IF INFINITE_BOMBS
       DEC    $2E                     ;5
  ELSE
       DEC    r83                     ;5
  ENDIF

 

LD5B3:
  IF INFINITE_INVISO
       DEC    $2E                     ;5
  ELSE
       DEC    r84                     ;5
  ENDIF





0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users