Jump to content
IGNORED

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


Recommended Posts

Let me see if I can clarify what I mean.

 

The title screen, End of Wave screen, etc are all built with about 6 sections of images that are pieced together in lined segments. Like, Bonus x100 defined almost as BO NU Sx 1 and then 00. In the current definition, most of this exists in the same general area. Between F700 and F7FF, or F800 and F8FF, etc; depending on the screen being built (that's an example and not the truth).

 

I guess I'm asking, is there a reason for the ROM addresses to be close together or does the length away from each other matter? Meaning can I logically put BO as f700, NU in f900, Sx in Fd00 and so on (again, a sample not real positions). I know this isn't a physical media where seek times matter, I'm just unsure of the segmenting of these ROM parts that cause a lengthier read time depending on the addresses used in one page. I can't image that is the case, just more curious about it.

Link to comment
Share on other sites

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.

 

My focus is in two places now:

1) finding where enemy speed is increased in each wave and how that is calculated. I am suspecting this in page 0 in the LDD12 area, but working that out on what is what potentially

 

2) Mountains - removing

 

Like I said, I got a bad cityscape put in just to show myself I could change the playfield. But it definitely needs to be made to be better. But I didn't take out the mountain effect to do that. I used your tip above to find all these areas of concern.

1) LF405 - looking at this code i think this has to do with enemy missiles

2) LF444 - Unsure what this one is doing - startfield maybe?

3) LF492 - This looks like part of the mountains - like maybe the top?

4) LF4E4 - This one I have yet to identify

 

 

So, I am looking at the mountain creation and trying to see the rough difference between "planet" vs "planet destroyed"

Link to comment
Share on other sites

To remove the mountain, you just need to erase the low nybble at addresses $FE00 to $FE1C. Ram vector $9B/$9C creates the mountians as well as the starfield. This normally points at the data starting at $FE00 (so the mountain is drawn as the scanline counter counts down to zero). When address $A9 is non-zero, it alters the LSB of this vector...counting upward to $1C. When $1C is reached, the flashing stops...no mountain is left.

 

Bit 5 in this data table is used to set the width of ball and missile. It extends a little further in the data table because the sprite size is not set on every scanline up to this point.

 

So $A9 = 0 for planet OK, $A9 < $1C currently being destroyed, $A9 = $1C fully destroyed.

LD41C:
       LDA    rA9                     ;3
       BEQ    LD430                   ;2 branch if planet is still OK
       CMP    #$1C                    ;2 Reached the end of mountian data?
       BCS    LD430                   ;2 branch if so
       INC    rA9                     ;5  or, increase the pointer to slowly eat away mountian
       AND    #$03                    ;2
       BNE    LD442                   ;2
       LDA    #$05                    ;2
       STA    r90                     ;3
       BNE    LD442                   ;2 always branch

BTW:

Tag LFBD0 is calling the data at $FC00 (used for sprite positioning and motion values).

 

So add label LFC00 to that data table and replace all instances of LFBD0 with LFC00-$30

 

 

Q:

If you are using playfield to draw the city, how will you then fire at enemies that go that low? Playfield is used for player's laser...the playfield collision register is used to record hits.

Edited by Nukey Shay
Link to comment
Share on other sites

Q:

If you are using playfield to draw the city, how will you then fire at enemies that go that low? Playfield is used for player's laser...the playfield collision register is used to record hits.

 

not sure I've through that far ahead, but that's a good point. I think you could technically let the humanoids reside in the top of builds, therefore its not a problem, or I'll illegitimately have to figure something else out which will take a bit of research.

Link to comment
Share on other sites

