Info Guide #11
05 июля 2015

Системки - Как приручить IAR C Compiler.

<b>Системки</b> - Как приручить IAR C Compiler.
Как приручить IAR C Compiler
DimkaM 

   IAR'из коробки' совершенно не подходит
для Спекки и спектрумиста.В нём нет библи─
отек для Спектрума,он стоит бешеных денег,
им не удастся  скомпилировать бинарь одной
строчкой вcmd,и он не умеет генерировать 
trd/tap/scletc.
  Но всё-таки попробуем его осилить.

                  * * *

  С чего начать? Создадим директорию"IAR"
(или какую хотите) и скопируем в неё папку
"z80" из архива с IAR'ом. Скачиваем свежий
xlink.exe, с  официального  сайта IAR'а, в
директорию "z8Obin" .  Теперь  создадим
в  директории "IAR"  папочку  с  проектом
"lesson1", а  в ней  директорию"list" для 
всякого полезного мусора.
   Скопируем   дефолтный cstartup.s01  из
IAR'а(z8Oiccz80) в директорию со своим
проектом.В нём нас интересует два момента:
первый - это начало бинарника, он же старт
программы:

       ASEG
       ORG 0

   Соответственно, меняем  на  свой адрес,
допустим,ORG 0x6000:

       ASEG
       ORG 0x6000

   Второй  момент  -  запретим  прерывания
сразу после меткиinit_C:

init_C
       DI
       LD SP,.SFE.(CSTACK-1);from high
                           ;to low address

   На этом изменения закончены.

   Теперь  нам нужно создать файлLnk.xcl,
пустой, в нём пропишем строчки:

-cZ80 //процессор, под который собираем
-Z(CODE)RCODE,CODE,CDATAO,CONST,CSTR,
CCSTR=6000-BFFE//сегменты памяти с
                //константами и кодом
-Z(DATA)INTVEC=BFFF-COO0 //сегмент с
             //таблицей для прерываний im2
-Z(DATA)DATAO,IDATAO,UDATAO,ECSTR,
ALIGN8|8,CSTACK+200=C001-FFFF//сегменты
                //стека, переменных и т.п.
-e_medium_write=_formatted_write
             //конфигурация printf/sprintf
-e_medium_read=_formatted_read
               //конфигурация scanf/sscanf
cstartup //линкуем наш стартап
-C ../z80/lib/clz80 //подключаем
     //библиотеку, опция '-C' позволит нам
     //прилинковать свой cstartup
-Fraw-binary //собрать чистый бинарь
-l list/cout.html
-o code.cou //имя бинарника
-xehinms //включим всё для полноты картины

   Сохраняем,закрываем. Если что-то не по─
нятно,то всегда можно заглянуть в докумен─
тацию, там всё подробно описано.

Создадим файлmain.c:
//тут всё банально 
void main(void)
{
}

   Создадим  батник"make_c.bat", опять же
не  поленитесь  прочитать описание опций в
документации: 

..z8Obiniccz80 -v0 -ml -uua -q -e -K
-gA -s9 -t4 -T -Llist -Alist
-I"../z80/inc/" main.c
..z8Obinaz80 Cstartup.s01
..z8Obinxlink main -f Lnk.xcl
del *.r01

   И запустим  его. У нас  скомпилировался
"голый" бинарьcode.cou (если вы не забыли
скачать  свежийxlink ), который можно за─
грузить и запустить с адреса0x6000. Также
в папкеlist появился файл main.s01 с чис─
тым асмом  и файлcout.html с картой адре─
сов, эти файлы могут пригодится для отлад─
ки.
   При использовании  оператора'?'  (тер─
нарная  условная операция) со сложными вы─
ражениями  очень рекомендую оптимизацию не
выше 7 (-s7 либо -z7 ),  так как замечены
баги.

   Текущий  проект  будем использовать как
шаблон. Для  создания образа дискеты можно
воспользоватся утилитойtrdtool, добавив в
конец батника:

..z8Obintrdtool # test.scl
..z8Obintrdtool + test.scl boot.b
..z8Obintrdtool + test.scl code.cou

   Нда, наблюдать чистый экран очень инте─
ресно. Тут два варианта: писать всё на Си,
либо создать библиотеку на асме.

                  * * *

   Рассмотрим первый вариант.
   Скопируем шаблонный проект.
   Нам нужны  инициализация экрана, печать
символа  и статичная  переменная с текущим
адресом знакоместа:

#include <string.h>
#include <intrz80.h>
#include <stdio.h>
static union {char * w;char b[2];}scrxy;
void scr_init(char a){
       *((char *)0x5800)=a;
       output8(Oxfe,a>>3);
       memcpy((void *)0x5801,
              (void *)0x5800, 32*24-1);
       scrxy.w=(void *)0x4000;
       *((char *)0x4000)=0;
       memcpy((void *)0x4001,
              (void *)0x4000,
              (unsigned int)256*192/8-1);
}
int putchar(int ch){
       switch(ch){
             case 'n':
                    scrxy.b[0]+=32;
             case 'r':
                    scrxy.b[0]&=OxeO;
                    break;
             default:{
                      char* s=(char*)
                        ((ch<<3)+OxЗcOO);
                      unsigned char i=8;
                      while(i--){
                        *scrxy.w=*(s++);
                        scrxy.b[1]++;
                      }
                     }
                     scrxy.w-=0x07ff;
                     break;
       }
       if(!scrxy.b[0]){
               if((scrxy.b[1]+=8)==0x58)
                      scrxy.b[1]=0x40;
       }
       return 1;
}
void main(void){
       scr_init(0x07<<3);
       puts("Hello World!");
       while(1) printf(
               "Keyboard scan: 0x%02Xr",
               input(OxOOfe));
}

   Комментировать код нет смысла, т.к. это
типичная  печаталка  символов. Нашputchar
подменит собой библиотечный, который испо─
льзуютputs, printf и т.п.

   Чтобы  каждый раз это не компилировать,
нужно  скомпилировать исходник как библио─
теку.
   Удалите  функцию main() и переименуйте
исходник  в "mylib.c". Также  переименуем
директорию  проекта  в"mylib". Удалите из
проекта все файлы, кроме"mylib.c". Созда─
дим  файл "make_c.bat"  и пропишем в него
следующую строчку:

..z8Obiniccz80 -v0 -ml -uua -b -q -x -K
-gA -z9 -t4 -T -Llist -Alist
-I"../z80/inc/" mylib.c

   И запустим  его, у нас скомпилировалась
библиотека"mylib.r01".
   Создадим заголовочный файл"mylib.h" со
строкой:

void scr_init(char a);

   Теперь откроем файл"Lnk.xcl" из нашего
шаблонного проекта и перед строчкой
"-C ../z80/lib/clz80" добавим строку
"../mylib/mylib". Должно получиться:

...
cstartup //линкуем наш стартап
../mylib/mylib //линкуем собственную
               //библиотеку
-C ../z80/lib/clz80 //подключаем
   //библиотеку IAR'а, опция '-C' позволит
   //нам прилинковать свой cstartup.s01
...

   Можно проверить нашу библиотеку, создав
новый проект и скомпилировав строчки:

#include <stdio.h>
#include <intrz80.h>
#include "../mylib/mylib.h"
void main(void){
       scr_init(0x07<<3);
       puts("Hello World!");
       while(1) printf(
"Keyboard scan: 0x%02Xr",input(OxOOfe));
}

                  * * *

   Функции IO обычно пишутся на асме, поэ─
тому  следующую  функцию  будем  писать на
нём. Каждую функцию желательно оборачивать
в модули, чтобы при линковке цеплялись то─
лько используемые модули:

       MODULE mymod1
       ...
       ENDMOD
       MODULE mymod2
       ...
       ENDMOD
       MODULE mymodЗ
       ...
       END  ;последний в файле модуль
    ;заканчивается именно так, а не ENDMOD
        
   Создадим в проектеmylib файл graf.s01,
