ACNews #71
03 августа 2018

Programming - Banking in IAR and ZX Spectrum 128K

<b>Programming</b> - Banking in IAR and ZX Spectrum 128K
               Banking in IAR and ZX Spectrum 128K
                          by DimkaM


After numerous requests, and also for my own memo, I decided to
describe banking in IAR C Compiler.
I must distress you at once - the banking doesn't work for
variables and constants (except for some cases), only for code.

This article assumes that you are already familiar with my
publication in Info Guide #11 and have the bundled files,
because I will point to these examples.

First, some FAQ, because not all readers are opening manuals, so
they ask:

Q:Why everything is wrapped in modules? 
R: At least, to avoid the label mishmash. Also, when you link 
(libraries), only the used modules are linked. 

Q:How to pass/receive arguments of C functions in asm? 
R: Up to 2 arguments in registers, others are on stack. 
If there is an undefined number of arguments (printf(...) etc), 
all of them are on stack. 
The first argument is passed in E, DE, CDE, or BCDE, depending 
on its width. 
If the first and second parameters are both no wider than 16 
bits, then the second parameter is passed in B or BC, or else on 
Return value is passed in register A (L with banking), HL, CHL, 
or BCHL, depending on its width. 


In the beginning, we need procedures allowing to call banked
functions and return from them.
The are already present in libraryz8Oincclz80b.r01, but that
version uses an 8-bit address port, even with bidirectional
So we replace the needed procedures in that library.

Create the project directoryfix_clz80b.
Create there a filezx128k.s01 with the following contents:

;we can't read the current bank in window OxcOO0-Oxffff from 
;hardware, so we mark all the used banks with their numbers 
;at location OxFFFF. 

       RSEG  RCODE
       push hl
       ld   hl,(MY_CURRENT_PAGE-1)
       push bc
       ld bc,0x7ffd
       out  (c),a
       pop bc
       ex   (sp),hl
       jp   (hl)

       MODULE  ?BANK_LEAVE_32_L08
       PUBLIC  ?BANK_LEAVE_32_L08
       RSEG  RCODE
       ld   sp,ix
       pop  ix
       pop  de
       inc sp
       inc sp
       pop af
       push bc
       ld bc,0x7ffd
       out  (c),a
       pop bc

       RSEG  RCODE
       ld   sp,ix
       pop  ix
       pop  de
       pop  bc
       pop  af
       push bc
       ld bc,0x7ffd
       out  (c),a
       pop bc

       RSEG  RCODE
       ex   af,af'
       ld   a,(MY_CURRENT_PAGE)
       push af
       ex   af,af'
       push bc
       ld bc,0x7ffd
       out  (c),a
       pop bc
       jp   (hl)

Then we need filezx128k.bat with the following lines:
..z8Obinaz80 -uu -b -v0 zx128k.s01
copy ..z8Olibclz80b.r01 ..z8Olibclzx128k.r01 /Y
..z8Obinxlib -c "fetch-modules zx128k.r01
..z8Obinxlib -c "replace-modules zx128k.r01

Run it, and we have a library file..z8Oincclzx128k.r01 -
a copy ofclz80b.r01 with our own banking procedures.
We don't need the projectfix_clz80b any more.


