rallyrabbit Posted April 5, 2019 Share Posted April 5, 2019 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. defender-arcade_1.asm defender-arcade_2.asm Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 7, 2019 Share Posted April 7, 2019 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. Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 10, 2019 Author Share Posted April 10, 2019 This was fantastic. Just that one hint at the top gave me enough information to sort out a good portion of the code. Thanks! Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 12, 2019 Author Share Posted April 12, 2019 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.... Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 12, 2019 Share Posted April 12, 2019 (edited) 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 Defendr2.asm Edited April 14, 2019 by Nukey Shay Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 13, 2019 Author Share Posted April 13, 2019 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 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 13, 2019 Share Posted April 13, 2019 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. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 13, 2019 Share Posted April 13, 2019 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. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 13, 2019 Share Posted April 13, 2019 Nevermind...the kernel just displays bitmap values (going upward in Rom) until a zero is reached. No size variable. Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 14, 2019 Author Share Posted April 14, 2019 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. Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 14, 2019 Author Share Posted April 14, 2019 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. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 14, 2019 Share Posted April 14, 2019 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. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 14, 2019 Share Posted April 14, 2019 (edited) 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 April 14, 2019 by Nukey Shay Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 17, 2019 Author Share Posted April 17, 2019 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? Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 18, 2019 Share Posted April 18, 2019 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. Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 21, 2019 Author Share Posted April 21, 2019 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.... Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 21, 2019 Share Posted April 21, 2019 (edited) 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 April 21, 2019 by Nukey Shay Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 21, 2019 Author Share Posted April 21, 2019 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. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 22, 2019 Share Posted April 22, 2019 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 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 22, 2019 Share Posted April 22, 2019 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! Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 22, 2019 Share Posted April 22, 2019 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 Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 22, 2019 Author Share Posted April 22, 2019 Its weird, I moved the graphics for the lander and mutant into FC from FF (updated all the tables). So, the lander gets glitchy occassionally when being destroyed. As soon as I move it back to FF, it starts working fine again. This makes me think that something else is up with the mapping that I am not quite figuring out just yet. So graphics compression is taking a bit more time. I did actually get some code in to change the radar to look more like Defender 1 (trying to get some small wins while doing this). so I have a bar going across almost the entire top of the play area and a full box around the radar area. So, hey, that's kind of cool. I actually found a few places where I could change branching/instructions around to save some cycles and keep the address space uniform. Now back to the graphics..... Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 23, 2019 Share Posted April 23, 2019 +And the color tables? Gotta be on the same page as the bitmap(s). Why move stuff outta $FF? No wasted space there. Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 23, 2019 Author Share Posted April 23, 2019 +And the color tables? Gotta be on the same page as the bitmap(s). Why move stuff outta $FF? No wasted space there. My thought was, remove enemies which is somewhat what PacManPlus did in Defender Arcade (removing unique Phred, and the guppy completely, I may have to dump the Dynamo too). At that point, consolidate everything up to create as much free space as possible. The thought there is that since there isn't enough free RAM without drastically changing the program, that I would take the "bitmap" idea for the cityscape, but I need to put that somewhere and the best idea was to do in gigantic chunk at the bottom of page 2. Like you said, I need 160 to 240 bytes free for that. On top of that, I need space for the routines to handle the cityscape too. I fixed the glitch, which seemed to be a graphics bitmap spacing thing, which I am not sure I fully understand. I moved the lander FCA0 to FCA9 which gave me 2 0x00 rows at the bottom at FCA0 and FCA1. But, that was casuing a glitch that was making a random and dramatic line of graphics interpreted garbage that would show up from the top to bottom of the pay area for one cycle of the counter. So, I shifted it down to FCA3 to FCAC and let FCA0-FCA2 be 0x00 lines as well; which seemed to solve that, which I cannot explain. I can work with it. I guess one of the things I am surprised as are the two ships (one ship with person). The fall at the end of large 0x00 defined graphics area used for other things. So it looks like the ship reads in a large amount of lines above the end of the ship (including the 0x00 space) to draw the ship graphic. So in reality it appears the ship is drawn across a whole column of the play area, it just happens that most of it is 0x00 so is unseen. ITs not the way I was expecting this to be either, which means I'll have trouble consolidating free space without changing the algorithms that draw the ship/ship with person too. Roadblocks that I'll have to overcome. I'm just a bit surprised at how some of this works. In some cases I see coding that could majorly be consolidated, and in other places, code that is majorly compact and in other places I see places where space is just, for lack of a better term, wasted. Quote Link to comment Share on other sites More sharing options...
rallyrabbit Posted April 25, 2019 Author Share Posted April 25, 2019 Well all my glitches you out to be a storage location naming problem in page 1. Question, is there any speed reason that all the custom screen images in LFA3B are in close areas of ROM. Is there that much of a speed advantage? Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.