![]() |
![]() |
#21 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,536
|
The simplest answer might be that cop1lc to internal copy is done only when DMA is active.
But here I venture with my 'alternative' explanation* (which will be refuted when we have more informations ![]() I think it has to do with the absolute first DMA fetch word at the VB (or, as in this case, at the DMA reactivation after VB). It is not as you might expect the first instruction of the 'new' copper list, but the word following the last of the 'old' one. So I think what happens is that it is simply used as STROBE (and therefore starts as if it were done manually) from the value present in COP1LC. The problem is that the address of COPJMP is not present on the RGA but that of COPINS... EDIT: *no, this cannot be for 'prefetch' reasons The 'old' word act like the second word after a COPJMP strobe, i.e. suppressed to COPINS destination. So the simplest answer remains the first: the Copper start require both VB and COPEN -> strobe -> 'standard' COP1LC to COPPTR (and 'usual' 'old' word suppressed to COPINS because of prefetch). Sequence at VB+COPEN start: COPINS (old) COPINS (new) DEST (new) Last edited by ross; 17 July 2024 at 20:16. |
![]() |
![]() |
#22 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,612
|
COPJMPx (or indirect via VBLANK) strobe only pre-selects which pointer register to copy. Actual COPxLC to internal pointer register copy requires enabled DMA and execution of COPJMP cycle sequence. Which means last written COPxLC is copied when DMA is re-enabled and copper got few free cycles.
Infamous copper wait blitter bug is related to this (happens when blitter is active, copper is waiting and CPU writes to COPJMPx during odd cycle and blitter also wants the cycle), the copper cycle that does the COPxLC to internal copy gets "stolen" by blitter and DMA addressing logic gets confused causing COPxLC getting copied to selected blitter pointer.. |
![]() |
![]() |
#23 | |
Registered User
Join Date: Dec 2007
Location: Aarhus / Denmark
Posts: 48
|
Quote:
AFAICT, a MOVE will halt the copper if (and only if) it attempts to write to a register that is prohibited according to the current setting of CDANG. Specifically, on ECS and above, when CDANG=1, the copper can access all registers, and thus a MOVE will never halt the copper due to this mechanism, even when writing to register 0. Last edited by Blueberry; 23 July 2024 at 21:00. |
|
![]() |
![]() |
#24 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,536
|
Quote:
So if you want to use CHALT for some reason, and that it works on any chipset, it is important to set CDANG=0 first (as it usually is, but better to do it because someone might have changed it before you..). |
|
![]() |
![]() |
#25 |
German Translator
Join Date: Aug 2018
Location: Drübeck / Germany
Age: 50
Posts: 218
|
brief summary and some additional questions:
In the Agnus chip (not directly in the Copper) there are five (7) Copper registers 2xCOPxLCx, 2xCOPJMPx and 1xCOPINS. COPxLCx are fixed location (pointer) registers (or COP1LCH $80, COP1LCL $82, COP2LCH $84, COP2LCL $86) COPJMPx are strobe registers (or COPJMP1 $88, COPJMP2 $8a) COPINS is a Copper Dummy Fetch Register (COPINS $8c) - The Copper has its own Copper Program Counter (COPPTR). - This is loaded with a COPxLCx address by a strobe signal. - The strobe signal comes either by writing to COPJMP1/2 or automatically after a vertical blank and then with the address from COP1LCx. - However, the internal COPPTR is only reloaded if Copper DMA is also activated. - If Copper DMA is deactivated, this is also referred to as Copper Stop or Copper Halt. - If Copper DMA is deactivated in the middle of a frame, the internal COPPTR remains frozen until the next time Copper DMA is activated. The COPPTR then continues its process from there. - After a vertical blank, the COPPTR is only reset to the COP1LCx address value if Copper DMA is activated. - The address is initially only prepared by a strobe signal and only written to the internal COPPTR when Copper DMA is activated. - Before starting from the new address, however, a call is made from the old copper address, which is discarded - the discarded copper instruction is marked with a 'C' in the DMA debugger e.g. if Copper DMA remains activated, vertical blank, Copper instruction of 10560 is discarded. 'C' (Sequence at VB+COPEN start: COPINS (old) COPINS (new) DEST (new)) Code:
>v 0 0 Line: 00 0 HPOS 00 0: [00 1BE -] [01 1C0 -] [02 1C2 -] [03 1C4 -] [04 1C6 -] [05 002 -] [06 004 -] [07 006 -] RFS0 03A COP 08C RFS1 1FE COP 08C RFS2 1FE *B C 0002 00E0 00065910 00010560 00065912 00010520 00065914 188 12C 0B0 082 189 12C 090 082 18A 12C Code:
[28 048 -] [29 04A -] M [2A 04C -] [2B 04E -] [2C 050 -] [2D 052 -] [2E 054 -] [2F 056 -] CPU-RWI O COP 08C CPU-RWI COP 08C CPU-RWI COP 180 CPU-RWI 0001 V C 0002 0508 0180 0080 00F0 3D7C 0002115E E 00010518 00021160 00010510 00021162 00010512 00021164 1AF 008 08C 082 1B0 008 088 082 1B1 008 089 082 1B2 008 1. what is the meaning of the 'C' in the discarded copper call? Cleared? 2. it takes 3 to 5 bus cycles from the activation of Copper DMA to the first valid Copper call? What are the rules here? 3. What are the rules at the end of the scan line? If I remember correctly there are special rules for COPJMPx at the end of the scan line. 4. if a Copper Jump is executed in the middle of the frame with Copper DMA enabled, two Copper DMA fetches are discarded, but only one is marked as 'C'? Ex. 1A and 1C discarded, but only 1C has 'C' mark. Code:
[10 018 -] [11 01A -] [12 01C -] [13 01E -] [14 020 -] [15 022 -] [16 024 -] [17 026 -] COP 080 COP 08C COP 082 COP 08C 0001 0082 051C 008A 00010512 00010514 00010516 00010518 089 082 08A 082 08B 082 08C 082 [18 028 -] [19 02A -] [1A 02C -] [1B 02E -] [1C 030 -] [1D 032 -] [1E 034 -] [1F 036 -] COP 08A COP 08C COP 08C COP 08C 0000 00E0 C 0002 008E 0001051A 0001051C 0001051E 0001052C 08D 082 08E 082 08F 082 096 082 It also reminds me of: https://eab.abime.net/showpost.php?p...2&postcount=20 |
![]() |
![]() |
#26 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,612
|
1: C was originally (I think) meant to show cycle was allocated for copper that does not do any DMA transfers. Now it also marks cycle when COPxLC -> internal pointer copy happens. It does not really mean anything specific.
2: COPJMPx write -> Copper does new DMA request in next available cycle (This still use old address) -> pointer copy happens when DMA is done in next available cycle for the copper, new DMA request is queued -> read from new address (first part of MOVE cycle). CPU COPJMPx write causing waiting copper to conflict with blitter: If CPU does write to COPJMPx during odd cycle, copper sequencer still assumes DMA request is done in next copper cycle (2 CCKs) but because COPJMPx write was odd cycle, DMA addressing logic gets copper's DMA pointer copy request still in 2 CCKs which is not the cycle that copper allocated for the DMA transfer (it is next cycle). And if this cycle is used by lower priority DMA channel (=blitter). DMA addressing logic gets two address pointer select signals at the same time.. If this cycle is unused (or used by CPU), COPJMP sequence works correctly. There is also another COPJMP related bug: if DMA is off and both strobes are written: New pointer will be COP1LC OR COP2LC when DMA is resumed. (OR as in logical OR operation). This happens because DMA addressing logic gets select signal for both COPLC registers and multiple address register selects = OR operation. (Data conflict in internal RGA bus causes AND operation) 3: There are two side-effects, both only happen when last cycle is even (always if PAL) PAL last cycle is 226 and next cycle is 0. Which means 2 even cycles back to back. If copper does DMA request at cycle 226, cycle 0 gets allocated by the copper and not used for anything and cycle 2 finally does the DMA transfer. Copper sequencer needs even->odd->even cycle sequence to advance fully. Except if it is COPJMP which is written during cycle 2226, COPJMP sequence allocates cycle 1 (which is not available for the copper normally but still used for address copy, because cycle is allocated, blitter conflict is not possible), cycle 4 is first part of new MOVE cycle. COPJMP DMA request that normally returns word from old address never happens. This should be enough for now.. |
![]() |
![]() |
#27 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,536
|
4: only 1C is discarded
Copper sequencer (pre-)fetches 1A as a normal opcode. The Strobe at 18 starts the new COPPTR copper jump sequence (old address fetch to COPINS, COPxLC copy, new COPINS start) after 1A. For all intents and purposes in that case two fetches are ignored. But if you had written the Strobe with the CPU, in the subsequent cycle the Copper could have potentially completed an instruction. 5: it's possible to write some code for this, Toni explained how to make it happen, so it can be a good exercise. But I think it is better to specify how NOT to make this happen: wait until the blitter has completed its operations or have the Copper inactive before writing COPJMP with the CPU. Even better don't use COPJMP at all or only when you know what you're doing (I mean with the CPU, with the Copper do it as you like, no restriction here ![]() |
![]() |
![]() |
#28 | |
Registered User
Join Date: May 2013
Location: Grimstad / Norway
Posts: 878
|
Quote:
Is it reset automatically (TOF?), or can be be reset some other way? Do you need a physical reset from the reset pin? |
|
![]() |
![]() |
#29 | |
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,319
|
Quote:
It's restarted on next strobe (maybe there are some corner cases), but you definitely do not need a physical reset ![]() KS3.0/3.1 would be in bad shape if you did. In particular the NULL view has a buggy copper list that relies on the copper halting. So don't restore that view's copperlist without clearing CDANG! (Or you will have mysterious crashes when exiting your demo or temporarily revive the system for example). |
|
![]() |
![]() |
#30 |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,536
|
Not that I know
![]() @NorthWay: Copper (re-)start at vertical blank is to be considered a strobe. Yep, KSs completely ignore CDANG, so it's always up to the user to restore the situation. A bit like BLTPRI which can be dangerous... |
![]() |
![]() |
#31 | |
Registered User
Join Date: Jan 2012
Location: USA
Posts: 374
|
Quote:
How about: CPU write to DMACON to turn blitter off essentially pausing blitter. CPU strobes COPJMP. New copper list first instruction turns blitter DMA back on. Thing about this solution is less worry about final blitter write that might have been blocked at some point. |
|
![]() |
![]() |
#32 | |
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,536
|
Quote:
EDIT: ah, maybe I understand what you mean, that is that you have incorrect blitter wait code (so only the last D channel write pending but the DMA active). Well, in that case it's your fault for writing wrong code ![]() Last edited by ross; 26 July 2024 at 09:59. |
|
![]() |
![]() |
#33 | |
German Translator
Join Date: Aug 2018
Location: Drübeck / Germany
Age: 50
Posts: 218
|
ross @Toni Thanks, for your reply, it's a lot new info.
Quote:
![]() |
|
![]() |
![]() |
#34 | ||
Registered User
Join Date: Dec 2007
Location: Aarhus / Denmark
Posts: 48
|
Quote:
Quote:
How about this: - Point COP1LC to my copperlist - Save first longword of copperlist and write $FFFFFFFE there instead - Strobe COP1JMP (or wait for vblank) - Enable copper DMA - Write back original first longword of copperlist with the blitter. DMA priorities ensure that the copper will have executed the WAIT before it is overwritten. At the next vblank, the copper will execute my copperlist as desired. |
||
![]() |
![]() |
#35 |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,612
|
|
![]() |
![]() |
#36 |
Registered User
Join Date: Dec 2007
Location: Aarhus / Denmark
Posts: 48
|
But if copper DMA is disabled at the vblank, and I strobe COP2JMP before enabling it, I'll still get the OR behavior, right?
|
![]() |
![]() |
#37 |
Registered User
Join Date: Feb 2017
Location: Denmark
Posts: 1,319
|
How about:
- setup everything (copper DMA off) - point COP1LC at start of CL - backup long word at start of CL - move.l #-2 to start of CL - enable copper DMA - wait for vblank - (don't think this is ever needed, but will let you sleep safely) wait a bit (say one chip cycle while you clear INTB_VERTB or even complete raster line) - restore start of CL (copper is idle waiting for EOF) You're now early in a frame where the next one will use correct copper list. |
![]() |
![]() |
#38 | |
WinUAE developer
Join Date: Aug 2001
Location: Hämeenlinna/Finland
Age: 49
Posts: 26,612
|
Quote:
Only difference between COPJMP1 strobe and indirect vblank COPJMP1 strobe is that vblank also "resets" the copper. (Clears the possible stopped state) |
|
![]() |
![]() |
#39 | |
Registered User
Join Date: Dec 2007
Location: Aarhus / Denmark
Posts: 48
|
Quote:
This is interesting in the light of the earlier revelation that the NULL View contains such an illegal MOVE. It means that in my latest suggestion (in the version that strobes, rather than waiting for vblank), the dummy copperlist will not be executed if no vblank has happened since copper DMA was disabled. The code will still work as desired, though, as the real copperlist will still be executed normally on the next vblank. |
|
![]() |
![]() |
#40 | ||
Defendit numerus
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 54
Posts: 4,536
|
Quote:
[multiple]EDIT: But please wait, some tests for WinUAE are underway. Quote:
It is also not present in all KS. So don't take it as something to be exploited in some way to your advantage (but protect yourself from a possible eventuality) ![]() Last edited by ross; 04 August 2024 at 18:09. |
||
![]() |
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests) | |
Thread Tools | |
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Copper WAIT, copper SKIP and $80/$100 vpos problem | defor | Coders. Asm / Hardware | 2 | 23 July 2021 08:32 |
Combining copper scrolling with copper background | phx | Coders. Asm / Hardware | 16 | 13 February 2021 12:41 |
Copper, Horizontal Blanking, and DMA | AlexBruger | support.Hardware | 5 | 19 July 2020 17:31 |
Copper instructions and dma | Jherek Carnelia | Coders. Asm / Hardware | 4 | 05 December 2019 22:33 |
Best way to mix blitting with copper and copper effects | roondar | Coders. Asm / Hardware | 3 | 12 September 2016 13:12 |
|
|