English Amiga Board


Go Back   English Amiga Board > Coders > Coders. System

 
 
Thread Tools
Old 10 March 2024, 18:47   #1
paraj
Registered User
 
paraj's Avatar
 
Join Date: Feb 2017
Location: Denmark
Posts: 1,104
ScrollVPort called from VBlank interrupt

Sorry if this is basic stuff, I'm not used to being "system friendly"
I'm working on hopefully optimizing WHDLoad version of TornadoAGA a bit (https://eab.abime.net/showthread.php?t=117092), so this isn't my idea of good code, and also note that ROM is fixed to kick40068.A1200 (i.e. "3.1 A1200/A4000"), so I only care about that version here (though general comments are welcome).

A tester (Aardvark) report two crashes that occur in what I from crash dumps think is the following situation:
- Game is calling LoadRGB32 to update palette
- While that's happening, vblank interrupt occurs and installed interrupt handler calls ScrollVPort (to handle camera shaking, I think)

I assume this is crashing because this kind of update/change is not allowed (doesn't seem unreasonable that OS would not having internal locks to support this operation).

My questions:
- Does above sound reasonable (i.e. likely cause for crash)
- How do I best fix it with minimal effort/without changing how game works too much?

For the last part, game originally updated display by doing:
Code:
WaitTOF(..)
LoadRGB32(..)
ChangeVPBitMap(..)
WaitTOF would have made it very unlikely that LoadRGB32/ChangeVPBitMap would have ever interfered with ScrollVPort in interrupt routine, but I guess it's still theoretically unsafe.

I patched out WaitTOF in effort to increase frame rate (maybe I'll-advised, but game really needs all the help it can get), so I would like to avoid it (and if it's not 100% safe, I would like better solution).

Would it be sufficient to wrap LoadRGB32 call in Disable/Enable or is that too terrible, what about ChangeVPBitMap? I guess safe route would be to move ScrollVPort() call from interrupt context, but that would make "shaking" worse that it was when update rate is lower..
paraj is offline  
Old 10 March 2024, 19:06   #2
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,231
Quote:
Originally Posted by paraj View Post
- While that's happening, vblank interrupt occurs and installed interrupt handler calls ScrollVPort (to handle camera shaking, I think)
ScrollVPort is not interrupt-callable. Actually, there are only very few Os functions that are. From what I remember, Signal() and PutMsg() are interrupt-calllable, and that is already almost the complete list.


Quote:
Originally Posted by paraj View Post
- Does above sound reasonable (i.e. likely cause for crash)
- How do I best fix it with minimal effort/without changing how game works too much?
What about sending a signal in the VBLank IRQ (please use a struct Interrupt and hook it into the exec list), and then check in the main program whether the signal has been received? You can still do the ScrollVPort() then if the signal bit is set. WaitTOF() blocks the calling task, this is probably not what you want - by checking the signal, you could do something else (advance the game logic) while the signal is not yet there.


Quote:
Originally Posted by paraj View Post
Would it be sufficient to wrap LoadRGB32 call in Disable/Enable or is that too terrible, what about ChangeVPBitMap?
No, that doesn't work either. ScrollVPort may or may not run into a semaphore, and blocking an interrupt from ObtainSemaphore() does not work. It surely runs into a semaphore under an RTG system.
Thomas Richter is offline  
Old 10 March 2024, 19:37   #3
paraj
Registered User
 
paraj's Avatar
 
Join Date: Feb 2017
Location: Denmark
Posts: 1,104
Quote:
Originally Posted by Thomas Richter View Post
ScrollVPort is not interrupt-callable. Actually, there are only very few Os functions that are. From what I remember, Signal() and PutMsg() are interrupt-calllable, and that is already almost the complete list.
Thanks for confirming, "unfortunately" it apparently worked well enough in practice that it's now my problem once I'm changing stuff (I'm sure you know this issue...).


Quote:
Originally Posted by Thomas Richter View Post
What about sending a signal in the VBLank IRQ (please use a struct Interrupt and hook it into the exec list), and then check in the main program whether the signal has been received? You can still do the ScrollVPort() then if the signal bit is set. WaitTOF() blocks the calling task, this is probably not what you want - by checking the signal, you could do something else (advance the game logic) while the signal is not yet there.
Problem is that original game logic is running at ~5fps but screen shaking would be done at ~50fps.


Quote:
Originally Posted by Thomas Richter View Post
No, that doesn't work either. ScrollVPort may or may not run into a semaphore, and blocking an interrupt from ObtainSemaphore() does not work. It surely runs into a semaphore under an RTG system.
Since this is whdload slave (always running "soft-kicked" 3.1) AGA game, RTG does no come into play. As long as LoadRGB32 would never break Disable state I guess it would work (dirty as it is..)
paraj is offline  
Old 10 March 2024, 21:34   #4
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,231
Quote:
Originally Posted by paraj View Post
Problem is that original game logic is running at ~5fps but screen shaking would be done at ~50fps.
Create another task, send the signal to this task, and call ScrollVPort from this second task.
Thomas Richter is offline  
Old 11 March 2024, 07:46   #5
paraj
Registered User
 
paraj's Avatar
 
Join Date: Feb 2017
Location: Denmark
Posts: 1,104
Quote:
Originally Posted by Thomas Richter View Post
Create another task, send the signal to this task, and call ScrollVPort from this second task.
Ah, of course, don't know why I didn't think to spin up another "thread" Thanks
paraj is offline  
Old 11 March 2024, 08:14   #6
Olaf Barthel
Registered User
 
Join Date: Aug 2010
Location: Germany
Posts: 532
Quote:
Originally Posted by Thomas Richter View Post
ScrollVPort is not interrupt-callable. Actually, there are only very few Os functions that are. From what I remember, Signal() and PutMsg() are interrupt-calllable, and that is already almost the complete list.

What about sending a signal in the VBLank IRQ (please use a struct Interrupt and hook it into the exec list), and then check in the main program whether the signal has been received? You can still do the ScrollVPort() then if the signal bit is set. WaitTOF() blocks the calling task, this is probably not what you want - by checking the signal, you could do something else (advance the game logic) while the signal is not yet there.
Back in the Kickstart 1.x days, it was common enough to call LoadRGB4() or SetRGB4() from interrupt code, e.g. for use with images that would use palette cycling. Sadly, this seemed to work so well that it didn't cause crashes or lock-ups almost all the time that developers considered it a dependable approach. Bonus: the palette change was triggered from the vertical blanking interrupt, which means that the change was perfectly smooth.

Commodore had the devil of a time walking back this "feature" and crash-proofing it when called from interrupt state with Kickstart 2.04.

The robust and correct way involves a Task context. If I remember correctly, even the original Deluxe Paint got this right (perhaps after having exhausted all other alternatives first).
Olaf Barthel is offline  
Old 11 March 2024, 08:35   #7
Thomas Richter
Registered User
 
Join Date: Jan 2019
Location: Germany
Posts: 3,231
Quote:
Originally Posted by Olaf Barthel View Post
Back in the Kickstart 1.x days, it was common enough to call LoadRGB4() or SetRGB4() from interrupt code, e.g. for use with images that would use palette cycling. Sadly, this seemed to work so well that it didn't cause crashes or lock-ups almost all the time that developers considered it a dependable approach. Bonus: the palette change was triggered from the vertical blanking interrupt, which means that the change was perfectly smooth.

I remember fighting this function in the graphics.library, and this had several consequences as of today graphics also depends on a semaphore in this regime. What the original code did is to check whether the stack pointer was in the region of the supervisor stack as indicated by exec, and then bypassed the semaphore - which of course did not work with various hacks and tweaks that attempt to relocate the SSP to fast memory. What it's currently doing is checking the status register to find this out. Within P96, I made the decision to simply not support this anymore. If the code is called from supervisor mode, nothing happens. The entire access to VGA registers is too delicate (requiring access to a port and a data register to be written one after another) to allow any direct communication with the chip without proper serializing the access.


IOWs, just don't do that.
Thomas Richter is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
VBLANK wait in C 8bitsten Coders. Language 6 02 March 2023 12:05
Blitter interrupt during VERTB interrupt phx Coders. Asm / Hardware 38 01 October 2021 19:54
ScrollVPort double buffer problem with garbage pixels balrogsoft Coders. General 5 29 May 2014 12:31
RTG and chipset vblank rate Mad-Matt support.WinUAE 8 26 July 2011 12:16
CIA timer interrupt handler called twice during mod playback absence Coders. General 5 16 March 2009 18:55

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 03:38.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.07408 seconds with 15 queries