That's not really true at all IMO Sadly the Mega CD didn't get enough PC point & click ports and most of the FMV games either came from old Laserdisc games or were built for the Mega CD itself. And what did you expect CD-ROM to offer at that time? It's hard to think of PC CD-ROM Dos games that didn't do anything different from the floppy version, other than add voice-overs and FMV. Why people expected the Mega CD to be so different, I do not know . PC's were super expensive in the 90's and out of the reach of many, that's why in the UK at least we had the big uptake in micro computers and btw the Mega Drive had a number of watered down PC ports, not that it really mattered. Star Flight and Buck Rogers are some of the best games you can buy on the Mega Drive IMO
It seems to me like it's saying "don't go crazy with FMVs". I like how they misspelled "quite" as "quiet" at one point.
But, they make it seem like it's the Genesis VDP's fault that video cannot be full screen with a smooth framerate, when that's not exactly the full truth. Yeah, the VDP has its limitations with VRAM space and data transfer bandwidth, but those aren't egregious enough to really prevent a smooth fullscreen video. On the Genesis alone, lack of ROM space just makes that unrealistic. With the Sega CD, you have RAM and disc reading limitations that prevent an adequate amount of data from reaching the Genesis in time to really get a smooth video in full screen. The comments about color count and resolution are just dumb, and the comments regarding the graphics operations(??) are just plain gibberish to me here. Get used to it, the manuals are filled with typos and bad grammar.
The comments on colour and resolution are to do with horizontal sprite limit, they're implying plane A and B would display the first two palette lines, and sprites filling up the entire H40 range would display the third line. Another line of sprites (for the fourth line) cannot be layered on top due to the horizontal limit, and they're suggesting to cut the motion image horizontally in half so two sprite layer's worth can overlay, allowing all four lines to display in every 8x8 space. You can garnish 16fps (3 frames per render) on a 50Hz Mega Drive system, transfering a full H40 screen worth of tile graphics, but on a 60Hz system, you're lucky to get 12fps (5 frames per render), with no processing of any data, just direct DMA transfer during V-blank periods. 12fps is considered bearly acceptable for human motion portrayal, though the minimum tolerable perceived motion is said to be 24fps. The human eye is complex and isn't a camera, so it's quite subjective, but from what I've seen, 16fps is considered smooth enough, but 12fps just isn't enough, and tricks have to be used to hide it. These transfers are for a single layer of tiles too, and multi-layer would cost more transfer time, and more VRAM space, only a single layer of H40 tiles can fit into VRAM at any one time, which is perhaps why they were suggesting 38x24 ($7200 bytes of VRAM for double buffer and space left for plane mappings). So the blame cannot be placed solely on ROM space limitations, video smoothness and colour range are still issues even with unlimited ROM space. It's true the Mega CD has its own limitations, but they're not wrong about the Mega Drive's role in the issues. Also, a side note, it's the Mega Drive's fault the contacts for the expansion slot are coating in Aluminium which is a poor conductor, and probably didn't help the data transfer rate.
Okay, yeah, that makes a lot more sense. The wording of the manual definitely threw me off, BUT I also completely forgot to take into account the cost of additional layer data AND forgot about the sprite limit, because what I had in my mind was single layer videos that had different tiles using different palette lines. That's completely on me, so my bad. Interesting tidbit on the contacts on the expansion slot, too. As a side note, I saw this thread on SpritesMind that was posted back in 2017 that mentioned JVC X'Eye service manuals, and how they actually document the CDD command and status codes. Thought it was interesting.
Been a while, huh? So, I've pretty much gotten a good idea of what the list of entry points found in the BIOS starting at address 0x280 point to. I will list them all here. Enjoy! Relevant Work RAM addresses 0xFFC000 (0x1400 bytes) - Security block animation object slots 0xFFE000 (0x1700 bytes) - Decompression buffer area 0xFFF700 (0x200 bytes) - Nemesis decompression buffer (officially called "bitdevwk") 0xFFF900 (0x280 bytes) - Sprite data buffer (officially called "spr_list") 0xFFFB80 (0x80 bytes) - Palette data buffer (officially called "color_ram") 0xFFFDA8 (6 bytes) - JMP instruction that jumps to a user defined V-BLANK handler, which is called by the main V-BLANK handler (user defined handler should return using rts). 0xFFFDB4 (w) - VDP register 0x00 cache. 0xFFFDB6 (w) - VDP register 0x01 cache. 0xFFFDB8 (w) - VDP register 0x02 cache. 0xFFFDBA (w) - VDP register 0x03 cache. 0xFFFDBC (w) - VDP register 0x04 cache. 0xFFFDBE (w) - VDP register 0x05 cache. 0xFFFDC0 (w) - VDP register 0x06 cache. 0xFFFDC2 (w) - VDP register 0x07 cache. 0xFFFDC4 (w) - VDP register 0x08 cache. 0xFFFDC6 (w) - VDP register 0x09 cache. 0xFFFDC8 (w) - VDP register 0x0A cache. 0xFFFDCA (w) - VDP register 0x0B cache. 0xFFFDCC (w) - VDP register 0x0C cache. 0xFFFDCE (w) - VDP register 0x0D cache. 0xFFFDD0 (w) - VDP register 0x0E cache. 0xFFFDD2 (w) - VDP register 0x0F cache. 0xFFFDD4 (w) - VDP register 0x10 cache. 0xFFFDD6 (w) - VDP register 0x11 cache. 0xFFFDD8 (w) - VDP register 0x12 cache. 0xFFFDDE (b) - Main CPU communication flag cache. 0xFFFDDF (b) - Sub CPU communication flag cache. 0xFFFDE0 (16 bytes) - Main CPU communication registers cache. 0xFFFDF0 (16 bytes) - Sub CPU communication registers cache. 0xFFFE20 (b) - Player 1 controller data (held buttons). 0xFFFE21 (b) - Player 1 controller data (tapped buttons). 0xFFFE22 (b) - Player 2 controller data (held buttons). 0xFFFE23 (b) - Player 2 controller data (tapped buttons). 0xFFFE24 (b) - Player 1 directional pad hold timer. 0xFFFE25 (b) - Player 2 directional pad hold timer. 0xFFFE26 (b) - V-BLANK flags (gets cleared at the end of a V-BLANK handler). Bit 0 - Enables sprite updates for handlers that handles them. Bit 1 - Enable user defined V-BLANK handler. 0xFFFE27 (b) - User V-BLANK counter 0xFFFE28 (b) - Disable VDP updates and user defined V-BLANK handler (overrides bit 1 of 0xFFFE26). 0xFFFE29 (b) - Palette update flag (must use bit 0). 0xFFFE2A (w) - Random number generator seed. 0xFFFE2C (w) - Base tile ID of font. 0xFFFE2E (w) - Stride of a VDP plane (plane width * 2). 0xFFFE30 (l) - Pointer to object sprite buffer in RAM (set in object update function). 0xFFFE34 (l) - Pointer to object index table. 0xFFFE38 (w) - Object sprite link value (used by object update function). 0xFFFE3A (w) - BIOS status 0xFFFE3C (w) - Absolute disc time 0xFFFE3E (w) - Relative disc time 0xFFFE40 (3 bytes) - End disc time 0xFFFE43 (b) - Current disc track 0xFFFE44 (b) - First disc track 0xFFFE45 (b) - Last disc track 0xFFFE46 (b) - Palette fade in offset 0xFFFE47 (b) - Palette fade in length 0xFFFE48 (w) - Palette fade in intensity 0xFFFE4A (l) - Palette fade in data 0xFFFE4E (w) - Time subtraction minuend (should be a longword, but a bug messes with this). 0xFFFE50 (l) - Time subtraction subtrahend. Object slot structure 0x00 (w) - ID (must be multiple of 4, 0 means empty slot) 0x02 (b) - Sprite flags Bit 1 - Enable sprite drawing Bit 7 - X flip 0x04 (l) - Pointer to sprite data 0x08 (l) - X position (16.16 fixed point) 0x0C (l) - Y position (16.16 fixed point) 0x10 (l) - X speed (16.16 fixed point) 0x14 (l) - Y speed (16.16 fixed point) 0x18 (b) - Base sprite tile flags (formatted like a VDP sprite's tile properties' high byte) 0x19 (b) - Sprite flip flag (set by object update function) 0x20 (b) - Animation frame (used in security block animation) 0x21 (b) - Animation timer (used in security block animation) 0x26 (b) - Palette cycle index (used in security block animation) 0x28 (w) - Movement timer (used in security block animation) Object sprite data 0x00 (b) - Number of sprite pieces (minus 1) 0x01 (b) - Some sort of flag that is incremented by 1 if the sprite is flipped (not really used) For each sprite piece 0x00 (b) - Y offset 0x01 (b) - Sprite size 0x02 (w) - Tile ID 0x03 (b) - X offset (when sprite is not flipped) 0x04 (b) - X offset (when sprite is flipped) 0x280 - Soft reset Performs a soft reset (mainly skips the stock SEGA hardware initialization). 0x284 - Hard reset This just jumps directly to the BIOS' entry point. 0x288 - Go to Control Panel Goes to the control panel. 0x28C - Go to Control Panel (and reset stack pointer) Goes to the CD control panel in the BIOS, and also resets the stack pointer. 0x290 - V-BLANK handler A pretty basic V-BLANK handler that updates communication registers, triggers the Sub CPU's IRQ2, transfers palette data from Work RAM, and reads the standard 3 button controllers, while also calling the user defined V-BLANK handler, if enabled. This differs from the BIOS' main V-BLANK handler, which handles multiple controller types (including the multitap and mouse) and manages some disc information. This is only really useful in the context of the BIOS itself, as the communication register update relies on the way the BIOS manages communication via the registers and cache. When a disc game is booted, the BIOS' program data gets overwritten with the initial system program found on the disc, so this ends up being sort of useless for the user, unless they were to simulate communication flag handling the same way as the BIOS. 0x294 - Enable H-BLANK interrupt and set handler This enables the H-BLANK interrupt and sets its handler to whatever is stored in register a1. 0x298 - Read standard 3 button controllers Reads standard 3 button controller data into RAM. 0x29C - Get controller ID Gets the peripheral ID of a controller. Which port is checked is determined by whether register a6 is set to 0xA10003 or 0xA10005. The value is stored in register d7. 0x2A0 - Clear VDP memory Wipes the VDP's memory (although only the first CRAM entry gets cleared). 0x2A4 - Initialize the screen Clears all the VDP planes and sprites (the first sprite slot is cleared with its link value set to 0). 0x2A8 - Clear VSRAM Clears the VDP's VSRAM. 0x2AC - Set default VDP register values Sets the VDP registers to use the BIOS' default values. 0x2B0 - Set VDP registers Sets the VDP registers to a user defined list of values, pointed to in register a1. The list of values is just a list of direct VDP register settings (i.e. 0x8004 to set register 0 to value 4), terminated with a 0. 0x2B4 - Fill region of VDP memory Fills a region of VDP memory, with register d0 containing the VDP command and register d2 containing the word value to fill the region with. 0x2B8 - Clear region of VDP memory The same as 0x2B4, except d2 is preset to 0, clearing out the region. 0x2BC - Clear region of VRAM via VRAM FILL Sets up a VRAM FILL command to clear a region of VRAM, with register d0 containing starting VRAM address already shifted to fit a VDP command (0x40000080 gets OR'd to it in the function), and register d1 set to the size of the region (minus 1). 0x2C0 - Fill region of VRAM via VRAM FILL Same as 0x2C0, except the register d2 is set to the value to fill VRAM with. 0x2C4 - Draw tilemap Draws a tilemap in VRAM, with register d0 containing the VDP command, register d1 being the width of the tilemap (minus 1), and register d2 being the height of the tilemap (minus 1). 0x2C8 - Draw tilemap that uses byte sized tile IDs Same as 0x2C4, except register d3 contains the base tile properties, and the map data uses bytes for the tile IDs, which are set into the lower byte of the base tile properties value to draw the map. 0x2CC - Fill VDP plane region Same as 0x2C4, except it fills a region of a VDP plane with a word value set in register d3. Uses no tilemap data. 0x2D0 - DMA transfer from 68000 memory to VRAM Performs a DMA transfer from 68000 memory into VRAM, with register d0 containing starting VRAM address already shifted to fit a VDP command (0x40000080 gets OR'd to it in the function), register d1 being the source address, and register d2 being the size of the transfer in words. 0x2D4 - DMA transfer from Word RAM to VRAM Same as 0x2D4, except it's designed for transferring from Word RAM by adding 2 to the source address and manually copying the first 2 bytes, due to an issue with Word RAM that causes latency. 0x2D8 - Enable display Enables display of graphics. 0x2DC - Disable display Disables display of graphics. 0x2E0 - Load palette data into RAM Loads palette data pointed to in register a1, with the first byte being the palette buffer offset, the second byte being the size of the palette data (minus 1), and then the rest being the palette data itself. 0x2E4 - Load palette data into RAM and enable palette update Same as 0x2E4, except that it also sets the palette update flag that is to be checked for copying the Work RAM buffer into the VDP's CRAM with. 0x2E8 - Update palette Checks the palette update flag, and if it's set, it copies the palette data stored in Work RAM into the VDP's CRAM. To be used in a V-BLANK handler. 0x2EC - Decompress Nemesis graphics into VRAM Decompresses graphics compressed in Nemesis into VRAM, with the VDP command set in the VDP control port, and the pointer to the data stored in register a1. 0x2F0 - Decompress Nemesis graphics into RAM Same as 0x2EC, except register a2 contains the pointer to the buffer in RAM to decompress the data into, with no VDP command to be set. 0x2F4 - Update objects Updates objects that are spawned in memory, with register a0 pointing to the object slots in RAM, register a1 pointing to the sprite data buffer in Work RAM to store sprite data in, register d0 containing how many object slots to update (minus 1), and register d1 containing the size of a object slot in Work RAM. 0x2F8 - Clear memory region Clears a region of memory, pointed to in register a0, with register d7 containing the size of the region in longwords (minus 1). 0x2FC - Clear large memory region Clears a large region of memory, pointed to in register a0. This is done block by block, with register d5 containing the number of blocks (minus 1) and register d7 containing the size of the first block in longwords (minus 1). The remaining blocks are set to be 0x40000 bytes in size each. 0x300 - Update object sprite Updates an object's sprite, with register a0 pointer to the object slot in RAM, register a2 pointing to the current sprite buffer slot in RAM, and d6 containing the sprite link value (which is incremented after each sprite piece stored). 0x304 - Perform VSync Performs VSync, with register d0 containing the value that is stored in the V-BLANK flags (which must be nonzero for VSync to actually work properly). Also updates the random number generator seed. 0x308 - Performs VSync with default flags Same as 0x304, except the V-BLANK flag is set to 0b11, which enables sprite updates and the user defined V-BLANK handler. 0x30C - Update sprites Checks the sprite update flag, and if it's set, it copies the sprite data stored in RAM into the VDP's CRAM. To be used in a V-BLANK handler. 0x310 - Some weird (bugged) copy function and caller This odd function uses register a0 as a pointer to a set of source data, register a1 as a pointer to a destination buffer, and register d0 as the size of the copy in bytes (must be a multiple of 4), which is set as a longword. After the copy, it jumps to the address stored in register a2. Unfortunately, this function is bugged. Similar to 0x2FC, it uses 2 registers to perform the loops, block by block. Except, instead of the user defining the 2 registers, they are automatically calculated by whatever is in d0. There is a flaw in the calculation where there are some edge cases where an additional 0x40000 bytes will be copied, due to an underflow issue. The way it's done is that the size of data to copy is divided by 4 to become a size in terms of longwords. Then, the first block size in longwords is set to the lower word, and the number of blocks is set to the high word. For some reason, they only apply the subtract by 1 for the DBF instruction on the lower word, and any underflows from 0 to 0xFFFF do not decrement the higher word... they should have just subtracted 1 after dividing the whole count by 4, but they didn't... 0x314 - Enable H-BLANK interrupt (in Work RAM) and set handler Same as 0x294, except the pointer to the H-BLANK handler must be in address range 0xFF8000-0xFFFFFF, the second half of Work RAM. 0x318 - Disable H-BLANK interrupt Disables the H-BLANK interrupt. 0x31C - Draw text Draws a string of ASCII text, with register d0 containing the VDP command, and register a1 pointing to the string. In the string data, a byte value of 0x00 adds a new line, and a byte value in the range 0x80-0xFF terminates the string. 0x320 - Load 1BPP graphics Loads a set of 1BPP graphics into VRAM, with register d0 containing the VDP command, register d1 containing the decode values, register a1 pointing to the graphics data, and register d2 containing the number of tiles to decode. Data is decoded 2 bits at a time to correspond with 2 pixels per byte. From highest to lowest byte in register d1: Expanded value when both bits are 0. Expanded value when the low bit is 1, and the high bit is 0. Expanded value when the high bit is 1, and the low bit is 0. Expanded value when both bits are 1. The value you would want to set would have to fit this pattern: XXXYYXYY, where X and Y are the colors you want to use in a palette line. 0x324 - Load BIOS' 1BPP font Same as 0x320, except loads the BIOS' 1BPP font. The VDP command and decode values must still be defined. When using the font to draw text, the base tile ID value should be stored in 0xFFFE2C. 0x328 - Load BIOS' 1BPP font with default parameters Same as 0x324, except it defaults to loading the font at the beginning of VRAM, and uses color 1. 0xFFFE2C is automatically set to 0. 0x32C - Update controller directional pad hold timer This updates a timer that is used when holding down on the directional pad on the controller. Register d0 is set to 0 for player 1, 1 for player 2. Register a1 is set to the pointer to a byte where the directional pad button bits are stored when the timer has reset. When a button is first pressed, the timer is set to a value 20 (21 frames, minus 1), and as it is held, the timer ticks down, and when it goes negative, it refreshes with a value of 5 (6 frames, minus 1). Useful for stuff like scrolling through options. 0x330 - Decompress Enigma tilemap data Decompresses tilemap data compressed in Enigma, with register a1 pointing to the tilemap data, and register d0 containing the base tile properties. 0x334 - Draw tilemap for graphics generated by the Sega CD This draws a tilemap specifically made for graphics that are generated by the Sega CD, which stores the tiles in columns instead of rows. Register d0 contains the VDP command, register d1 contains the width of the tilemap (minus 1), register d2 contains the height of the tilemap (minus 1), and register d3 containing the base tile properties. 0x338 - Get a random number Takes an additional input seed in register d0 along with the main seed and generates a random number into register d0. 0x33C - Update random number generator seed Updates the main random number generator seed. This is also called by the VSync function. 0x340 - Clear communication registers Clears the communication registers and cache. 0x344 - Update communication registers and trigger Sub CPU IRQ2 Updates communication flags and performs checks, and then copies the Main CPU communication cache into the registers, and then caches the Sub CPU communication registers. Also triggers the Sub CPU's IRQ2. This is called by the BIOS' V-BLANK handlers. This is only really useful in the context of the BIOS itself, as it relies on the way the BIOS manages communication via the registers and cache. When a disc game is booted, the BIOS' program data gets overwritten with the initial system program found on the disc, so this ends up being sort of useless for the user, unless they were to simulate communication flag handling the same way as the BIOS. 0x348 - Get disc track information (BIOS only) Retrieves disc track information from the Sub CPU. Information that gets retrieved include the current seek time, current track, first and last tracks on the disc, and the disc's end time. This should be avoided, as it relies on code on the Sub CPU side to get the data to begin with. When a disc game is booted, the BIOS' program data gets overwritten with the initial system program found on the disc, so this ends up being useless for the user. 0x34C - Sync with Sub CPU Syncs with the Sub CPU. This is only really useful in the context of the BIOS itself, as it relies on the way the BIOS manages communication via the registers. When a disc game is booted, the BIOS' program data gets overwritten with the initial system program found on the disc, so this ends up being sort of useless for the user, unless they were to simulate communication flag handling the same way as the BIOS. 0x350 - Set Sub CPU BIOS function (BIOS only) This sets up a Sub CPU BIOS function call by setting parameters for it in registers d0 and d1. This should be avoided, as it relies on code for communication and code on the Sub CPU side to manage it in a specific way. When a disc game is booted, the BIOS' program data gets overwritten with the initial system program found on the disc, so this ends up being useless for the user. 0x354 - Set Sub CPU Backup RAM function (BIOS only) This sets up a Sub CPU Backup RAM function call by setting parameters for it in registers d0 and d1. This should be avoided, as it relies on code for communication and code on the Sub CPU side to manage it in a specific way. When a disc game is booted, the BIOS' program data gets overwritten with the initial system program found on the disc, so this ends up being useless for the user. 0x358 - Set unknown Sub CPU function (BIOS only) This sets up some sort of unknown function call on the Sub CPU by setting parameters for it in registers d0 and d1. Doesn't seem to actually be used. This should be avoided, as it relies on code for communication and code on the Sub CPU side to manage it in a specific way. When a disc game is booted, the BIOS' program data gets overwritten with the initial system program found on the disc, so this ends up being useless for the user. 0x35C - Set Sub CPU BIOS scene function to the Sub CPU (BIOS only) This sets up a Sub CPU BIOS scene function call by setting parameters for it in registers d0 and d1. This should be avoided, as it relies on code for communication and code on the Sub CPU side to manage it in a specific way, and is also mainly used to tell the Sub CPU when a BIOS scene has changed (a scene meaning the main screen, the control panel, the Backup RAM manager, etc.). When a disc game is booted, the BIOS' program data gets overwritten with the initial system program found on the disc, so this ends up being useless for the user. 0x360 - Trigger the Sub CPU's IRQ2 Triggers the Sub CPU's IRQ2. 0x364 - Display security block animation Displays the "SEGA" animation that plays when a security check has passed. This is called by the security block code itself, with register a1 pointing to a set of data needed to display the animation. 0x368 - Set V-BLANK handler Sets the V-BLANK handler pointer to the address stored in register a1. 0x36C - Draw tilemap with sequential tile IDs. Draws a tilemap that uses a sequential set of tile IDs (i.e. 0, 1, 2, 3, 4, 5...). Register d0 contains the VDP command, register d1 contains the width of the tilemap (minus 1), register d2 contains the height of the tilemap (minus 1), and register d3 contains the starting tile ID and properties. 0x370 - Draw partial tilemap Partially draws a tilemap. Register d0 cotnains the VDP command, register d1 contains the partial width of the tilemap to draw (minus 1), register d2 contains the height of the tilemap (minus 1), and stride of the tilemap (its full width * 2) in register d3. 0x374 - Perform VRAM copy Performs a VRAM copy operation on the VDP, with register d0 containing destination VRAM address already shifted to fit a VDP command (0x000000C0 gets OR'd to it in the function), register d1 containing the destination VRAM address, and register d2 containing the number of bytes to copy (minus 1). 0x378 - Set Sub CPU BIOS function by index (BIOS only) Similar to 0x350, except that register d0 is used as an index for a table of function IDs and parameter types, with register d1 being the primary parameter, and register d2 being a secondary parameter. This should be avoided, as it relies on code for communication and code on the Sub CPU side to manage it in a specific way. When a disc game is booted, the BIOS' program data gets overwritten with the initial system program found on the disc, so this ends up being useless for the user. 0x37C - Convert byte value to BCD format Converts a byte value stored in register d1 to BCD format. 0x380 - Convert word to BCD format Converts a word value stored in register d1 to BCD format. 0x384 - Black out display Disables display and also sets the first VDP CRAM color to black. 0x388 - Fade out palette towards black Performs one operation of a palette fade out, with register d0 being the palette buffer offset, and register d1 being the number of colors to fade (minus 1). Call this multiple times to fully fade out to black. The zero condition flag will be set if the palette has faded entirely to black. 0x38C - Fade in palette from black Performs one operation of a palette fade in. Must be first set up with function 0x390. 0x390 - Set up palette fade in Sets up a palette fade in. Register a1 points to palette data that should be faded towards, with the first byte being the palette buffer offset, the second byte being the size of the palette data (minus 1), and then the rest being the palette data itself. 0x394 - Flush a Word RAM DMA queue This flushes a queue pointed to in register a1 that contains Word RAM DMA queue command data. Each slot contains 3 values: 0x00 (w) - The size of the transfer in words 0x02 (l) - The starting VRAM address already shifted to fit a VDP command (0x40000080 gets OR'd to it in the function). 0x04 (l) - The source address. 0x398 - Flush a short Word RAM DMA queue (bugged) Basically the same as 0x394, except that the source address is the size of the word, and is relative to the start of the queue slot. Unfortunately, this function seems to be bugged, because this logic only applies to the first slot. The function then ends up jumping to function 0x394 for the rest of the slots. 0x39C - Add time values together Adds 2 time values together. Register a1 points to a memory address that contains a mm:ss (minute and second) word value in BCD format, and register a2 points to the end of another memory address that contains the same format word. They get added together, and the result is stored in memory pointed to by register a1. 0x3A0 - Subtract time value from another (bugged) Subtracts a time value from another time value. Register d0 contains the minuend and register d1 contains the subtrahend. Both are mm:ss:cc:xx values (minute, second, and centisecond, xx is ignored) BCD format. The result is returned as a mm:ss (minute and second) value in BCD format in register d0. Unfortunately, this function is bugged, because they only allocated 2 bytes for the destination buffer instead of 4. The source destination is placed right after it, so the lower 2 bytes of the minuend get overwritten by the upper 2 bytes of the subtrahend.
Heya, so I made an updated version of my mode 1 library. It includes an easier setup (no longer requires you to set up your V-BLANK interrupt and enable interrupts, though you can still do that if you wish), simpler BIOS detection (checks the presence of a string within the compressed Sub CPU BIOS data at different locations), and my custom Kosinski decompression function in case you don't have one. Eventually, I do want to figure out a better way to detect where the Sub CPU BIOS is, mainly to better support custom BIOSes in the event that one is made and used. But, for now, the current method works, at least for the official ones.
I actually liked the older version since it's a bit more precise with identifying the sub CPU device (storing the ID of the BIOS entry in RAM could even be used for a few things, such as distinguishing between models with motorized trays and those without). But given how complicated setting up Mode 1 can get, I do like the ease of use changes here, particularly the handling of VBlank. Something I considered for my own init code at one point was expanding the BIOS table to allow the program to decompress the BIOS using the copy of KosDec that is included in each bootrom. Unfortunately, there's even more variation with that location compared to the BIOS payloads, so it would have required more extensive checking of the BIOS headers. While this could be of benefit in determining exact models, I decided it wasn't worth the effort. Code (ASM): ; If only this was as easy to implement as it looks... move.b (a3),d6 ; a3 = mcd_mem_mode andi.b #(~program_ram_bank)&$FF,d6 ; first program RAM bank move.b d6,(a3) lea (program_ram).l,a1 ; start of program RAM window move.b (v_bios_id).w,d4 ; get BIOS ID (d4 is already 0) lea MCDBIOSList(pc),a0 move.w -2(a0,d4.w),d4 ; -2 since IDs start at 2 movea.l 4(a0,d4.w),a2 ; a2 = bootrom's KosDec function movea.l (a0,d4.w),a0 ; a0 = compressed BIOS payload jsr (a2) ; decompress the BIOS
I was thinking of adding back the old detection method, but as a separate function for determining if an official BIOS is used and which one. Like I said in my post, I want to be able to support custom BIOSes (particularly since I wrote one for clownmdemu), so there could be some use in that.