English Amiga Board


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

 
 
Thread Tools
Old 22 July 2022, 21:38   #1
Bartman
Registered User
 
Join Date: Feb 2019
Location: Munich, Germany
Posts: 63
DDFSTRT/DDFSTOP for Hires reverse calculation.

I'm trying to extract display/bitmap width information from the copperlist, and while my code works fine for lo-res, it doesn't handle hi-res.

const fetchWidth = hires ? ((((DDFSTOP - DDFSTRT) >>> 2) + 2) << 4) : ((((DDFSTOP - DDFSTRT) >>> 3) + 1) << 4);
const displayWidth = (hires ? 2 : 1) * (((DIWSTOP & 0xff) + 256) - (DIWSTRT & 0xff));

Let me give you a simple example.
Workbench 1.3: DDF: 3c d0 DIW: 0581 40c1 (modulo 0) gives fetchWidth: 624 displayWidth: 640 which is clearly incorrect.
However: HRM says, standard hires DDF is 3C D4, which would give 640 pixels width. What am I missing here?

I have 2 more examples which also don't work:
Workbench 2.0: DDF: 38 d8 DIW: 2c81 2cc1 (modulo 76) gives fetchWidth: 672 displayWidth: 640.
Workbench 2.0 with 690px overscan: DDF: 30 d8 DIW: 2c6e 2cc7 (modulo 88) gives fetchWidth: 704 displayWidth: 690.
Bartman is offline  
Old 22 July 2022, 23:08   #2
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
For OCS and hires:

const fetchWidth = (((DDFSTOP&0xfc)-(DDFSTRT&0xfc)+0xc)&0xf8)*4;


It's not exactly the same in ECS+ (there is 1 bit more in DDF, so the mask is different) or FMODE>0 ('blocks' are different), but you get the idea.
(I'm not even 100% sure if that is valid for all combinations, but I think so.. )

The difficulty is that the hardware does not use a 'formula', but starts (and finishes) fetches using match values of the Agnus counter and DDF registers, but using defined 'blocks' and minimum fetch per block.
What I wrote is the closest thing the hardware does under the conditions listed.

Last edited by ross; 22 July 2022 at 23:52. Reason: added informations
ross is offline  
Old 23 July 2022, 00:06   #3
Bartman
Registered User
 
Join Date: Feb 2019
Location: Munich, Germany
Posts: 63
Thanks.
I'd be willing to implement a more "complete" display emulator, but the WinUAE source is unfortunately quite difficult to comprehend. Do you know of a somewhat simple implementation of the bitplane/display logic?

Also, it seems my lores calculation may also be flawed. You got one for that, too?

Last edited by Bartman; 23 July 2022 at 00:18.
Bartman is offline  
Old 23 July 2022, 00:47   #4
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by Bartman View Post
Thanks.
I'd be willing to implement a more "complete" display emulator, but the WinUAE source is unfortunately quite difficult to comprehend. Do you know of a somewhat simple implementation of the bitplane/display logic?
In case we will deepen later,
Fetches start at DDFSTRT, no matter what, bitplanes DMA have priority over anything.

From that moment a 'block' of n slots start, with n depending on FMODE: FMODE=1x n=8, FMODE=2x n=16, FMODE=4x n=32.
The starting alignment depends on the most valid low bit in DDF: bit 2 in OCS, bit 1 in ECS+.

The blocks are divided into sub-blocks according to the resolution: with FMODE=1x -> 1*8 in lores, 2*4 in hires, 4*2 in shres
(this is because the pixels have to be emitted more often); of course there are fewer bplanes available in higher resolutions.

As FMODE increases, the width of the sub-blocks also increases [2x, 4x, equally spaced], so that higher resolutions have more slots (and more bitplanes) usable
[the DMA slots are packed to the right of the (sub-)block, by writing BPL1DAT exactly when you need to output a valid and complete pixel sequence of 16, 32 or 64 pixels].
You can notice that the blocks are more 'distant' in higher fetch mode. but the bits per fetch are greater (2x=32bit per slot, or 4x=64bit per slot) so the pixels emitted are always at the correct frequency; of course there are many more free slots for other DMA channels in this cases.

When DDFSTOP matches, the sequencer define a latest block to be fetched after the executing block,and then stop.
This is the reason why a start of $3c do the last block fetch starting from $d4 (with DDFSTOP = $d0).
It complete [with FMODE=1x] the penultimate fetch block of 8 slots from $cc, then do a last one from $d4, for a grand total of max($dc-$3c)=$a0 slots -> 160*16/4=640pixes.

Sorry if the grammar is awful, I hope you understand something

EDIT:
Quote:
Originally Posted by Bartman View Post
Also, it seems my lores calculation may also be flawed. You got one for that, too?
The same with a final *2 (if OCS).

EDIT2:
@Toni: yes I simplified a bit, I have not considered the delay for the start of the first 'block' (4 cycles), what happens for some particular start and stop values, what happens for values that overrun (or underrun)...
But it's just to give a general idea and to specify what happens when the values are set 'correctly'.

Last edited by ross; 23 July 2022 at 09:00.
ross is offline  
Old 23 July 2022, 00:56   #5
TCD
HOL/FTP busy bee
 
TCD's Avatar
 
Join Date: Sep 2006
Location: Germany
Age: 46
Posts: 31,518
I only skimmed over this conversation, but I wonder if there is a way to use this information to tell for example WinUAE how to save screenshots that have the 'correct' resolution.

Quick reason why I care: Often I need to check at which position the actual image data starts and how wide and high it is. That often results in a lot of educated guesses and checking for 2 pixel wide black borders. Afterwards I need to check if it's lo-res or hi-res (you get an eye for it, but often it involves halving the resolution and checking if it's the same). If all that stuff could be automated it would save a lot of time, so I'm just curious if it is at all possible.
TCD is offline  
Old 23 July 2022, 22:20   #6
Bartman
Registered User
 
