Points of Required Attention™
Please chime in on a proposed restructuring of the ROM hacking sections.
Views: 88,517,650
Main | FAQ | Uploader | IRC chat | Radio | Memberlist | Active users | Latest posts | Calendar | Stats | Online users | Search 05-03-24 02:08 AM
Guest: Register | Login

0 users currently in SMW Hacking | 3 guests

Main - SMW Hacking - Question: Spawning a sprite in-level? [ASM] New thread | New reply


Goldensunboy
Posted on 07-10-07 06:15 AM Link | Quote | ID: 53614


Goomba
Level: 15

Posts: 1/32
EXP: 14280
Next: 2104

Since: 04-19-07
From: Albany, GA

Last post: 5715 days
Last view: 5715 days
How would I go about popping a sprite out of thin air in mid-level, once certain conditions are met? I have a code I'm working on (called each frame by LevelASM, thanks BMF) that requires, at a certain point, a sprite to be spawned, move, and transform into a map16 block. (I found out how to do that finally)

I have taken a long break from SMW hacking until now, and I am a bit rusty on which sprite tables are important in spawning a sprite, and what the bytes written to the tables would have to be. (ex: write byte Y to table Z and it will spawn sprite Y) Help would be very much appreciated, because I can't find (or at least haven't found yet) any threads with information on important sprite tables.

Also, could I have a little help on how to find the sprite index of the first unused sprite? Of course, that would be necessary in creating a sprite from scratch, because the current sprite's index isn't easily accessible anywhere. (the code isn't contained in a sprite's code)

Thanks!

Raccoon Sam
Posted on 07-10-07 06:46 AM Link | Quote | ID: 53623


Cobrat
Level: 56

Posts: 282/672
EXP: 1380755
Next: 17421

Since: 02-19-07
From: Hi

Last post: 3474 days
Last view: 2705 days
I can't help you too much with this problem of yours, but I can give a link to a topic I think this might go into.

____________________


Goldensunboy
Posted on 07-10-07 07:36 AM Link | Quote | ID: 53637


Goomba
Level: 15

Posts: 2/32
EXP: 14280
Next: 2104

Since: 04-19-07
From: Albany, GA

Last post: 5715 days
Last view: 5715 days
I already read the stickies and found no useful information about updating tables concerning sprite creation.

mikeyk
Posted on 07-10-07 07:40 AM (rev. 4 of 07-11-07 10:07 AM) Link | Quote | ID: 53640


Paragoomba
Level: 22

Posts: 13/74
EXP: 50005
Next: 8345

Since: 06-11-07

Last post: 6054 days
Last view: 4130 days
This is my bread and butter

If you are just dealing with regular sprites, this is a skeleton of the routine that you'll need to run. If you want to create a custom sprite rather than a regular one, there are a few differences. Let me know if you want to know.

; This routine loads Y with the index of the first free sprite slot
; If all slots are full Y = #$FF. This is why we return if we get a
; negative value.
22 E4 A9 02 JSL.L $02A9E4
30 XX BMI Return

; Next set the sprite status into $14C8,Y
; Possible values are:
; 1 - Initialization
; 2 - Falling off screen (hit by star, shell, etc)
; 3 - Smushed
; 4 - Spin Jumped
; 5 - ?
; 6 - End of level turn to coin
; 7 - Nothing, points to return
; 8 - Normal
; 9 - Stationary (Carryable, flipped, stunned)
; A - Kicked
; B - Being carried
; C - Power up created from carrying a sprite through goal
;
; You probably want to use #$01 or #$08, depending if you want
; the initialization routine to be run
A9 XX LDA.B #$XX
99 C8 14 STA.W $14C8,Y

; Set the sprite to generate
A9 XX LDA.B #$XX
99 9E 00 STA.W 009E,Y

; Set X/Y Positions
; ...
99 E4 00 STA.W 00E4,Y
; ...
99 E0 14 STA.W 14E0,Y
; ...
99 D8 00 STA.W 00D8,Y
; ...
99 D4 14 STA.W 14D4,Y

; This subroutine clears out all of the sprite table values,
; and loads the new values for the 6 tweaker tables.
; It requires the sprite index to be in X
DA PHX
BB TYX
22 D2 F7 07 JSL.L $07F7D2
FA PLX

; (EDIT: moved this below the table clearing subroutine)
; Set sprite direction
; ...
99 7C 15 STA.W 157C,Y


