Ah, that makes sense (this also explains why Sonic 1/3K doesn't have them, since they leave their data uncompressed AND only have one collision file). Decided to experiment around with commenting out one of the "broken" palette indexes and then playing as Knuckles; it crashed without the alignment, but didn't with it, so... ¯\_(ツ)_/¯ (to be fair, the developers were probably never even intending on having this many palettes).
I meant the section where you put the alignment. Also can we please move this to Basic Q&A? This thread's getting clogged again.
Code (Text): ; =========================================================================== ;---------------------------------------------------------------------------- ; Palette pointers ; (PALETTE DESCRIPTOR ARRAY) ; This struct array defines the palette to use for each level. ;---------------------------------------------------------------------------- palptr macro ptr,lineno dc.l ptr ; Pointer to palette dc.w (Normal_palette+lineno*palette_line_size)&$FFFF ; Location in ram to load palette into dc.w bytesToLcnt(ptr_End-ptr) ; Size of palette in (bytes / 4) endm even PalPointers: PalPtr_SEGA: palptr Pal_SEGA, 0 PalPtr_Title: palptr Pal_Title, 1 PalPtr_BGND: palptr Pal_BGND, 0 PalPtr_EHZ: palptr Pal_EHZ, 1 PalPtr_EHZ2: palptr Pal_EHZ2, 1 PalPtr_OWZ1: palptr Pal_OWZ1, 1 PalPtr_OWZ2: palptr Pal_OWZ2, 1 PalPtr_WZ: palptr Pal_WZ, 1 PalPtr_SSZ1: palptr Pal_SSZ1, 1 PalPtr_SSZ2: palptr Pal_SSZ2, 1 PalPtr_MTZ: palptr Pal_MTZ, 1 PalPtr_MTZ2: palptr Pal_MTZ, 1 PalPtr_WFZ: palptr Pal_WFZ, 1 PalPtr_HTZ: palptr Pal_HTZ, 1 PalPtr_HPZ: palptr Pal_HPZ, 1 PalPtr_RWZ: palptr Pal_RWZ, 1 PalPtr_OOZ: palptr Pal_OOZ, 1 PalPtr_MCZ: palptr Pal_MCZ, 1 PalPtr_CNZ: palptr Pal_CNZ, 1 PalPtr_CPZ: palptr Pal_CPZ, 1 PalPtr_CPZ2: palptr Pal_CPZ2, 1 PalPtr_DEZ: palptr Pal_DEZ, 1 PalPtr_ARZ: palptr Pal_ARZ, 1 PalPtr_ARZ2: palptr Pal_ARZ2, 1 ;palptr Pal_EHZ, 1 ; for some reason, this specific entry crashes the game... PalPtr_SCZ: palptr Pal_SCZ, 1 PalPtr_OWZ1_U: palptr Pal_OWZ1_U, 1 PalPtr_HPZ_U: palptr Pal_HPZ_U, 0 PalPtr_CPZ_U: palptr Pal_CPZ_U, 0 PalPtr_SS: palptr Pal_SS, 0 PalPtr_ARZ_U: palptr Pal_ARZ_U, 0 PalPtr_ARZ2_U: palptr Pal_ARZ2_U, 0 PalPtr_MCZ_B: palptr Pal_MCZ_B, 1 PalPtr_CNZ_B: palptr Pal_CNZ_B, 1 PalPtr_SS1: palptr Pal_SS1, 3 PalPtr_SS2: palptr Pal_SS2, 3 PalPtr_SS3: palptr Pal_SS3, 3 PalPtr_SS4: palptr Pal_SS4, 3 PalPtr_SS5: palptr Pal_SS5, 3 PalPtr_SS6: palptr Pal_SS6, 3 PalPtr_SS7: palptr Pal_SS7, 3 PalPtr_SS1_2p: palptr Pal_SS1_2p,3 PalPtr_SS2_2p: palptr Pal_SS2_2p,3 PalPtr_SS3_2p: palptr Pal_SS3_2p,3 PalPtr_OOZ_B: palptr Pal_OOZ_B, 1 PalPtr_Result: palptr Pal_Result,0 ; palptr Pal_EHZ, 1 ; this too! ; palptr Pal_EHZ, 1 ; this too! ; palptr Pal_EHZ, 1 ; this too! PalPtr_Knux: palptr Pal_Knux, 0 PalPtr_CPZ_K_U: palptr Pal_CPZ_K_U, 0 PalPtr_ARZ_K_U: palptr Pal_ARZ_K_U, 0 PalPtr_SS_K: palptr Pal_SS_K, 0 PalPtr_HPZ_K_U: palptr Pal_HPZ_K_U, 0 align $200 ; ---------------------------------------------------------------------------- ; This macro defines Pal_ABC and Pal_ABC_End, so palptr can compute the size of ; the palette automatically ; path2 is used for the Sonic and Tails palette, which has 2 palette lines palette macro {INTLABEL},path,path2 __LABEL__ label * BINCLUDE "art/palettes/path" if "path2"<>"" BINCLUDE "art/palettes/path2" endif __LABEL___End label * endm Pal_SEGA: palette Sega screen.bin ; SEGA screen palette (Sonic and initial background) Pal_Title: palette Title screen.bin ; Title screen Palette Pal_BGND: palette SonicAndTails.bin,SonicAndTails2.bin ; "Sonic and Miles" background palette (also usually the primary palette line) Pal_EHZ: palette EHZ.bin ; Emerald Hill Zone Act 1 palette Pal_EHZ2: palette EHZ2.bin ; Emerald Hill Zone Act 2 palette Pal_OWZ1: palette OWZ1.bin ; Ocean Wind Zone Act 1 palette Pal_OWZ1_U: palette OWZ1 underwater.bin ; Ocean Wind Zone Act 1 underwater palette Pal_OWZ2: palette OWZ2.bin ; Ocean Wind Zone Act 2 palette Pal_WZ: palette Wood Zone.bin ; Wood Zone palette Pal_SSZ1: palette SSZ1.bin ; Sand Shower Zone Act 1 palette Pal_SSZ2: palette SSZ2.bin ; Sand Shower Zone Act 2 palette Pal_MTZ: palette MTZ.bin ; Metropolis Zone palette Pal_WFZ: palette WFZ.bin ; Wing Fortress Zone palette Pal_HTZ: palette HTZ.bin ; Hill Top Zone palette Pal_HPZ: palette HPZ.bin ; Hidden Palace Zone palette Pal_HPZ_U: palette HPZ underwater.bin ; Hidden Palace Zone underwater palette Pal_RWZ: palette RWZ.bin ; Rock World Zone palette Pal_OOZ: palette OOZ.bin ; Oil Ocean Zone palette Pal_MCZ: palette MCZ.bin ; Mystic Cave Zone palette Pal_CNZ: palette CNZ.bin ; Casino Night Zone palette Pal_CPZ: palette CPZ.bin ; Chemical Plant Zone Act 1 palette Pal_CPZ2: palette CPZ2.bin ; Chemical Plant Zone Act 2 palette Pal_CPZ_U: palette CPZ underwater.bin ; Chemical Plant Zone underwater palette Pal_DEZ: palette DEZ.bin ; Death Egg Zone palette Pal_ARZ: palette ARZ.bin ; Aquatic Ruin Zone Act 1 palette Pal_ARZ2: palette ARZ2.bin ; Aquatic Ruin Zone Act 2 palette Pal_ARZ_U: palette ARZ underwater.bin ; Aquatic Ruin Zone Act 1 underwater palette Pal_ARZ2_U: palette ARZ2 underwater.bin ; Aquatic Ruin Zone Act 1 underwater palette Pal_SCZ: palette SCZ.bin ; Sky Chase Zone palette Pal_MCZ_B: palette MCZ Boss.bin ; Mystic Cave Zone boss palette Pal_CNZ_B: palette CNZ Boss.bin ; Casino Night Zone boss palette Pal_OOZ_B: palette OOZ Boss.bin ; Oil Ocean Zone boss palette Pal_SS: palette Special Stage Main.bin ; Special Stage palette Pal_SS1: palette Special Stage 1.bin ; Special Stage 1 palette Pal_SS2: palette Special Stage 2.bin ; Special Stage 2 palette Pal_SS3: palette Special Stage 3.bin ; Special Stage 3 palette Pal_SS4: palette Special Stage 4.bin ; Special Stage 4 palette Pal_SS5: palette Special Stage 5.bin ; Special Stage 5 palette Pal_SS6: palette Special Stage 6.bin ; Special Stage 6 palette Pal_SS7: palette Special Stage 7.bin ; Special Stage 7 palette Pal_SS1_2p:palette Special Stage 1 2p.bin ; Special Stage 1 2p palette Pal_SS2_2p:palette Special Stage 2 2p.bin ; Special Stage 2 2p palette Pal_SS3_2p:palette Special Stage 3 2p.bin ; Special Stage 3 2p palette Pal_Result:palette Special Stage Results Screen.bin ; Special Stage Results Screen palette Pal_Knux: palette Knuckles.bin,SonicAndTails2.bin ; "Sonic and Miles" background palette (also usually the primary palette line) Pal_CPZ_K_U: palette CPZ Knux underwater.bin ; Chemical Plant Zone underwater palette Pal_ARZ_K_U: palette ARZ Knux underwater.bin ; Aquatic Ruin Zone underwater palette Pal_SS_K: palette Special Stage Main (Knuckles).bin ; Special Stage palette (Knuckles) Pal_HPZ_K_U: palette HPZ Knux underwater.bin ; Hidden Palace Zone underwater palette Pal_SonicMenu: palette menus/Sonic.bin ; Sonic theme Pal_TailsMenu: palette menus/Tails.bin ; Tails theme Pal_KnuxMenu: palette menus/Knuckles.bin ; Knuckles theme Pal_EggmanMenu: palette menus/PISS DROPLETS.bin ; Eggman theme Pal_RetroMenu: palette menus/Retro.bin ; Retro theme Pal_Ending: palette Ending.bin Yes, I'll try to move it to Basic Q&A soon.
Alright, it's been figured out. It's not an issue with stock Sonic 2 or the disassembly. I would advise you to first post an issue you're hacking when making a hack in Basic Q&A to resolve it before coming in this thread claiming that a potential bug in stock Sonic 2 was found, if you're unsure of what's even going on. This thread is mainly for documenting confirmed bugs and fixing them, and other helpful tweaks.
Ive been reading the programmer's user manual for 68000 assembly, and found that there are cases were there are 2 instructions that are represented differently but do the same thing. For example, Code (Text): ADD.W #1234,D0 Would be represented as Code (Text): 1101000001111100 [16 bits immediate data] However, the notes say that if you are trying to add an immediate to a data register, then the assembler should automatically convert `ADD` to `ADDI` (despite `ADD` seeming to support adding immediates to data registers as well) But, the bit representation for Code (Text): ADDI.W #1234,D0 is Code (Text): 0000011001000000 [16 bits immediate data] . So, there seem to be 2 different totally equivalent instructions that both can add immediates to data registers. Is there one that is preferred? Is there any benefit to one over the other that I'm not seeing? This duplication is also seen instructions like `OR` vs `ORI`, among others.
The difference between those 2 is that "ADD" requires that one of the operands be a data register. Only 1 address mode can be encoded in the "ADD" opcode, and it uses a bit to determine if the source or destination is the register. If you were to set the direction bit to 1 in your "ADD" example, it'd be interpreted as Code (Text): ADD.W D0,#1234 Which is obviously very much not valid. This also means something like Code (Text): ADD.W #1234,$FF0000 is not possible to assemble. "ADDI" forces the source operand to be an immediate, which allows the destination to be anything (other than another immediate, of course). "ADDI" would allow you to use the operands from the example above. "ADDA" also exists if one if the source operand is not an immediate, and the destination operand is an address register.
Yes, this distinction makes sense, but I am wondering in the case where I do just want to add an immediate to a data register, which operation should I use? (since both can do this). Is there any benefit to using one over the other in the case when you want to add an immediate to a register? (assuming `ADDQ` is not applicable -- also, I do follow what you are saying about them being able to do different things, I'm just asking about this particular situation you actually can use either one for the same function).
No. "ADDI" exists to get around a limitation of "ADD". Otherwise, they take the same amount of space and same number of cycles to execute. I personally just stick with "ADDI" for consistency. Some assemblers would just turn an "ADD" into an "ADDI" if the source operand in an immediate, anyways.
Hey, so I managed to hit a roadblock when porting the Sonic and Knuckles driver into Sonic 1, everything builds fine however I received this error: It's telling me to increase the value of something I don't even have in my disassembly (that being AS GitHub Two Eight disassembly) nor the sound driver itself. I tried increasing Size_of_sounddriver and Size_of_sounddriver2 to see if something did change but to no avail. Is there anything I'm supposed to specifically change from here or do I need to modify s1p2bin itself as the code is telling me to increase something that isn't defined?
Cheers for that; it works as intended. I might step it up by porting flamewing's SK driver over that. EDIT: Got flamewing's SK driver installed successfully however I ran into an issue where a few channels would play the last note after resting the note. Here's a YouTube video comparing how it's played between S1's and S3K's drivers: If you want to take a look at the song file in ASM, please let me know and I'll DM it to you if you know how to fix it.
Came up with three new symbolic constants for my Sonic 2 disassembly for code handling bounds checking (MarkObjGone and DeleteObject), but I'm not sure if my line of thinking with them is correct. Are render_margin, render_width, and render_height correct with regards to how the VDP works internally in H40 mode, or am I off? Code (Text): screen_width: equ 320 screen_height: equ 224 render_margin: equ 128 ; space beyond edges of screen rendered by the VDP internally screen_top: equ render_margin ; VDP y coordinate of top edge of screen screen_left: equ render_margin ; VDP x coordinate of left edge of screen screen_bottom: equ screen_top+screen_height screen_right: equ screen_left+screen_width render_width: equ screen_width+(render_margin*2) ; 640, total width of VDP render render_height: equ screen_height(render_margin*2) ; 480, total height of VDP render
The sprite plane (512x512), bg/fg plane (512x256) and object despawning are all pretty much independent. I'm not sure it makes sense to link them in that way.
The question is still up there in case anyone has missed it. I think it's probably due to how S3K handles note delays comparing to Sonic 1, so I should make a separate flag for that, right? Also, I'm planning to include up to 60 songs with flamedriver in mind. Will the fit under the Z80 bank or do I need to remove certain aspects to make it possible?l And aso, what's the limit to DAC banks? Is it the same as Sonic 1's or MegaPCM? Sorry if I'm being such a bother with these questions, but I'd rather ask now than later in case the driver doesn't support what I have and would be painful to revert everything to a 68k driver and make sure all songs work from there. If I know it's limitations now, then I should feel confident working with flamedriver from there on out.
Uhh, so in the Advanced Debug Handler installation guide, there is a step like this: The build.bat file was removed in the Git disasm, so how do I do this in the new build.lua file? Thanks in advance.
I actually figured out how to install Vladikcomper's error handler in the new Lua-based build system a few weeks ago, so might as well share it: 1. Follow the steps to install the debugger macros and error handler blob. 2. Place convsym.exe in build_tools/xxx, where xxx is your platform (e.g., Win32 if Windows). 3. In build.lua, find this line near the top: Code (Lua): local tools, platform_directory = common.find_tools("s2p2bin", "fixpointer", "saxman") Change it to this: Code (Lua): local tools, platform_directory = common.find_tools("s2p2bin", "fixpointer", "saxman", "convsym") 4. Finally, find this near the end of build.lua: Code (Lua): -- Correct the ROM's header with a proper checksum and end-of-ROM value. common.fix_header("s2built.bin") Underneath that, insert this: Code (Lua): -- Run convsym to add the symbol table to the end of the ROM. os.execute(tools.convsym .. " s2.lst s2built.bin -input as_lst -a") That's pretty much all there is to it. :>