Could just draw the city where standing humanoids are, and prevent any enemy from going that low. Landers just need to lock on to their position without touching them. Not sure how "friendly fire" would work, tho (this was N/A for Atari's Defender...as only humanoids were shown in the city).

 

Current progress:

Defendr2.asm

Edited by Nukey Shay
Link to comment
Share on other sites

Now back to this after work has calmed down....

 

What all have you changed overall. Just a did a diff with my code and trying to figure out what to merge. Added a bunch of comments. Which I am incorporating. But running the program is pretty much a blank screen (so assuming you are ripping stuff out)? Looks like just title screen, end of wave screen and the radar/score?

 

I've done a bit of work trying to get graphics like the original defender with a newer twist (not sure I like it yet), isolate enemy speeds (not adjusted yet), changed a lot with colors, things like graphic area consolidation and reduction of sapce, changed some screen, no dogfights, no warps (got rid of warp screens), no stargate (reused that graphic area), took some of the defender arcade lessons form the enemy tables, trying to isolate sounds (not sure I like my enemy shot sound yet, but it is what it is for now), trying to do some color adjustments elsewhere and all over the place. Fixed the score on the end of wave screen. Made the digits look like original defender. Took out my cityscape that didn't work. Removed inviso mode stuff so far. Tried to comment the code based on what I think is going on. Took some mountains changes from defender arcade as well that'll go away eventually. Added my initials to title screen until I get closer to completion.

 

Again, scalpel. So I finally see how mountains vs destroyed planet are done (its an adjustment to the index). not I am trying to see how I can do a simply cityscape and see what are the base cycles I need to do it to see if I kill everything and scanline time. Working out ideas for now.

 

 

 

That leaves some of the bigger things left:

1) Figure out how to do smartbomb from joystick 1 below mountain level (still working this out)

2) Cityscape algorithm and see if I can do it in space available and without killing scanline timeframe

3) Adjusting enemy speeds across waves so that the game doesn't get so impossible so fast

 

 

defender1.asm

defender2.asm

Edited by rallyrabbit
Link to comment
Share on other sites

I've stayed away from data table changes because I know that you are moving those around. Although I did merge table LFA00 with the empty area at $FE67 to $FE7B (bit0 is ignored for ball/missile sprites), and used an additional bankswitch at the end of each bank to eliminate the redundant score routine in the display bank (used during the # humanoids remaining tally). If you already noticed, I've switched the 2 banks so that $F000 occupies the first bank, and $D000 occupies the second (this takes advantage of the hotspot jumps to save a little Romspace). Otherwise, I've only been doing code optimizations. So you should be able to take all of your data tables and paste them directly into the current assembly.

 

NOTE: there was a timing glitch present in the previous assembly I did which caused HMOVE to hit 1 cycle too late on occasion (fixed).

 

Current progress:

Defendr2.asm

Link to comment
Share on other sites

I've stayed away from data table changes because I know that you are moving those around. Although I did merge table LFA00 with the empty area at $FE67 to $FE7B (bit0 is ignored for ball/missile sprites), and used an additional bankswitch at the end of each bank to eliminate the redundant score routine in the display bank (used during the # humanoids remaining tally). If you already noticed, I've switched the 2 banks so that $F000 occupies the first bank, and $D000 occupies the second (this takes advantage of the hotspot jumps to save a little Romspace). Otherwise, I've only been doing code optimizations. So you should be able to take all of your data tables and paste them directly into the current assembly.

 

NOTE: there was a timing glitch present in the previous assembly I did which caused HMOVE to hit 1 cycle too late on occasion (fixed).

 

Current progress:

 

Ok, cool, I was trying to go through the code and see what you did. I wasn't sure what the intended result was, so I was going through line by line to see what changed. I'll start merging now.

 