That really should do it for the basics. Everything else would just be gravy.

Goldensunboy
Posted on 07-10-07 08:33 AM Link | Quote | ID: 53649


Goomba
Level: 15

Posts: 3/32
EXP: 14280
Next: 2104

Since: 04-19-07
From: Albany, GA

Last post: 5715 days
Last view: 5715 days
Unbelievable.

And most of the work's already done for me? I really want to thank you, mikeyk! This is very helpful and has made my day.

I just wanted to spawn a sprite out of nowhere. The sprite I'm trying to spawn (as in spawn, 1 - initialization, maybe?) is a custom sprite I made that moves in one of four linear directions, determined by a RAM byte that's pretty much just set before the sprite's ever spawned. It moves two pixels per frame for eight frames in that direction, then disappears and turns the map16 block under it into another one (determined by other RAM addresses)

I am attempting to make it look like a block moves, or sort of slides, in a direction one block length. (16 pixels) The code works like a charm so far, and if I finish this code, I will release a mini-hack in which it will all be clear why I am doing that.

I'm not quite sure what you mean by regular or custom sprite, all I know is that the one that I'm trying to spawn is already inserted with SpriteTool, and is working properly, and I just tweak it a little as needed as I'm working on code.

Oh, and which byte should be written to have the initialization run, #$00 or #$08, and which part of the code does this byte go in?

Thanks again, mikeyk!

mikeyk
Posted on 07-10-07 09:09 AM Link | Quote | ID: 53656


Paragoomba
Level: 22

Posts: 14/74
EXP: 50005
Next: 8345

Since: 06-11-07

Last post: 6054 days
Last view: 4130 days
If you are looking to spawn a sprite that was inserted with Sprite Tool, then you need to make a few modifications. I'll post back tomorrow when I have my notes on hand.

Glad I'm able to help you out. It sounds like you have a pretty cool idea brewing -- I'll be anxious to see the final result

Goldensunboy
Posted on 07-10-07 09:25 AM (rev. 2 of 07-10-07 08:52 PM) Link | Quote | ID: 53658


Goomba
Level: 15

Posts: 4/32
EXP: 14280
Next: 2104

Since: 04-19-07
From: Albany, GA

Last post: 5715 days
Last view: 5715 days
Then I might as well go to bed now.

I am currently hand-documenting the routine and outlining everything in the notepad file i'm using to make the assembly. Those darn tracers always so no to me, so I find it easier (although more tedious) to do it that way. All I need to do now is turn a map16 location into a sprite's x/y low bytes.

G'night, and thanks again, mikeyk!

Edit: I set it up as a test so that if I press left, it spawns the sprite at a set location. (I'm just trying to perfect this process right now, I'll get to setting where it spawns later) It seems like it's spawning a different sprite, because I also had one of my sprites added in at the beginning of the level anyway with Lunar Magic; I set a breakpoint in Geiger's SNES debugger to a ram address that's only used by the sprite.

It broke every frame that that ram address was read or written to for the sprite that was there anyway from Lunar Magic (good so far...) then, it never broke when I pressed left and spawned the sprite out of nothing. it didn't crash, but it behaved differently, because it was rapidly moving left and right, which isn't what it's supposed to do. I know it spawned properly, but I'm thinking it spawned the wrong one? Does it have to do with Lunar Magic's "Extra Info" field required by SpriteTool sprites?

Some extra information: The graphics of the sprite that pressing left spawned were the same as the sprite I would have gotten if I inserted one with Lunar Magic and left the "Extra Info" as 0.

mikeyk
Posted on 07-10-07 10:22 PM (rev. 5 of 07-12-07 07:22 PM) Link | Quote | ID: 53718


Paragoomba
Level: 22

Posts: 15/74
EXP: 50005
Next: 8345

Since: 06-11-07

Last post: 6054 days
Last view: 4130 days
This code is for generating a Sprite Tool sprite. Hopefully I didn't mess anything up. The major differences are:
1. Store the sprite to create into 7FAB9E rather than 9E
2. Load the 6 Tweaker bytes from the custom sprite table, not the original sprite table
3. Store processing bits to $7FAB10

; This routine loads Y with the index of the first free sprite slot
; If all slots are full Y = #$FF. This is why we return if we get a
; negative value.
JSL $02A9E4
BMI Return

; Put sprite index in X, as the called routines require this
PHX
TYX