Now we change the drawing procedures from the previous
publication to work from a bank.
Create a directorymylibb, and its inner directory list.
Copy in the current project the following files:
mylib.c (rename it toputchar.c ) and graf.s01 from the 
directorymylib (see Info Guide #11 ).

Editgraf.s01 the following way:
put FastPixel and the table in unbanked memory, i.e. in the
segment RCODE. So, it quits with simple ret.
       MODULE  fast_set_pix
       PUBLIC  fast_set_pix,fast_set_pix_table
       RSEG  RCODE  ;UNbanked segment
fast_set_pix  ;
procedure body 
       ret  ;regular exit
       RSEG  ALIGN8
       DEFS 1024

Put the table initialization and SlowPixel into the banked
segment CODE, so we need there the library procedure for exit.
       MODULE  fast_set_pix_init
       PUBLIC  fast_set_pix_init
       EXTERN  fast_set_pix_table,?BANK_FAST_LEAVE_L08
       RSEG  CODE  ;banked segment
procedure body 
       ;change ret to exit from banked procedure:

       MODULE  little_set_pix
       PUBLIC  little_set_pix
       RSEG  CODE  ;banked segment
procedure body 
       ;change ret to exit from banked procedure:

..z8Obiniccz80 -v0 -mb -uua -b -q -x -K -gA -z9 -t4 -T
-Olist -Llist -Alist -I"../z80/inc/" putchar.c
..z8Obinaz80 -uu -b -v0 -Olist graf.s01

Option -mb forces to compile all the functions for banked calls,
because the library functions puts and printf expect a banked
function putchar.

Later add the linkage of the library:
del /Q mylibb.r01
..z8Obinxlib -c "fetch-mod listputchar.r01 mylibb.r01"
   "fetch-mod listgraf.r01 mylibb.r01"
    "LIST-ALL-SYMBOLS mylibb.r01 listmods.txt"

Link the library with this batch script.

In a new file'mylibb.h' define a variable MY_CURRENT_PAGE, it
will be used to tell the current bank:
extern unsigned char MY_CURRENT_PAGE;

And the other functions, don't forget about banking options:
banked void scr_init(char atribute);
banked void fast_set_pix_init(void);
non_banked void fast_set_pix(unsigned char x,unsigned char y);
#define set_pix fast_set_pix
#define set_pix_init fast_set_pix_init
#define set_pix_init()
banked void little_set_pix(unsigned char x,unsigned char y);
#define set_pix little_set_pix

You can skip the option "banked", because everything is banked
by default, but it might help in the future.


Well, we are finally prepared for HelloWorld. Let's try.
Create a project'HelloWorld', with inner directories list and

-cZ80 //процессор
  //[3C000-ЗFFFF]*2+10000,[6C000-бFFFF]*2+10000 //reserve banks
  //0,1,3,4,6,7 for banking (no 5 and 2 as they are hard-wired)
//however note the bit in port 7ffd that sets 48K ROM. If you 
/need 128K ROM, use the previous line. 
                                  //with constants and code
                              //segs with stack, variables etc.
-e_medium_write=_formatted_write //config for printf/sprintf
-e_medium_read=_formatted_read //config for scanf/sscanf
../mylibb/mylibb //link our library
-C ../z80/lib/clzx128k //link IAR library
-o list/aout.a01
-l list/cout.html
-xehinms //add everything for full picture
-w47 //suppress warnings that I don't know how to avoid

..z8Obiniccz80 -v0 -mb -uua -q -e -K -gA -s9 -t4 -T -Llist
                        -Olist -Alist -I"../z80/inc/" main.c
..z8Obinaz80 -Olist -Dbanking Cstartup.s01
..z8Obinxlink -Ilist main cstartup -f Lnk.xcl

Copycstartup from the previous publication, add bank numbering,
using the following new code just after labelinit_C:
#ifdef banking
#if NOT procбЧ180
       ld hl,MY_CURRENT_PAGE
       ld bc,0x7ffd
       ld a,0x17
       REPT 2
       out (c),a
       ld (hl),a
       dec a
       dec a
       cp OxOe
       jr nz,bankIniLoop


#include <stdio.h>
#include <intrz80.h>
#include <math.h>
//#define FASTPIXEL
#include "../mylibb/mylibb.h"
void KbdScan(void){
       printf("Keyboard scan: 0x%02Xr",input(OxOOfe));
C_task void main(void){
       unsigned char x=0;
       puts("Hello World!");
       while(1) KbdScan();

Compile it with the batch script.


New trouble: how to handle the filelistaout.a01 !?
It is encoded inmotorola s-records format.
To convert thisaout.a01, use an external utility SRecord - find
it in the supplement to this ACNews.

Add inbuild.bat (attention! that's for start address 0x6000 !):

@echo off
..z8Osrecordsrec_cat listaout.a01 -offset -0x6000 -crop 0
                                    0x6000 -o bincode.c -Binary
FOR %%i IN (00,01,03,04,06,07,10,11,13,14,16,17) do
      ..z8Osrecordsrec_cat listaout.a01 -offset -0x%%~iCOO0
      -crop 0 0x4000 -o bin%%~i.c -Binary
for /R bin %%i in (*.c) do (if %%~zi==0 (del /Q %%i)
   ELSE (echo crop file:%%~nxi size:%%~zi out^(7FFD^),0x%%~ni))
echo on

A binary file'code' will appear in directory 'bin' . We must
load and run it from address 0x6000. Also the numbered files
will appear (with bank number plus ROM selection bit) - they
must be loaded in the corresponding banks.

You might have your own means to create a loader and a disk
image. If you don't have one, just add the following line in
..z8Obinbuild128k.bat buildscl

And you will see an scl file with all your files and a loader.
Run it and enjoy a pure sine.

                             * * *

In the future article we will discuss dirty hacks, such as 
putting variables and constants in banked segments. 

Другие статьи номера:

Новости - В эмуляторе Unreal Speccy Portable появилась поддержка расширенных экранов ATM2, Utz/irrlicht project организует конкурс графики, Ещё Utz написал по поводу своего языка программирования для музыки.

News - DimkaM wrote a manual about high memory handling in IAR Z80, Unreal Speccy Portable now includes support for extra screen modes of ATM2, Utz/irrlicht project organizes a graphics compo.

Программирование - работа с банками памяти в IAR'е.

Programming - Banking in IAR and ZX Spectrum 128K

Новости языка Listh - плюсы и минусы хранения в списках против хранения в куче.

Listh language news - down pros and cons of lists vs. heap.

Темы: Игры, Программное обеспечение, Пресса, Аппаратное обеспечение, Сеть, Демосцена, Люди, Программирование

Похожие статьи:
Маленькие хитрости-2 - Как перекинуть целый экран в один INT.
Письмо №286
Лит.страничка - Дневник. Дон Громкий. (продолжение)
F-lame - Смокеры откопали топор войны: Always VS Body.
Разное - Электронный самиздат: Несколько слов о новом виде софта - электронных книгах.

В этот день...   8 декабря