Join Date: Feb 2019
Location: Munich, Germany
Posts: 63
Thanks again. I now got a rudimentary Denise emulator working.
Bartman is offline  
Old 25 July 2022, 18:57   #7
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Before anyone complains: this is a prank

I said that the formula to use would be complex, but in fact for the first time on these screens, here it is:

Code:
//res:
#define LORES 0
#define HIRES 1
#define SHRES 2

//chipset:
#define OCS 0
#define ECS 1
#define AGA 2

int fetchWidth (int DDFSTRT, int DDFSTOP, int chipset, int res, int FMODE)
{
    return ((((DDFSTOP&=chipset?0xfe:0xfc)-(DDFSTRT&=chipset?0xfe:0xfc)+((((chipset\
    ==AGA)?(((FMODE&=3)<=1)?(FMODE&=3):(FMODE&=3)-1):0)>((chipset==OCS)?res&1:res))\
    ?(8<<(((chipset==AGA)?(((FMODE&=3)<=1)?(FMODE&=3):(FMODE&=3)-1):0)-((chipset==\
    OCS)?res&1:res)))-1:8-1))>>(3+((((chipset==AGA)?(((FMODE&=3)<=1)?(FMODE&=3):(\
    FMODE&=3)-1):0)>((chipset==OCS)?res&1:res))?((chipset==AGA)?(((FMODE&=3)<=1)?(\
    FMODE&=3):(FMODE&=3)-1):0)-((chipset==OCS)?res&1:res):0)))+1)<<(4+((chipset==\
    AGA)?(((FMODE&=3)<=1)?(FMODE&=3):(FMODE&=3)-1):0)+((((chipset==OCS)?res&1:res)\
    >((chipset==AGA)?(((FMODE&=3)<=1)?(FMODE&=3):(FMODE&=3)-1):0))?((chipset==OCS)\
    ?res&1:res)-((chipset==AGA)?(((FMODE&=3)<=1)?(FMODE&=3):(FMODE&=3)-1):0):0));
}
Yes, it works, if I haven't forgotten a few brackets

ross is offline  
Old 25 July 2022, 19:15   #8
BippyM
Global Moderator
 
BippyM's Avatar
 
Join Date: Nov 2001
Location: Derby, UK
Age: 48
Posts: 9,355
I just puked a little bit looking at that formila!
BippyM is offline  
Old 25 July 2022, 19:18   #9
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by BippyM View Post
I just puked a little bit looking at that formila!
Yes, this is one of the expected side effects.
There are some much, much worse
ross is offline  
Old 25 July 2022, 19:19   #10
TCD
HOL/FTP busy bee
 
TCD's Avatar
 
