Jump to content
IGNORED

Smooth scrolling


Asmusr

Recommended Posts

Further news:

 

I played Lock&Chase on my Colecovision for one hour, then before putting again in its place I tried again the test 2, incredibly the VDP changed its behavior.

 

1. bit 5 = collision bit starts to lose collisions at same rate that interrupt bit.

2. bit 6 = 5th bit starts to lose collisions at double rate that interrupt bit.

 

Because the chip is now hot or somehow voltage drop slightly? I cannot explain it :-o .

 

Anyway, this finally settles matters for me about why my poor little game failed so many years ago.

 

Recipe: No polling, use interrupt if you want to use collisions. Better, handle collision with your own code and stop worrying about possible VDP misbehavior.

 

I don't think your recipe is correct....... The VDP is doing what the VDP does.....

Link to comment
Share on other sites

I email Karl Guttag (one of the designers of the 9918A VDP at TI back in the day) and he had this to say:

 

I'm not sure I can be much help. I don't have the schematics and I did not work directly on that section of the 9918.

 

It was my first design at TI and I know that it was not robust in terms of dealing with asynchronous events (on my next project, the 9995, I remember spending some considerable effort on asynchronous hazards). To get the design to fit we did all the logic as minimally as possible. So it is possible that the designer did not worry about someone reading and resetting at the same time so long as it did not cause the chip to melt.

 

Somewhere deep in my mind, I think there might have been an issue with polling (but I really don't remember).

 

Sorry I couldn't be of more help.

 

Based on that, I would say there is no 100% reliable way to poll the status register without first getting the interrupt from the VDP. For the 99/4A, that means letting the console ISR run (but disable as much of it as possible) and hooking into the user subroutine. On other systems I don't know what it means. If you do poll, be prepared to have some misses from time to time. Or do what Tim suggested. I'll have to look into that one. It might be an interesting alternative.

 

Link to comment
Share on other sites

Uh.... cause we are ignorant of that.

 

So with interrups disabled in the CPU the vdp will pass it's. Interrupt signal to the 9901 at CRU 2?

 

Does the 9901 maintain this output until it's read?

 

Thanks T.

Here's salt water I'm your eye ;-).

 

Reading the CRU bit does not clear the output. However, you will need to reset the interrupt bit so that your routine does not get caught in an endless service loop.

 

To answer your first question yes, the VDP will present its interrupt signal even when the mask is 0 so long as the VDP chip's interrupts are enabled. The mask does not inhibit the VDP or other devices from presenting their interrupts to the system but it does play into whether or not they are serviced by the ISR. You can use these characteristices to your advantage, especially when you roll your own code and do not require the ISR.

  • Like 1
Link to comment
Share on other sites

I do a "LIMI 0" in the very beginning of my code, and then never issuing a "LIMI 2". No console ISR will run.

 

When all my game logic/whatever is done, or sliced so it's done within 1/60th of a sec, then the following waits for the interrupt. The routine will return immediately if a frame has already been displayed since the last run/read. Call it twice to run at 30 frames a sec.

 

wait1 movb @>8802,r0 ; wait for end of VDP displaying frame (reading it will reset it)

andi r0,>8000 ; isolate bit 0 (set when end of frame)

jeq wait1

rt

 

Here is a snippet that should perform the same assuming the interrupt mask is 0 (LIMI 0) and the VDP interrupts are enabled. I sometimes get the TB and SBO/SBZ conditions mixed up and unfortunately, I do not have the ability to test at the moment. This should adhere to the 9918s comments regarding reading the status following detection of an interrupt.

 

wait1 clr r12
wait2 tb	 2		*VDP interrupt (poll 9901)
	jeq	wait2 *no, keep waiting
	sbo 2	 *yes, clear 9901 bit/VDP interrupt 
	movb @8802,r0 *read status from VPD
	rt

 

[Edit: See posts 173-175 for proper interpretation of the CRU bit settings for the 9901]

Edited by InsaneMultitasker
  • Like 1
Link to comment
Share on other sites

Here is a snippet that should perform the same assuming the interrupt mask is 0 (LIMI 0) and the VDP interrupts are enabled. I sometimes get the TB and SBO/SBZ conditions mixed up and unfortunately, I do not have the ability to test at the moment. This should adhere to the 9918s comments regarding reading the status following detection of an interrupt.

 