So, while I am working on combining, let me ask your opinion. I was wanting to do some similar to defender that once your ship gets below a certain point, that allows the smart bomb use (although that would have some challenges in game such as this where it stands now. So, I'd have to remove the checks for joystick 2 for this, but would have to have a "height" check somewhere to replace the use of it. Any opinions here?

Link to comment
Share on other sites

  • 4 weeks later...

A little update as it has been a few weeks. I put most of your changes and omissions (some I chose not to do), also found some more small places to save some ROM space. I'm really unhappy with how some of the game was coded, definitely not how I would have coded some of this stuff. So I've been making some notes on how to re-code large portions of this while preserving the game if I need to. So far, I am going to avoid big changes unless I need to. Right now, working on getting an algorithm for the cityscape that works properly. Trying to play with using a RAM model like in the original defender or using a graphics model that fits how defender works today.

  • Like 1
Link to comment
Share on other sites

Well,

 

Now let me post to solicit ideas. I created a ROM graphics area for the cityscape and successfully killed off the mountains. So, to make the cityscape show, I tried using the Defender mentality and did something like this (this is grossly simplified as it doesn't contain the bit shifting of the ROM area to match ship movement. Roughly, in this example I am loaded cityscape from a static area that doesn;t rotate based on ship movement). So this basically creates a cityscape that is static in how it shows.

LF444: 
       LDA    (_ram94_shipVector),Y     ;5
       STA    GRP1           ;3

;rr marker
       LDA    (_ram9B_planetVector),Y     ;5 makes stars/mountains.
                             ;  _ram9B is FE00 for mountains
                             ;  _ram9B is FE1C for no mountains

;marker
       CMP    #$FF
       BNE    LF444a
;       LDA    #$0F
;       LSR
;       LSR
;       STA    WSYNC
;       STA    _ram84_invisoUnits
       LDA    $96               ; sets the playfield color?
       STA    COLUPF
       LDA    LFCDE,Y
       STA    PF0
       LDA    LFCDE,Y
       STA    PF1
       LDA    LFCDE,Y
       STA    PF2
       LDA    #$00
;end marker

LF444a:
       STA    ENAM1          ;3
       STA    ENABL          ;3


So basically, I re-used the area FE00 in Bank 2 that defines that starfield and mountains area and use a marker instead of the mountains to indicate where to start building the city down. At that point, I update the playfield with the cityscape. This allows the enemies and the ship to migrate below the skyline. And it actually works. But I have two problems.
  1. it seems that the extra processing in this area causing un-intended consequences for the horizontal update timing (screen jumps) and sometimes I get scren jumps, stella indicating that my screen rate goes over 60hz (typically with enemies on the screen too). So, I am struggling with the code addition and timings I need to maintain. Any suggestions?
  2. Updating the playfield seems to work for the bottom of the screen (I have other problems with it that I can debug out), but it bleeds into the radar area and score/extra lives/bombs) my guess is because this uses the playfield too. Am I missing something to allow playfield area updates where I am trying without bleed through on the top half (I attached a screenshot of this)

 

Really could use some help/advice. I am feeling better with my progress, but this is attempt #10 on an algorithm and how to do it over the course of a few weeks. So obviously I am struggling :-/

post-67063-0-85466600-1560019743_thumb.jpg

Link to comment
Share on other sites

1) Timing is *very* tight in Stargate...most lines have no free cycles at all (certainly not enough to update 3 PFs from Rom tables)...so you might need to resort to flickering the city if you still rely on all of the other existing display routines

 

2) Clear your PFs after the display has ended, or they bleed into the next frame.

Link to comment
Share on other sites

I pulled everything else except a compare, branch and Load Accumulator and those 12 cycles were too much for it to handle!

 

At this point, I'm not sure what else to cut out. I guess losing the starfield could be an option. But best I can tell that is 16 cycles at most. Do you know why this routine deals with the ship and planet vector twice in the same loop? Got any suggestions? I wasn't expecting this to be this tight!

Link to comment
Share on other sites

Flicker is the only thing I can think of to still maintain sprite display and PF lasers. The original Defender didn't need either (disappearing into the background), so it had plenty of cycle time to show a scrolling PF city. Of course, introducing PF flicker in this manner means that sprite management flicker could take a hit.

 

The way that this works is at some point low to the existing planet surface, decide if to branch out of the existing kernel if the frame count is odd or even. That is only a few cycles. In the new "city kernel" to be created at the branch destination, store the PF values (and the ship and enemy, if time remains). In this manner, you can ignore PF collision of sprites on the frames where the city is displayed.