Join Date: Sep 2006
Location: Germany
Age: 46
Posts: 31,518
Quote:
Originally Posted by ross View Post
Yes, it works, if I haven't forgotten a few brackets
Could you ask Toni to add it to WinUAE as "Ross' super accurate screenshot mode"? Kthxbye
TCD is offline  
Old 25 July 2022, 19:21   #11
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by TCD View Post
Could you ask Toni to add it to WinUAE as "Ross' super accurate screenshot mode"? Kthxbye
Toni passed out (another side effect).

ross is offline  
Old 25 July 2022, 20:21   #12
paraj
Registered User
 
paraj's Avatar
 
Join Date: Feb 2017
Location: Denmark
Posts: 1,098
A bit disappointed that you didn't express it more clearly as an irreducible polynomial in GF(2^8). That would have been much more readable

Tried refactoring it a bit (maybe not the best chosen variable names), but should give same results:
Code:
int fetchWidth2 (int DDFSTRT, int DDFSTOP, int chipset, int res, int FMODE)
{
    if (chipset == OCS) {
        res &= 1;
        DDFSTRT &= 0xFC;
        DDFSTOP &= 0xFC;
    } else {
        DDFSTRT &= 0xFE;
        DDFSTOP &= 0xFE;
    }
    if (chipset == AGA) {
        FMODE &= 3;
        if (FMODE > 1)
            FMODE--;
    } else {
        FMODE = 0;
    }
    int blockSizeShift = 3;
    int pixelsPerFetchShift = 4 + FMODE;
    const int fetchDiff = FMODE - res;
    if (fetchDiff > 0)
        blockSizeShift += fetchDiff;
    else if (fetchDiff < 0)
        pixelsPerFetchShift -= fetchDiff;
    return (((DDFSTOP - DDFSTRT + (1<<blockSizeShift) - 1) >> blockSizeShift) + 1) << pixelsPerFetchShift;
}

Last edited by paraj; 25 July 2022 at 21:26. Reason: Remove unncessary variable
paraj is offline  
Old 25 July 2022, 20:24   #13
TCD
HOL/FTP busy bee
 
TCD's Avatar
 
Join Date: Sep 2006
Location: Germany
Age: 46
Posts: 31,518
That's far too easy to read for Amiga code
TCD is offline  
Old 25 July 2022, 20:37   #14
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by paraj View Post
Tried refactoring it a bit (maybe not the best chosen variable names), but should give same results:
hahaha, do you really refactored it? Great

This is the original function, written this way to generate 'the monster'.

Code:
int fetchWidth (int DDFSTRT, int DDFSTOP, int chipset, int res, int FMODE)
{
    // validate bits
    FMODE &= 3;
    DDFSTRT &= chipset ? 0xfe : 0xfc;
    DDFSTOP &= chipset ? 0xfe : 0xfc;
    res=(chipset==OCS)?res&1:res;

    // fetch=log2(fetch_width)-4; fetch_width=16,32,64
    int fetch = (chipset == AGA) ? ((FMODE <= 1) ? FMODE:FMODE-1) :0;

    // sub-block (OCS/ECS) and large-block (AGA) stop pad
    int pad = (fetch > res) ? (8 << (fetch - res))-1 :8-1;

    // OCS/ECS/(AGA) sub-block
    int sub = (res > fetch) ? res - fetch :0;

    // AGA large-block
    int large = (fetch > res) ? fetch - res :0;

    // DMA fetched blocks
    int blocks = ((DDFSTOP - DDFSTRT + pad)>> (3 + large)) +1;

    // 16 pixels per fetch_width per sub-block per block
    return blocks << (4 + fetch + sub);
}
Warning: there is no check for 'impossible' combinations (like OCS 8 planes) or 'prohibited' DDF values.


Last edited by ross; 25 July 2022 at 22:35. Reason: crossed out the out of context '8 planes' :)
ross is offline  
Old 25 July 2022, 20:40   #15
TCD
HOL/FTP busy bee
 
TCD's Avatar
 
