(Link to AcmlmWiki) Offline: thank ||bass
Register | Login
Views: 13,040,846
Main | Memberlist | Active users | Calendar | Chat | Online users
Ranks | FAQ | ACS | Stats | Color Chart | Search | Photo album
06-26-24 07:28 PM
0 users currently in ROM Hacking.
Acmlm's Board - I3 Archive - ROM Hacking - Enemy Sprite counter, 2nd attempt New poll | |
Add to favorites | Next newer thread | Next older thread
User Post
Kailieann



 





Since: 11-18-05

Last post: 6337 days
Last view: 6337 days
Posted on 11-25-05 01:31 AM Link | Quote
Okay, thanks to BMF's Sprite Creation routine, I've come up with a potential solution to my Enemy Counter problem.

Note that this is theoretical, hastily written, and completely untested, any feedback or suggestions would be highly welcome.

Now, instead of coming up with a way to count how many enemies have been killed, this version uses LevelASM to create the sprites needed, and then continuously checks to see if they're still in use.

This will be done on a one-screen level with borders, so that the sprites won't just vanish when they go offscreen. There will also be a loading zone prior to the level with the counter, to clean the special level settings in case the player has to restart due to death.

Also note that $enemy_counter isn't strictly necessary for the code as is, but I figured it might be useful if I wanted to use something like the Level Names hack to show the player how many enemies are left.

Level Initialization routine

--- LDA $level_init_flag ;; Unused RAM address that tells LevelASM the status of the custom code
--- CMP #$01 ;; Arbitrary 'code is active' value
--- BEQ Main Level routine ;; Goes to the main code if the level has already been initialized
--- LDA #$01 ;; Arbitrary 'code is active' value
--- STA $level_init_flag ;; Sets 'code is active' status
--- LDA #$08 ;; Arbitrary number of enemies to use (I'd probably use fewer)
--- STA $enemy_counter
--- LDA #$FF ;; Binary flags (1 = enemy active)
--- STA $enemy_status
--- LDX #$08 ;; Arbitrary number of enemies to use

