Is there any other way I can do this? The "split" program doesn't seem to want to take my sa2.cdi iso. :/
You can load the levels from the STG##.PRS files directly in SALVL, however the wiki only has addresses for the US version.
I asked this on SSRG, but just in case any of you know the answer, here it is. As some of you know, I'm making a guide for porting flamewing's S3K driver into Sonic 1. I'm trying to get it to be incbin'd, but it won't assemble. Every time I build I get this error: "ERROR: Second segment of sound driver at $1300 MUST follow directly after the first". I know what that means, but I've checked every aspect and it appears to be fine, so I have no idea what's going on. Apparently, when you add any 68k assembly code before the Z80 code, it assembles just fine, but without it, it gives the error. Even if it assembles, it's broken. I even removed the assembled 68k code from the bin file, but no luck.
is there an equivalent to the (maincharacter+anim) command in Sonic 1's asm? I try using the standard one ($1C) and it doesn't work, suggesting it needs to know it's Sonic as well.
^ I haven't touched Sonic 1 in forever, but I'm pretty sure that Sonic's data is still loaded at $FFFFB000, so adding the offset for an object's animation ID to that value is the same thing that MainCharacter+anim equates to in Sonic 2.
So ($FFFFB000+$1C) then? EDIT: Oh also concerning Sonic 2 this time, does anyone know how to get breakable objects such as obj32 (CPZ/HTZ blocks) to react with another object than Sonic or Tails?
^ IF $1C is an object's animation offset in Sonic 1, then that's correct. The other possibility is to load $FFFFB000 into a register aN and then check $1C(aN).
The SST (Sprite Status Table) for Sonic 1 is held in RAM from D000 to EFFF, what you're looking for is; $FFFFD01C or $FFFFD000+$1C. But pretty much what Thorn said...
^ Welp, I take fault for having the wrong address. Disregard me, I hack Sonic 2, I'm strange, etc. Regarding the other question E-122-Psi edited in, it's really dependent on what you're doing. In some situations, it may be necessary to run other objects through the same routines Sonic and Tails use, but in other cases, it may make more sense to code a special routine just for the object doing the interacting. Can you elaborate on what you need?
Okay I think that's given results. Thanx. That's okay, working on Sonic 2's the reason I needed that in the first place. :P To elaborate it's for my Sally in Sonic 2 hack. She has a projectile attack and I want the projectile object (objDE) to react with rocks,plugs,etc to smash them.
The older one seemed to work (there are some oddities, but I think that's more down to some other coding I need to fine tune). I'm having a concern with a new object I've made, I've got it to mostly run as it should, however no matter how much I edit, it just won't display it's sprite. It's a bit of mess here, it was translated from some Sonic 2 coding and originally used a unique compression which I've altered to see if it makes things any clearer here: Code (ASM): Obj10: ; XREF: Obj_Index moveq #0,d0 move.b $24(a0),d0 move.w Obj_Blob_Index(pc,d0),d0 jmp Obj_Blob_Index(pc,d0) Obj_Blob_Index: dc.w Obj_Blob_Init-Obj_Blob_Index dc.w Obj_Blob_Move-Obj_Blob_Index dc.w Obj_Blob_Destroy-Obj_Blob_Index Obj_Blob_Init: lea ($FFFFD000).w,a1 move.l #Map_obj10,4(a0) ; ($C) move.w #$7A0,2(a0) move.w #$2,$18(a0) move.b #$8,$19(a0) move.b #$4,1(a0) move.b #$4,$16(a0) ; $A move.b #$20,$30(a0) ; distance laser will travel cmpi.b #$25,$1C(a1) ; is NICOLE attack being performed? beq.w ObjDE_DownwardNICOLE ; if not, branch move.w #$700,$10(a0) ; speed of laser jmp ObjDE_ForwardNICOLE ObjDE_DownwardNICOLE: move.w #$700,$12(a0) ; speed of laser ObjDE_ForwardNICOLE: add.w #$10,8(a0) btst #0,$22(a1) beq.s Obj10_Cont neg.w $10(a0) sub.w #$20,8(a0) Obj10_Cont: lea (Art_Lazerart).l,a1 move.w #$7A0*$20,d2 addq.b #2,$24(a0) ; Obj_Blob_Move: cmp.b #$0,$30(a0) beq.w Obj_Blob_Destroy sub.b #$1,$30(a0) jsr SpeedToPos2 move.b $40,$20(a0) ; lol clr.w d0 move.b $1A(a0),d0 asl.w #$1,d0 ; *2 for correct offset adda.w (a1,d0.w),a1 move.w #$7A0*$20,d2 lea (Ani_Laser).l,a1 jsr AnimateSprite jsr (TouchResponse).l ;Touch_KillEnemy, Touch_Monitor jmp DisplaySprite Obj_Blob_Destroy: clr.b ($FFFFFFA4).w ; clear missle flag jmp DeleteObject Ani_Laser: dc.w laser0-Ani_Laser laser0: dc.b 3,0,1,1,1,2,2,2,3,3,3,$FD,0 even It seems to recognise the object itself but it's invisible and never shows any art unless it merges into another objects VRAM (I moved the lamp post's VRAM before you point that out by the way). Anyone have any idea why it won't display?
Is the art actually being loaded? I ask because there is nothing in the code that suggests it, but you could be loading it with PLCs elsewhere, so I don't know. I do see fragments of code that could indicate art being loaded (the bits with "$7A0*$20"), but they are incomplete.
Just looking at the code, I found few possible causes for it not to work: Your object will be created at either x $10, or x -$10, and y 0. You never copy X and Y positions from Sonic's RAM in above code. Most of the time, when running the object, a1 will not point to Art_Lazerart, with the exception of initializing frame, because you define it at Obj10_Cont, which isn't accessed if routine counter is 2 or above. It seems you are trying to do some kind of Dynamic art loading method in the routine as well, but it doesnt seem you actually ever load the art
This version I admit probably isn't done right. The original coding uses a unique compression provided by snkenjoi that I wasn't sure people would be able to help with, so I tried haphazardly to make one using uncompressed art. Here's the original if it helps: Code (ASM): Obj10: moveq #0,d0 move.b $24(a0),d0 move.w Obj_Blob_Index(pc,d0),d0 jmp Obj_Blob_Index(pc,d0) Obj_Blob_Index: dc.w Obj_Blob_Init-Obj_Blob_Index dc.w Obj_Blob_Move-Obj_Blob_Index dc.w Obj_Blob_Destroy-Obj_Blob_Index Obj_Blob_Init: lea ($FFFFD000).w,a1 move.l #SME_0iwB5,4(a0) ; ($C) move.w #$7A0,2(a0) move.w #$2,$18(a0) move.b #$8,$19(a0) move.b #$4,1(a0) move.b #$4,$16(a0) ; $A move.b #$20,$30(a0) ; distance laser will travel cmpi.b #$25,$1C(a1) ; is NICOLE attack being performed? beq.w ObjDE_DownwardNICOLE ; if not, branch move.w #$700,$10(a0) ; speed of laser jmp ObjDE_ForwardNICOLE ObjDE_DownwardNICOLE: move.w #$700,$12(a0) ; speed of laser ObjDE_ForwardNICOLE: add.w #$10,8(a0) btst #0,$22(a1) beq.s Obj10_Cont neg.w $10(a0) sub.w #$20,8(a0) Obj10_Cont: lea (ArtSNK_Laser0).l,a1 move.w #$7A0*$20,d2 jsr (SNKDec).l addq.b #2,$24(a0) ; Obj_Blob_Move: cmp.b #$0,$30(a0) beq.w Obj_Blob_Destroy sub.b #$1,$30(a0) jsr SpeedToPos2 move.b $40,$20(a0) ; lol clr.w d0 move.b $1A(a0),d0 asl.w #$1,d0 ; *2 for correct offset lea (LaserArtPointers).l,a1 adda.w (a1,d0.w),a1 move.w #$7A0*$20,d2 jsr (SNKDec).l lea (Ani_Laser).l,a1 jsr AnimateSprite jsr (TouchResponse).l ;Touch_KillEnemy, Touch_Monitor jmp DisplaySprite Obj_Blob_Destroy: clr.b ($FFFFFFA4).w ; clear NICOLE flag jmp DeleteObject Ani_Laser: dc.w laser0-Ani_Laser laser0: dc.b 3,0,1,1,1,2,2,2,3,3,3,$FD,0 even SME_0iwB5: dc.w SME_0iwB5_8-SME_0iwB5, SME_0iwB5_12-SME_0iwB5 dc.w SME_0iwB5_1C-SME_0iwB5, SME_0iwB5_26-SME_0iwB5 SME_0iwB5_8: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_12: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_1C: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 SME_0iwB5_26: dc.b 0, 1 dc.b $F8, 5, 0, 0, 0, 0, $FF, $F8 even
So I ported the S2 Rings Manager to S1... having a priority issue, in which the rings appear over the title card, in instances like Marble Zone 1. Normally rings in S2 and S3K get drawn over everything else... whereas that wasn't the case with Sonic 1, where they'd have a priority of 2 and then after Sonic collected them, they'd get a priority of 1.... Anyone know how I can mod a Ring Manager to emulate this priority change in any way?
You actually have to mod the BuildSprites routine (or whatever it is called in S1) to render the rings at the right priority. Using S2's BuildSprites as an example, since you probably used it as a base: in stock S2, you have this: [68k]BuildSprites: tst.w (Two_player_mode).w bne.w BuildSprites_2P lea (Sprite_Table).w,a2 moveq #0,d5 moveq #0,d4 tst.b (Level_started_flag).w beq.s + bsr.w JmpTo_BuildHUD bsr.w BuildRings + lea (Sprite_Table_Input).w,a4 moveq #7,d7 ; 8 priority levels ; loc_16628: BuildSprites_LevelLoop: tst.w (a4) ; does this level have any objects? beq.w BuildSprites_NextLevel ; if not, check the next one moveq #2,d6 ; loc_16630: BuildSprites_ObjLoop:[/68k] You want something like this: [68k]BuildSprites: tst.w (Two_player_mode).w bne.w BuildSprites_2P lea (Sprite_Table).w,a2 moveq #0,d5 moveq #0,d4 tst.b (Level_started_flag).w beq.s + bsr.w JmpTo_BuildHUD + lea (Sprite_Table_Input).w,a4 moveq #7,d7 ; 8 priority levels ; loc_16628: BuildSprites_LevelLoop: tst.b (Level_started_flag).w beq.s + cmpa.w #Sprite_Table_Input+$80,a4 bne.s + bsr.w BuildRings + tst.w (a4) ; does this level have any objects? beq.w BuildSprites_NextLevel ; if not, check the next one moveq #2,d6 ; loc_16630: BuildSprites_ObjLoop:[/68k] This will render all rings and ring sparkles as priority 1; you won't be able to render them with different priorities in S2 or S3&K engines. Using priority 1 will generally not make much difference in practice, but if you want to have rings and sparkles render with priority 2 instead, just change this line: [68k] cmpa.w #Sprite_Table_Input+$80,a4[/68k] to this: [68k] cmpa.w #Sprite_Table_Input+2*$80,a4[/68k] Edit: @E-122-Psi: Is this code for S1 or S2? If for S2, then this code: [68k] lea ($FFFFD000).w,a1[/68k] is wrong and should be this: [68k] lea ($FFFFB000).w,a1[/68k] (another reason to use symbolic constants instead of raw addresses, but I digress) Other than this, the only other thing I can think of is what Green Snake mentioned about starting X and Y not being initialized in this code (which could simply mean it is being initialized when the object is created). Out of curiosity, would SNKDec be this function?
I believe it is, yes. The coding is for Sonic 1, but I've converted it from Sonic 2 coding. The objects positioning is loaded at the end of the routine for whatever move uses it, like so: Code (ASM): move.b #1,($FFFFFFA4).w ; if not, set jumpdash flag move.b #$20,$1C(a0) ; show NICOLE animation bsr.w SingleObjLoad bne.s NoProjectile_NICOLE move.b #$10,0(a1) ;Obj10 move.w 8(a0),8(a1) move.w $C(a0),$C(a1) NoProjectile_NICOLE: Out of interest would the fact that the actual object routine comes before Sonic's in Sonic 2 but after in Sonic 1 make any difference here?
I tried that... IDK if it is something with Sonic 1, but when I built and ran, I got an empty black screen after the SEGA screen...