News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_ervin

Using extra 64KB of 6128

Started by ervin, 12:54, 11 February 24

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

ervin

Hi everyone.

I have a vague memory of reading a post a long time ago regarding the use of the extra 64KB in a 6128, and that it's possible to use different 16KB banks of the extra RAM for double buffering. However I can't find the post where I read that, and I haven't been able to find out how to do it using Google either.

Has anyone done something like this?
Any tips on good uses of the extra 64KB?

I would love to use it in the project I'm working on, but I don't know how.


Jean-Marie

When I was working on Spellbound & Sly Spy, I used this memento I found on ChibiAkuma website.
Back then, I used the C2 configuration, where the Instruction Pointer would "jump" in extra-ram. It then ran the music player code, with all the music data stored in extra-ram as well. Then it switched back to regular ram. Check out the diagram below.
For a double buffer, I guess you could use the C7 setup, to have RAM7 windowed at offset 4000h, and switch the CRTC reading from C000h to 4000h.

Prodatron

#2
Quote from: ervin on 12:54, 11 February 24and that it's possible to use different 16KB banks of the extra RAM for double buffering.
Please note that you can't use the extra 64K as video memory.

The most common way is to map one of the four additional 16K blocks into the visible memory at #4000-#7FFF with...
OUT #7Fxx,#C4 (maps block 0)
OUT #7Fxx,#C5 (maps block 1)
OUT #7Fxx,#C6 (maps block 2)
OUT #7Fxx,#C7 (maps block 3)
(xx can be everything)

Another possibility is to map block 3 at #c000-#ffff with
OUT #7Fxx,#C1

What is really cool about the CPC is the possibility to map the whole 64K at #0000-#ffff:
OUT #7Fxx,#C2
which was necessary for the large TPA of CP/M Plus.

You can always switch back to the primary 64K with
OUT #7Fxx,#C0

See...
https://www.cpcwiki.eu/index.php/Gate_Array#Register_3_-_RAM_Banking
...for all configurations.

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

Prodatron

Quote from: Jean-Marie on 15:05, 11 February 24For a double buffer, I guess you could use the C7 setup, to have RAM7 windowed at offset 4000h, and switch the CRTC reading from C000h to 4000h.
The CRTC will still display the content of the primary 64K. It can't access the extra ram.

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

ZorrO

You don't need extra RAM to use double buffering.
MEMORY &3fff - Now you can switch to display lower screen.
OUT &BDFF,&10 - Now displays lower screen from address &4000, and PRINT and DRAW commands still work on upper screen from &C000.
OUT &BDFF,&30 - Now displays top screen again.
POKE &B7C6,&40 - Now PRINT and DRAW work on lower screen.
POKE &B7C6,&C0 - Now back to top one.

To use RAMDISK, you may switch blocks of 16KB assigned to address &4000.
OUT &7F00, - and as a parameter you specify from 204 to 207 as extra RAM blocks, or number 192, this will restore standard block. However, only the processor sees these blocks and graphics always displays standard block (not the one from the RAMDISK),
even if you do OUT &BDFF,&10 and OUT &7F00,240

Now you need a procedure with LDIR in code to flip entire top screen to the bottom and back.
DATA 21.00,C0,11,00,40,01,00,40,ED,B0,C9 - top screen going down
DATA 21,00,40,11,00,C0,01,00,40,ED,B0,C9 - bottom screen going up
I hope you know what to do with it. :)
CPC+PSX 4ever

eto

But keep in mind that the Gate Array will always only read from the first 64KB. It can't read from the second RAM bank.

andycadley

You can, of course, use the extra 64K for software buffering of the screen but the main advantage is being able to move more code/data out of the core 64K leaving room for a hardware double buffer.

The "easiest" way to use banked RAM was just to write your game as a multi-loading 64K game and then patch the "load level" routine to pull data out of the extra RAM rather than from tape/disk. Managing the banks to switch code/data in and out on the fly is a bit more complex but perfectly doable if you have a solid grasp on how your memory is laid out (classic mistakes being paging out running code or the stack).

McArti0

