Jump to content

webdeck

Members
  • Posts

    117
  • Joined

Recent Profile Visitors

1,051 profile views

webdeck's Achievements

Chopper Commander

Chopper Commander (4/9)

159

Reputation

  1. Thanks - I missed this manual - I was using a different TMS9918A reference.
  2. Yep, instruction timing. I was trying to be super-accurate by sleeping after every instruction, but the sleep resolution isn't granular enough for that, and despite my trying to compensate, I was running a bit too fast. Now I'm accumulating the sleep amount after each instruction and only sleeping after it gets large enough to warrant a sleep call (still fine tuning what that number is), and that seems to be working better.
  3. Ok, the explosion appearing too far to the left was a silly early clock bit mistake in sprite rendering (was looking at the wrong bit.) As for the Parsec timing issues, it seems to be related to instruction timing - I need to check my math on instruction times because it seems I'm running a bit too fast.
  4. Could someone point me to what the proper timing is to use for the VDP drawing? I've been looking for it, but I can't find it.
  5. I will probably have issues now that I think about it. I have a separate thread that is doing the rendering every 1/60th of a second, and that thread renders at full speed, so I may need to slow it down to whatever rate the VDP actually renders scan lines at.
  6. Thanks - I'll need to try all of these out. I already saw the Popeye issue and now have it fixed thanks to your pointer as to what was causing it. I'm doing the >8000 mirroring and partial address line decoding, so those should be good. I haven't gotten around to implementing sound, speech, or SAMS yet. I'm curious about what you mean by "Eric in Monsterland requires that you scan for collisions more than once per frame." My rendering approach is that I have two back buffers - one for the screen bitmap, and one for the sprite bitmap. Both bitmaps start out as all transparent pixels. I render the screen buffer based on the graphics mode and tables. Then I do a pass on the sprite attributes to mark which sprites exist on which scan lines. Then I render the sprites by scan line from top to bottom onto the sprite bitmap, starting with the 4th lowest sprite number on that line to the highest number - whenever I see a write to a pixel where there isn't transparency, I set COINC, and the first time I see 5 sprites on a scan line I set the 5th sprite flag and set the 5th sprite number. If I don't see 5 sprites on any lines in the frame, I set a random 5th sprite number, since I saw the thread on the Miner 2049er bug that looks at the wrong bit for COINC. Then I blit the screen bitmap onto the background color, and blit the sprite bitmap on top of it. To cut down on work, I only re-render those buffers if there have been VDP writes to any registers or to any address ranges that matter for whatever screen mode I'm in based on the table ranges. So what does scanning for collisions more than once per frame mean? I've got what I assume is some sort of timing issue with Parsec - the enemy ships are flying down too low when they first appear and the ones that come from behind are wrapping all the way around off the right and back to the left again when they come out. I also see the explosion that appears when I hit a ship to be shifted to the left of where the ship was by a good amount.
  7. Thank you so much for this! It found some stupid status flag mistakes for ABS, S, and SRA in my emulator. I managed to get the MOV *R0+,*R0+ correct.
  8. I've been learning a lot about various edge cases from threads here, and I am wondering if anyone has already compiled a good set of tests to put an emulator through. Right now I've just been trying different carts, but that's not a very methodical approach.
  9. I am attempting to sleep based on the number of cycles each instruction is supposed to take. It's not perfect due to the sleep resolution available, but I think it's close enough. I track how long it actually sleeps for vs how long I ask for and I dynamically adjust my sleep amounts to account for that delta (about 1000ns.) If I take too long on one instruction I reduce the sleep time for the next one to get back on track. The good thing is that macOS lets me tie into the native 60Hz screen refresh so I'm locked at a solid 60 fps for rendering and the VDP interrupt.
  10. Okay, this is a long shot, but maybe someone knows the answer... I'm plowing ahead with my Swift TI emulator. I've got VDP Graphics 1 implemented, so I can start to test more things. I'm having an interesting issue with Hunt the Wumpus. Namely, sometimes pressing one arrow key results in the game moving two spaces instead of one. I'm not seeing this with other modules I've tested (granted, I haven't tested very many modules due to the limitations of what I have working in the emulator.) The interesting thing is that I've seen the exact same issue with the TI-99/Sim emulator, but I don't see it with MAME or JS99er. Does anyone have any ideas on how to track this down? Details on how the emulator works - I listen for native key down and key up events, marking a table with which keys are down, and the CRU emulation uses that table to determine what CRU bits to show as set for the keyboard row/column scan. Thanks!
  11. All the interrupts on the TI-99/4A are tied to level 1. So LIMI 2 is exactly the same as LIMI 1, because LIMI masks interrupts with a higher number than the operand, so LIMI 1 lets interrupt levels 0 and 1 proceed, which is all that is implemented in the hardware. By any chance, does anyone know if the TI-99/4 used interrupt level 2? That would be one explanation as to why the docs say to use LIMI 2 and not LIMI 1. Or they wanted to future-proof for another compatible variant in the future that would make use of interrupt level 2? But maybe apersson850 is right and the hardware was going to have interrupt level 2 do something... The cleaner thing would have been to have peripheral interrupts tied to level 1 and the VDP refresh tied to level 2. Maybe that's what they originally wanted to do? But in the ROM, the vector for level 2 skips over all the parts of the ISR that would have dealt with the VDP like sprite motion and sound lists... Here is the end portion of the level 1 ISR that the level 2 ISR jumps into: Interrupt level 2: 0A92 D30A MOVB 10,12 VDP register 1 0A94 098C SRL 12,8 0A96 026C ORI 12,>8160 Basis value 0A98 8160 0A9A 024C ANDI 12,>FFBF Turn off screen 0A9C FFBF 0A9E D820 MOVB @>83D9,@>8C02 Load VDP register 0AA0 83D9 0AA2 8C02 0AA4 D80C MOVB 12,@>8C02 0AA6 8C02 0AA8 02E0 LWPI >83E0 GPLWS 0AAA 83E0 0AAC B80E AB 14,@>8379 VDP interrupt timer (system flags!) 0AAE 8379 0AB0 C320 MOV @>83C4,12 User defined interrupt 0AB2 83C4 0AB4 1301 JEQ >0AB8 None, then jump 0AB6 069C BL *12 Otherwise execute 0AB8 04C8 CLR 8 Clear GROM search pointer 0ABA 02E0 LWPI >83C0 INTWS 0ABC 83C0 0ABE 0380 RTWP And end interrupt This is right after the check for the screen timer countdown, so it always blanks the screen, calls the user-defined ISR hook, and then exits. That makes no sense to me. It would have made more sense for the ISR 2 vector to point to >094A, which is where the VDP stuff is done. >0A92 is odd and that's why I was asking what the purpose is...
  12. 1. Interrupt mask: We always seem to use LIMI 2 to enable interrupts. But the docs say on the TI that all interrupts are tied to level 1 on the 9901. So why do we do LIMI 2 (which allows levels 0-2) instead of LIMI 1? 2. Interrupt vector 2: In the console ROM, there is a vector for interrupt vector 2 that points to >0A92 which seems to blank the screen. Is this actually used for anything? 3. Initial VDP register values: The initial VDP register values in GROM 0 have a number of "reserved" bits set to 1 instead of 0. Why is that?
  13. Guilty as charged, since I am a software engineer and not a hardware engineer. I am completely amazed at the amazing things hardware engineers can do, but it's not my skillset. I took this up for two reasons: 1) to learn more about writing performant Swift applications, and 2) the fact that I had that bug and never figured it out gnawed at me. I don't expect this to turn into anything that ever get shipped, and it will never match the depth of features that the existing emulators have taken on. It's just a little fun project for me to learn on. Fair point. I am trying to follow the flow diagrams for machine cycles in Appendix A of the TMS9900 Family System Development Manual, as well as cross-referencing the TMS9900 Microprocessor Data Manual, along with the E/A manual and TI-99/4A Console Technical Data, as well as the awesome TI-99/4A Tech Pages. I didn't have all of those resources back in the day. I'm trying to count accurate clock cycles for instructions and memory accesses with wait states, etc. But then macOS doesn't provide nanosecond level accuracy on sleep since it's not a realtime OS, so it winds up being approximate anyway. But at the same time, I am trying to make the emulator be able to provide a lot more visibility into what is going on. I'm intentionally being less efficient than I could be in how I'm approaching this. When decoding an instruction, I'm actually parsing it out into a data structure first before executing it, allowing me to audit what is happening. Swift is a language that enforces bounds checking and type safety at the expense of performance. But again, this is for fun, so it's fine, and Swift allows me to easily connect up inspectors to visualize what's happening, once I figured out how to do that without completely tanking performance (I manually update them every 1/60 of a second when the emulator is running.) Maybe the Cyc version renumbers the pages, but it's pages 34 and 35 in the version I have, and I used those extensively. Very helpful in explaining all of the status bits except for Carry. It just has the sentence "If Carry out = 1" which I guess was too vague for me. I still don't know what it means. I understand what two's complement means in terms of how negative numbers are represented in binary, but I still don't get what "carry out" means. I guess I'm missing something there. Here's a short video of what I have so far. I don't have the VDP rendering implemented yet, so it is just showing ASCII characters in a grid for now. Screen Recording 2024-02-08 at 9.01.25 PM.mov
×
×
  • Create New...