News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_Sid_

switching screen bank strategy

Started by Sid_, 09:45, 27 April 18

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Sid_

Hi
I would like to do an animation in a futur demo. I have 5 screens to switch speediest as possible.
I have a look on the gate array function 3. (ex: http://www.cpcwiki.eu/index.php/Gate_Array#Register_3_-_RAM_Banking)
is it the best strategy ?


Sid

freemac

#1
Using RAM Banking 4 5 6 7 you can put 1st 2nd 3rd 4th image into RAM_4/RAM_5/RAM_6/RAM_7. And copy it (memcpy) into RAM_3 for show (RAM_3 is shown by default)

If you rewrite interrupt (killing firmware that is installed at RAM_2), RAM_2 can be used for 5th image (CRTC offset &8000 (always RAM_2 reading for display))

RAM_1 can be used as buffer of RAM_3 (offset of CRTC at &C000 (always RAM_3 reading for display) or else at &4000 (always RAM_1 reading for display))
while writing on RAM_3 (from RAM_5 for sample) you display RAM_1, while writing on RAM_1 from RAM_3 (using RAM Banking 0) you display RAM_3 (that's a buffer purpose, switching display (CRTC offset &C000 or else &4000) at each vsync() => then our animation is at 25Hz (each vsync() being at 50Hz)

RAM_0 has your program.

GOB

Note que le cpc ne peut adresser graphiquement que la RAM centrale. Donc si tes 5 ecrans font la taille d'un écran standard, tu peux directement oublier le flipping. Ta RAM centrale peut contenir seulement 4 ecrans de taille standard. Si t'as d'autres écran mais dans la ram supérieure, faudra alors passer par de la copie vers la RAM centrale. Autant te dire que même en faisant la copie à la pile ca va prendre du temps...

Sid_

ok 4 images it's the best solution to flip in central memory.
With an ldir instruction I can flip the images. Is it speed enough ?

freemac

#4

more important is to synchronize the flip (when changing CRTC offset) in order to get a full image displayed each vsync.


a ldir (==memcpy in SDCC) is quite long, but human eyes are quite slow to understand an animation.


sure you can change palette at 50Hz if you want to gain effects.


Just think about that, let's move a 10x10 pixels sprite from left to right of screen at 50Hz in mode 2, it does take 640 steps to do that.


50 images => 1 sec
640 images => ? sec


?=(640*1)/50=12.5 seconds : the sprite moving at max of speed for a human (let's say he saw 50Hz) without loosing any pixel step does take 12.5 seconds !


Now let's compare our animation speed to "a man walking speed", a man does take 0.5 seconds to do one step.


most of time animations are about actions, steps.

freemac

#5
(drop me)

Docent

#6
Quote from: Sid_ on 09:45, 27 April 18
Hi
I would like to do an animation in a futur demo. I have 5 screens to switch speediest as possible.
I have a look on the gate array function 3. (ex: http://www.cpcwiki.eu/index.php/Gate_Array#Register_3_-_RAM_Banking)
is it the best strategy ?


Sid

If you can live with 4 screen animation and small code space, load screens into memory at appropriate addresses (for example $50, $4050, $8050, $c050) and use these addresses to manipulate crtc's display start address - it will flip images instantly. If you use RAM banks, you'll need to copy each screen to video ram and it will take approx. 98300 microseconds per screen i.e. you'll get max 10 frames per second.

Btw: You'll need to kill system, take over the interrupts and change screen size a bit to hide your code, but the switching will be instant and you can even run it on cpc 464.

Longshot

Hi
If you want to copy 16 kilobytes from extra-ram, you can reach 11.60 frame/sec with this code.
(you can go faster but you need to unroll the code)

copy
         ld (updsporg+1),sp
        di
        xor a
        ex af,af'
        ld a,4
trall
        ex af,af'
updspsrc    ld sp,#4000
         pop bc        ; 4000/4001
        pop de        ; 4002/4003
        pop hl        ; 4004/4005
        pop iy        ; 4006/4007
        pop ix        ; 4008/4009
        exx
        pop bc        ; 400A/400B
        pop de        ; 400C/400D
        pop hl        ; 400E/400F
        ld (updspsrc+1),sp
updspdst    ld sp,#0000
        push hl        ; FFFF/FFFE
        push de        ; FFFD/FFFC
        push bc        ; FFFB/FFFA
        exx       
        push ix        ; FFF9/FFF8
        push iy        ; FFF7/FFF6
        push hl        ; FFF5/FFF4
        push de        ; FFF3/FFF2
        push bc        ; FFF1/FFF0
        ld (updspdst+1),sp
        dec a
        jr nz,updspsrc
        ex af,af'
        dec a
        jr nz,trall
updsporg    ld sp,0
        ret       


To use this code, you need to sort screen datas before:

        org #A000
        run $
        ld a,1
        call #bc0E
        ld bc,1000
afftst
        ld a,r
        and 31
        add a,65
        call #bb5A
        dec bc
         ld a,b
        or c
        jr nz,afftst
        ;
        ld hl,#C000+15
        ld de,#7FFF
fmtscr   
        ld bc,16
        lddr
        ld bc,32
        add hl,bc
        ld a,h
        or a
        jr nz,fmtscr
        ;
        call #bb06
        ld hl,#C000
        ld de,#C001
        ld (hl),l
        ld bc,#3FFF
        ldir
        call #bb06
        call copy
moimeme
        jr moimeme

If you need the system, the copy function need to save and restore the exx registers.

If you want to switch with the crtc (instantly) (if you do not need more than 4 pages in main-64kb-videoram)
You do not need to hide any code  :P
You have just to run your code in extra-ram and switch the offset videoram through crtc offset registers.
And you do not need to kill the system.  :-\
You can do that in basic.

You just need to switch the system on extra-ram with this little code

                org #a000
Switch64k
               di
              ld bc,#7FC7         ; copy C000-FFFF to 1C000-1FFFF
               out (c),c
               ld hl,#C000
               ld de,#4000
               ld bc,#4000
               ldir   

              ld bc,#7FC0         ; copy 4000-7FFF to C000-FFFF
               out (c),c
               ld hl,#4000
               ld de,#C000
               ld bc,#4000
               ldir   

              ld bc,#7FC5         ; copy C000-FFFF (4000-7FFF) to 14000-17FFF
               out (c),c
               ld hl,#4000
               ld de,#C000
               ld bc,#4000
               ldir   

               ld bc,#7FC3
               out (c),C
               ld  hl,#C000        ; copy the original videoram
               ld  de,#4000
               ld bc,#4000
               ldir

               ld bc,#7fc4   ; copy  0000-3FFF to 10000-13FFF
              out (c),c
               ld hl,#0000
               ld de,#4000
               ld bc,#4000
               ldir 

               ld bc,#7fc6 ; copy 8000-BFFF to 18000-1BFFF
               out (c),c
               ld hl,#8000
              ld de,#4000
               ld bc,#4000
              ldir
         
               ld bc,#7fc2
               out (c),c     ; switch 64k
               ei
               ret   


With this code in basic:

10 mode 1:load "switch64k",&A000:call &A000
20 for page=0 to 3
30 out &bc00,12:out &bd00,page*16
40 next:goto 20


memory &3fff: load "screen",&4000
you will not see anything because extra ram is not displayed
You just need a little extra code to copy the screen loaded in &4000 in the main ram.
To do that, the easier method is to use C1/C3 mode of RMR
Rhaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!!

Docent

#8
Quote from: Longshot on 20:12, 28 April 18
If you want to switch with the crtc (instantly) (if you do not need more than 4 pages in main-64kb-videoram)
You do not need to hide any code  :P
You have just to run your code in extra-ram and switch the offset videoram through crtc offset registers.
And you do not need to kill the system.  :-\
You can do that in basic.

You just need to switch the system on extra-ram with this little code

                org #a000
Switch64k
               di
              ld bc,#7FC7         ; copy C000-FFFF to 1C000-1FFFF
               out (c),c
               ld hl,#C000
               ld de,#4000
               ld bc,#4000
               ldir   

              ld bc,#7FC0         ; copy 4000-7FFF to C000-FFFF
               out (c),c
               ld hl,#4000
               ld de,#C000
               ld bc,#4000
               ldir   

              ld bc,#7FC5         ; copy C000-FFFF (4000-7FFF) to 14000-17FFF
               out (c),c
               ld hl,#4000
               ld de,#C000
               ld bc,#4000
               ldir   

               ld bc,#7FC3
               out (c),C
               ld  hl,#C000        ; copy the original videoram
               ld  de,#4000
               ld bc,#4000
               ldir

               ld bc,#7fc4   ; copy  0000-3FFF to 10000-13FFF
              out (c),c
               ld hl,#0000
               ld de,#4000
               ld bc,#4000
               ldir 

               ld bc,#7fc6 ; copy 8000-BFFF to 18000-1BFFF
               out (c),c
               ld hl,#8000
              ld de,#4000
               ld bc,#4000
              ldir
         
               ld bc,#7fc2
               out (c),c     ; switch 64k
               ei
               ret   



Now try to run this code on 464 :)
btw: you do not need 6 ldirs to transfer base 64k memory to additional banks

Quote from: Longshot on 20:12, 28 April 18

To do that, the easier method is to use C1/C3 mode of RMR


MMR :)

Longshot

QuoteMMR :)
:doh: of course!

Quoteyou do not need 6 ldirs to transfer base 64k memory to additional banks
Old code.  ;)
Indeed, 5 is the minimum (page 1 to 7, 7 to 5 instead of 1 to 3, 3 to 5, 7 to 3).

QuoteNow try to run this code on 464 :)
Now try to load the 4 16kb files (screen pages) from disk (or tape) from a code fragmented in the dummies zones... :)
Rhaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!!

Sid_

Thanks Longshot for this answer.
I'll try it.
I also think to compress the screens and try to uncompress in ram.
The performance is awful😖

Powered by SMFPacks Menu Editor Mod