CPC 6128, Whole 6128 and Only 6128, with .....
NewPAL v3 for use all 128kB RAM by CRTC as VRAM
TYPICAL :) TV Funai 22FL532/10 with VGA-RGB-in.

ervin

Thanks everyone for your thoughts and info.
It gives me some ideas and things to think about.

ZorrO

You can also use BANKMAN program from your system disk, and USER GUIDE describes how. :)
CPC+PSX 4ever

McArti0

best way to double buffer is C1, C3. Now you have two screen at the same place &4000-7FFF. BANKs 0,1,2,7 and 0,3,2,7 and work firmware.
CPC 6128, Whole 6128 and Only 6128, with .....
NewPAL v3 for use all 128kB RAM by CRTC as VRAM
TYPICAL :) TV Funai 22FL532/10 with VGA-RGB-in.

gurneyh

Quote from: McArti0 on 08:39, 12 February 24best way to double buffer is C1, C3. Now you have two screen at the same place &4000-7FFF. BANKs 0,1,2,7 and 0,3,2,7 and work firmware.
In my opinion, this configuration is not so practical if you want to use the extra 64kb.

andycadley

Quote from: gurneyh on 10:58, 12 February 24
Quote from: McArti0 on 08:39, 12 February 24best way to double buffer is C1, C3. Now you have two screen at the same place &4000-7FFF. BANKs 0,1,2,7 and 0,3,2,7 and work firmware.
In my opinion, this configuration is not so practical if you want to use the extra 64kb.
It really depends on what you need the extra RAM for. C2 can work well with this in some situations. Or a small amount of code in RAM0 that access the rest via C4/5/6.

ervin

Quote from: McArti0 on 08:39, 12 February 24best way to double buffer is C1, C3. Now you have two screen at the same place &4000-7FFF. BANKs 0,1,2,7 and 0,3,2,7 and work firmware.

This is precisely what I would like to do.
However, since either bank1 or bank3 is not accessible at any one time, I can't figure out how to use one as a back buffer, as the back buffer won't be accessible.

And even then, if I then use C2 in order to bring in data or code from banks 4 to 6, will that mess up the screen display?
(As banks 1 and 3 will be switched out)

eto

Quote from: ervin on 14:15, 12 February 24And even then, if I then use C2 in order to bring in data or code from banks 4 to 6, will that mess up the screen display?
(As banks 1 and 3 will be switched out)

No, RAM banking won't mess up the screen display.

RAM banking only affects the CPU. The Gate Array will always access the first 64KB and always see data at exactly the same position. So if you e.g. set C3, the CPU will see RAM bank 3 at "virtual address" &4000 but the Gate Array will still access the same data at the physical address &C000. If the CPU writes e.g. 255 to &4000, the Gate Array will see that &255 at &C000.



ervin

Quote from: eto on 14:39, 12 February 24
Quote from: ervin on 14:15, 12 February 24And even then, if I then use C2 in order to bring in data or code from banks 4 to 6, will that mess up the screen display?
(As banks 1 and 3 will be switched out)

No, RAM banking won't mess up the screen display.

RAM banking only affects the CPU. The Gate Array will always access the first 64KB and always see data at exactly the same position. So if you e.g. set C3, the CPU will see RAM bank 3 at "virtual address" &4000 but the Gate Array will still access the same data at the physical address &C000. If the CPU writes e.g. 255 to &4000, the Gate Array will see that &255 at &C000.




That's very interesting! And certainly not what I expected.

I'll do some experiments.

McArti0

When you kick off firmware use bank 0 and 1 for soft+data and bank 2 and 3 for screen.
CPC 6128, Whole 6128 and Only 6128, with .....
NewPAL v3 for use all 128kB RAM by CRTC as VRAM
TYPICAL :) TV Funai 22FL532/10 with VGA-RGB-in.

eto


ervin

#18
Thanks to everyone's advice and assistance... I've been able to get this working!
I'm using banking schemes C1 and C3, all my drawing code is pointing to 0x4000 and the screen is double-buffered without any flicker between 0x4000 and 0xC000.
Now I need to think of some ways to intelligently use banks 4 to 7 for data and/or code.

