Jump to content
IGNORED

Half bitmap mode


Willsy

Recommended Posts

You can run Daniel Bienvenu's ROM in Meka (the SMS emulator, which also supports a host of closely related systems including the coleco), and capture the output to a VGM file, which can then be converted by Tursi's SPF tools. I don't have a Windows PC, but it should be a fairly easy process.

 

Great idea. It does work reasonably well except I have some difficulties getting the speed right, but unfortunately the ROM posted on AtariAge only sounds like an early draft compared to the one on YouTube.

Link to comment
Share on other sites

  • 3 weeks later...
I did some more research into the nature of the sprite duplication issue in hybrid modes with fewer than 3 pattern tables (only for sprites #8 and above):


Configuration 0 (VR4=0, a.k.a. half-bitmap mode. One pattern table for the whole screen):

Top third: sprites located here are duplicated both to the middle and bottom thirds. Only the part of the sprite within the top third is duplicated, i.e if the sprite extends into the middle third the bottom part of the sprite is not duplicated. This applies to the other configurations as well.

Middle third: sprites located here are not duplicated.

Bottom third: sprites located here are hidden. A sprite located in the middle third that extends into the bottom third will have the bottom part hidden (also applies to configuration 1).


Configuration 1 (VR4=1. Two pattern tables: one for the top and bottom thirds, another for the middle third):

Top third: sprites located here are duplicated to the bottom third.

Middle third: sprites located here are not duplicated.

Bottom third: sprites located here are hidden.


Configuration 2 (VR4=2. Two pattern tables: one for the top and middle thirds, another for the bottom third):

Top third: sprites located here are duplicated to the middle third.

Middle third: sprites located here are not duplicated.

Bottom third: sprites located here are not duplicated.


The test was done on a TMS9929A (PAL) machine using sprite #8. I used the attached program that allows you to move a sprite around with the joystick. SPRDUP0, SPRDUP1, SPRDUP2 on the disk correspond to configuration 0, 1, 2 above. If you press fire the mode will change to 3 pattern tables where no duplication occurs, this allows you to see the true position of the sprite.

sprdup.a99

SPRDUP.dsk

  • Like 4
Link to comment
Share on other sites

  • 10 months later...
From time to time I'm returning to think about the sprite duplication bug in the 9918A (see post above) and whether it would be possible to emulate it, and today I made a little progress. The reason for emulating the bug is to prevent developers from running into problems when they move their software from emulation to real hardware, like I did when I made Titanium.


When a VDP (real or emulated) is drawing a scanline and is considering whether a sprite should be drawn on the line, it must compare the position of the scanline (y) to the vertical position of the sprite (sy) like in the following pseudo code:


if y >= sy and y < sy + height

display line y - sy of the sprite

endif


where height is the height of the sprite.


Usually the scanline position y would run between 0 and 191 (0000 0000 to 1011 1111), but what would happen if we clear the two most significant bits of y before doing the comparison? When the VDP looks for sprites for a scanline >= 64, say 80 (0101 0000), it would be looking for sprites at scanline 80 mod 64 = 16 (0001 0000) instead. The result would be that sprites belonging at the top 3rd of the screen are mirrored to the middle and bottom 3rds. My current assumption is that something like this happens on the real VDP as well.


Since the 9918A bug has to do with the setting of the two least significant bits of VDP register 4 (the pattern table register) it's reasonable to assume that those two bits are involved in the masking of the scanline number. If we "and" the two bits with the two most significant bits of the scanline position y, it does indeed look like we have come a long way to emulate the bug. Note that this should only be done for sprite #8 and above since lower sprite numbers are not affected by the bug and it should only be done in bitmap mode. Also note that in the normal bitmap mode with 3 pattern tables the two lower bits are 11 so performing an "and" with them will have no effect, which is what we want.


This attempt does not fully emulate the bug as it's described in my post above. It takes care of the duplication and the situations when sprites are hidden, but it's also hiding too much. As described in the post above, sprites in the middle 3rd should appear as normal in configuration 0 and 2, and in this attempt to emulate the bug the sprites are hidden. Everything else seems to be working as described, and configuration 1 seems to be fully emulated.


I hope someone has an idea that will help to solve the remaining parts of this puzzle.


For now I have included the emulation of the bug as described in http://js99er.net. You can play around with the test programs from the previous post and see for yourself. Remember to reload the page, and disable the F18A emulation if you have previously turned it on, because the F18A obviously does not have this bug.


post-35226-0-92926000-1472312580_thumb.png

  • Like 2
Link to comment
Share on other sites

Copying the source from from https://github.com/openMSX/openMSX/issues/593 for future reference:

/* init sprite cloning */
        if (regs[0]&2&&(regs[4]&3)!=3&&!is_toshiba) {
            /* On TMS9xxx(/A) M3, sprites 8-31 Y position(s) is influenced by the least two
            bits of the pattern generator table offset, and somewhat by bits 5 and 6 of the
            colour table register. Sprite locations, mostly those on Y 0-63, will become
            glitchy, and cause a cloning effect similar to tiles with M3 table mirroring.
            This is not just a visual effect, as sprite collision and overflow behave as if
            sprites are normal. If the VDP is running hot, this effect will deteriorate
            (confirmed by flyguille with a blow dryer  ), starting with block 1, and
            block 2 shortly after (effect deterioration from heat is unemulated). I assume
            the reason for the first 8 sprites not being affected is due to them being
            preprocessed in hblank. This glitch is briefly mentioned in the official
            TMS91xx programming manual btw, meaning that it's not undocumented.

            Known software affected by this (not counting tests or small glitches):
            - Alankomaat by Bandwagon, at the fire part (intended)
            - Lotus F3, unintended problems in MSX1 palette mode (black screen on my MSX1s)

            The calculations below are done to get the correct result, I can't think of
            a way to solve this logically. This implementation has been tested side by side
            to my MSX1, with all possible sprite Y and addressmasks. */

            /* 0-255, 4 blocks of 64 lines */
            if (line>191) {
                /* block 3 (only visible at the far top of the screen)
                Sprites are cloned from block borders. The colour block
                erase effect is the same as on block 2 below. */
                clonemask[0]=0xff; clonemask[2]=~regs[4]<<6&0xc0;
                if (~regs[3]&0x40&&clonemask[2]&0x80) {
                    clonemask[0]&=0x7f;
                    clonemask[2]&=0x7f;
                }

                clonemask[3]=clonemask[0]; clonemask[5]=clonemask[2];

                clone=7;
            }
            else if (line>127) {
                /* block 2, sprites are cloned from block 0.
                The bottom part of sprites on block 1+2 is always
                invisible. If this colour block mask is reset, real
                sprites in block 2 will be erased. */

                /* only has effect if this pattern block mask is reset */
                if (~regs[4]&2) {
                    clonemask[1]=clonemask[4]=0x80;
                    clonemask[5]=regs[3]<<1&0x80;

                    clone=7;
                }
            }
            else if (line>63) {
                /* block 1, sprites are cloned from block 0.
                If this colour block mask is reset, the bottom part of
                sprites on block 0+1 will be invisible. */

                /* only has effect if this pattern block mask is reset */
                if (~regs[4]&1) {
                    clonemask[0]=0x3f;
                    clonemask[5]=~regs[3]<<1&0x40;

                    clone=7;
                }
            }
            else {
                /* block 0, no effect */
                ;
            }
        }

However, I'm not sure this is correct: "I assume the reason for the first 8 sprites not being affected is due to them being preprocessed in hblank".

 

This is a quite from Matthew's correspondence with Karl Guttag where he explains about sprite processing. It describes another preprocessing mechanism:

 

 

During the active display we did sprite preprocessing where we went though the 32 sprites looking ONLY at the line number and the size (which was the same for all sprites because we didn’t have the memory cycles to fetch the information). These sprite preprocessing access were done every 4th memory cycle (with some of these given to the CPU). This would determine if the sprite was active on the next line. If a Sprite was “active” we would save the sprite number and on a first in first out (FIFO) stack which was 5 entries long (4 active and the 5th sprite number.

 

When we hit blanking, we use the sprite number stack to go back and fetch the 4 bytes information for each sprite. We then used the size and starting line of the sprite and current line of the display to compute which the address of the line of the sprite.

During the active display we did sprite preprocessing where we went though the 32 sprites looking ONLY at the line number and the size (which was the same for all sprites because we didn’t have the memory cycles to fetch the information). These sprite preprocessing access were done every 4th memory cycle (with some of these given to the CPU). This would determine if the sprite was active on the next line. If a Sprite was “active” we would save the sprite number and on a first in first out (FIFO) stack which was 5 entries long (4 active and the 5th sprite number.

 

When we hit blanking, we use the sprite number stack to go back and fetch the 4 bytes information for each sprite. We then used the size and starting line of the sprite and current line of the display to compute which the address of the line of the sprite.

During the active display we did sprite preprocessing where we went though the 32 sprites looking ONLY at the line number and the size (which was the same for all sprites because we didn’t have the memory cycles to fetch the information). These sprite preprocessing access were done every 4th memory cycle (with some of these given to the CPU). This would determine if the sprite was active on the next line. If a Sprite was “active” we would save the sprite number and on a first in first out (FIFO) stack which was 5 entries long (4 active and the 5th sprite number.

 

When we hit blanking, we use the sprite number stack to go back and fetch the 4 bytes information for each sprite. We then used the size and starting line of the sprite and current line of the display to compute which the address of the line of the sprite.

 

 

By the way, does this explain why sprites are displayed one line below what you would expect from the y coordinate?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...