don't click here

Basic Questions & Answers thread

Discussion in 'Engineering & Reverse Engineering' started by Tweaker, May 29, 2008.

  1. OrionNavattan

    OrionNavattan

    Tech Member
    175
    177
    43
    Oregon
    Maybe belated, but those build errors are a direct result of there being an odd number of bytes in the SoundTypes data. The 68K cannot read word or longwords, including instructions, from odd addresses. Inserting an "even" command after the SoundTypes Data should fix that issue.
     
    • Like Like x 1
    • Agree Agree x 1
    • List
  2. XPointZPoint

    XPointZPoint

    That's no good! Member
    One question, this is relating to the MCD question I asked a while back, but is there a way for Genesis games to be ported to the MCD? I'm trying to make a ROM hack and then port it to the MCD for extra features and all that bluff. I'm using Sonic 1 and it's a fresh disassembly with no changes.
     
  3. Devon

    Devon

    La mer va embrassé moi et délivré moi lakay. Tech Member
    1,425
    1,744
    93
    your mom
    The MCD adds the following:
    • A CD drive (duh)
    • An additional 68000 CPU (Sub CPU) for interacting with the MCD hardware and communication with the Genesis CPU (Main CPU)
    • 256 KiB of RAM (Word RAM) that can either be assigned to 1 CPU at a time in its entirety (2M mode), or can be split between the 2 CPUs (1M/1M mode)
    • 512 KiB of RAM (PRG RAM) that the Sub CPU uses for code and data
    • 8 channel PCM sound chip (Ricoh RF5C164)
    • Additional graphics operations, depending on the mode of Word RAM
      • 2M mode enables scaling/rotation capabilities. It takes a tilemap source image and uses a table of values to render it in a specific way. The source and output data is all stored in Word RAM, and to get it drawn on screen, you must copy the rendered output from Word RAM to VRAM.
      • 1M/1M mode enabled bitmap and decoding capabilities.
        • From the Main CPU, it takes in pixel data stored in its section of Word RAM, arranged in a more linear bitmap format, and converts it to Genesis tile data.
        • From the Sub CPU, it can convert pixel data from the standard Genesis pixel data format (2 pixels per byte/1 pixel per nibble) to a "decoded" format, where each pixel gets their own byte, and vice versa.
      • In either mode, if you aren't using these, then you are fine to use Word RAM for general code and data on either CPU, with the proper access permissions set.
    Assuming you are wanting to go for mode 2, which is booting to the BIOS and then booting into a disc game, then tl;dr it's more complicated/different to set up compared to a Genesis ROM. Data from a CD is not as accessible as data from a cartridge, as it requires an actual CD reader to read the data from the disc and then store it somewhere. Because of that, the data on the disc is not mapped to any memory addresses. It's a matter of getting data read from the disc and stored in RAM somewhere for the CPUs to run.

    This is basically how a disc game is booted:
    • The BIOS boots up and verifies the disc in the drive.
    • If verified, it loads the "initial program"/"IP" into the start of the Genesis' RAM. This is what the Main CPU runs on boot.
    • It also loads the "system program"/"SP" into address $6000 in the MCD's PRG RAM. This is the main program of the Sub CPU.
    The disc header will contain info on where the IP and SP are on the disc. This is the minimum required to get anything running. The rest is figuring out how you want to use the rest of the data on the disc to get a full game running. Games back in the 90s typically just stored their files in ISO9660 format (file data and structures start at address $8000 in the disc image in 2048 mode), but this is not a requirement. Regardless, you'll want to have some sort of system in place where you can locate file data, and then use the Sub CPU to call the correct functions to load the data from the disc into RAM.
    • As a side note, with the BIOS data transfer function, you can load the read disc data into Word RAM or PRG RAM, but you can also set up the CDC to DMA the data directly into Word RAM, PRG RAM, and even PCM sample RAM. You can also choose to only set up the data read on the Sub CPU side and have the Main CPU read the data from via a register (the standard BIOS data transfer function does this, but on the Sub CPU side).
    You'll also want to set up some kind of basic protocol for communication between the Main and Sub CPUs via the communication registers, if you want the Main CPU to be able to tell the Sub CPU what to do, and vice versa.

    As for porting an existing game to the MCD, it's a matter of figuring out how you want to segment the game and organize your variables in RAM. With limited RAM space, you're not likely to fit an entire game in. Segment different game modes and level data into separate files, and tell the MCD side when to load them and where.

    If you want a small and basic example of an MCD disc program that uses ISO9660, you can refer to this repository I made a while ago that also shows an example of the 2M graphics operation. You can also try to refer to the official documentation, but be warned that there are tidbits of info that are worded weirdly/mistranslated.
     
    Last edited: Oct 30, 2022
    • Useful Useful x 2
    • Like Like x 1
    • Informative Informative x 1
    • List
  4. E-122-Psi

    E-122-Psi

    Member
    2,502
    681
    93
    Does anyone know how to convert the final Sonic 2 act clear screen into the beta one (ie. no scoreboard, just music plays and then fade out)?
     
  5. Any branches to DisplaySprite are removed, as is the code that handles the score itself, although the latter may be more complicated than Sonic 1's.

    And just because I know people will ask for it since Devon mentioned Sega CD abilities, here's what the 32X adds:
    • Two 32-bit Hitachi SH-2 processors (one master, one slave) at 23MHz, and with 256 KB in "SDRAM".
    • One Sega 32X VDP with the following abilities:
      • 32,768 maximum colors at once, with the following options using the double-buffered framebuffer:
        • A "packed" pixel mode allowing for 256 colors and 8 bits per pixel, with additional support for "full" screen (320x408). Each color here is indexed into CRAM.
        • A "run-length" pixel mode also allowing for 256 colors, but with 16-bits per pixel, at the cost of reducing the maximum screen resolution to the standard of 320x224/240; also has each color in an index, but can also specify how many pixels are displayed.
        • A "direct color" pixel mode allowing for 32,768 simultaneous colors one-screen, as well as 16-bits per pixel; this mode reduces the maximum resolution down to 320x204, and works by setting each individual pixel its color value.
      • 256 KB VRAM, alongside the partial ability to overlay or underlay the graphics on the Genesis/MCD-side.
      • The (practical) ability to display up to 80000 polygons on screen at once without shading or textures, and 20000 on screen with shading and textures; note that textures MUST be stored within the first 4-8 MB of the ROM.
      • Sprite scaling, scrolling, rotation, and alpha blending, as well as up to 3800/1900 sprites (depending on the bit-depth) on screen at once.
    • Custom QSound chip with support of 4 PWM channel, as well as 11-bit PCM output.
    • The ability to communicate with the Sega CD, allowing for Sega CD 32X games.
    Sure, a lot of this sounds cool, however the 32X itself is infamous for both the sheer difficulty of programming, and several caveats they have; this includes just how notoriously slow the data bandwidth is (just play Knuckles' Chaotix and see for yourself), as well as a non-bankswitched ROM being limited to just 1.5 MB (the first 512 KB being static, while the other 1 MB being able to be swapped) in size due to how it re-arranges the cartridge location in memory, hence why there really isn't many 32X ROM hacks in general.

    If you do want to at least experiment around with the 32X, there is an old conversion of Sonic 1 for it (as well as MarkeyJester's Sonic 32X+), however RedhotSonic has also noted how the PWM support causes it to crash on real hardware.
     
  6. Devon

    Devon

    La mer va embrassé moi et délivré moi lakay. Tech Member
    1,425
    1,744
    93
    your mom
    "408" is just how many lines it can store in the frame buffer. However, there's only 256 available entries in the line table that points to the pixel data, and the visible vertical resolution is still 224 or 240.

    [​IMG]
    [​IMG]

    The reason for "204" is because there's not enough room in the frame buffer for 224 or 240 lines, so you'd have to make the line table reuse some lines to fill up the remaining screen space.

    I'm pretty iffy with these points, considering that all rendering is done to the frame buffer in software, and aren't *exactly* native features of the 32X; it's just more capable of doing them with the hardware that it provides compared to the Genesis'. It really depends on your implementation.

    What?

    It's actually just stereo and the input data is 12-bit, although this actually gets cut down depending on the frequency of PWM interrupts (I've read it's 10-bit for 22050 Hz in a couple places). The 4 channel thing came from software mixing.

    [​IMG]

    [​IMG]

    Not really. Really, the 32X was more designed to take over the game cartridge and communicate with the Genesis 68000. Otherwise, you have to transfer data yourself to the 32X (I might be wrong, but I think I read that using DREQ on RAM is prone to issues, too, so bleh. Really, I've barely heard anything good things at all about DREQ, so lol).

    It's really moreso taking the 4 MiB ROM space in memory and banking it. The first 512 KiB are fixed at $880000, but ROM space is split into 4 1 MiB banks, with that first 512 KiB included in the first bank, mapped to $900000. I believe you can still use the SSF2 mapper to get ROMs larger than 4 MiB, but you're basically dealing with 2 layers of bank switching, 1 for mapping from the cartridge to ROM space, and the ROM space then being banked on the M68K side. The 32X, though, can see the full 4 MiB ROM space.

    [​IMG]

    [​IMG]

    Personally, I have more beef with the SH-2 configuration (both are on the same bus, with a lack of bus contention protection, I believe), the initialization process, and the RV flag (which basically exists to hack around issues revolving around how the 32X basically takes over the cartridge). Also the fact that 32X emulation at this current moment isn't exactly accurate (Things that might work in emulation could break horribly on hardware. See this), so hardware testing is basically a must for 32X, in my opinion.

    In the end, the 32X is basically a couple of CPUs with a frame buffer, palette, and stereo sampling audio, all hastily glued together into a bugged disaster of an add-on. All the fancy things that are done on it are effectively done through software, since the hardware provides a more suitable environment for that sort of stuff. Really, the issues with the hardware I've mentioned are just the surface.

    [​IMG]
     
    Last edited: Nov 5, 2022
  7. XPointZPoint

    XPointZPoint

    That's no good! Member
    Is there a way that Sonic CD's special stages, including mode 7 and the 3d rendering and stuff can be ported to Sonic 1? I'm using that as a bonus stage and you earn an extra life if you do it. The sonic 1 special stages are the special stages.
     
  8. Devon

    Devon

    La mer va embrassé moi et délivré moi lakay. Tech Member
    1,425
    1,744
    93
    your mom
    If you're just talking a standalone Genesis ROM, then you would need to implement the 3D rendering in software. It's very much possible, as proven time and time again, but it's very difficult if you don't know what you're doing. You'd need to figure out how to set up your render buffer and optimally calculate the math and optimally transfer the pixels over. The last part is especially tricky due to the fact the Genesis uses tiles, and it stores 2 pixels per byte.

    You can linear-ize the rendering process by arranging your tiles in the render buffer from top to bottom instead of left to right (i.e. tile 1 is below tile 0 instead of right of it). Each tile uses 8 longwords to define 8 rows of pixels from top to bottom. In memory, with tiles being arranged vertically, the next longword after the last in a tile would be the first row of pixels in the next tile. With this, it's easier to basically stream pixels top to bottom for each column.

    You can further linear-ize this by splitting the buffer into 2. The 1st buffer will hold the pixels in the left half of each tile, and the 2nd will hold the right half of each tile. In each longword in a tile, it holds 8 pixels, 1 per nibble, left to right. You're basically splitting the high words from the low words. With this, you can then also use the stack pointer to write data into the buffer. If you read or write a byte on the stack, it'll always advance by 2 bytes, in an attempt to keep an even address (although it'll still advance by 2 if you force it to be odd). With this, in each buffer, you can basically get even more precise and draw a column of 2 pixels. Unfortunately, this is as far as it will go since 1 byte holds 2 pixels, but it should definitely make the drawing process much easier. To then copy the buffers into VRAM, you set auto-increment to 4 (effectively makes it skip every other word in VRAM) copy the 1st buffer into the base address in VRAM, and then the 2nd into the base address + 2.

    If you're talking something like Sega CD mode 1, where it's still a cartridge game, but with the Sega CD hardware available, then you can just get the code from Sonic CD and implement it to work in Sonic 1 instead.
     
  9. XPointZPoint

    XPointZPoint

    That's no good! Member
    Well. If that's the case, this'll take me way too long. I don't know much about MCD stuff other than some code for Sonic 1 (and possibly other games) where it just checks for the MCD and if it is detected, it does something. I know nothing about reading data from the disc or mode 1 or anything. I've heard of them and seen what they are, but don't know how to implement it in and get it working. Let's go step by step. How can I do mode 1?
     
  10. Devon

    Devon

    La mer va embrassé moi et délivré moi lakay. Tech Member
    1,425
    1,744
    93
    your mom
    I have a small library of functions of helping with that. Basically, you use it to detect the BIOS, and then load a Sub CPU program. The Sub CPU program is where you would do your main interactions with the MCD hardware. My GitHub has other repositories for MCD stuff, and you can reference their Sub CPU programs.

    As it currently stands, though, documentation is pretty iffy with MCD. One of these days, I would personally like to write my own, but I'm also juggling a bunch of other things as is. I do also think you are jumping a bit too far ahead into things that are currently beyond your skill level, so you should take things 1 step at a time and put your focus more on building up your skills at a level you are comfortable with.
     
  11. XPointZPoint

    XPointZPoint

    That's no good! Member
    Is there a way to the Sonic 3 data select menu to Sonic 2? I'm using AMPS Sonic 2 GitHub disassembly.
     
  12. XPointZPoint

    XPointZPoint

    That's no good! Member
    I was implementing Mode 1 into Sonic 1 when I got this error regarding this line:

    Code (Text):
    1.     move.w    #$8000|%xx1xxxxx,$C00004    ; Enable V-BLANK interrupts
    2.  
    and this is the build error:

    Code (Text):
    1. SN 68k version 2.53
    2.  
    3. J:\S1SPINDASHASM - COPY - COPY\SONIC1.ASM(3399) : Error : Non-binary character following %
    4.  move.w #$8000|%xx1xxxxx,$c00004
    5. Errors during pass 1 - pass 2 aborted
    6. Assembly completed.
    7. 1 error(s) from 49407 lines in 0.34 seconds
    8.  
    9. Reported Size:  100303C Reported Checksum:    0
    10.  Size applied: FFFFFFFF  Checksum Applied:    0
    11. Press any key to continue . . .
    12.  
    Help?
     
  13. Devon

    Devon

    La mer va embrassé moi et délivré moi lakay. Tech Member
    1,425
    1,744
    93
    your mom
    You're supposed to fill in the "x" bits. It was designed to be more generalized and not made specifically for Sonic ROM hacks. In the case of Sonic 1, "%1110100" will do fine. See this for more info.

    I will repeat:
    Not trying to completely discourage you, but I would personally recommend you study how the Genesis and lower level programming works a bit before you tackle the Sega CD. Take things 1 step at a time. It's pretty clear to me that you're just kinda throwing shit at the wall without much thought or knowledge of why it works the way it does. I'm not trying to gatekeep or anything, but the Sega CD is an extension of the Genesis, and if you don't know the Genesis very well, then you're not going to have a fun time.
     
    Last edited: Nov 9, 2022
  14. Nik Pi

    Nik Pi

    Member
    504
    368
    63
    Kazakhstan
    Sonic 2: Archives
    How can I make my custom DAC sample?
    I try to export sample to .SND format, but in game it works... weird
     
  15. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,249
    509
    93
    Japan
    That depends on the driver you're using.

    Natively, the DAC sample format is unsigned 8-bit mono, but since the sample playback is software driven, the format can be anything in theory. Many official sound drivers use lossy compression formats such as the DPCM where the inverse logarithmic difference is stored. In these instances, you'll need a compressor.

    Until we know what driver you're working with however, we can't really help.
     
  16. Nik Pi

    Nik Pi

    Member
    504
    368
    63
    Kazakhstan
    Sonic 2: Archives
    I work with Sonic 2 clone driver
     
  17. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,249
    509
    93
    Japan
    If I remember rightly, that uses (or at least used to use) a DAC driver jman originally wrote.

    ...if that's the case, you'll need to convert your sample to PCM 8-bit unsigned mono format, the sample rate will depend on how you want the pitch to sound. The header will need stripping out, you can either strip it from the file manually with a hex editor, or some audio tools might have the ability to save/export a sample as "RAW" without the header, if you save/export in "SND" format, it may contain a header which the DAC driver will try to play as if it were audio.

    An alternative option; asm68k has a few suffix options for incbin (AS may have the same), for example:
    Code (Text):
    1.        incbin   "Sample.snd", $30
    This will include the file starting from offset 30 instead of offset 0, the $30 is just an example number, the header size and the actual starting offset of the data won't necessarily be fixed to a specific spot, and some tools might setup different header data in the "SND" file, so it's hard to predict. But if you know what size your audio tool will export, then there's no harm in doing this for your own personal project.
     
  18. Devon

    Devon

    La mer va embrassé moi et délivré moi lakay. Tech Member
    1,425
    1,744
    93
    your mom
    There's also Clownacy's continuation of the clone driver which uses a custom 2 channel PCM driver, but it looks like the sample format is the same (unsigned 8-bit mono raw) with varying sample rates, so the same sort of steps would need to be taken, except that you cannot use 00 anywhere in the sample data, as that is reserved for denoting the end of a sample. You'd have to go into a hex editor and replace all the 00s with 01s or something. The sample inclusion macro automatically inserts 00s at the end.
     
    Last edited: Nov 12, 2022
  19. Strange oddity I've noticed for some time, but the collision loading routine messes with the stack pointer to prevent collision issues in CPZ and ARZ.
    Code (Text):
    1.     moveq    #0,d0
    2.     move.b    (Current_Zone).w,d0
    3.     lsl.w    #2,d0
    4.     move.l    #Primary_Collision,(Collision_addr).w
    5.     move.w    d0,-(sp)
    6.     movea.l    Off_ColP(pc,d0.w),a0
    7.     lea    (Primary_Collision).w,a1
    8.     bsr.w    KosDec
    9.     move.w    (sp)+,d0
    10.     movea.l    Off_ColS(pc,d0.w),a0
    11.     lea    (Secondary_Collision).w,a1
    12.     bra.w    KosDec
    The thing is, why do the issues happen to begin with? I am aware that Kosinski decompression stores its variable on the stack, but they are reset after decompression is finished anyways. And yes, it only effects CPZ and ARZ.

    (also, about the PalPointers crashes, apparently the palettes need to be aligned correctly, which this guide sets to $200 bytes)
     
  20. Devon

    Devon

    La mer va embrassé moi et délivré moi lakay. Tech Member
    1,425
    1,744
    93
    your mom
    It's saving d0 onto the stack before decompressing the 1st collision layer's block IDs and the restoring it so that it can be reused the get the pointer to the 2nd collision layer's block IDs for decompression. KosDec overwrites d0 when decompressing data, so d0 being saved/restored on the stack is needed. If you don't save/restore d0, then d0 ends up being 0 after KosDec is called, which means that the 2nd EHZ collision layer block IDs will be chosen. The issues are just more apparent in CPZ and ARZ because they have more path swappers, HTZ uses the same collision data as EHZ, and some stages don't even make use of path swapping at all.

    The stack is only used in KosDec to perform little-endian to big-endian conversion, since the description fields are stored in little-endian.
    Code (Text):
    1.     move.b    (a0)+,1(sp)
    2.     move.b    (a0)+,(sp)
    3.     move.w    (sp),d5

    To give you a full picture of what's going on with the stack pointer...

    LoadCollisionIndexes pushes d0 (word) to the stack with this line:
    Code (Text):
    1.     move.w    d0,-(sp)

    Then, KosDec is called, which then pushes the address after the call (the return address) onto the stack and jumps to KosDec:
    Code (Text):
    1.     bsr.w    KosDec

    At the beginning of KosDec, is shifts the stack pointer up by 2 bytes, which effectively allocates 2 bytes for handling little-endian to big-endian conversions
    Code (Text):
    1. KosDec:
    2.     subq.l    #2,sp

    Then at the end of KosDec, it calls these 2 lines. The first shifts the stack pointer back down 2 bytes, effectively deallocating the endianess conversion buffer. "rts" then pops the return address from the stack and jumps to it.
    Code (Text):
    1. Kos_Done:
    2.     addq.l    #2,sp
    3.     rts

    Back in LoadCollisionIndexes, it then runs this, which pops a word from the stack into d0, which is the original value of d0 from before KosDec was called, which is then used for indexing the 2nd collision path collision IDs:
    Code (Text):
    1.     move.w    (sp)+,d0

    That value for alignment is used in other places, too, so it seems like an arbitrary decision by whoever wrote the guide. Needing the alignment outside of keeping things even makes no sense, because PalLoad just gets the direct address of the palette and copies the data into RAM.
     
    Last edited: Nov 18, 2022