Link to comment
Share on other sites

Flicker is the only thing I can think of to still maintain sprite display and PF lasers. The original Defender didn't need either (disappearing into the background), so it had plenty of cycle time to show a scrolling PF city. Of course, introducing PF flicker in this manner means that sprite management flicker could take a hit.

 

The way that this works is at some point low to the existing planet surface, decide if to branch out of the existing kernel if the frame count is odd or even. That is only a few cycles. In the new "city kernel" to be created at the branch destination, store the PF values (and the ship and enemy, if time remains). In this manner, you can ignore PF collision of sprites on the frames where the city is displayed.

 

Are you sure that the original Defender doesn't flicker? My assumption on flicker was that you have, what, 60 frames per second on NTSC. Best I can tell in the original defender is that the city was updated on each frame, but the ship and all enemies were not and were flickered.

 

So back to stargate. I was thinking something like frame 1 might have ship/enemies; frame 2 might have city, and back to 1 and so on. So, in looking at that, I added only two instructions to do a Load, compare and branch and believe it or not, those 8 cycles were too much and killed the display code. Best I can tell, there are 4 cycles free. I'm going to be honest, this may kill it for me. I just don't get enough about the display loop and TIA to understand where I can make compromises....

Link to comment
Share on other sites

Guess again...by losing the missile/ball to draw the planet, there is no need to reset NUSIZ1 and CTRLPF (as well as the preceding AND #$F0). 8 cycles right there. Load frame counter, LSR, branch = 8 cycles. There's actually 2 cycles free at the end of the scanline, too (worst case):

 

LF409:
       STA    WSYNC                   ;3
       STA    HMOVE                   ;3 3
       STA    COLUP0                  ;3 6
       LDA    (ship_vector),Y         ;5 11
       STA    GRP1                    ;3 14
       LDA    (planet_vector),Y       ;5 19
       STA    ENAM1                   ;3 22
       STA    ENABL                   ;3 25
       AND    #$F0                    ;2 27
       STA    NUSIZ1                  ;3 30
       STA    CTRLPF                  ;3 33
       DEY                            ;2 35
       BEQ    LF3FB                   ;2 37
       CPY    r97                     ;3 40
       BCS    LF42A                   ;2 42
       LDA    r96                     ;3 45
       STA    ship_vector             ;3 48
LF42A:
       LDA    #$00                    ;2 50
       STA    HMP0                    ;3 53
       CPY    rA1                     ;3 56
;       BCC    LF438                   ;2
;       STA    WSYNC                   ;3
;       STA    HMOVE                   ;3
;       BCS    LF444                   ;2 always branch
       BCS    LF43E                   ;2 58
       LDA    (object_gfx_vector),Y   ;5 63
       STA    GRP0                    ;3 66
       LDA    (object_color_vector),Y ;5 71
LF43E:
       STA    WSYNC                   ;3

 

BTW I was referring to flickering the city...which the original Defender does NOT do.

Link to comment
Share on other sites

LF409:
       STA    WSYNC                   ;3
       STA    HMOVE                   ;3 3
       STA    COLUP0                  ;3 6
       LDA    (ship_vector),Y         ;5 11
       STA    GRP1                    ;3 14
       LDA    (planet_vector),Y       ;5 19
       STA    ENAM1                   ;3 22
       STA    ENABL                   ;3 25
       bpl    SkipCity                ;2 27
       lda    frame_counter           ;3 30
       lsr                            ;2 32
       bcs    DrawCity                ;2 34
SkipCity:
       DEY                            ;2 36
       BEQ    LF3FB                   ;2 38
       CPY    r97                     ;3 41
       BCS    LF42A                   ;2 43
       LDA    r96                     ;3 46
       STA    ship_vector             ;3 49
LF42A:
       LDA    #$00                    ;2 51
       STA    HMP0                    ;3 54
       CPY    rA1                     ;3 57
;       BCC    LF438                   ;2
;       STA    WSYNC                   ;3
;       STA    HMOVE                   ;3
;       BCS    LF444                   ;2 always branch
       BCS    LF43E                   ;2 59
       LDA    (object_gfx_vector),Y   ;5 64
       STA    GRP0                    ;3 67
       LDA    (object_color_vector),Y ;5 72
LF43E:
       STA    WSYNC                   ;3

Drawcity tag would be on the preceding page...leading to a JMP instruction to the minikernel. This will limit the intrusion in the existing kernel.

 

The code which erases the planet and sends you to space would still function :)