; Set the sprite to generate into the custom sprite number
LDA #$XX
STA $7FAB9E,X

; Set the "normal" sprite status into $14C8 table
LDA #$08
STA $14C8,X

; Set X/Y Positions
; (insert code to set up position)
STA $00E4,X
; (insert code to set up position)
STA $14E0,X
; (insert code to set up position)
STA $00D8,X
; (insert code to set up position)
STA $14D4,X

PHY
; This subroutine clears out all of the sprite table values,
; It requires the sprite index to be in X
JSL $07F7D2
; This routine loads the 6 Tweaker properties for the custom sprite
; It also puts the address of the INIT routine in $00
JSL $0187A7
; Set as a custom sprite
LDA #$88
ORA #$01 ; <---Only if you want the extra bit to be set
STA $7FAB10,X
; Call INIT routine on sprite
PHK
PER.W #$0002
JML ($0000)
PLY

PLX

Goldensunboy
Posted on 07-10-07 11:31 PM Link | Quote | ID: 53726


Goomba
Level: 15

Posts: 5/32
EXP: 14280
Next: 2104

Since: 04-19-07
From: Albany, GA

Last post: 5715 days
Last view: 5715 days
After putting in this information, I tried it and it froze. It didn't crash (the animation stopped but the music kept going), but it got stuck in an endless loop:


$06/F620 A8 TAY A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F621 0A ASL A A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F622 AA TAX A:FFFE X:FFFE Y:FFFF P:eNvmxDizC
$06/F623 BF 00 E0 12 LDA $12E000,x[$12;DFFE] A:FFFE X:FFFE Y:FFFF P:eNvmxDizC
$06/F627 C9 00 02 CMP #$0200 A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F62A B0 F4 BCS $F4 [$F620] A:FFFF X:FFFE Y:FFFF P:eNvmxDizC

$06/F620 A8 TAY A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F621 0A ASL A A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F622 AA TAX A:FFFE X:FFFE Y:FFFF P:eNvmxDizC
$06/F623 BF 00 E0 12 LDA $12E000,x[$12;DFFE] A:FFFE X:FFFE Y:FFFF P:eNvmxDizC
$06/F627 C9 00 02 CMP #$0200 A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F62A B0 F4 BCS $F4 [$F620] A:FFFF X:FFFE Y:FFFF P:eNvmxDizC

$06/F620 A8 TAY A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F621 0A ASL A A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F622 AA TAX A:FFFE X:FFFE Y:FFFF P:eNvmxDizC
$06/F623 BF 00 E0 12 LDA $12E000,x[$12;DFFE] A:FFFE X:FFFE Y:FFFF P:eNvmxDizC
$06/F627 C9 00 02 CMP #$0200 A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F62A B0 F4 BCS $F4 [$F620] A:FFFF X:FFFE Y:FFFF P:eNvmxDizC

$06/F620 A8 TAY A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F621 0A ASL A A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F622 AA TAX A:FFFE X:FFFE Y:FFFF P:eNvmxDizC
$06/F623 BF 00 E0 12 LDA $12E000,x[$12;DFFE] A:FFFE X:FFFE Y:FFFF P:eNvmxDizC
$06/F627 C9 00 02 CMP #$0200 A:FFFF X:FFFE Y:FFFF P:eNvmxDizC
$06/F62A B0 F4 BCS $F4 [$F620] A:FFFF X:FFFE Y:FFFF P:eNvmxDizC

It got stuck in this loop a good while after the code, I pressed "step into" many times and never reached it manually.

I really don't understand what's going on here, I need some help please!

Thanks!

mikeyk
Posted on 07-11-07 12:02 AM Link | Quote | ID: 53729


Paragoomba
Level: 22

Posts: 16/74
EXP: 50005
Next: 8345

Since: 06-11-07

Last post: 6054 days
Last view: 4130 days
There's really no way to tell how you ended up in that loop. Could you at least post the routine that you created to generate the sprite?

Goldensunboy
Posted on 07-11-07 03:59 AM Link | Quote | ID: 53784


Goomba
Level: 15

Posts: 6/32
EXP: 14280
Next: 2104

Since: 04-19-07
From: Albany, GA

Last post: 5715 days
Last view: 5715 days
------------------+---handles left-moving sprite creation

