English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 18 November 2021, 07:30   #1
Muzza
Registered User
 
Muzza's Avatar
 
Join Date: Sep 2019
Location: Sydney
Posts: 357
BPLCON0 causing hang

I've been looking at a hang that occurs on the first frame of my game on my real hardware A1200 but not in emulation.

After cutting things out bit by bit, I've narrowed down to a case where I can change one tiny copper list to make it hang or run. This is the first frame of the game, so there is no display initialised yet.

Hangs:

Code:
BPLCON0 = 0
0xfffffffe
Works:
Code:
COLOR0 = F00
0xfffffffe
I feel sure there must be something else going on as this seems very strange. There are some other aspects to it that imply it is some kind of race condition, but I don't see why under any circumstances the above change would make a difference.
Or is there some genuine reason setting BPLCON0 in this way could cause hang?
Muzza is offline  
Old 18 November 2021, 07:56   #2
aros-sg
Registered User
 
Join Date: Nov 2015
Location: Italy
Posts: 191
Maybe this copper/blitter bug. From quick search in forums: "If the copper is WAITing and the blitter is running and the CPU touches COPJMP to strobe the address of a new copper list into the copper's instruction pointer, a blitter channel pointer can be updated instead.". So try blit wait, before starting copper list.
aros-sg is offline  
Old 18 November 2021, 08:32   #3
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Muzza View Post
.... There are some other aspects to it that imply it is some kind of race condition, but I don't see why under any circumstances the above change would make a difference.
Circumstance could be the previous value in BPLCON0.
How are the BPUx bits previously set? (in practice some race condition because the code is possibly executed in advance in the first case)

Is this BPLCON0 write the first instruction in the copper list?
Are you forcing the copper list to restart by writing in COPJMP (see previous message from aros-sg)?
It is not recommended for several reasons, unless you know what you are doing.

Can you post a small exe where it happens?
ross is offline  
Old 18 November 2021, 09:34   #4
Toni Wilen
WinUAE developer
 
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,505
BPLCON0 write can only cause hang directly if ERSY (bit 1) is set without connected genlock.
Toni Wilen is offline  
Old 18 November 2021, 09:57   #5
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
Quote:
Originally Posted by aros-sg View Post
Maybe this copper/blitter bug. From quick search in forums: "If the copper is WAITing and the blitter is running and the CPU touches COPJMP to strobe the address of a new copper list into the copper's instruction pointer, a blitter channel pointer can be updated instead.". So try blit wait, before starting copper list.
Quote:
Originally Posted by ross View Post
Are you forcing the copper list to restart by writing in COPJMP (see previous message from aros-sg)?
It is not recommended for several reasons, unless you know what you are doing.
Just to add my 2 cents on this one: aros-sg & ross speak volumes of wisdom here!

I recently had a sporadic bug on real hardware that did not occur on emulation and it was exactly this. I was well aware of the COPJMP strobe bug, but even so I managed to forgot that the Blitter could still be running at the time in my code where I wrote to COPJMP with the CPU.

It's best to make 100% sure that any CPU write to COPJMP is done in such a way the Blitter can't be running. Or bad things might happen.
roondar is offline  
Old 18 November 2021, 11:29   #6
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by roondar View Post
It's best to make 100% sure that any CPU write to COPJMP is done in such a way the Blitter can't be running. Or bad things might happen.
Yep, or do not strobe COPJMP at all , I see only one reason to do it, but it certainly does not fall into muzza's case study, since for him it's the initialization frame.
Anyhow it is a good habit to 'let complete the frame' to the copper, otherwise, as happens very often, you will find glitches on the video very visible for at least the initial frame.

Since the copper does auto-reload the pointer at frame start I don't see the reason to manually force a restart (ok, ok maybe laziness ).
(the problem arose when old initialization code spread that contained this setting and others continued to use it without asking why...)

Even in the case of deactivation of the copper DMA there is no need for a COPJMP if you wait for the start of the next frame (yes, even with the DMA off, COP1PRT is forced in COPPTR).
In that case the reactivation of the DMA must be done synced with frame beginning as not to generate glitches in your own frame... (or risking to restart a partial copper list perhaps overwritten by decompression code or other data).

