+wavemotion Posted October 22, 2022 Share Posted October 22, 2022 Greetings programs! This community has always been super helpful and I'm in need of a little push in the right direction. My A7800DS emulator (for the DS/DSi) is based on ProSystem. I know that emulator has been problematic with accuracy but in the past year I've worked hard to rectify many of the small glitches to the point where it's generally been really solid (with thanks to @raz0red and the Wii port of the same as he figured out some of the glitch areas). The one remaining known glitch is on @Muddyfunster's amazing Keystone Koppers. Let me make it clear that it's not his program that's buggy - it's my emulator... but after looking at the Maria documents online, trying to understand the various graphics modes, background and transparency handling... I'm still not able to rectify this glitch shown in the image below. All other graphics look basically correct - including the player sprite. But you can see the black box around the robber... at first I thought maybe Kangaroo mode was screwed up in my emulation but the game doesn't appear to be using that. I thought it might have been one of the odd quirks of 320 mode where both halves of the pixel must be 0 for transparency to work - but this game appears to be using the more standard 160 mode. And so after having exhausted my skills in this area I'm hopeful that someone will have a clue or breadcrumb that might push me in the right direction. Even the smallest of clues can go a long way to finding a needle in a haystack! I'd love to know what's being done in a possibly unusual manner for this particular sprite to let me focus in on that area of emulation. Kindest regards for any help anyone might provide - random guesses are always welcome 1 Quote Link to comment Share on other sites More sharing options...
+Muddyfunster Posted October 22, 2022 Share Posted October 22, 2022 11 minutes ago, llabnip said: All other graphics look basically correct - including the player sprite. But you can see the black box around the robber... at first I thought maybe Kangaroo mode was screwed up in my emulation but the game doesn't appear to be using that. I thought it might have been one of the odd quirks of 320 mode where both halves of the pixel must be 0 for transparency to work - but this game appears to be using the more standard 160 mode. And so after having exhausted my skills in this area I'm hopeful that someone will have a clue or breadcrumb that might push me in the right direction. Even the smallest of clues can go a long way to finding a needle in a haystack! I'd love to know what's being done in a possibly unusual manner for this particular sprite to let me focus in on that area of emulation. The game is fully 160 Mode, no 320 elements are used and Kangaroo mode is not used. The Robber sprite is a 160B sprite (this was just because the colours needed were in multiple palettes), with green in the image below indicating the transparent index. The Kop sprite is also 160B but I notice there are no issues with that in the emulation. The same glitch appears to be present in JS7800 and other prosystem based emulators. Sorry I can't be of more help with hardware side of the discussion. 1 Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 22, 2022 Share Posted October 22, 2022 Best guess off the top of my head, is the transparent index for the robber in the game is mapped to one of the alternate transparent indexes, and the emulator isn't handling the other transparent indexes correctly. Assuming the maria object is using pallete 0, the value->color mapping for any 160A pixel (which is 2 bits) breaks down like this... 0=transparent 1=P0C1 2=P0C2 3=P0C3 Assuming the maria object is using pallete 0, the value->color mapping for any 160B pixel (which is 4 bits) breaks down like this... 0=transparent 1=P0C1 2=P0C2 3=P0C3 4=transparent 5=P1C1 6=P1C2 7=P1C3 8=transparent ... etc. So for transparency, you want to skip the pixel update if (value&3)==0, rather than value==0. If I'm right with my guess, that is. 2 Quote Link to comment Share on other sites More sharing options...
+wavemotion Posted October 22, 2022 Author Share Posted October 22, 2022 Hugely appreciate the detailed responses guys! I spent the day all over that 160B handling and I can't see anything obviously wrong. And it is interesting that the Kop sprite is right but the Robber is not. When we grab the color, we do properly mask off the lower bits for the transparency check. Without this, other artifacts appear on some games. static inline byte maria_GetColor(byte data) { return (data & 3) ? memory_ram[BACKGRND | data] : memory_ram[BACKGRND]; } I'll keep looking and experimenting! 2 Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 23, 2022 Share Posted October 23, 2022 Ok, bad guess on my part then. Lewis, would you mind shooting me the *.list.txt file in PM? I have another idea here, but I'd like to confirm. 1 Quote Link to comment Share on other sites More sharing options...
+Muddyfunster Posted October 23, 2022 Share Posted October 23, 2022 12 minutes ago, RevEng said: Ok, bad guess on my part then. Lewis, would you mind shooting me the *.list.txt file in PM? I have another idea here, but I'd like to confirm. Will do. 2 Quote Link to comment Share on other sites More sharing options...
Trebor Posted October 23, 2022 Share Posted October 23, 2022 In case it helps in understanding what is missing or incorrect under the A7800DS emulator, another off-shoot of the ProSystem emulator, JS7800, furnishes a black box around the entire "Krook" in JS7800: 3 Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 23, 2022 Share Posted October 23, 2022 For the write-mode graphic modes, you should only be using the top bit of the palette. I'm not that familiar with your source, but I think I have this right... static inline void _maria_StoreCells4(byte data) { if((maria_horizontal) < MARIA_LINERAM_SIZE) { byte *ptr = &(maria_lineRAM[maria_horizontal]); #ifdef KANGAROO_MODE_SUPPORTED if (memory_ram[CTRL] & 4) { if (data & 0x03) *ptr-- = (maria_palette & 0x10) | (data & 0x03); else *ptr-- = 0; data = data >> 2; if (data & 0x03) *ptr-- = (maria_palette & 0x10) | (data & 0x03); else *ptr-- = 0; data = data >> 2; if (data & 0x03) *ptr-- = (maria_palette & 0x10) | (data & 0x03); else *ptr-- = 0; data = data >> 2; if (data) *ptr = (maria_palette & 0x10) | (data); else *ptr = 0; } else #endif { if (data & 0xC0) *ptr++ = (maria_palette & 0x10) | ((data & 0xC0) >> 6); else ptr++; if (data & 0x30) *ptr++ = (maria_palette & 0x10) | ((data & 0x30) >> 4); else ptr++; if (data & 0x0C) *ptr++ = (maria_palette & 0x10) | ((data & 0x0C) >> 2); else ptr++; if (data & 0x03) *ptr++ = (maria_palette & 0x10) | (data & 0x03); } } maria_horizontal += 4; } i.e. all references to "maria_palette" in the original h_maria_StoreCells4() should be "(maria_palette & 0x10)" ...my guess now is the 160B robber object has a palette index that's neither 0 nor 4, but some other number. 1 Quote Link to comment Share on other sites More sharing options...
+wavemotion Posted October 23, 2022 Author Share Posted October 23, 2022 Herculean effort here @RevEng and much appreciated no matter the outcome! I tried your suggestion and there was no change to the Robber sprite but all the other colors got very trippy - like a Grateful Dead concert circa '79. I think the write mode store already had that correct: // ---------------------------------------------------------------------------- // StoreCell - write mode // ---------------------------------------------------------------------------- static inline void maria_StoreCellWide(byte data) { if(maria_horizontal < MARIA_LINERAM_SIZE) { if (data) { byte *ptr = (byte *)&maria_lineRAM[maria_horizontal]; if (data & 0xF0) // high { *ptr = (maria_palette & 0x10) | (data >> 4); } if (data & 0x0F) // low { ptr++; *ptr = (maria_palette & 0x10) | (data & 0x0F); } } } ... Quote Link to comment Share on other sites More sharing options...
+Muddyfunster Posted October 23, 2022 Share Posted October 23, 2022 Mike, the list file is in your inbox. 1 Quote Link to comment Share on other sites More sharing options...
+Muddyfunster Posted October 23, 2022 Share Posted October 23, 2022 8 hours ago, RevEng said: my guess now is the 160B robber object has a palette index that's neither 0 nor 4, but some other number. Mike, in the source, the robber only uses palette 0. Quote Link to comment Share on other sites More sharing options...
Eagle Posted October 23, 2022 Share Posted October 23, 2022 @Muddyfunster is the Robber in indirect mode? Quote Link to comment Share on other sites More sharing options...
Ecernosoft Posted October 23, 2022 Share Posted October 23, 2022 1 hour ago, Muddyfunster said: Mike, in the source, the robber only uses palette 0. Then why 160B? Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 23, 2022 Share Posted October 23, 2022 1 hour ago, llabnip said: I think the write mode store already had that correct: Yeah, my bad. I mixed up your write and non-write functions. 1 hour ago, Muddyfunster said: Mike, in the source, the robber only uses palette 0. Thanks! 47 minutes ago, Eagle said: @Muddyfunster is the Robber in indirect mode? Nope. It's just a regular sprite. 2 minutes ago, Ecernosoft said: Then why 160B? Palette 0 for 160B really means P0+P1+P2+P3. 2 Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 23, 2022 Share Posted October 23, 2022 Try this update... // ----------------------------------------------------------------------------// StoreCell - write mode// ----------------------------------------------------------------------------static inline void maria_StoreCellWide(byte data) { if(maria_horizontal < MARIA_LINERAM_SIZE) { if (data) { byte *ptr = (byte *)&maria_lineRAM[maria_horizontal]; if (data & 0xcc) // high { *ptr = (maria_palette & 0x10) | (data & 0x0c) | (data >> 6); // P2 D3 D2 D7 D6 } if (data & 0x33 ) // low { ptr++; *ptr = (maria_palette & 0x10) | ((data & 0x03) << 2) | ((data & 0x30) >> 4); // P2 D1 D0 D5 D4 } } } [edit 1 - updated to fix the nibble tests too] [edit 2 - had to fix the nibble test again. ugh.] 1 Quote Link to comment Share on other sites More sharing options...
+wavemotion Posted October 23, 2022 Author Share Posted October 23, 2022 Another valiant effort, Rev. This code is called by a transposition function which does a table-look-up to transpose those funky bit patterns into something I can blaze through... so I don't have to do too much bit twiddling and gain the speed I need on the older Nintendo DS (67Mhz processor). I made your changes with the change in nibble tests (checking 0xCC and 0x33) and undid my table-lookup and while it runs about 25% slower, it produces the exact same results: Kop looks great but Robber has the black around it. A good confirmation that the look-up transposition table is working... though I was pretty sure I didn't screw that up as other ProSystem based emulators have the same glitch (and they would have done the code closer to your fine example). Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 23, 2022 Share Posted October 23, 2022 4 minutes ago, llabnip said: Another valiant effort, Rev. This code is called by a transposition function which does a table-look-up to transpose those funky bit patterns into something I can blaze through. Ah, my lack of familiarity with your source strikes again. When I saw the "missing" transposition, I thought I had it. Ok, back to the analysis. 1 Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 23, 2022 Share Posted October 23, 2022 I know it's not being used in the game, but is the glitch still present if kangaroo mode is compile-time disabled in your source? 1 Quote Link to comment Share on other sites More sharing options...
+wavemotion Posted October 23, 2022 Author Share Posted October 23, 2022 (edited) 56 minutes ago, RevEng said: I know it's not being used in the game, but is the glitch still present if kangaroo mode is compile-time disabled in your source? Yes... it doesn't matter if Kangaroo mode is enabled or disabled... and I did verify that the Roo-mode bit is never enabled in this game. So I don't know if this will help or not... but I dumped out the maria_palette as well as the actual color byte (pre-transformation - so basically the data as you would have it for your most recent bit-shifting algorithm and not muddied by my table lookup). I don't have a pause feature for my crude debugging but I tried to capture 200 bytes of robber vs kop. In the first picture you can see the robber is on screen but not the cop. In the second you can see both. The bytes are in HEX and arranged in vertical columns. The upper leftmost byte is the palette followed by the data byte directly under it. This streams in pairs until all 200 bytes are shown. Something to note is that the robber colors shift from the white to some blue once the Kop shows up... maybe a clue. Again, I can't thank you guys enough for the effort! Edited October 23, 2022 by llabnip Quote Link to comment Share on other sites More sharing options...
+wavemotion Posted October 23, 2022 Author Share Posted October 23, 2022 And here is another point captured in time of the robber coming in from the left... not sure it matters. Quote Link to comment Share on other sites More sharing options...
+wavemotion Posted October 23, 2022 Author Share Posted October 23, 2022 (edited) I have a new working theory... Every time we grab the background color for 160B I just use blue instead. And lo-and-behold... the robber background is blue. Which makes me think that the Maria code is operating fine - but the background is actually black at the point of the 160b robber being drawn. Which may come down to the infamous cycle in-accuracy of ProSystem. Maybe on a real system the timing is such that the background register would have been written sooner/later or... well... something. I also can't explain why the Kop background is NOT also blue... perplexing. Edited October 23, 2022 by llabnip Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 23, 2022 Share Posted October 23, 2022 Yeah, it's not cycle accuracy. At the high level, the problem is the emulator is rendering transparent colored pixels into the buffer, instead of skipping them. I don't see a reason for it in the code, yet. 1 Quote Link to comment Share on other sites More sharing options...
RevEng Posted October 23, 2022 Share Posted October 23, 2022 // ---------------------------------------------------------------------------- // StoreCell - write mode // ---------------------------------------------------------------------------- static inline void maria_StoreCellWide(byte data) { if(maria_horizontal < MARIA_LINERAM_SIZE) { if (data) { byte *ptr = (byte *)&maria_lineRAM[maria_horizontal]; if (data & 0xB0) // high { *ptr = (maria_palette & 0x10) | (data >> 4); } if (data & & 0x0B) // low { ptr++; *ptr = (maria_palette & 0x10) | (data & 0x0F); } } } ... Quote Link to comment Share on other sites More sharing options...
+wavemotion Posted October 23, 2022 Author Share Posted October 23, 2022 A bit worse... but as I would expect since now we would skip some pixels that should otherwise render. Quote Link to comment Share on other sites More sharing options...
+splendidnut Posted October 23, 2022 Share Posted October 23, 2022 Wouldn't you want to use (data & 0x30) and (data & 0x03) for the IF conditions? Because, unless I'm mistaken, Color data (in 160B) uses the values of 0,4,8,C for the transparent pixels... so long as the bottom two bits aren't 0, the value in lineRAM should be overwritten. 1 1 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.