LDA $7E0016 | AD 16 00 \
CMP #$02 | C9 02 |-executes this code block if
BNE "next" | D0 43 / left is pressed
|
LDA #$00 | A9 00 \
STA $7FFF1F | 8F 1F FF 7F |-sets up RAM bytes for sprite
LDA $7FFF1A | AF 1A FF 7F | code: direction, and number
TAX | AA | of graphic tile.
INX | E8 |
LDA $7FFF00,x | BF 00 FF 7F |
STA $7FFF1D | 8F 1D FF 7F /
LDA $7FFF19 | AF 19 FF 7F \
INC A | 1A |-disables controller for 8
STA $7FFF19 | 8F 19 FF 7F | frames if left was pressed
LDA #$08 | A9 08 |
STA $7FFF1E | 8F 1E FF 7F /
------------------|
JSL $02A9E4 | 22 E4 A9 02 \---get index for first free sprite
BMI "end" | 30 1A / slot
|
LDA #$08 | A9 08 \-create sprite
STA $14C8,y | 99 C8 14 /
|
PHX | DA
TYX | BB
LDA #$11 | A9 11
STA $7FAB9E,x | 9F 9E AB 7F
PLX | FA
|
LDA #$00 | A9 00 \
STA $14E0,y | 99 E0 14 |-set hardcoded X/Y high bytes for
LDA #$01 | A9 01 | sprite creation
STA $14D4,y | 99 D4 14 /
|
BRA "past end" | 80 01 <---temporary code finisher reached by branching
RTL | 6B
|
LDA #$00 | A9 00 \
STA $00D8,y | 99 D8 00 |-temporarily hardcoded low bytes for sprite
LDA #$10 | A9 10 | creation
STA $00E4,y | 99 E4 00 /
PHY | 5A
PHX | DA
TYX | BB
JSL $07F7D2 | 22 D2 F7 07
JSL $0187A7 | 22 A7 87 01
LDA $08 | A9 08
STA $7FAB10,x | 9F 10 AB 7F
|
PLX | FA
PLY | 7A
RTL | 6B


The "sets up RAM bytes for direction, and number of graphic tile" uses some free ram to remember some custom info; for direction, I (respectively) store 0, 1, 2,or 3 to 7FFF1F. (in this case, left, since this code is executed only if you press left at any time) At 7FFF00 is a table of 25 bytes used for a secondary internal tilemapping. (graphics determined by the bytes in the table)

Everything below the line about 35% of the way through the code is adapted from your code. The "hardcoded x/y high bytes" for the sprite will never change, and the "temporarily hardcoded" bytes are just there for the time being to set an easily visible spawn point for the sprite until I start working on the routine that determines where it spawns under certain conditions.

mikeyk
Posted on 07-11-07 08:08 AM Link | Quote | ID: 53835


Paragoomba
Level: 22

Posts: 17/74
EXP: 50005
Next: 8345

Since: 06-11-07

Last post: 6054 days
Last view: 4130 days
Try putting 88 into 7FAB10 instead of 08. I made an error in my original post, and edited it a few minutes after making it. Other than that, it looks good. So let me know how it goes

Goldensunboy
Posted on 07-11-07 09:18 AM Link | Quote | ID: 53847


Goomba
Level: 15

Posts: 8/32
EXP: 14280
Next: 2104

Since: 04-19-07
From: Albany, GA

Last post: 5715 days
Last view: 5715 days
Thanks, that one byte change worked! However, the sprite now spawns, but turns into a map16 block immediately. I had it set so that upon initialization, a free RAM byte is STZ'd and is used as a counter until the sprite becomes a block. I'm thinking the sprite isn't running the "dcb init" thing, and so it sees the un-reset counter, and just turns into a block immediately. Now, this is when I spawned a sprite after already having one in the level to see if it works properly when the one spawned is a second one. When I took the sprite out of the level then spawned one, it kept going to the left for a few seconds, then turned into a map16 block. Pressing left after that first one then just started making the ones that spawn and immidiately transform.

Is there a way to make it run the "dcb INIT" code, too? If it's really too much of a hassle to do that, I can and already have an idea of how I could be able to change the sprite's code to work around that. However, I might run into a few more problems later if I do that.

Thanks for all your help so far! I think I'm learning alot about these sprites from this experience, and I could maybe make a custom sprite or two in the future from what I'm learning here.

mikeyk
Posted on 07-11-07 10:06 AM Link | Quote | ID: 53853


Paragoomba
Level: 22