Moral: always make these settings well synchronized with the beam (frame start or not), sure that the old work of the blitter (perhaps performed by some system process) is completed
ross is offline  
Old 18 November 2021, 15:08   #7
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
Quote:
Originally Posted by ross View Post
Yep, or do not strobe COPJMP at all
...
Since the copper does auto-reload the pointer at frame start I don't see the reason to manually force a restart (ok, ok maybe laziness ).
(the problem arose when old initialization code spread that contained this setting and others continued to use it without asking why...)

Even in the case of deactivation of the copper DMA there is no need for a COPJMP if you wait for the start of the next frame (yes, even with the DMA off, COP1PRT is forced in COPPTR).
Ah, you're right of course. Usually you don't need to write COPJMP1 with the CPU at all. Somehow I keep having the notion that you need to do that once at start of Copper DMA in my mind. Probably indeed because of all the initialisation code that does write to it. Good to have a refresher on that

On a side note: the COPJMP1 CPU strobe bug is only one possibility here, it's possible something else is going on of course - but it's unlikely to be dependent on the actual write to BPLCON0 (as Toni pointed out, writing to BPLCON0 normally doesn't lead to crashes/hangs).
roondar is offline  
Old 18 November 2021, 15:59   #8
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by roondar View Post
.. but it's unlikely to be dependent on the actual write to BPLCON0 (as Toni pointed out, writing to BPLCON0 normally doesn't lead to crashes/hangs).
As mentioned it could be indirectly dependent on the write.
If for some reason the missed fetches due to BPL DMA non-executed (BPLCON0=0) define a race condition, here is a possible explanation (some chip memory access coud be delayed because of this, i.e. a previous BPUx value that continue to fetch data, delay CPU execution and 'hide' the race problem only by chance).
Muzza specified that "there is no display initialised yet"; what this *exactly* means? Which is an unknown situation because it derives from the state of the system prior to the takeover? Or that the system has been properly deactivated in advance, including therefore IRQ and DMA?
I think that only an executable that presents the problem in a replicable way can clarify the situation.
ross is offline  
Old 18 November 2021, 16:39   #9
roondar
Registered User
 
Join Date: Jul 2015
Location: The Netherlands
Posts: 3,408
Quote:
Originally Posted by ross View Post
As mentioned it could be indirectly dependent on the write.
Ah, that's what I meant. I.E. the write to BPLCON0 itself isn't likely to be the culprit, but it could trigger some other issue. The trick is finding that issue
roondar is offline  
Old 18 November 2021, 17:10   #10
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by roondar View Post
Ah, that's what I meant. I.E. the write to BPLCON0 itself isn't likely to be the culprit, but it could trigger some other issue. The trick is finding that issue
ross is offline  
Old 18 November 2021, 21:58   #11
Muzza
Registered User
 
Muzza's Avatar
 
Join Date: Sep 2019
Location: Sydney
Posts: 357
Thanks for the replies, I'm going over everything but I don't write to COPJMP using the CPU (only the copper), so I don't think it can be the COPJMP strobe bug.
Muzza is offline  
Old 18 November 2021, 22:10   #12
Muzza
Registered User
 
Muzza's Avatar
 
Join Date: Sep 2019
Location: Sydney
Posts: 357
One thing that I have wondered about is the way I chain my copper lists together for triple buffering.

Each copper list ends with this:
Wait for VPOS 303
COP1LC = pointer to top of THIS copper list
COP2LC = points to label N
COPJMP2
COP1LC = pointer to the top of NEXT copper list
[Label N]
END OF LIST

This means that a copper list will repeat itself forever, but when the next frame is ready to go, I overwrite COPJMP2 with COPPER_NOP, so that it will start the next frame as soon as the existing frame is complete.

I did wonder what happens if the copper happens to be reading the COPJMP2 when the CPU changes it to COPPER_NOP. It's a single word write, so would this be atomic?
I also tried adding protection around the CPU write so that if VPOS is at 302/303 it will wait, but this did not fix my hang problem. Also if this really was a race condition I would expect to see if every so often during the game, and not just on the first frame.

Last edited by Muzza; 18 November 2021 at 22:16.
Muzza is offline  
Old 18 November 2021, 22:41   #13
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Muzza View Post
It's a single word write, so would this be atomic?
Yes, it's atomic.

But why you need to rewrite COP1LC with THIS copper_list?
You can simply setup a small list that set the new COP1LC just in case the new list is needed.