Sprite Creation loop
(this is mostly the same as BMF's 'Start of code')

--- LDA #$08
--- STA $14C8, X
--- LDA $sprite_number
--- STA $9E, X
--- LDA $xpos_low
--- STA $E4, X
--- LDA $xpos_high
--- STA $14E0, X
--- LDA $ypos_low
--- STA $D8, X
--- LDA $ypos_high
--- STA $14D4, X
--- JSL $07F7D2
--- DEX ;; Lower the number of enemies that still need to be created
--- CPX #$00 ;; Checks to see if enemies still need to be created
--- BNE Sprite Creation loop
--- RTL ;; End LevelASM code for current frame

Main Level routine

--- JSL Sprite Test loop
--- LDA $enemy_counter
--- CMP #$00
--- BEQ End Level routine ;; Goes to level end sequence if no enemies remain
--- RTL ;; End LevelASM code for current frame

This next part is where my inexperience with ASM really starts to show. If there's an easier way to do this, for the love of god, TELL ME.
Especially since I don't think there's a way to change the values used by the ANDs, which would mean I'd have to rewrite the main loop segment for each sprite, or give each sprite their own RAM address for the status flags.

Sprite Test loop

--- LDX #$08 ;; Number of enemies to check
(start of main loop segment)
--- LDA $enemy_status ;; Load enemy status flags
--- AND #$xx ;; AND flags with current enemy flag (80, 40, 20, 10, 08, 04, 02, 01)
--- CMP #$00 ;; Check to see if current enemy flag is unset
--- BEQ end of main loop segment ;; Exit current loop if enemy is already dead
--- LDA $14C8, X ;; Load enemy status flag
--- CMP #$08 ;; Check to see if sprite is currently in use
--- BNE end of main loop segment ;; Exit current loop if enemy isn't dead yet
--- LDA $enemy_status ;; Load enemy status flags
--- AND #$xx ;; Unset current enemy flag (7F, BF, DF, EF, F7, FB, FD, FE)
--- STA $enemy_status ;; Store new enemy status flags
--- LDA $enemy_counter ;; Load enemy counter
--- DEC ;; Decrement enemy counter
--- STA $enemy_counter ;; Store enemy counter
--- CMP #$00 ;; Check to see if that was the last enemy
--- BEQ end of sprite test loop
(end of main loop segment)
--- DEX ;; Decrease number of enemies to check
(return to main loop segment)
--- RTL ;; Return to Main Level routine

This part isn't exactly perfect yet, either. It'll end the level, but it'll do so pretty darn fast, since the only way I know how to end levels is by writing to $7E1493, and since all the code will be executed on the same frame...
Is there any way to delay code execution?

End Level routine

--- STZ $level_init_flag ;; Clears custom level settings ($enemy_status and $enemy_counter should already be #$00, so no need to clear them)
--- LDA #$FF ;; Load 'screen goes dark' value
--- STA $1493 ;; Make the screen go dark and Mario begin his victory march
--- LDA #$01 ;; Load 'this level is over' value
--- STA $1493 ;; Tell the game that the level is over
--- STZ $1493 ;; Fade to overworld

Am I the only one who thinks it's weird that 1493:01 doesn't end the level automatically? It waits until 00 has been written after 01, which is even stranger since 00 is the default value anyways.
Be easier if there was just an End Level subroutine I could jump to.
HyperHacker

Star Mario
Finally being paid to code in VB! If only I still enjoyed that. <_<
Wii #7182 6487 4198 1828


 





Since: 11-18-05
From: Canada, w00t!
My computer's specs, if anyone gives a damn.
STOP TRUNCATING THIS >8^(

Last post: 6338 days
Last view: 6338 days
Posted on 11-25-05 09:49 PM Link | Quote
That certainly is odd, seeing as you do STA and then STZ right afterward. Unless that's some special hardware address or an interrupt happens to occurr right between those (which is like a 1 in 4 million chance), the code that handles that address wouldn't even know you'd written a 1, because you'd have written a 0 again right afterward.
Kailieann



 





Since: 11-18-05

Last post: 6337 days
Last view: 6337 days
Posted on 11-26-05 01:08 AM Link | Quote
Like I said, I haven't tested it yet. It may or may not work in LevelASM, I don't know. I only found out about it by playing with ZSNES's cheat function.
7E149300: does nothing. 7E149301: does nothing. 7E149300 after 7E149300: fade to overworld. But it'll mess up the palettes if you try to do that while the level is active, hence the 7E1493FF (fade to black) before it. I'm not sure but I think it was 7E14939E that brings up the timer = points part.

Speaking of I also found the address for the Timer x 50 that gets added to your score at the end of the level. 7E0F40 I think. Two bytes, and I think 100 points lower than the actual score display.
Could be useful for anyone who wants to give the player some points for clearing a no-timer level.

Anyways, I'm kinda thinking now that instead of trying to LevelASM my way out of a level, I'll just spawn goal spheres instead.
Sukasa

Birdo
Not quite as active as before.
Xkeeper supporter
Xk > ||bass
I IP Banned myself! Twice!








Since: 11-17-05
From: Somewhere over there

Last post: 6338 days
Last view: 6337 days
Posted on 11-28-05 09:44 PM Link | Quote
Also, I have another idea how to do this: create the sprites in LM, then make a block that sets some RAM offset (which resets every time you enter a level) to a number other than 0, then place that in the midle of your screen.

Then, also have the block stop scrolling for now.

After that, have the LevelASM code continuously check the number of sprites left alive, and if there are none (X will return either 1 or zero [not sure which] when there are no sprites left), you can either set the scrolling back on, or, if you wanted the level to take and exit or end, you can do that as well.

Hey, if you were really good (you are), you could have the code LDA $002132 after LDA #$EF STA $002121, and either end the level, take the exit, or resume scrolling, depending on what entry $EF in the level palette is, using CMP's and the like!
Kailieann



 





Since: 11-18-05

Last post: 6337 days
Last view: 6337 days
Posted on 11-28-05 09:58 PM Link | Quote
Originally posted by Sukasa
After that, have the LevelASM code continuously check the number of sprites left alive


Yes, but the original problem was that I didn't know how to check how many sprites are left alive.
It occurred to me to just check the all 12 sprite slots, but they're also used for non-enemies, and I figured instead of checking to see what each sprite was, it would be easier to just forcefully shove in the sprites I wanted.

Boy, was I an idiot.

But I'm thinking of putting project 0 on hold and opting for project -1 instead. Which will only work if I can figure out how to manually control Layer 2's position, since none of the auto-scroll commands are suitable for my purposes.


(edited by Kailieann on 11-28-05 09:01 PM)
Add to favorites | Next newer thread | Next older thread
Acmlm's Board - I3 Archive - ROM Hacking - Enemy Sprite counter, 2nd attempt |


ABII

Acmlmboard 1.92.999, 9/17/2006
©2000-2006 Acmlm, Emuz, Blades, Xkeeper

Page rendered in 0.014 seconds; used 378.60 kB (max 455.94 kB)