Here is my current cpctelera code (it's very much a prototype for bank switching experiments).

#include <cpctelera.h>

void populateYaddress();

void checkInput();
void updateScreen();

void changeVideoMemoryPage();
void ramBankC1();
void ramBankC3();

void printVerticalLine();
void drawTile();

#define SCREEN_BUFFER (u8*)0x4000

const u8* pTile;

u8 ramBank;

u8 x;
u8 y;

__at(0x0200) u8* yAddress[200]; // 400 bytes MUST BE BYTE ALIGNED

__at(0x0400) const u8 tile[16]={ // 16 bytes MUST BE BYTE ALIGNED
    0x44,0x22,0x44,0x22,0xE8,0x99,0xE8,0x99,0x22,0x44,0x22,0x44,0x88,0x40,0x88,0x40
};

void main(void) {
   cpct_disableFirmware();
   cpct_setStackLocation((u8*)0xC000);

   cpct_memset_f64(CPCT_VMEM_START,0x00,0x4000);
   cpct_setBorder(HW_BRIGHT_WHITE);
   cpct_setVideoMode(0);

   cpct_setVideoMemoryPage(cpct_pageC0);
   ramBankC1();
   ramBank=1;

   populateYaddress();

   while(1){
      checkInput();
      updateScreen();
      changeVideoMemoryPage();
   }
}

void populateYaddress(){
    for (u8 i=0;i<200;i++){
        yAddress[i]=cpct_getScreenPtr(SCREEN_BUFFER,0,i);
    }
}

void checkInput(){
   cpct_scanKeyboard_f();

   if (cpct_isKeyPressed(Key_CursorLeft)){
      x-=2;
   }

   if (cpct_isKeyPressed(Key_CursorRight)){
      x+=2;
   }
}

void updateScreen(){
   cpct_waitVSYNC();
   cpct_memset_f64(SCREEN_BUFFER,0x00,0x4000);
   printVerticalLine();
}

void changeVideoMemoryPage(){
   if (ramBank==1){
      cpct_setVideoMemoryPage(cpct_page40);
      ramBankC3();
      ramBank=3;
   }
   else{
      cpct_setVideoMemoryPage(cpct_pageC0);
      ramBankC1();
      ramBank=1;
   }
}

void ramBankC1(){
   __asm

   ld b,#0x7f
   ld c,#0xc1
   out (c),c

   __endasm;
}

void ramBankC3(){
   __asm

   ld b,#0x7f
   ld c,#0xc3
   out (c),c

   __endasm;
}

void printVerticalLine(){
   u8 px;

   pTile=tile;
   px=x;

   for (u8 j=0;j<=2;j++){
      for (u8 i=0;i<=24*8;i+=8){
         y=i;
         drawTile();
      }

      x+=4;
   }

   x=px;
}

void drawTile(){
    __asm

    ld de,(_pTile)

    // vram=yAddress[y]+x/2;

    ld hl,(_y)
    ld h,#0x00
    add hl,hl
    ld bc,#_yAddress
    add hl,bc

    ld c,(hl)
    inc l
    ld b,(hl)

    ld hl,(_x)
    ld h,#0x00
    srl l
    add hl,bc

    // ROW 1

    ex de,hl

    ldi
    ldd

    set 3,d
    inc l
    inc l

    // ROW 2

    ldi
    ldd

    set 4,d
    res 3,d
    inc l
    inc l

    // ROW 3

    ldi
    ldd

    set 3,d
    inc l
    inc l

    // ROW 4

    ldi
    ldd

    set 5,d
    res 4,d
    res 3,d
    inc l
    inc l

    // ROW 5

    ldi
    ldd

    set 3,d
    inc l
    inc l

    // ROW 6

    ldi
    ldd

    set 4,d
    res 3,d
    inc l
    inc l

    // ROW 7

    ldi
    ldd

    set 3,d
    inc l
    inc l

    // ROW 8

    ldi
    ldd
   
    ex de,hl

    __endasm;
}

ervin

Now that I've got bank switching and double buffering working together, I'm thinking about code and data.

Is it sensible to put code into the banks of the extra 64KB?
I'm just wondering how the main loop (likely in the 16KB block at 0x8000) would know how to find code that sits in the extra 64KB.
That code would probably need to be loaded in to one of the extra banks manually, but I'm struggling to figure out how the main program would know the addresses of functions up there.
Actually even storing data in the extra banks confuses me. Would I need to have some sort of mapping so that the main program knows where such data lives?
(Sorry I'm having trouble explaining all of this!)

andycadley

It depends.

In the simple case, you always know that, e.g. sprite graphics are in Bank 4 (and only there) so all you code needs to do is select a suitable banking arrangement and then fetch data. Everything else "just works".

In more complex cases data may be in multiple banks, so you might need to start storing pointers such that you can switch to the relevant bank first.

For code, I generally try to avoid it if I can as that simplifies things (or exclusively use one of the banks, like bank 7 for code). This is probably even more true with C code than assembly. If you have to have code across multiple banks, you can borrow a trick from the firmware and set up one of the RSTs to act as a "FAR CALL". Then maintain a jump table of parameterized RST instructions somewhere in memory you won't page out. Since your jump table entries are static, you can write code to call them and it doesn't matter if you end up having to move code around inside the banks (you just have to regenerate that jump table when you do).

McArti0

; soft in &4000 to &7fff only. call to all banks C4,C5,C6,C7 and return.
org #4000

ld de,1234 ; sample data
ld hl,#6000 ; sample adress to call
ld a,#c4    ;bank number
call far ;to c4
inc a
call far ;to c5
inc a
call far ;to c6
inc a
call far ;to c7
ret

org #7ff0
.far
ld bc,#7FC0
out (C),A
push BC
ld bc,return
push bc
jp (hl) ;call hl
.return
pop bc
out (C),C
ret

write direct -1,-1,#C4

;far
org #7ff0
ld bc,#7FC4
out (C),A
push BC
ld bc,return
push bc
jp (hl) ;call hl
;return
pop bc
out (C),C
ret

org #6000
ret

write direct -1,-1,#C5

;far
org #7ff0
ld bc,#7FC5
out (C),A
push BC
ld bc,return
push bc
jp (hl) ;call hl
;return
pop bc
out (C),C
ret

org #6000
ret

write direct -1,-1,#C6

;far
org #7ff0
ld bc,#7FC6
out (C),A
push BC
ld bc,return
push bc
jp (hl) ;call hl
;return
pop bc
out (C),C
ret

org #6000
ret

write direct -1,-1,#C7

;far
org #7ff0
ld bc,#7FC7
out (C),A
push BC
ld bc,return
push bc
jp (hl) ;call hl
;return
pop bc
out (C),C
ret

org #6000
ret
CPC 6128, Whole 6128 and Only 6128, with .....
NewPAL v3 for use all 128kB RAM by CRTC as VRAM
TYPICAL :) TV Funai 22FL532/10 with VGA-RGB-in.

ervin

Thanks @andycadley and @McArti0. I'll have a think about your ideas and advice. 😊

GUNHED

The coolest CPC Banking feature is RAM configuration &C3. It's like &C1, but in addition it moves the upper 16 KB block of the main RAM (usually Video-RAM) from &C000-&FFFF to &4000-&7FFF. That's used by CP/M Plus, FutureOS and some cool demos too.
http://futureos.de --> Get the revolutionary FutureOS (Update: 2023.11.30)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> Get the RSX-ROM for LambdaSpeak :-) (Updated: 2021.12.26)

eto

Quote from: GUNHED on 17:37, 16 February 24The coolest CPC Banking feature is RAM configuration &C3. It's like &C1, but in addition it moves the upper 16 KB block of the main RAM (usually Video-RAM) from &C000-&FFFF to &4000-&7FFF. That's used by CP/M Plus, FutureOS and some cool demos too.
I can understand that C3 is the best mode to adapt a normal 64KB game to use double buffering on a 128KB machine as it requires  minimal change to the original code, but why is C3 a benefit for games that take real advantage of 128K memory and more? There I would have expected that C3 is even slower as it's impossible to copy anything from RAM4,RAM5 and RAM6 to RAM 1 directly.

Powered by SMFPacks Menu Editor Mod