wait1 clr r12

wait2 tb 2..........*VDP interrupt (poll 9901)

jeq wait2
.....
*no, keep waiting

sbo 2
.........
*yes, clear 9901 bit/VDP interrupt

movb @8802,r0 *read status from VPD

rt

 

This method will not work with CPU interrupts enabled, correct? If so, would it work by disabling interrupts (LIMI 0) at wait1 and enabling them (LIMI 2) just before rt?

 

...lee

Link to comment
Share on other sites

Very nice to get some detail study on this issue, and thanks to Marc for reporting it in the first place way back when. :)

 

Agreed, that it seems it is not safe to read the status register during active screen generation due to the chance of a race condition losing a bit. Seems the odds of the race vary some from system to system, run to run. None of the bits can theoretically be set during vertical blank, so reading then should be safe.

 

Damn. :)

Link to comment
Share on other sites

If you are writing programs or making use of interrupt-controlled processing, LIMI 2 is mandatory. You can turn off interrupts, gaining speed, but also losing features like automotion of sprites, sound processing, or QUIT key processing.

 

I found it interesting to see that with TI's most advanced CPUs of the 99er family, the TMS99000 series, LIMI is taken away from the user processes. Only the operating system should have the right to disable interrupts. Calling LIMI within the user mode will cause a trap.

 

Well, our 99/4A is not really a multiprocessing machine...

  • Like 2
Link to comment
Share on other sites

If you are writing programs or making use of interrupt-controlled processing, LIMI 2 is mandatory. You can turn off interrupts, gaining speed, but also losing features like automotion of sprites, sound processing, or QUIT key processing.

 

In my programming I consider those features (auto-motion of sprites, sound processing, or QUIT key processing) undesirable, but the interrupt itself without those features would be nice to have.

Link to comment
Share on other sites

Polling the CRU seems to solve the issue entirely. When your finished with your processing....

 

Test CRU bit 2(please verify this) until it is set.

 

When it is set then read the status bit, update your sprite info and RESET bit 2.

 

Exit your ISR...

 

Much better method. I'll update my strategy post Hast....

  • Like 1
Link to comment
Share on other sites

Yes, please. I don't remember having seen this.

 

I could not find it either, but I did find some related information I had written earlier (pg2 about post #38 in the link below). I added a new post to the Assembly thread about hooking the console ISR:

 

http://atariage.com/forums/topic/162941-assembly-on-the-994a/page__st__225#entry2797433

 

I'll have to see about using the CRU for polling the VPD too. Maybe Marc will do it first and post an example. I wonder if polling the 9901 will cause *it* to start to fail in strange ways? Doh. On some consoles I have seen the 9901 with its own heat sink like the VDP...

 

Link to comment
Share on other sites

Polling the CRU seems to solve the issue entirely. When your finished with your processing....

 

Test CRU bit 2(please verify this) until it is set.

 

When it is set then read the status bit, update your sprite info and RESET bit 2.

 

Exit your ISR...

 

Much better method. I'll update my strategy post Hast....

 

I'm not sure I got it all. Could probably try and read it (all) again. Could you eventually post code that works on the TI ? Please.

 

Hopefully Classic99 and MESS will work too. We'll see.

 

:)

Link to comment
Share on other sites

I'm not sure I got it all. Could probably try and read it (all) again. Could you eventually post code that works on the TI ? Please.

 

Hopefully Classic99 and MESS will work too. We'll see.

 

:)

 

 

I'm out of town and won't be able to get to some particulars so others correct the mistakes please.... This is generated per Tim's info so if it doesn't work then it's his fault ;-)...

 

 

ISR1 CLR R12 BASE 0 OF CRU ISR ENTRY POINT

ISR2 TB 2 TEST CRU BIT 0002

JEQ ISR2 IF ZERO THEN NO INTERUPT HAS OCCURRED (ZERO ???)

 

MOVB @VDPSTA,R0 GET STATUS REGISTER NOT PAD COPY....

SBZ 2 RESET CRU BIT

 

RT

 

Status byte will be contained in MSB or R0...

 

 

 

 

Can't test this till next week so if someone can then please do.

Edited by marc.hull
  • Like 1