с кодом:

       MODULE  fast_set_pix
       PUBLIC  fast_set_pix,
               fast_set_pix_table
       RSEG    CODE
fast_set_pix
 ;http://zxdn.narod.ru/coding/zg1etud2.txt
       push bc
       push de
       ld l,c
       LD H,HIGH(fast_set_pix_table)
       LD D,HIGH(fast_set_pix_table)+2
       LD A,(DE)
       INC D
       OR (HL)
       INC H
       LD H,(HL)
       LD L,A
       LD A,(DE)
       OR (HL)
       LD (HL),A
       pop de
       pop bc
       ret
       RSEG    ALIGN8
fast_set_pix_table
       DEFS 1024
       ENDMOD
        
       MODULE  fast_set_pix_init
       PUBLIC  fast_set_pix_init
       EXTERN  fast_set_pix_table
       RSEG    CODE
fast_set_pix_init
       push bc
       push de
       LD HL,fast_set_pix_table+256
       LD DE,0x4000
GENO
       LD (HL),D
       DEC H
       LD (HL),E
       INC H
       INC D
       LD A,D
       AND 7
       JR NZ,LABEL
       LD A,E
       SUB OxEO
       LD E,A
       SBC A,A
       AND -8
       ADD A,D
       LD D,A
LABEL
       LD A,D
       SUB 88
       JR NZ,$+3
       LD D,A
       INC L
       JR NZ,GENO
       INC H
       LD A,128
GEN1
       LD (HL),E
       INC H
       LD (HL),A
       DEC H
       RRCA
       JR NC,$+3
       INC E
       INC L
       JR NZ,GEN1
       pop de
       pop bc
       ret
       ENDMOD
        
       MODULE  little_set_pix
       PUBLIC  little_set_pix
       RSEG    CODE
little_set_pix
       ld a,c
       and 0x07
       or 0x40
       ld h,a
       ld a,c
       rrca
       rrca
       rrca
       ld l,a
       and %00011000
       or h
       ld h,a
       ld a,l
       ld l,e
       rrca
       rr l
       rra
       rr l
       rra
       rr l
       rra
       rrca
       rrca
       and %00111000
       xor %11111110
       ld (l2+1),a;конечно, так нельзя
                    ;делать в либах
l2      set 0,(hl)
       ret
       END

   Здесь у нас две типичные рисовалки точ─
ки,одна побыстрее,вторая покороче.Уточнить
про  параметры  при  вызове  функций можно
в документации, раздел  "Assembly language
interface". 

                  * * *

   Чтобы  не плодить библиотеки, будем со─
бирать их в одну.
   В новом файле с именемmylib.xlib запи─
шем строчки:

fetch-modules graf.r01 mylib.r01
list-modules mylib.r01
quit

   После строчки"quit" обязательно должна
быть пустая  строка, т.к.xlib ругается на
отсутствующий EOF.
   Это  скрипт  для сборщика библиотек, он
объединит две либы в одну.
   Добавим  в"make_c.bat" строку компиля─
цииgraf.s01 и соберём либу в один файл.
   Батник будет выглядеть:

..z8Obiniccz80 -v0 -ml -uua -b -q -x -K
-gA -z9 -t4 -T -Llist -Alist
-I"../z80/inc/" mylib.c
..z8Obinaz80 -uu -b -v0 graf.s01
..z8Obinxlib mylib.xlib

   Соответственно в заголовочный файл
mylib.h добавьте:

void fast_set_pix_init(void);
void fast_set_pix(unsigned char x,
                 unsigned char y);
void little_set_pix(unsigned char x,
                   unsigned char y);
#ifdef FASTPIXEL
#define set_pix fast_set_pix
#define set_pix_init fast_set_pix_init
#else
#define set_pix_init()
#define set_pix little_set_pix
#endif

   Теперь  запустим батник и проверим биб─
лиотеку:

#include <math.h>
//#define FASTPIXEL 
#include "../mylib/mylib.h"
void main(void){
       unsigned char x=0;
       scr_init(0x07<<3);
       set_pix_init();
       do{
            set_pix(x,
              (sin((double)x/20)*20+95));
       }while(++x);
}

   На  фоне  вычислений  даблов  и синусов
быстрый  и маленький  пиксели  практически
неотличимы  по скорости, только по размеру
занимаемой памяти.

                  * * *

   Ну и напоследок освоим прерывания (дан─
ный код не будет работать на машинах,у ко─
торых мусор на шине данных):

#include <intrz80.h>
unsigned int int_count=0;
interrupt[0] void myint(void){
       int_count++;
       output8(Oxfe,
     ((unsigned char)int_count&0x70)>>4);
}
C_task void main(void){
       load_I_register(Oxbf);
       interrupt_mode_2();
       enable_interrupt();
}

   Для "мусорных" шин  красивого решения я
не знаю.
   Как вариант выделить сегмент памяти под
таблицу  прерываний(INTTABLE) и сегмент с
"зеркальным" (Oxbfbf,0x8181 и т.п.) адре─
сом подJP:

-Z(CODE)RCODE,CODE,CDATAO,CONST,CSTR,
CCSTR=6000-BEBD//сегменты памяти с
                 //константами и кодом
-Z(DATA)INTJP=BEBE-BECO //сегмент с JP для
                        //прерываний im2
-Z(DATA)DATAO,IDATAO,UDATAO,ECSTR,
ALIGN8|8,INTTABLE|8,CSTACK+200=BEC1-FFFF
//сегменты стека, переменных и т.п. 

   В проектmylib добавим myim2.s01, в ко─
тором  разместимJP на обработчик прерыва─
ния, таблицу векторов и инициализацию:

       MODULE  my_im2
       PUBLIC  my_im2_init
       RSEG    INTJP
       DEFS 3
       RSEG    INTTABLE
       DEFS 257
       RSEG    CODE
my_im2_init
       di
       ld a,OxcЗ
       ld (SFB(INTJP)),a
       ld (SFB(INTJP)+1),de
       ld a,HIGH(SFB(INTTABLE))
       ld i,a
       inc a
       ld hl,SFB(INTTABLE)-1
tloop
       inc hl
       ld (hl),HIGH(SFB(INTJP))
       cp h
       jr nz,tloop
       im 2
       ret
       END

   Строка компиляции в батнике:

...
..z8Obinaz80 -uu -b -v0 myim2.s01
...

   Строка вmylib.xlib:

...
fetch-modules myim2.r01 mylib.r01
...

   Соответственно вmylib.h добавим:

extern void my_im2_init(void *);

   И собственно пример использования:

#include <intrz80.h>
#include "../mylib/mylib.h"
unsigned int int_count=0;
interrupt void myint(void){
       int_count++;
       output8(Oxfe,
     ((unsigned char)int_count&0x70)>>4);
}
C_task void main(void){
       my_im2_init(myint);
       enable_interrupt();
}

                  * * *

  Все  примеры  вы  можете найти в прило─
жении к журналу. Для  сборки  используется
утилита  trdtoolby Shiru  с исправлениями 
от Trefiи DimkaM, к ней прилагаются исхо─ 
дники.



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

Об оболочке - журнал состоит из разделов, а разделы из статей.

От авторов - предисловие: Прошло 8 лет с момента выхода прошлого номера Info Guide. Что изменилось на Спектруме за это время?

Комьюнити - Spectrum в глубинке: в городе, население которого не превышает 15 тысяч человек, появление компьютера было сравнимо с изготовлением атомной бомбы в гараже.

Комьюнити - Forever 2015: отчет с демопати для всех 8-битных компьютеров.

Комьюнити - DiHalt 2015: отзывы от Lilka и Louisa.

Комьюнити - Как это было в Бразилии: история развития Спектрума в Бразилии от Paulo Silva.

Комьюнити - Беседа с Tiboh/Debris - программистом из Красноярска, долгие годы занимавшимся обработкой архивов спектрумовских программ.