Something like:
Wait for VPOS near_the_end (even 312)
COP2LC = points to chainN
COPJMP2/NOP
END OF LIST

chainN
COP1LC = pointer to the top of NEXT copper list
END OF LIST
ross is offline  
Old 18 November 2021, 22:47   #14
Muzza
Registered User
 
Muzza's Avatar
 
Join Date: Sep 2019
Location: Sydney
Posts: 357
Quote:
Originally Posted by ross View Post
Circumstance could be the previous value in BPLCON0.
How are the BPUx bits previously set? (in practice some race condition because the code is possibly executed in advance in the first case)

At this point, no display registers have been set at all, so they are whatever it was from Workbench before I did a system takeover. This setting of BPLCON0 will be the first display setting modified.

I've just tried having the CPU set BPLCON0 to zero immediately after system takeover, and that fixes it. So either it coincidentally fixes a race condition, or you're right that it is something to do with the previous values.


Are there any other display registers it would be good practice to set to a 'neutral' value immediately after system takeover?
Muzza is offline  
Old 18 November 2021, 22:51   #15
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Muzza View Post
Are there any other display registers it would be good practice to set to a 'neutral' value immediately after system takeover?
LoadView(NULL) do the job for you (indeed it is mandatory if you have active graphics cards).
Then set the BPLxxx registers as you need/want.
ross is offline  
Old 18 November 2021, 22:54   #16
Muzza
Registered User
 
Muzza's Avatar
 
Join Date: Sep 2019
Location: Sydney
Posts: 357
Quote:
Originally Posted by ross View Post
Yes, it's atomic.

But why you need to rewrite COP1LC with THIS copper_list?
You can simply setup a small list that set the new COP1LC just in case the new list is needed.

Something like:
Wait for VPOS near_the_end (even 312)
COP2LC = points to chainN
COPJMP2/NOP
END OF LIST

chainN
COP1LC = pointer to the top of NEXT copper list
END OF LIST

COP1LC gets set a few times because I do some 'go-subs' to other copper lists, so at the very end I reset it to the start to ensure it is valid.
Wouldn't the COPJMP2 in your list start running ChainN immediately, rather than at the start of the next frame?
Muzza is offline  
Old 18 November 2021, 22:57   #17
Muzza
Registered User
 
Muzza's Avatar
 
Join Date: Sep 2019
Location: Sydney
Posts: 357
Quote:
Originally Posted by ross View Post
LoadView(NULL) do the job for you (indeed it is mandatory if you have active graphics cards).
Then set the BPLxxx registers as you need/want.

I do LoadView(NULL), but I wasn't setting any BPL registers until after some initialisation work had been done (so potentially some vblanks had passed)
Muzza is offline  
Old 18 November 2021, 23:02   #18
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Muzza View Post
I do LoadView(NULL), but I wasn't setting any BPL registers until after some initialisation work had been done (so potentially some vblanks had passed)
Well, it should be fine.
It remains to be understood why zeroing BPLCON0 immediately there is not the race condition..
ross is offline  
Old 18 November 2021, 23:05   #19
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Muzza View Post
Wouldn't the COPJMP2 in your list start running ChainN immediately, rather than at the start of the next frame?
It depends if I completed the frame or not, in rest condition is a NOP.
(I would do it this way simply because it's slightly faster, but that's okay as well as you do )

EDIT:
hmm, I reread and here too I would do different:
Quote:
COP1LC gets set a few times because I do some 'go-subs' to other copper lists, so at the very end I reset it to the start to ensure it is valid.
I would always use COP2 for subs and keep COP1 valid so it is always available if I don't have time to complete the frame (and I don't have to set/reset it)
That's also why I'd use line 312 for the last selection for chainN.

But of course it's just an implementation detail

Last edited by ross; 18 November 2021 at 23:19.
ross 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
Behavior with BPLCON1 shifts and mid-scanline BPLCON0 change losso support.WinUAE 11 21 November 2021 13:46
Could the PSU be causing these problems? -Acid- support.Hardware 5 07 March 2016 21:39
Sram causing flickering daznic support.Hardware 6 11 February 2009 06:05
WHDLoad causing havoc(!) Iznougoud Retrogaming General Discussion 0 08 November 2007 01:29
AmiBlitz causing havoc jobro support.Apps 17 07 December 2005 17:18

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 22:24.

Top

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