Link to comment
Share on other sites

I could not find it either, but I did find some related information I had written earlier (pg2 about post #38 in the link below). I added a new post to the Assembly thread about hooking the console ISR:

 

Thanks Matthew. I think I will stick to the polling. Firstly I only have 6 unused bytes left in scratch pad! Secondly I'm writing to the VDP RAM pretty much all of the time, so I don't know when I could enable interrupts. For the interrupt to be useful for me it would have to break into my CPU RAM to VDP RAM copying routine, execute the sprite moving/joystick reading/sound playing routines and then return to the execution of the VDP RAM copying routine. That would ensure that no CPU cycles are wasted, but it doesn't sound like that would be possible.

Link to comment
Share on other sites

Well, if you are only using the ISR to set up a known timing, or as an indicator as to when to sample user input or update sounds, then only enable the interrupt during the loop where you wait:

 

VSYNC
  LIMI 2
VWAIT
  MOV  @INTFLG,@INTFLG
  JEQ  VWAIT
  LIMI 0
  CLR  @INTFLG

 

Of course you still have to worry about what the ISR does with the scratchpad. Otherwise, Tim's example of polling via the 9901 is probably the best way.

 

Link to comment
Share on other sites

I'm out of town and won't be able to get to some particulars so others correct the mistakes please.... This is generated per Tim's info so if it doesn't work then it's his fault ;-)...

 

 

ISR1 CLR R12 BASE 0 OF CRU ISR ENTRY POINT

ISR2 TB 2 TEST CRU BIT 0002

JEQ ISR2 IF ZERO THEN NO INTERUPT HAS OCCURRED (ZERO ???)

 

MOVB @VDPSTA,R0 GET STATUS REGISTER NOT PAD COPY....

SBZ 2 RESET CRU BIT

 

RT

 

Status byte will be contained in MSB or R0...

 

 

 

 

Can't test this till next week so if someone can then please do.

 

I included a code segment similar to yours in my email reply to Sometimes99er a few days ago, but it looks like the AA forum inserted a whole bunch of formatting codes into the CODE section. :( One thing you need to do is turn off the CRU bit so that the next time through your loop you don't encounter the past interrupt. This can be done immediately before reading the VDP status byte.

[Edit: See posts 173-175 for proper interpretation of the CRU bit settings for the 9901]

Edited by InsaneMultitasker
  • Like 1
Link to comment
Share on other sites

I'll have to see about using the CRU for polling the VPD too. Maybe Marc will do it first and post an example. I wonder if polling the 9901 will cause *it* to start to fail in strange ways? Doh. On some consoles I have seen the 9901 with its own heat sink like the VDP...

Interesting thought. Marc would need to chime in as I seem to recall his issue was either with the timer mode or changing the 9901 input/output modes very rapidly. I am not aware of any maximum polling frequency limits for an output line but it certainly wouldn't hurt to look into it.

Link to comment
Share on other sites

 

 

I included a code segment similar to yours in my email reply to Sometimes99er a few days ago, but it looks like the AA forum inserted a whole bunch of formatting codes into the CODE section. :( One thing you need to do is turn off the CRU bit so that the next time through your loop you don't encounter the past interrupt. This can be done immediately before reading the VDP status byte.

 

7:15 pm....

 

 

Your code did indeed get mangled.

 

I follow the logic but could use an explanation as to why you use SBO instead of SBZ to turn off the bit?

Link to comment
Share on other sites

I follow the logic but could use an explanation as to why you use SBO instead of SBZ to turn off the bit?

 

I hope I don't get into trouble with this explanation attempt. :) I also apologize for the formatting, I still can't get AA's code sections to work properly.

 

From what I understand, the interrupt signal originating from the 9918 is active low, meaning that when the 9918 signals an interrupt it is presented to the 9901 as output state "0"; conversely, when there is no interrupt pending the output state is "1". When we test the 9901 CRU bit, there are two interrupt states (see the 9918 manual, sections 2.3 and 2.3.1, for interrupt and status flag information).

  • 0 = VDP Interrupt occured
  • 1 = VDP Interrupt has not yet occured (since the last frame).

But wait - there's more. We must also contend with the EQual status bit. Recall that instructions like MOV can be used to compare the contents of a register (or memory location) to zero. Testing the EQual status bit tells you whether or not the value is zero.

 

 

MOV R1,R1 * move value of R1 into R1.

JEQ ZERO * If R1 is zero, the EQ bit is set (1) and we jump to ZERO

* conversely:

JNE NOTZERO * If R1 is not zero, the EQ bit is reset (0), and we jump to NOTZERO

 

Here the EQ status bit is set (EQ=1) when the register content is zero and reset (EQ=0) when the register content is not zero.

 

However, when we test a CRU bit, the EQ status bit matches the logic level of the output being tested. While this may be more intuitive, the EQ status bit usage has the opposite effect:

 

CLR R12 * set our CRU Base

TB 2 * test CRU bit 2

JEQ NOTZERO * If CRU bit is "1" or "set", then EQ is set and we jump to NOTZERO

* Conversely:

JNE ZERO * if CRU bit is "0" or "reset", then the EQ bit is reset (0) and we jump to zero

 

 

Let's combine the interrupt states with the above knowledge using the earlier code suggestion based on Sometime99er's VDP Status test code:

 

wait1 clr r12

wait2 tb 2 * test the VDP interrupt line, active LOW, presented to the 9901 by the 9918

jeq wait2 * If EQ is set (1) then we are still waiting for an interrupt to occur.

*

* To get here, the EQ bit is now reset (0) which means there was a VDP interrupt

* "Clear" the interrupt condition by setting the 9901 bit to "1"

* Edit: Incorrect - SBO 2 simply ensures this line of the 9901 can generate

* an interrupt for the system. Probably not needed since we assume interrupts

* are turned off with LIMI 0 and no ISR usage.

*

sbo 2 *yes, clear 9901 bit/VDP interrupt Enable 9901 interrupt for this line.

movb @8802,r0 *read status from VPD, clear VDP interrupt

rt

 

 

One additional thought: I have always cleared the interrupt condition with "SBO 2".

[Edit: upon review of some of my old code, I re-discovered I read the VDP status byte to clear the VDP interrupt condition similar to the example above. I use the SBO 2 in some programs to ensure this interrupt line is enabled. Unlike the TI, with the Geneve one can modify the interrupt vector and eliminate or intercept the ISR. Shame on me for mixing up the two systems.]

 

However, since the 9918 VIDINT is an output, I surmise the SBO 2 may simply turn the 9901 line into an input until the next pending VDP interrupt (at which time the 9918 sets the interrupt and returns the line to an output condition) or until the next CRU test of the 9901 line. Reading the status register (which clears the pending interrupt condition) might be the only true way to clear the 9918 output. Maybe someone here can give a more definitive answer.

 

[Edit: My interpretation of the 9901 interrupt line usage was incorrect. See Michael's reference in post #174. Writing to this 9901 CRU bit either enables or disables the 9901 interrupt mask. It may be more appropriate, though probably not necessary, to disable the interrupt mask for this bit (SBZ 2) during program setup. Then polling this CRU line would be done as a true input.]

 

Tim

Edited by InsaneMultitasker
Link to comment
Share on other sites

I surmise the SBO 2 may simply turn the 9901 line into an input until the next pending VDP interrupt (at which time the 9918 sets the interrupt and returns the line to an output condition) or until the next CRU test of the 9901 line. Reading the status register (which clears the pending interrupt condition) might be the only true way to clear the 9918 output. Maybe someone here can give a more definitive answer.

 

Within the first 16 lines of the TMS9901 you have only inputs, and when you set the bit to 1 you enable the interrupt for this line. Zero disables the interrupt for this line. When you do a SBZ, the state of the line can still be read with LDCR or TB, but it does not trigger an interrupt.

 

See the TMS9901 manual on WhTech, page 6 (of the PDF).

  • Like 1
Link to comment
Share on other sites

Within the first 16 lines of the TMS9901 you have only inputs, and when you set the bit to 1 you enable the interrupt for this line. Zero disables the interrupt for this line. When you do a SBZ, the state of the line can still be read with LDCR or TB, but it does not trigger an interrupt.

 

See the TMS9901 manual on WhTech, page 6 (of the PDF).

Ah yes, the first 16 are not programmable IO. I have edited my earlier posts to correct my mistake. :skull: Thank you!

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...