Asmusr Posted September 21, 2015 Share Posted September 21, 2015 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. Quote Link to comment Share on other sites More sharing options...
Asmusr Posted October 11, 2015 Share Posted October 11, 2015 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 4 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted August 27, 2016 Share Posted August 27, 2016 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. 2 Quote Link to comment Share on other sites More sharing options...
Tursi Posted August 27, 2016 Share Posted August 27, 2016 Allow me to re-share my bitmap test program, which you can use to quickly play with the masking bits in real time and watch what the machine does Hope it helps... bitmaptest.zip 1 Quote Link to comment Share on other sites More sharing options...
artrag Posted August 29, 2016 Share Posted August 29, 2016 The cloning effect in half bitmap mode is fully emulated in meisei and documented in openmsx. You could read more here https://github.com/openMSX/openMSX/issues/593 2 Quote Link to comment Share on other sites More sharing options...
Asmusr Posted August 29, 2016 Share Posted August 29, 2016 Cool, I need to read it in detail, but this is interesting: on VDP's without heat sink, the clones gradually (and randomly) disappear when the VDP gets hot. With a heat sink, they do not disappear Quote Link to comment Share on other sites More sharing options...
Tursi Posted August 29, 2016 Share Posted August 29, 2016 Seems to cover the cases I remember trying to document back in the day... wouldn't take much to run it up and see if it matches hardware. Quote Link to comment Share on other sites More sharing options...
Asmusr Posted August 30, 2016 Share Posted August 30, 2016 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? Quote Link to comment Share on other sites More sharing options...
Tursi Posted August 30, 2016 Share Posted August 30, 2016 By the way, does this explain why sprites are displayed one line below what you would expect from the y coordinate? Correct, the sprites are processed for display on the next line. Quote Link to comment Share on other sites More sharing options...
Fredrik Öhrström Posted August 31, 2016 Share Posted August 31, 2016 Cool, I need to read it in detail, but this is interesting: on VDP's without heat sink, the clones gradually (and randomly) disappear when the VDP gets hot. With a heat sink, they do not disappear Ah, this is indeed very interesting! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.