Difference between revisions of "RIOT limitations and workarounds"

From 8BitDev.org - Atari 7800 Development Wiki
Jump to: navigation, search
(Making RIOT RAM and timer operations reliable)
(Making RIOT timer and RAM operations more reliable)
 
(8 intermediate revisions by the same user not shown)
Line 3: Line 3:
 
<blockquote>This chip is used only for I/O in 7800 mode, whereas in 2600 mode it also supplies access to all RAM and timers.</blockquote>
 
<blockquote>This chip is used only for I/O in 7800 mode, whereas in 2600 mode it also supplies access to all RAM and timers.</blockquote>
  
...without a lot of technical explanation as to why this is. In fact, if you test this RIOT functionality, at first it would seem to be working just fine. However the longer you test with real world examples, you would would discover that the RIOT RAM and timers are indeed sometimes unreliable.
+
...without a lot of technical explanation as to why this is. In fact, if you test this RIOT functionality, at first it would seem to be working just fine. However the longer you test with real world examples, you would would discover that the RIOT timers and RAM are indeed sometimes unreliable.
  
The Memory Map appendix of the Software Guide goes into a little more detail, blaming the RIOT RAM reliability issue on speed differences. While this may be true for access at Maria speeds, otherwise this story seems to be fiction.
+
The Memory Map appendix of the Software Guide goes into a little more detail, blaming the RIOT RAM reliability issue on speed differences. While this may be true for access at Maria speeds, at 6502 speeds this explanation isn't the whole story.
  
  
==Why RIOT RAM and timers are unreliable in 7800 mode==
+
==Why RIOT timers and RAM are unreliable in 7800 mode==
  
In a word, the reason why writing to the RIOT RAM and timers are unreliable, is DMA. When Maria halts the 6502 for DMA, it doesn't have a corresponding halt line for the RIOT chip, so RIOT continues to run while the 6502 is halted. If the halt begins in the middle of a RIOT update, the address and write enable asserted by the 6502 will disappear on RIOT mid-operation.
+
There's are two main reasons why accessing RIOT timers and RAM is unreliable - DMA, and Maria's own logic failings.
 +
 
 +
===DMA===
 +
 
 +
When Maria halts the 6502 for DMA, it doesn't have a corresponding halt line for the RIOT chip, so RIOT continues to run while the 6502 is halted. If the halt begins in the middle of RIOT access, the address and write enable asserted by the 6502 will disappear on RIOT mid-operation.
  
 
This may manifest differently on different consoles, with some consoles being seemly immune to the issue, likely due to rate of transition (hang-time) of the relevant lines when the 6502 is halted.
 
This may manifest differently on different consoles, with some consoles being seemly immune to the issue, likely due to rate of transition (hang-time) of the relevant lines when the 6502 is halted.
  
The heavier the DMA is while you attempt to write to RIOT RAM or timers, the more likely it is that you'll run into issues. Conversely, the reliability issues go away if Maria has DMA turned off.
+
The heavier the DMA is while you attempt to access RIOT timers or RAM, the more likely it is that you'll run into issues. Conversely, the reliability issues go away if Maria has DMA turned off. In fact, the 7800 BIOS actually turns off DMA and uses RIOT RAM to boot into 2600 mode.
 +
 
 +
===Logic Problems===
 +
 
 +
When the 6502 accesses TIA or RIOT addresses, Maria is responsible for slowing down the clock it feeds to these chips, as well as managing the chip enable and write enable lines. It seems to do a great job keeping track of the timing required for regular 6502 access modes - Absolute, Absolute Indexed, Indirect Indexed - but Maria's internal counters that manage the timings of the various lines go completely haywire when you try to execute code out of RIOT RAM.
  
==Making RIOT RAM and timer operations more reliable==
+
==Making RIOT timer and RAM operations more reliable==
  
The easiest way to make the RIOT timer writes reliable in 7800 mode (without having to turn off the display) is to double-check the value you've just tried to write, and repeat it if required...
+
The easiest way to make the RIOT timer writes reliable in 7800 mode (without having to turn off DMA) is to double-check the value you've just tried to write, and repeat it if required...
  
 +
  Repeat64T
 
     lda #10
 
     lda #10
  Repeat64T
 
 
     sta TIM64T
 
     sta TIM64T
 
     lda INTIM
 
     lda INTIM
     cmp #9 ; should always be the value you stored, less 1.
+
     cmp #9 ; immediately reading the value returns what you stored, less 1.
 
     bne Repeat64T
 
     bne Repeat64T
  