Posts: 18/74
EXP: 50005
Next: 8345

Since: 06-11-07

Last post: 6054 days
Last view: 4130 days
I believe if you set $01 rather than $08 into $14C8,Y, the INIT routine will run.

It's been awhile since I looked into the ASM hacks that Sprite Tool installs, so I'd been a bit fuzzy with the details. I just had an opportunity to look at the source, so I think I'm starting to remember it a little better.

RAM table $14C8 is the sprite's status. It can take the values 01-0C (I listed them out in my first post in this thread). Sprite tool only deals with status 01 (calls INIT routine) and 08 (calls MAIN routine). All other statuses are passed on to the original SMW handling code with the "acts like" byte as the sprite number ($9E).

Goldensunboy
Posted on 07-11-07 07:00 PM Link | Quote | ID: 53922


Goomba
Level: 15

Posts: 9/32
EXP: 14280
Next: 2104

Since: 04-19-07
From: Albany, GA

Last post: 5715 days
Last view: 5715 days
I don't think it's running the sprite code now. The sprite spawns and just falls through everything offscreen now.

Since you can only write one byte to $14C8,y, would it be impossible to run both? Or too much of a hassle? Again, you've done more than enough for me, and if it would be hard to do so, I could write the code in such a way that it works around it.

Sukasa
Posted on 07-12-07 09:37 AM Link | Quote | ID: 54128


Red Birdo
Level: 92

Posts: 344/2112
EXP: 7693428
Next: 63509

Since: 02-19-07

Last post: 4454 days
Last view: 3226 days
Posted by Goldensunboy
I don't think it's running the sprite code now. The sprite spawns and just falls through everything offscreen now.


Um, that would mean your code runs, but it's not working right likely it isn't hitting the ground properly.

Goldensunboy
Posted on 07-12-07 06:44 PM (rev. 2 of 07-12-07 07:07 PM) Link | Quote | ID: 54181


Goomba
Level: 15

Posts: 14/32
EXP: 14280
Next: 2104

Since: 04-19-07
From: Albany, GA

Last post: 5715 days
Last view: 5715 days
I've decided at this point that I'll just make it so all the code is in the sprite code, nothing in the "dcb INIT" stuff. Time to do some heavy tracing.

Edit: It all works! Thank you mikeyk! The sprite spawns when I press left, moves left 16 pixels, and turns into a map16 block. You have been a great help. I can do the rest without any extra help (hopefully), and it certainly shouldn't involve generating sprites.

Oh, thanks to you too, Sukasa; I didn't think anything was wrong with my code, but there was an error in it that wasn't significant until some other codes I put in were in play. I wouldn't have checked if I thought there was something wrong with the sprite routine.

I'll finish up the code and release a mini-hack soon, maybe a few days or so.

mikeyk
Posted on 07-12-07 07:21 PM Link | Quote | ID: 54182


Paragoomba
Level: 22

Posts: 20/74
EXP: 50005
Next: 8345

Since: 06-11-07

Last post: 6054 days
Last view: 4130 days
I went back and looked at how I handled things in the generic generator that I include in Sprite Tool. It looks like I gave you a little bit of bad information. You do want to set 08 at the sprite status, and you can just call the INIT routine from your sprite generating subroutine. I edited my previous code post to be accurate.

Goldensunboy
Posted on 07-12-07 08:22 PM Link | Quote | ID: 54196


Goomba
Level: 15

Posts: 15/32
EXP: 14280
Next: 2104

Since: 04-19-07
From: Albany, GA

Last post: 5715 days
Last view: 5715 days
Well, it's a little late now, I already reprogrammed the sprite so it doesn't have any necessary codes in "dcb INIT". Your edit may help in the future though, if I felt like using this thread as a reference if I tried to spawn a sprite or custom sprite again.

Sorry to have troubled you so much about this sprite issue, but it is coming together now; thanks for bearing with me. I already programmed the same routine to work when you press up; that is, the sprite moves up 16 pixels and turns into a map16 block. Just two more directions, and a few more critical routines, and it'll be done.

Main - SMW Hacking - Question: Spawning a sprite in-level? [ASM] New thread | New reply

Acmlmboard 2.1+4δ (2023-01-15)
© 2005-2023 Acmlm, blackhole89, Xkeeper et al.

Page rendered in 0.055 seconds. (341KB of memory used)
MySQL - queries: 127, rows: 165/166, time: 0.032 seconds.