Join Date: Sep 2006
Location: Germany
Age: 46
Posts: 31,518
Quote:
Originally Posted by TCD View Post
That's far too easy to read for Amiga code
Quote:
Originally Posted by ross View Post
Code:
int fetchWidth (int DDFSTRT, int DDFSTOP, int chipset, int res, int FMODE)
{
    // validate bits
    FMODE &= 3;
    DDFSTRT &= chipset ? 0xfe : 0xfc;
    DDFSTOP &= chipset ? 0xfe : 0xfc;
    res=(chipset==OCS)?res&1:res;

    // fetch=log2(fetch_width)-4; fetch_width=16,32,64
    int fetch = (chipset == AGA) ? ((FMODE <= 1) ? FMODE:FMODE-1) :0;

    // sub-block (OCS/ECS) and large-block (AGA) stop pad
    int pad = (fetch > res) ? (8 << (fetch - res))-1 :8-1;

    // OCS/ECS/(AGA) sub-block
    int sub = (res > fetch) ? res - fetch :0;

    // AGA large-block
    int large = (fetch > res) ? fetch - res :0;

    // DMA fetched blocks
    int blocks = ((DDFSTOP - DDFSTRT + pad)>> (3 + large)) +1;

    // 16 pixels per fetch_width per sub-block per block
    return blocks << (4 + fetch + sub);
}
Ah, that's more like it
TCD is offline  
Old 25 July 2022, 21:33   #16
paraj
Registered User
 
paraj's Avatar
 
Join Date: Feb 2017
Location: Denmark
Posts: 1,098
Quote:
Originally Posted by ross View Post
hahaha, do you really refactored it? Great
Yeah, knew you were BSing when I saw repeated FMODE&=3 and figured it might be interesting to see what it could be reduced to (also for going the other way when you need to).
Quote:
Originally Posted by ross View Post
Warning: there is no check for 'impossible' combinations (like OCS 8 planes)
OCS 8 planes? (I know about the 7-planes thing where Agnus only fetches 4 planes but 6 are active, but that shouldn't affect this calculation IIRC).
paraj is offline  
Old 25 July 2022, 21:53   #17
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by paraj View Post
OCS 8 planes? (I know about the 7-planes thing where Agnus only fetches 4 planes but 6 are active, but that shouldn't affect this calculation IIRC).
uh, yeah, ignore it, the function count the blocks fetched (so the pixels, in any bplane mode)

Setting bit for 8 bplanes does nothing in OCS/ECS.
ross is offline  
Old 25 July 2022, 22:12   #18
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by paraj View Post
(also for going the other way when you need to).
Yes, this could be achieved by studying the function, interesting is that it is not bijective, so there can be many solutions.

This is probably what confuses most.

But the key is the 'pad' variable (I haven't found a better name...) that basically define where the penultimate block is 'active' and DDFSTOP could match to define the last fetch.
This works differently with AGA 'large' blocks because it is not like before in a predefined range (in OCS/ECS there are only sub-blocks).

The side effect is that you could have odd numbers of block fetches in HIRES or SHRES in AGA, that's impossible in OCS/ECS.
ross is offline  
Old 26 July 2022, 15:48   #19
BippyM
Global Moderator
 
BippyM's Avatar
 
Join Date: Nov 2001
Location: Derby, UK
Age: 48
Posts: 9,355
Now we just need it in assembler
BippyM is offline  
Old 26 July 2022, 23:53   #20
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by BippyM View Post
Now we just need it in assembler
It's simple, but ..how about a small competition for those who make the smaller (68000) version?

So with the DDF registers with usual values, chipset and res limited to those of the #define and FMODE a word value (which can therefore also contain the bits not strictly related to the fetches of the bitplanes).

It does not matter to save the used registers, RTS counted (because it could be anywhere in code..).

input: d0.w=DDFSTRT, d1.w=DDFSTOP, d2.w=chipset, d3.w=res, d4.w=FMODE
output: d0.w: fetchWidth

Do not post code immediately!, leave some suspense and post only number of byte used
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
Exact functioning of DDFSTRT & STOP? TommoH Coders. Asm / Hardware 19 04 July 2023 21:31
OCS + DDFSTRT=$30 - Losing spr6? Antiriad_UK Coders. Asm / Hardware 5 18 December 2019 14:43
diwstrt, ddfstrt and hires leonard Coders. Asm / Hardware 6 02 December 2019 00:38
7th sprite corrupt with DDFSTRT of 0x30 FSizzle Coders. Asm / Hardware 9 11 November 2017 17:36
DDFSTOP question FrenchShark Coders. General 5 08 August 2009 20:42

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 17:01.

Top

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