Edited by Nukey Shay
Link to comment
Share on other sites

Ok, cool. Wow. Thank you sir. Let me give it a shot and some attempts to see what I can get out of this.

 

Back to my original question on the city. When you say clear my PFs after I draw the city, is that simply setting PFs to 0x00 after the last horizontal line it taken care of because that doesn't seem to work.

Link to comment
Share on other sites

I also do not fully understand why they didn't use the whole game display area (see the gap). I assume maybe because of the TIA defect where the "lines" show up.... but I made the radar lower bar go the whole length of the screen easily enough.

post-67063-0-46167900-1560203744_thumb.jpg

Edited by rallyrabbit
Link to comment
Share on other sites

LF409:
       STA    WSYNC                   ;3
       STA    HMOVE                   ;3 3
       STA    COLUP0                  ;3 6
       LDA    (ship_vector),Y         ;5 11
       STA    GRP1                    ;3 14
       LDA    (planet_vector),Y       ;5 19
       STA    ENAM1                   ;3 22
       STA    ENABL                   ;3 25
       bpl    SkipCity                ;2 27
       lda    frame_counter           ;3 30
       lsr                            ;2 32
       bcs    DrawCity                ;2 34
SkipCity:
       DEY                            ;2 36
       BEQ    LF3FB                   ;2 38
       CPY    r97                     ;3 41
       BCS    LF42A                   ;2 43
       LDA    r96                     ;3 46
       STA    ship_vector             ;3 49
LF42A:
       LDA    #$00                    ;2 51
       STA    HMP0                    ;3 54
       CPY    rA1                     ;3 57
;       BCC    LF438                   ;2
;       STA    WSYNC                   ;3
;       STA    HMOVE                   ;3
;       BCS    LF444                   ;2 always branch
       BCS    LF43E                   ;2 59
       LDA    (object_gfx_vector),Y   ;5 64
       STA    GRP0                    ;3 67
       LDA    (object_color_vector),Y ;5 72
LF43E:
       STA    WSYNC                   ;3

Drawcity tag would be on the preceding page...leading to a JMP instruction to the minikernel. This will limit the intrusion in the existing kernel.

 

The code which erases the planet and sends you to space would still function icon_smile.gif

 

 

Ok, but jumping out of the kernel and into the minikernel I am making, don't I need to jump back into the kernel at some point after I draw the city piece during the flicker? Maybe back to LF457 or would maybe LF444?

Link to comment
Share on other sites

I also do not fully understand why they didn't use the whole game display area (see the gap). I assume maybe because of the TIA defect where the "lines" show up.... but I made the radar lower bar go the whole length of the screen easily enough.

 

Because HMOVE is hit on every scanline during the main display (needs to be done when stars/planet and objects are repositioned...doing it every scanline removes the question "should I?", saving a few cycles).

 

I'll try to dig up some time in the next week to have a demo of a city minikernel. First test didn't do so hot (flicker management needs a bit of work).

Link to comment
Share on other sites

 

Because HMOVE is hit on every scanline during the main display (needs to be done when stars/planet and objects are repositioned...doing it every scanline removes the question "should I?", saving a few cycles).

 

I'll try to dig up some time in the next week to have a demo of a city minikernel. First test didn't do so hot (flicker management needs a bit of work).

 

Mine looks pretty bad too. I am trying to figure out if I am jumping back at the right point of the main kernel too... my flicker so far is WAY too slow

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