Jump to content


  • Content Count

  • Joined

  • Last visited

Community Reputation

888 Excellent

1 Follower

About PeteE

Profile Information

  • Gender
  • Location
    Beaverton, OR

Recent Profile Visitors

5,806 profile views
  1. Understood, I only wanted to understand the reason why the effect didn't work on the F18A, and you have adequately explained it. Thank you.
  2. I've been meaning to dig into the FPGA code for the F18A in the Phoenix repository as part of my FPGA learning adventure. (I did manage to build it into a new empty machine type for the Phoenix, and saw the F18A test screen on HDMI when loaded onto the Phoenix.) In my video-processing opinion, to more accurately emulate the 9918A, it would need to double-buffer each scanline. Each scanline would be rendered into a buffer every ~63.3us at the same speed as the 9918A, and meanwhile the other buffer is output to the monitor twice at ~31.1us each, and then the buffers are swapped. This would delay output by 1 scanline, but should be imperceptible. The trouble with the copper demo on the F18A is that it tries to update two VDP registers during the border & horizontal-blank outside of the 256-pixels wide active video, at the end of every scan line. It does this by using status register feedback from sprite collisions to cycle-lock the loop which changes the registers. Changing the 2 registers takes 64 CPU cycles, or ~21.3us. (Given the whole scanline is ~63.3us on the 9918A, that's about 190 CPU cycles per loop iteration, which isn't very many instructions.) When a scanline is doubled and output at 31.1us, the register change happens mid-way though the 2nd scanline, where it glitches the transition in the visible portion of the screen. The way the character pattern table is interleaved with even and odd lines requires the corresponding color and screen tables be set in the registers, if the register changes happen too soon or too late, the effect is ruined.
  3. Weird, mine also says address 0x0000, but it loads at 6000 when I try it. In the debugger CPU pane, set to 6000, shows the cartridge loaded at the proper address 6000: AA 01 01 00 00 00 60 0A ......`. 6008: 00 00 00 00 60 36 0F 42 ....`6.B 6010: 4F 55 4E 43 45 27 4E 27 OUNCE'N' 6018: 50 4F 55 4E 43 45 04 E0 POUNCE.. 6020: 60 02 04 5A 04 E0 60 04 `..Z..`. 6028: 04 5A 04 E0 60 06 04 5A .Z..`..Z 6030: 04 E0 60 00 04 5A 04 E0 ..`..Z.. I'm out of ideas... maybe @Tursi could chime in?
  4. That all looks normal, what part isn't loading?
  5. Using bnp_8.bin from the Cartridge->User->Open menu? Please open Edit->Debugger window and copy the messages from the debug pane and post them here.
  6. Make sure your joystick is configured correctly. If set to keyboard, use arrow keys to move and tab to start/jump.
  7. Thanks for sharing the source code. I learned a few things from it that I didn't previously know about xas99.py: By the way, you could use the 'stri' directive to automatically prepend the length byte in the cartridge header: The quotes are taken from the XDT99 documentation.
  8. Sorry, I've been trying to make it work, but so far the effect is not stable yet. I will keep working on it and let you know.
  9. Here's the copper demo "how it works" explanation. Rotation There are 64 steps of rotation, at 5.625 degrees each. I calculated the slopes up to 45 degrees, and tried to make repeating slope character chunks that fit in the fewest number of character patterns. Angle 1 is horizontal bars, and uses 1 character for each bar: Angle 2 uses 10x1 characters per slope: (the most of any angle) Angle 3 uses 5x1: Angle 4 uses 3x1 or 4x1: (in an attempt to keep the width of the bars somewhat consistent during rotation) Angle 5 uses 5x2, with 6 characters: Angle 6 uses 2x1: Angle 7 uses 3x2, with 4 chars: Angle 8 uses 4x3, with 6 chars: Angle 9 uses 2x1, but with two different offset characters (for consistent bar width) Angles 10 to 16 are the same as angles 8 down to 2, except flipped diagonally. Angle 17 is vertical bars: Angles 18 to 32 are the same as angles 16 down to 2, except flipped vertically. Angles 33 to 64 are the same as angles 1 to 32, except the color bars are in reverse order. So all the image and pattern data is the same, except the copying a palette to the color table is reversed. Interleaving The "COPPER 99/4A" text and wide wipe bars exist on a different screen image table and color table. The black rectangle in the rotated bars images, above, is the same location as the "COPPER 99/4A" text, below. The demo interleaves two images together, drawing one line from the rotating bars and one line from the "COPPER 99/4A" image. The video screen on the TMS9918A is drawn from the top-left to the bottom-right, one scanline at a time, 60 times per second. On every video scanline, the demo changes the screen image table and color table registers between the two. This requires that the character patterns also be interleaved: all 8 of the rotation character pattern tables have the wide bars and copper text on the 2nd, 4th, 6th, 8th lines. So no matter which rotation (pattern table) is being used, the wide bar/copper text image stays the same. VDP Memory Layout 0000:02FF Screen image table A (rotation) 0300:037F Sprite list table 0400:07FF Character pattern table for angles 7-9 0800:0AFF Screen image table B (rotation) 0B00:0B1F Color table (rotation) 0B20:0B3F Color table (copper 99/4a) 0C00:0FFF Character pattern table for angles 10-12 1000:12FF Screen image table C (copper 99/4a) 1400:17FF Character pattern table for angles 26-28 1800:187F Sprite pattern table (limited to 4 sprites) 1A00:1FFF Character pattern table for angles 17,22-25 2200:27FF Character pattern table for angles 1-5 2A00:2FFF Character pattern table for angles 13-16 3200:37FF Character pattern table for angles 29-32 3A00:3FFF Character pattern table for angles 18-21 Pattern tables actually overlap the other tables in memory, except the characters in overlapping areas are not actually used. Some rotation angle pattern sets use 24 characters per bar, and other pattern sets use 16 characters per color bar - allowing room for the screen image and other tables in the upper half. The black rectangle on rotation images does use character 0, but the color table is set to black on black so the pattern doesn't matter. Changing the rotation requires double-buffering the screen image table because 32*24 (768) bytes cannot be written to the VDP memory fast enough during vertical blanking. The two halves are copied over two frames, and then the register flips to the new image to be displayed. So the main loop looks like this: Copy upper half of rotation image to table A (or B next iteration) Do interleaving scanlines loop Copy lower half of rotation image to table A (or B) Do interleaving scanlines loop Change character pattern table register to the appropriate set for the current angle Change the screen image table register to table A (or B) Furthermore, there still wasn't enough time in the vblank even for a fast-ram unrolled loop copy... maybe 256 bytes per update would have worked, but it also reduce the frame rate from 30Hz to 20Hz, no thanks. Instead the data is converted to asm instructions that Load Immediate each byte into a workspace register mapped to the VDP Write Data register. Like this: SCR_0A LWPI VDPWD LI R0,>8800 LI R0,>8800 ... 384 total LI instructions LWPI WRKSP CLR @BANK0 RT Unfortunately this quadruples the size of the data in ROM... 384 bytes becomes 1.5KB, so I can fit only 4 halves (6KB) into one cart bank (8KB.) So all 32 angles would require 16 banks, and that's why the cartridge is 128KB. (More to come...)
  10. I looked at ABS also, but initially dismissed it because the number of clock cycles isn't constant based on the source argument: (MSB=0) 12 cycles, (MSB=1) 14 cycles. The MSB in the VDPSTA register (interrupt flag) will be 0 during scanout, so it would actually be fine. Thanks!
  11. Thanks, Tursi. I've grown to trust Classic99 based on how much work you've done to make it cycle accurate.
  12. I don't care about the write, I only need the read to clear VDPSTA to clear the collision flag, etc. I have "LWPI VDPWA" in effect, so I don't want to write to any of the R0 registers, and I want to use as few clock cycles as possible. If you know of a better way...
  13. How many clock cycles should "CLR @VDPSTA" take? (VDPSTA EQU >8802) According to http://www.unige.ch/medecine/nouspikel/ti99/tms9900.htm it should be 26 clock cycles for instructions in fast memory and address in slow memory. Yet Classic99 tells me: 8390 04E0 clr @>8802 (22) 8802 Does the VDPSTA register somehow only incur the 4-cycle penalty for reads, not writes?
  14. Okay, thanks, that makes sense. When either sprite has color 0 (transparent), the (collision) bit will not (be set.)
  15. Thanks, my PDF copy doesn't have the handwritten note there: "when either sprite has color 0, the "... I can't quite make out the rest, what does it say?
  • Create New...