If you're checking INTIM during the visible screen, it should also be noted that DMA may make it difficult to catch the exact moment when 0 is reached, because the timer will switch to single-cycle resolution at the time. In this case you can either work with an offset value (e.g. add 10 to the timer value you want, and then act accordingly when INTIM is 10 or less.) or you can use the RIOT interrupts, and rely on TIMINT instead of INTIM.
+
If you're checking INTIM during the visible screen, it should also be noted that DMA may make it difficult to catch the exact moment when 0 is reached, because the timer will switch to single-cycle resolution at the time. In this case you can either work with an offset value (e.g. add 10 to the timer value you want when setting the timer, and then act accordingly when INTIM is at 10 or less.) or you can use the RIOT interrupts, and just check TIMINT instead of INTIM.
 
 
In theory you could take the same approach with RIOT RAM writes if desired...
 
 
 
  WriteLoop
 
    lda MyData,y
 
    sta $480,y
 
    eor $480,y
 
    bne WriteLoop
 
  
...provided you're happy with jumping through these hoops for 128 bytes. RIOT RAM usage is far less tested at this point than the timers, so you may well encounter other previously undiscovered issues.
+
In theory you could take the same approach with RIOT RAM reads and writes, but in practise checking the consistency of reads and writes isn't tenable. If you wish to use RIOT RAM, it should probably be kept to periods of VBLANK, or when DMA is disabled.
  
 
==Authorship==
 
==Authorship==
  
 
RIOT Limitations and Workarounds was written by Mike Saarna (aka RevEng) as original content for 7800.8bitdev.org.
 
RIOT Limitations and Workarounds was written by Mike Saarna (aka RevEng) as original content for 7800.8bitdev.org.

Latest revision as of 03:18, 21 February 2023

The 7800 Software Guide has the following to say about the RIOT chip...

This chip is used only for I/O in 7800 mode, whereas in 2600 mode it also supplies access to all RAM and timers.

...without a lot of technical explanation as to why this is. In fact, if you test this RIOT functionality, at first it would seem to be working just fine. However the longer you test with real world examples, you would would discover that the RIOT timers and RAM are indeed sometimes unreliable.

The Memory Map appendix of the Software Guide goes into a little more detail, blaming the RIOT RAM reliability issue on speed differences. While this may be true for access at Maria speeds, at 6502 speeds this explanation isn't the whole story.


Why RIOT timers and RAM are unreliable in 7800 mode

There's are two main reasons why accessing RIOT timers and RAM is unreliable - DMA, and Maria's own logic failings.

DMA

When Maria halts the 6502 for DMA, it doesn't have a corresponding halt line for the RIOT chip, so RIOT continues to run while the 6502 is halted. If the halt begins in the middle of RIOT access, the address and write enable asserted by the 6502 will disappear on RIOT mid-operation.

This may manifest differently on different consoles, with some consoles being seemly immune to the issue, likely due to rate of transition (hang-time) of the relevant lines when the 6502 is halted.

The heavier the DMA is while you attempt to access RIOT timers or RAM, the more likely it is that you'll run into issues. Conversely, the reliability issues go away if Maria has DMA turned off. In fact, the 7800 BIOS actually turns off DMA and uses RIOT RAM to boot into 2600 mode.

Logic Problems

When the 6502 accesses TIA or RIOT addresses, Maria is responsible for slowing down the clock it feeds to these chips, as well as managing the chip enable and write enable lines. It seems to do a great job keeping track of the timing required for regular 6502 access modes - Absolute, Absolute Indexed, Indirect Indexed - but Maria's internal counters that manage the timings of the various lines go completely haywire when you try to execute code out of RIOT RAM.

Making RIOT timer and RAM operations more reliable

The easiest way to make the RIOT timer writes reliable in 7800 mode (without having to turn off DMA) is to double-check the value you've just tried to write, and repeat it if required...

 Repeat64T
   lda #10
   sta TIM64T
   lda INTIM
   cmp #9 ; immediately reading the value returns what you stored, less 1.
   bne Repeat64T

If you're checking INTIM during the visible screen, it should also be noted that DMA may make it difficult to catch the exact moment when 0 is reached, because the timer will switch to single-cycle resolution at the time. In this case you can either work with an offset value (e.g. add 10 to the timer value you want when setting the timer, and then act accordingly when INTIM is at 10 or less.) or you can use the RIOT interrupts, and just check TIMINT instead of INTIM.

In theory you could take the same approach with RIOT RAM reads and writes, but in practise checking the consistency of reads and writes isn't tenable. If you wish to use RIOT RAM, it should probably be kept to periods of VBLANK, or when DMA is disabled.

Authorship

RIOT Limitations and Workarounds was written by Mike Saarna (aka RevEng) as original content for 7800.8bitdev.org.