Комьюнити - интервью с Raver/Phantasy взятое на irc.forestnet.org

Code - Этюды: Вызов функции по номеру, Поиск текста по номеру, Определение наличия музыкального сопроцессора, Установка пикселя на ATM Turbo 2, Библиотеки процедур в ALASM, Короткий генератор случайных чисел, Ускорение LD:PUSH.

Code - точка зрения: проекция пространства на экран из одной точки.

Code - чанковый эффект: Magnets stretching

Code - О мерцающем бордере: использование мерцание для повышения разрешения на бордере.

Code - Скриптование в демо: синхронизация эффектов под музыку и не только.

Графика - режиссура в демо: палитра изобразительных средств в Демомейкинге.

Графика - Мини-опрос художников: Dimidrol, Einar Saukas, Sand, Rion, riskej.

Графика - интервью с художником RayNoa/MAYhEM.

Музыка - Синхронизация музыки: nq рассказывает о создании треков под таймлайн.

Музыка - Беседа с MmcM/Sage group, известным AY-музыкантом, о его знаменитой технике.

Музыка - Беседа с Manwe/SandS - известным композитором, одним из старейших демосценеров России.

Музыка - Однобитная музыка: почему бипер ZX Spectrum продолжает вызывать восхищение?

Музыка - Горизонты турбосаунда: Cj Splinter делится опытом работы с TurboSound.

Музыка - Снова о плейерах Pro Tracker 3.x

Музыка - Музыкальный движок Muse 128b.

Системки - Как приручить IAR C Compiler.

Системки - Оберон для ZX Spectrum: Тонкости при разработке на Обероне в среде ZXDev (часть 1).

Системки - Оберон и ассемблер: Сопряжение с ассемблером (часть 2).

Системки - ZX-Basic Compiler: расширяемый кросс-компилятор.

Системки - Программы с поддержкой HDD, или "Linux" для Спектрума с винтом (или SD-картой).

Системки - iS-DOS/TASiS: о базовых принципах программирования под ОС iS-DOS/TASiS (часть 1).

Системки - iS-DOS/TASiS: как писать игры под iS-DOS/TASiS (часть 2).

Системки - iS-DOS/TASiS: Работа с палитрой и переключение графических режимов в TASiS (часть 3).

Металлолом - о строении экрана 6912 с аппаратной точки зрения.

Металлолом - Палитра для ZX Spectrum в различных графических режимах.

Металлолом - Эмуляция контроллера дисковода 1818ВГ93.

Дикий ум - Генерация и оптимизация кода в компилятора (часть 1)

Дикий ум - Генерация и оптимизация кода в компилятора (часть 2).

Дикий ум - ловля багов: самые типичные ошибки, при разработке на ассемблере Z80 (часть 1).

Дикий ум - ловля багов: самые типичные ошибки, при разработке на ассемблере Z80 (часть 2).

Дикий ум - алгоритм сжатия видео - 16 цветов на точку.

Игрушки - Разработка игр на Evo SDK (часть 1).

Игрушки - Разработка игр на Evo SDK (часть 2).

Игрушки - секрет успеха игры Jet Set Willy выпущенной в 1984 году.

Игрушки - Metal Man Reloaded: История создания от Oleg Origin.

Игрушки - Строение скриптового движка игры на примере L7 script engine.

Мыльница - Секретные кнопки в играх: Project ROBO, Ninjajar!, Uwol, Quest for Money, Zooming Secretary, Game About Squares.

Мыльница - письма: Kq, elfh, mig'95, wbr^NOT-Soft.

Мыльница - errata: Работа над ошибками.

Мыльница - об авторах журнала.


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

Похожие статьи:
ОТ Автора - Выступательное слово.
События - Путешествие из Петербурга в Москву.
Доклад 1 - report from cafe'o2 или я спал на сцене ;)
Сцена vs профессионалы - собрав команду лучших людей со сцены, мы сможем создавать программы высочайшего качества...
Железо - ZX-NEXT: двух процессорный Спектрум-компьютер 90-х годов.

В этот день...   21 ноября