PDA

Просмотр полной версии : ZX Like Pascal



Страницы : [1] 2 3

Andrew771
01.04.2015, 22:49
Представляю свой готовый кросс-компилятор Паскаля для Спектрума (и это не первоапрельская шутка! :) ).

ZX Like Pascal – кросс-компилятор языка программирования Паскаль для компьютера ZX Spectrum. Имеет усеченную версию по сравнению с классическим Паскалем.
Исходная программа на Паскале создается в файле с расширением PRG в любом текстовом редакторе. Для компиляции необходимо запустить файл ZXLIKEPASCAL.EXE и выбрать необходимый файл PRG. Программа на Паскале скомпилируется в программу на Ассемблере и запишется в текстовый файл с тем же именем и расширением ASM. Ассемблерный файл можно далее скомпилировать в любом кросс-ассемблере для ZX Spectrum. В случае обнаружения синтаксической ошибки в исходной программе выводится сообщение на экран с описанием ошибки, конкретное местонахождение ошибки можно посмотреть в файле ERROR.PRG.
Поддерживаются только целочисленные и строковые типы, одномерные и двумерные массивы.
Символьный экран - 64х24. Шрифт используется 4х8, в строке 64 символа. Поддерживается латиница и кириллица, буквы только прописные.
Имеются встроенные операторы вывода окон, познакоместных спрайтов и двумерных карт из элементов-спрайтов. Карты могут представлять из себя ландшафты, лабиринты, игровые поля. Имеется также встроенный оператор поиска элементов на карте по различным критериям. Карта задается в двумерном массиве, байт на клетку. В программе может быть несколько карт, соответствующие нескольким массивам.
Флагами компиляции можно задать:
- использование атрибутов (да/нет);
- отслеживание границ спрайтов и вывод только помещающейся части спрайтов (да/нет);
- вывод на виртуальный экран (да/нет).
Выход за пределы допустимых значений переменных и массивов не отслеживается, за ними должен следить программист (это сделано для увеличения быстродействия программ).
После последнего END программы на Паскале в файле PRG могут записываться процедуры на Ассемблере, коды спрайтов, карт и другая информация. Она без изменения копируется в файл ASM.

Обновил 20.05.2020 версию до 1.0.

Также добавлен Генератор спрайтов ZxSprGen V.2.0.1 от AzAtom, специально написанный для ZX Like Pascal.

Viktor2312
01.04.2015, 23:47
мануал только на родном русском.

Это хорошо, мы пендосятский всё равно не понимаем.

Bolt
02.04.2015, 00:34
Почему ArrayByte[n1], а не array [1..n1] of byte?
Почему %, а не mod?
Логического xor, а также целочисленных and, or, xor, shl, shr - нет?
Указателей вообще никаких нет? И не будет? Будут ли параметры у процедур? Локальные переменные? функции?

Это такое авторское вИдение Паскаля или какой-то диалект, о котором я не знаю? :)

Andrew771
02.04.2015, 09:30
Это такое авторское вИдение Паскаля или какой-то диалект, о котором я не знаю?
Ну еще спроси, почему нет типа real и longint :)
Я сделал для создания игр на Спекки прежде всего, на мой взгляд только нужные операторы. Поэтому появились всякие непаскалевские PutSprite и MapPut.

Почему ArrayByte[n1], а не array [1..n1] of byte?
Потому что диапазоны нигде не поддерживаются, и нижняя граница всегда 1, а не любая. Только для формальности можно подогнать под Паскаль.

Почему %, а не mod?
если честно, х.з. :)

Логического xor, а также целочисленных and, or, xor, shl, shr - нет?
xor ни разу не использовал в жизни в логических выражениях на ЯВУ. And и Or есть в логических выражениях. Сдвиги нафиг, это для Асма.

Указателей вообще никаких нет? И не будет? Будут ли параметры у процедур? Локальные переменные? функции?
вряд ли.

Основное назначение - написание игр.

denpopov
02.04.2015, 10:57
Ну еще спроси, почему нет типа real и longint

кстати, да, почему?

---------- Post added at 11:57 ---------- Previous post was at 11:53 ----------


Сдвиги нафиг, это для Асма

я, кэшна не знаток спецификации, но БорманПаскаль говорит вот:
http://i60.fastpic.ru/big/2015/0402/91/54d2a2b277a7cf655da164b3e9234e91.png

Andrew771
02.04.2015, 13:10
Сообщение от Andrew771
Ну еще спроси, почему нет типа real и longint
кстати, да, почему?
real не будет, он в подавляющем большинстве игр не нужен.
longint - планируется в будущем. Но для этого нужно сделать процедуры сложения/вычитания/умножения/деления 32-битных чисел, пока отказался. У меня пока есть 16-битные процедуры.


я, кэшна не знаток спецификации, но БорманПаскаль говорит вот:
Сдвиги если для скроллинга окон, то у меня есть готовые операторы для этого. Для остального не знаю, где еще можно применить. Умножайте/делите на 2 вместо сдвигов. Компилятор оптимизирует такие умножения сам. :)

denpopov
02.04.2015, 13:34
Умножайте/делите на 2 вместо сдвигов. Компилятор оптимизирует такие умножения сам

хотелось бы готовый код со сдвигами скормить компилятору:)

Kakos_nonos
02.04.2015, 14:28
А хотябы стек для передачи параметров процедурам?:rolleyes:
А неудобно будет.

Andrew771
02.04.2015, 14:43
А хотябы стек для передачи параметров процедурам?
А неудобно будет.
ладно, приделаю. Пока через глобальные переменные можно передавать.

---------- Post added at 14:43 ---------- Previous post was at 14:37 ----------


хотелось бы готовый код со сдвигами скормить компилятору
тож на будущее вставлю. А пока придется адаптировать прогу под текущее.

Kakos_nonos
02.04.2015, 16:04
Обязательно компилятор опробую и что-нибудь напишу. Очень давно ищу подобное, попадаются только монстры типа Си или Оберона с компиляторами из 1000 файлов. А тут - один фаил. Всё по спектрумовски.

Andrew771
02.04.2015, 16:54
Я на нем планирую начать гига-проект "Цивилизация" :)

Andrew771
02.04.2015, 21:36
А тут - один фаил. Всё по спектрумовски.
если точнее, то два файла. Еще libasm.lib, библиотека асмовских процедур, без нее никак. Кстати, она тоже в текстовом виде, можно при желании редактировать продвинутым программерам на Асме.

ALKO
02.04.2015, 23:31
Как перегнать спрайты из bmp в DEF'ы ?
и да, кстати. по спрайтам. Там только прямоугольная область спрайтов выводится?
Или же заполняются только те знакоместа, где имеются включённые пиксели?

Andrew771
03.04.2015, 09:42
Спрайты могут быть любой формы. Заполняются только те знакоместа, где имеются включённые пиксели. На данный момент я конвертирую программой 3D-View, написанной когда-то для игры ZXOOM. См.файл.
Запускаешь, нажимаешь кнопку в правом верхнем углу "Загрузить грань из файла", выбираешь свой файл BMP, обязательно с 24-битной палитрой. Потом устанавливаешь флажок в правом нижнем углу "Включать байт атрибутов в спрайты". Потом нажимаешь кнопку "Исходная грань". В файле source.txt сгенерируется спрайт в кодах ассемблера в текстовом виде. Только атрибуты нужно вручную редактировать в нем (сейчас там единицы везде), пока не умеет автоматически.
Вообще мне надо написать нормальный спрайт-конвертер для Паскаля, займусь в ближайшее время.

ALKO
03.04.2015, 10:30
Только атрибуты нужно вручную редактировать в нем (сейчас там единицы везде), пока не умеет автоматически.

Мне для "Агрессора" без атрибутов нада.

Andrew771
03.04.2015, 11:30
Мне для "Агрессора" без атрибутов нада.
Формально они должны быть, т.к. процедуры Паскаля под них предусмотрены. Если у тебя черно-белые, то байты атрибутов будут везде 56 (%00111000).
Но я потом могу редактнуть сам процедуры в скомпилированном асме, чтоб их убрать.

denpopov
03.04.2015, 12:07
мне бы ваши проблемы:v2_dizzy_facepalm:
а без bmp2scr никак?

Andrew771
03.04.2015, 12:24
а без bmp2scr никак?
можно, только много перековыриваний и копи-паст. Тупая работа, если много спрайтов.

ALKO
03.04.2015, 13:10
а без bmp2scr никак?

Акак?

Чёт не видел в бмп-ту-сцр опции сохранения спрайтов в виде:

Заполняются только те знакоместа, где имеются включённые пиксели.

denpopov
03.04.2015, 13:31
Чёт не видел в бмп-ту-сцр опции сохранения спрайтов в виде

напиши сам

Andrew771
03.04.2015, 15:10
напиши сам
уже написано, см. выше. Осталось тока определение атрибутов вставить.

ALKO
03.04.2015, 22:32
Формально они должны быть, т.к. процедуры Паскаля под них предусмотрены.

расточительная трата драгоценных байт. Ведь мы адепты 48к.

---------- Post added at 23:32 ---------- Previous post was at 23:14 ----------

Мой хилоу-ворлд:

Перегнал тулзой в ДЭФы
http://cs624230.vk.me/v624230147/27aed/ktjmg5SQWEs.jpg

Исходник Пасцалевской проги:

Program EX4;

begin

PutSpriteClear(gg1,7+2,25-14);

end.


GG1
DEFB 24
DEFB 0,2, 15,7,3,3,7,29,246,155
DEFB 0,3, 252,254,255,234,255,245,255,255
DEFB 0,4, 0,0,0,0,0,128,128,128
DEFB 1,1, 3,7,6,14,15,31,63,63
DEFB 1,2, 237,119,183,191,127,237,246,123
DEFB 1,3, 227,240,248,248,252,252,254,95
DEFB 1,4, 128,0,0,0,0,0,0,0
DEFB 2,1, 127,126,124,63,63,31,15,7
DEFB 2,2, 104,223,254,253,94,255,245,239
DEFB 2,3, 1,255,71,255,127,234,103,243
DEFB 2,4, 12,255,255,170,255,224,224,128
DEFB 2,5, 64,240,240,188,224,64,56,0
DEFB 3,1, 3,0,0,0,0,1,1,1
DEFB 3,2, 31,255,255,255,255,252,252,252
DEFB 3,3, 248,252,254,255,255,255,127,31
DEFB 3,4, 0,0,0,0,128,192,224,240
DEFB 4,1, 1,1,3,7,14,29,51,103
DEFB 4,2, 120,184,112,240,240,224,192,128
DEFB 4,3, 15,3,1,1,0,0,0,0
DEFB 4,4, 184,88,176,248,184,184,216,92
DEFB 5,0, 0,0,0,1,1,1,1,1
DEFB 5,1, 206,220,248,240,112,248,254,127
DEFB 5,4, 108,44,60,60,46,127,127,103
DEFB 5,5, 0,0,0,0,0,128,224,240

Результат:

http://cs624230.vk.me/v624230147/27b05/D6LQXtBpsK0.jpg

В чём косяк?

Andrew771
03.04.2015, 23:36
отсутствуют байты атрибутов

---------- Post added at 23:24 ---------- Previous post was at 23:20 ----------


расточительная трата драгоценных байт. Ведь мы адепты 48к.
ты пиши пока с атрибутами, я потом редактну.
В принципе, планировал сделать флаг учета/не учета атрибутов в компиле. Но тоже отложил.

---------- Post added at 23:36 ---------- Previous post was at 23:24 ----------

Получилось?

ALKO
04.04.2015, 01:32
Получилось?

Да... но синий инк, чёрный пэйпер по дэфолту.

---------- Post added at 02:30 ---------- Previous post was at 01:21 ----------

Вписал бесконечный цикл:
while true do begin
...
end;

В асм компилируется, а из асма в машинные коды - пишет: name _TRUE not defined
(на инструкции ld hl,(_TRUE) )

---------- Post added at 02:32 ---------- Previous post was at 02:30 ----------

А... на пасцале repeat же... Совсем всё позабывал.

Alex Rider
04.04.2015, 04:18
while true do begin ... end должно работать

---------- Post added at 04:18 ---------- Previous post was at 04:18 ----------

Странно, что константу true скомпиленный код загружает из памяти.

ALKO
04.04.2015, 09:29
Отзеркаливание спрайтов реализовано?
Или

напиши сам
?

---------- Post added at 10:29 ---------- Previous post was at 10:10 ----------

И ещё с обновлением картинки как быть?
Допустим, есть бэкграунд, поверх него рисуются спрайты по принципу PutSpriteClear (затирание значений на знакоместе новыми).
На следующем шаге для смещения спрайта что надо, чтоб избежать заметных морганий\мерцаний ?

Andrew771
04.04.2015, 13:09
while true do begin ... end должно работать
---------- Post added at 04:18 ---------- Previous post was at 04:18 ----------
Странно, что константу true скомпиленный код загружает из памяти.
В выражениях допускаются только числовые типы, тип boolean не реализован. Так что, пиши чё-нить такое:
while 1<2 do begin ... end

И ещё с обновлением картинки как быть?
Допустим, есть бэкграунд, поверх него рисуются спрайты по принципу PutSpriteClear (затирание значений на знакоместе новыми).
На следующем шаге для смещения спрайта что надо, чтоб избежать заметных морганий\мерцаний ?
В асме есть несколько способов, некоторые из них:
1. Запоминать кусок фона под спрайтом, а потом обратно выводить.
2. Рисовать заново весь экран в памяти, а потом быстро копировать на экран (это когда много спрайтов сдвинулось).

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

---------- Post added at 13:09 ---------- Previous post was at 13:06 ----------


Отзеркаливание спрайтов реализовано?
еще нет.

В общем, я собираю для следующей версии доработки. :)

ALKO
04.04.2015, 13:21
Рисовать заново весь экран в памяти, а потом быстро копировать на экран
то бишь просрётся ещё 7 кб ОЗУ... эх... так не хочется вырвиглазным XOR-ом делать.

Вот на движке Savage (dan dare, extreme) круто сделано. Причём всё с огромными (как для спектрума) спрайтами, всё динамично, да и умещается в 48 кб. Там тоже экран рисуется в буфер ОЗУ ?

---------- Post added at 14:21 ---------- Previous post was at 14:10 ----------

В общем-то, нынешний паскал для написания крестиков-ноликов вполне годится.
Но дабы наваять экшон, уже без асмовских процедур никак. Жаль. Рано обрадовался.

ALKO
04.04.2015, 18:09
http://vk.com/doc53856147_379712037?hash=2c3c2e1cb6e3f8258d&dl=400c21c63fe1d4cc0d&wnd=1

Sameone
04.04.2015, 18:45
Предлагаю автору выделить работу со спрайтами в отдельную либу. zx82sprt.lib например. Если кто-то решит писать игру со своей спрайтовской либой (или воспользуется компилятором чтобы написать что-нибудь безспрайтовое) -- зачем ему грузить в память лишний код? Ещё нужна либа для работы с биперным звуком, это если для 48к. В дальнейшем (особенно если на этом писать что-то вроде Цивилизации) без поддержки разных вариантов 128к не обойтись, там потребуется и с АУ работать, и с дискетой.

Andrew771
04.04.2015, 20:05
В отдельную библиотеку не надо, потому что подгружаются из общей только нужные процедуры, которые точно используются в программе, а не все.
Да, со спрайтами мне надо еще поработать, дописать процедур. В общем, сразу же на след.неделе ими займусь. т.к. это самое важное. Отзеркаливание спрайтов по x и y, get, put, познакоместный скролл... Плюс конвертер спрайтов допилить.

ALKO
04.04.2015, 20:58
я вот чё думаю... если даже познакоместно будет скроллироваться экран, а тайлы будут размером больше знакоместа.
к примеру 48*48 пикселей.
Каков будет алгоритм скролла, чтоб незаметно было появление тайла?

Пока представляю себе это следующим образом:
1 есть экран, с массивом тайлов.
2 двигаем, допустим, влево. И на этом же этапе заполняем тайлами образовавшуюся пустую область справа, впритык.

Но помимо двигающегося бэкграунда у нас имеется(ются) персонаж(ы), которые тоже подвергаются скроллу, а должны двигаться наоборот - синхронно с камерой.

то есть от процедуры скроллирования толку никакого. А нужно рисовать каждый раз всю область видимости. а после этого персонажа(жей). И это надо делать за пределами видео ОЗУ, и лишь потом выплёскивать на экран.

Alex Rider
05.04.2015, 00:02
Есть процерура отрисовки 5 слоев тайлов (фон, герои, передний план) + слой маски на экран (переписанная из Саботера 2). Умеет зеркалить байты спрайтов. Надо? Очень быстрая, стек не использует, легко кастомизируется для переменного числа промежуточных слоев. Скоро будет быстрая процедура для рисования тайлов в слои с маскированием и копированием тайлов фона для детекции коллизий.

Andrew771
05.04.2015, 00:09
то есть от процедуры скроллирования толку никакого. А нужно рисовать каждый раз всю область видимости. а после этого персонажа(жей). И это надо делать за пределами видео ОЗУ, и лишь потом выплёскивать на экран.
вирт.экран тогда, полная перерисовка. Как в ZXOOM.

---------- Post added at 00:07 ---------- Previous post was at 00:06 ----------


Есть процерура отрисовки 5 слоев тайлов (фон, герои, передний план) + слой маски на экран (переписанная из Саботера). Надо? Очень быстрая, стек не использует, легко кастомизируется для переменного числа промежуточных слоев. Скоро будет быстрая процедура для рисования тайлов в слои с маскированием и копированием тайлов фона для детекции коллизий.
процедура классная, но как ее встроить в Паскаль. Команда с кучей параметров?

---------- Post added at 00:09 ---------- Previous post was at 00:07 ----------


то есть от процедуры скроллирования толку никакого. А нужно рисовать каждый раз всю область видимости. а после этого персонажа(жей). И это надо делать за пределами видео ОЗУ, и лишь потом выплёскивать на экран.
в Эйфории я кстати по другому поступил - вывод ландшафта из символов-тайлов. Сначала в буфере строим последовательность из кодов символов, а потом вывод на экран, как строку символов.

Alex Rider
05.04.2015, 00:14
процедура классная, но как ее встроить в Паскаль. Команда с кучей параметров?
Если адреса слоев задать системными константами, то без параметров совсем. Кстати, жырный минус - слои должны лежать один за другим в строком порядке.

Andrew771
05.04.2015, 00:43
а в слои как спрайты кладутся?

Alex Rider
05.04.2015, 01:22
Можно свой алгоритм написать для твоего Паскаля, можно из разогнанного Саботера 2 поиспользовать когда допишу. Ничего особого, процедура с кучей параметров, типа, X, Y, ширина, высота, направление, адрес тайлмапа спрайта,... (не помню все, ща не дома, посмотреть негде). Тайлмап пихается в слои с учетом кадрирования, заполняется слой маски и делается копия тайлов фона под спрайтом. Выводилка на экран смешивает слои по алгоритму "если в маске не 0, то берем тайл фона, накладываем на него по маске слои героев, сверху накладываем по маске спрайты переднего плана (есть нюансы с маскированием слоев и атрибутом выходного спрайта), и полученный микс кидаем в экран.

Epsilon
05.04.2015, 20:46
Я конешно дилетант, а не проще было сделать так

прогу на паскале конвертировать в Си-подобный код, и потом z88dk сделает из него asm?

Тогда имхо в разы проще сделать всякие штуки с указателями и прочее, а выражения вообще в неизменном виде можно оставить.

ALKO
05.04.2015, 21:19
прогу на паскале конвертировать в Си-подобный код, и потом z88dk сделает из него asm?

тогда проще сразу писать на сях напрямую в z88dk, безо всяких пасцалей.

Andrew771
05.04.2015, 21:32
прогу на паскале конвертировать в Си-подобный код, и потом z88dk сделает из него asm?
Тогда имхо в разы проще сделать всякие штуки с указателями и прочее, а выражения вообще в неизменном виде можно оставить.
Зачем такие сложности, если уже я написал кодогенератор с оптимизатором?
Так поступил Oleg N.Cher. с Обероном, см. тут (http://zx-pk.ru/showthread.php?t=18472)
Сейчас на повестке дня допиливание новых команд вывода спрайтов и экранов в библиотеке на асме, для практического применения в играх. ALKO и Alex Rider правильно тон задают.

Можно свой алгоритм написать для твоего Паскаля, можно из разогнанного Саботера 2 поиспользовать когда допишу. Ничего особого, процедура с кучей параметров, типа, X, Y, ширина, высота, направление, адрес тайлмапа спрайта,... (не помню все, ща не дома, посмотреть негде). Тайлмап пихается в слои с учетом кадрирования, заполняется слой маски и делается копия тайлов фона под спрайтом. Выводилка на экран смешивает слои по алгоритму "если в маске не 0, то берем тайл фона, накладываем на него по маске слои героев, сверху накладываем по маске спрайты переднего плана (есть нюансы с маскированием слоев и атрибутом выходного спрайта), и полученный микс кидаем в экран.
Наверно да, выгодно задать новую команду с кучей параметров. А ее встроить в библиотеку libasm.lib. Присылай, как будет возможность.
Я вот сейчас решил срочно сделать следующее:
- флажок "Вывод спрайтов в виртуальный экран", при включенном вывод спрайтов будет на вирт. экран, при выключенном сразу на экран;
- аналогично флажок для вывода текста на вирт.экран;
- флажки "Использовать атрибуты для спрайтов", "Использовать атрибуты для текста";
- команду копирования вирт.экрана на экран;
- допилить конвертер bmp в спрайты с атрибутами.

Kakos_nonos
05.04.2015, 22:00
И стек запилите, это просто. Две команды - push и pop. Зато возможностей добавится много, удобнее станет писать большие программы.

Andrew771
05.04.2015, 22:26
И стек запилите, это просто. Две команды - push и pop. Зато возможностей добавится много, удобнее станет писать большие программы.
в смысле, параметры процедур?

Barmaley_m
09.04.2015, 23:24
На следующем шаге для смещения спрайта что надо, чтоб избежать заметных морганий\мерцаний ?
О синхронизации с вертикальной разверткой не забыли?

Команда HALT между кадрами есть?

---------- Post added at 23:24 ---------- Previous post was at 23:19 ----------


Я вот сейчас решил срочно сделать следующее:
- флажок ...
- аналогично флажок ...
- флажки ...
Мне кажется, лучше сделать несколько точек входа для разных режимов работы. А то у вас будет общая точка входа, потом проверка всех этих флажков (такты, такты!), а потом код будет разветвляться в зависимости от значения флажков. А если вы сделаете несколько точек входа - то не надо будет проверять флажки и делать условные переходы, выиграете в скорости.

Andrew771
10.04.2015, 09:36
Мне кажется, лучше сделать несколько точек входа для разных режимов работы. А то у вас будет общая точка входа, потом проверка всех этих флажков (такты, такты!), а потом код будет разветвляться в зависимости от значения флажков. А если вы сделаете несколько точек входа - то не надо будет проверять флажки и делать условные переходы, выиграете в скорости.
я хитрее делаю. Флажки в опциях кросскомпилятора, а не в ассемблере. В зависимости от них в код добавляется/выбрасывается нужное/ненужное. Изначально все возможности прописаны в библиотеке.

О синхронизации с вертикальной разверткой не забыли?
Команда HALT между кадрами есть?
нет, до такого не дошел. Процедуры вывода спрайтов стандартные.

ALKO
10.04.2015, 10:13
Жду не дождусь обновы. Аж печёт в одном месте.

Andrew771
10.04.2015, 11:22
Жду не дождусь обновы. Аж печёт в одном месте.
делаю. Хотел бы закончить на след.неделе.

ALKO
10.04.2015, 17:15
делаю. Хотел бы закончить на след.неделе.

Помню у вас были ещё процедурки быстрого скейла спрайтов (x2).
Они бы тоже были бы весьма кстати в СДК... Но это уже второстепенное.

Andrew771
13.04.2015, 12:15
Помню у вас были ещё процедурки быстрого скейла спрайтов (x2).
Они бы тоже были бы весьма кстати в СДК... Но это уже второстепенное.
да, надо бы и зеркалки, и скэйлы добавить. Но пока сейчас делаю вирт.экран и вкл./выкл.атрибутов.

Руслан
14.04.2015, 19:34
Program EX4;

var
x,y,a1,a2: byte;
begin
x:=0;
y:=0;
readkey(a1,a2);
if a1=79 then x:=x+1;
if a1=80 then x:=x-1;


PutSpriteClear(sprite01,x,y);


end.


SPRITE01
DEFB 41
DEFB 0,1,1, 0,0,0,0,3,7,63,126
DEFB 0,2,1, 0,0,15,127,255,252,0,0
DEFB 0,3,1, 0,0,255,255,159,24,24,0
DEFB 0,4,1, 0,0,0,240,254,63,63,49
DEFB 0,5,1, 0,0,0,0,0,128,192,248
DEFB 1,0,1, 0,1,3,7,15,14,62,62
DEFB 1,1,1, 240,224,224,128,0,62,63,15
DEFB 1,2,1, 0,0,0,0,0,0,128,192
DEFB 1,3,1, 0,0,0,0,0,0,0,1
DEFB 1,4,1, 0,1,1,0,0,31,254,240
DEFB 1,5,1, 248,252,223,15,31,31,1,1
DEFB 1,6,1, 0,0,128,128,128,128,192,224
DEFB 2,0,1, 56,56,60,60,28,12,12,14
DEFB 2,1,1, 63,113,255,255,249,255,255,249
DEFB 2,2,1, 192,224,224,243,247,255,239,238
DEFB 2,3,1, 1,0,1,1,3,3,3,1
DEFB 2,4,1, 158,255,231,255,255,224,255,255
DEFB 2,5,1, 3,129,128,192,192,192,192,193
DEFB 2,6,1, 224,224,248,120,120,248,240,192
DEFB 3,0,1, 6,7,3,1,0,0,0,0
DEFB 3,1,1, 127,63,128,224,240,124,62,15
DEFB 3,2,1, 206,156,63,63,15,0,0,224
DEFB 3,3,1, 1,0,128,192,192,0,0,0
DEFB 3,4,1, 195,255,126,0,0,0,1,15
DEFB 3,5,1, 193,131,7,15,62,124,248,224
DEFB 3,6,1, 192,128,0,0,0,0,0,0
DEFB 4,1,1, 3,0,1,1,3,3,7,7
DEFB 4,2,1, 254,255,199,199,131,131,13,31
DEFB 4,3,1, 0,255,255,227,227,225,255,255
DEFB 4,4,1, 255,252,252,252,254,254,254,254
DEFB 5,1,1, 7,6,6,7,7,7,7,7
DEFB 5,2,1, 31,31,62,188,248,240,240,240
DEFB 5,3,1, 227,225,0,0,0,0,0,0
DEFB 5,4,1, 254,254,63,31,31,31,30,24
DEFB 6,1,1, 3,0,0,0,0,0,0,0
DEFB 6,2,1, 224,224,224,224,64,192,192,64
DEFB 6,3,1, 6,14,12,28,28,24,24,31
DEFB 6,4,1, 24,24,24,24,24,24,24,252
DEFB 7,2,1, 240,255,255,248,126,31,7,0
DEFB 7,3,1, 63,255,255,7,15,255,248,0
DEFB 7,4,1, 254,206,14,255,254,0,0,0


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

Andrew771
14.04.2015, 23:05
куда поставить изначальные координаты спрайта, что бы он клаву слушать начал?

Для начала организуй цикл. Ты же в бейсике про, тут все также только паскаль.
Угу, вот так:

Program EX4;

var
x,y,a1,a2: byte;
begin
x:=0;
y:=0;

while 1<2 do {бесконечный цикл, условие всегда выполняется}
begin
readkey(a1,a2);
if a1=79 then x:=x+1;
if a1=80 then x:=x-1;
PutSpriteClear(sprite01,x,y);
end;

end.


SPRITE01
DEFB 41
DEFB 0,1,1, 0,0,0,0,3,7,63,126
DEFB 0,2,1, 0,0,15,127,255,252,0,0
DEFB 0,3,1, 0,0,255,255,159,24,24,0
DEFB 0,4,1, 0,0,0,240,254,63,63,49
DEFB 0,5,1, 0,0,0,0,0,128,192,248
DEFB 1,0,1, 0,1,3,7,15,14,62,62
DEFB 1,1,1, 240,224,224,128,0,62,63,15
DEFB 1,2,1, 0,0,0,0,0,0,128,192
DEFB 1,3,1, 0,0,0,0,0,0,0,1
DEFB 1,4,1, 0,1,1,0,0,31,254,240
DEFB 1,5,1, 248,252,223,15,31,31,1,1
DEFB 1,6,1, 0,0,128,128,128,128,192,224
DEFB 2,0,1, 56,56,60,60,28,12,12,14
DEFB 2,1,1, 63,113,255,255,249,255,255,249
DEFB 2,2,1, 192,224,224,243,247,255,239,238
DEFB 2,3,1, 1,0,1,1,3,3,3,1
DEFB 2,4,1, 158,255,231,255,255,224,255,255
DEFB 2,5,1, 3,129,128,192,192,192,192,193
DEFB 2,6,1, 224,224,248,120,120,248,240,192
DEFB 3,0,1, 6,7,3,1,0,0,0,0
DEFB 3,1,1, 127,63,128,224,240,124,62,15
DEFB 3,2,1, 206,156,63,63,15,0,0,224
DEFB 3,3,1, 1,0,128,192,192,0,0,0
DEFB 3,4,1, 195,255,126,0,0,0,1,15
DEFB 3,5,1, 193,131,7,15,62,124,248,224
DEFB 3,6,1, 192,128,0,0,0,0,0,0
DEFB 4,1,1, 3,0,1,1,3,3,7,7
DEFB 4,2,1, 254,255,199,199,131,131,13,31
DEFB 4,3,1, 0,255,255,227,227,225,255,255
DEFB 4,4,1, 255,252,252,252,254,254,254,254
DEFB 5,1,1, 7,6,6,7,7,7,7,7
DEFB 5,2,1, 31,31,62,188,248,240,240,240
DEFB 5,3,1, 227,225,0,0,0,0,0,0
DEFB 5,4,1, 254,254,63,31,31,31,30,24
DEFB 6,1,1, 3,0,0,0,0,0,0,0
DEFB 6,2,1, 224,224,224,224,64,192,192,64
DEFB 6,3,1, 6,14,12,28,28,24,24,31
DEFB 6,4,1, 24,24,24,24,24,24,24,252
DEFB 7,2,1, 240,255,255,248,126,31,7,0
DEFB 7,3,1, 63,255,255,7,15,255,248,0
DEFB 7,4,1, 254,206,14,255,254,0,0,0



Кстати, обнаружил ошибку в компиле - цикл REPEAT неправильно работает, исправлю!!!

---------- Post added at 23:05 ---------- Previous post was at 23:03 ----------

Пока тестовая бета-версия компиля, еще могут быть глюки.

Andrew771
16.04.2015, 23:33
Обновил версию Паскаля до 0.901 в первом сообщении темы, перекачайте:

- ошибку с циклом repeat/until исправил;
- переименовал команды вывода спрайтов, так логичнее - SpritePutClear, SpritePutAnd, SpritePutOr;
- добавил флажки включения/отключения атрибутов спрайтов, карты и текста, флажок проверки краев спрайтов, флажки вывода на виртуальный экран спрайтов, карты и текста;
- добавил команды очистки и вывода виртуального экрана из памяти - VirtScreenClear, VirtScreenPut; применяются для полной перерисовки экрана в памяти, а потом быстрого вывода на экран (чтоб не было мерцания).

Теперь нужно внимательно смотреть при компиляции, какие спрайты заданы - с атрибутами или без, и будет ли использоваться вывод на обычный экран или на виртуальный экран. Формат спрайтов и спрайтов карт с атрибутами и без них немного отличается. Без атрибутов и/или проверки краев вывод спрайтов работает немного быстрее, и сами спрайты меньше занимают места в памяти примерно на 10%.

ALKO
17.04.2015, 11:34
А зеркалки спрайтов ещё нет?

Andrew771
17.04.2015, 12:03
А зеркалки спрайтов ещё нет?
пока нет, но будет в ближайшее время.
У тебя много зеркальных спрайтов, места жалко? Просто, вывод зеркалок медленнее, чем обычных.

Руслан
17.04.2015, 14:18
Зеркалка хороша для отрисовки заднего фона на статичном экране. Это позволяет в некоторых случаях порядочно места сэкономить.

Andrew771
17.04.2015, 17:33
Зеркалка хороша для отрисовки заднего фона на статичном экране. Это позволяет в некоторых случаях порядочно места сэкономить.
буду делать.
Сейчас на подходе WindowGet и WindowPut - запоминание в памяти окна на экране и вывод его из памяти в любое знакоместо. Т.е., можно куски экрана запоминать, например фон под движущимся спрайтом, а потом выводить обратно. Это будет быстрее, чем вирт.экран использовать, но нужно отслеживать все перемещения спрайтов.

denpopov
17.04.2015, 17:39
У тебя много зеркальных спрайтов, места жалко? Просто, вывод зеркалок медленнее, чем обычных

Одна табличка в 256 байт, и ты в шоколаде:)

Andrew771
17.04.2015, 17:47
Одна табличка в 256 байт, и ты в шоколаде
Это да. А координаты вывода как быстро посчитать? Ведь в исходном спрайте они заданы для "прямого" (формат спрайта приведен выше на этой странице).

denpopov
17.04.2015, 18:05
А координаты вывода как быстро посчитать? Ведь в исходном спрайте они заданы для "прямого" (формат спрайта приведен выше на этой странице)

я бы отложил Паскаль в сторону:)

Alex Rider
17.04.2015, 20:29
буду делать.
Зеркалирование байта сделать несложно и не торомзно.
Одна табличка в 256 байт, и ты в шоколаде
Воистину, в Саботере я это оптимизировал так (в A - номер тайла, тайл выводится в буфер PaintedChar):


ld l,a
ld h,#00
add hl,hl
add hl,hl
add hl,hl
ld de,Game.Sprites.Saboteur - #08 ; tile number was incremented
add hl,de
ex de,hl
ld bc,PaintedChar
ld h,high MaskTable
ld iyl,#08
.out_saboteur_loop:
ld a,(de)
ld l,a
dec h
.saboteur_mirroring_command:
ld l,(hl)
inc h
ld a,(bc)
and (hl)
or l
ld (bc),a
inc bc
inc de
dec iyl
jp nz,.out_saboteur_loop

Там тока еще и автомаскирование применяется, табличка зеркалирования находится перед табличкой маскирования, зеркалирование отключается засылкой nop'а в .saboteur_mirroring_command.
А вот отзеркалить тайлы при выводе спрайта сложнее. Особенно, если спрайт частично может выходить за границы экрана. Надо либо в обратном порядке идти по тайломапу, либо по тайловому слою. Поскольку в Саботере эта процедура занимается четырьмя вещами одновременно (заполняет слой маски, копирует тайлы из фона в буфер, предотвращает вывод тайла поверх непреодолимого препятствия и, собственно, копирует тайлмап в нужный слой), ее переписывание я отложил до 128-й версии.

denpopov
17.04.2015, 20:35
осталось сообразить, как на Паскале реализовать:) я просто зеркалирование байтов видел в одной деме.

Andrew771
18.04.2015, 21:32
осталось сообразить, как на Паскале реализовать я просто зеркалирование байтов видел в одной деме.
В моем формате надо пробежаться вначале по всем координатам, найти максимальную по X (если отзеркаливание по X), по Y (если отзеркаливание по Y) или по обоим сразу. Затем для каждого знакоместа сначала вычитать координату из найденной максимальной, а потом само изображение зеркалить по таблице. Собстно, из-за первого этапа будет вывод медленнее, но сделаю.

---------- Post added at 21:32 ---------- Previous post was at 21:26 ----------


По хорошему конечно нужны структуры, многомерные массивы и указатели, хоть как то сгладит отсутствие ООП.
для чего?

Andrew771
20.04.2015, 21:24
Обновил версию до 0.902, в первом посте, качайте заново :)
Добавил операторы:
WindowGet - запоминание изображения окна в памяти;
WindowPut - вывод изображения окна из памяти;
SpritePutXor - вывод спрайта по методу XOR.

WindowGet и WindowPut хорошо использовать для передвижения спрайтов, не перерисовывая весь экран, а только нужное окно. См. демо в файле demo_move_sprite_get_put.prg

Andrew771
24.04.2015, 10:44
Я подумал, пописАл, и решил всё-таки не делать вывод зеркальных спрайтов. Процедура получается очень огромная, более 600 байт (вместе с таблицей зеркальных байтов), универсальная и медленнее в 2 с лишним раза, чем обычный вывод спрайта. Универсальная - потому что, если не делать универсальной, нужна куча операторов Паскаля со всяческими комбинациями - отражение по X, Y, XY; принцип наложения clear, and, or, xor.
Проще сразу сделать зеркальные спрайты, какие надо, и выводить обычной процедурой вывода спрайта. Это и быстрее, и если немного спрайтов, то меньше места займут.

ALKO
24.04.2015, 20:21
. Это и быстрее, и если немного спрайтов, то меньше места займут.

ну да. Попсовые спрайты размером 16*16 с двумя кадрами анимации не много места займут.

А если спрайты 48*48 и их штук 30-40 ? Оптимально ли их хранить в памяти сразу в зеркальном виде

Andrew771
25.04.2015, 20:01
А если спрайты 48*48 и их штук 30-40 ? Оптимально ли их хранить в памяти сразу в зеркальном виде
Блин, уломал. Ну тогда придумай, как не увеличивая до бесконечности операторы, сделать не совсем универсальной. Универсальность тоже не айс.

denpopov
06.05.2015, 09:49
Странно, что компилятор подавился на:

var k,d,m:integer; << Error: TYPE expected >>

Andrew771
06.05.2015, 12:39
Он не поддерживает тип integer, а только byte, word и string[N]

---------- Post added at 12:39 ---------- Previous post was at 12:34 ----------

Byte - Целые числа от 0 до 255.

Word - Целые числа от 0 до 65535.

String[n] - Символьные строки. n – максимальная длина строки от 1 до 255.

ArrayByte[n1]
ArrayByte[n1,n2] - Одномерные и двумерные массивы целых чисел от 0 до 255.
n1,n2 – максимальные индексы от 1 до 65535.

ArrayWord[n1]
ArrayWord[n1,n2] - Одномерные и двумерные массивы целых чисел от 0 до 65535.
n1,n2 – максимальные индексы от 1 до 65535.

ArrayString[n1,n2] - Одномерные массивы символьных строк.
n1 – максимальный индекс от 1 до 65535, n2 – максимальная длина строк от 1 до 255.

denpopov
06.05.2015, 13:45
Он не поддерживает тип integer, а только byte, word и string[N]
да, я прочитал документцию:)

когда заработают процедуры с передачей параметров? а то выходит натуральная оберонщина.

Andrew771
06.05.2015, 15:51
когда заработают процедуры с передачей параметров? а то выходит натуральная оберонщина.
Сейчас бьюсь над зеркальным выводом спрайтов, уже заканчиваю, чтобы ALKO нормально игру свою писал.
После этого тогда займусь, по срокам не знаю как...
Кстати, меня самого начинает бесить, что нет записей. Из-за этого многие мои исходники на Паскале пока лежат без дела - долго переписывать под Недопаскаль.
После этого уже можно сунуть исходник компилятора самому компилятору. :)

Andrew771
07.05.2015, 10:37
Обновил сегодня до версии 0903, в первом посте.

Добавил:

- операторы зеркального вывода спрайтов относительно вертикальной оси с разными методами наложения изображения на экран: SpritePutMirrorClear, SpritePutMirrorAnd, SpritePutMirrorOr, SpritePutMirrorXor.
- оптимизировал процедуры вывода на виртуальный экран, чуть быстрее стали работать.

Andrew771
21.09.2015, 21:23
Обновил сегодня до версии 0.904, в первом посте.

Обнаружил и исправил баг - не всегда верно присваивались ячейки строковых массивов. Теперь правильно. Также добавил пару оптимизаций для строковых выражений.

А вообще начал глобальную работу, чтобы поддерживались записи, параметры процедур и функций, типы char и boolean, а также чтобы остальное было в точности со спецификацией Паскаля. Но это надолго, не всё так просто, сам несколько раз переписывал начатое :(

Andrew771
07.12.2015, 15:52
Обновил сегодня до версии 0.905, в первом посте.

Операторы и внешне ничего не изменилось, так что полностью совместим с предыдущими версиями 0.903 и 0.904.

Сделал:
- оптимизации для присваиваний и сравнений переменных и констант типа byte - теперь производится в 8-битной арифметике, а не в 16-битной, что увеличивает быстродействие и экономит память;
- удаление повторных присваиваний переменных с одинаковыми значениями;
- удаление повторных строковых констант из данных.

- - - Добавлено - - -

Исходник ZX Like Pascal на Delphi тут: http://zx-pk.ru/showthread.php?t=54&page=14&p=810433&viewfull=1#post810433

Andrew771
01.02.2016, 10:41
Обновил сегодня до версии 0.906, в первом посте. Исправлены замеченные баги при выводе спрайтов и карт.

Kakos_nonos
02.03.2016, 21:34
Andrew771, можешь сделать поддержку запуска из коммандной строки, чтоб входной фаил PRG фаил передавать в качестве параметра.
Например:
zxpascal.exe game.prg

и на выходе будет game.asm

Это намного сократит количество телодвижений при разработке, сделает ее более удобной. Я сейчас хочу сделать игру на этом паскале, но данное обстоятельство мешает.

- - - Добавлено - - -

Это так делается:

В обработчик события запуска (form1create):

if paramcount<>0 then button1click(self);

И в самой компиляции,

if OpenDialog1.execute then Name:=Opendialog1.Filename;

Заменить на

if paramcount<>0 then Name:=paramstr(1) else
if OpenDialog1.execute then Name:=Opendialog1.Filename;


Я так сделал в той версии, что есть исходники, но она не самая новая.

- - - Добавлено - - -

Делаю щас one-click комплект, уже сделал автоматическую сборку trd из паскаль файла. Надо только перенести prg фаил на батник и оно скомпилируется, сассемблируется и запустится. Сейчас прикручу редактор какой-нибудь и вообще будет круто.
Я ещё в коде убрал вывод org 23900, поскольку это очень рано, trd не хочет работать, дописывается 25000, но это уже во внешнем файле (выходной асм инклюдится).
Я думаю, такие готовый сборки будут способствовать популярности платформы и игрописания.

Kakos_nonos
03.03.2016, 16:28
Обнаружил баг - не работает read и readln переменных типа byte и word, туда заносятся непонятные значения. Сейчас попробую покопаться в исходниках, но врядли найду.

- - - Добавлено - - -

Нашел почему не работает ввод чисел - сжасм интерпретирует sub a,48 как sub a,a:sub a,48
Надо заменить все вхождения просто на sub 48

Andrew771
03.03.2016, 17:24
Спасибо за наводку! Проверю. Официально команда должна быть sub n, посмотрю в исходнике, так ли она генерируется.

- - - Добавлено - - -


Andrew771, можешь сделать поддержку запуска из коммандной строки, чтоб входной фаил PRG фаил передавать в качестве параметра.
Например:
zxpascal.exe game.prg

и на выходе будет game.asm
Сделаю, как написал. Я еще так не делал никогда.

- - - Добавлено - - -

Исходник забыл обновить на сайте, исправлюсь :)

- - - Добавлено - - -


Я сейчас хочу сделать игру на этом паскале, но данное обстоятельство мешает.
ЗдОрово. Я тоже на нем начал писать игру а-ля Z.

Kakos_nonos
03.03.2016, 18:06
Вот, сейчас такая сборка
https://yadi.sk/d/y3IQQWDhptLqA

Для работы надо ассоциировать prg-файлы с compile.bat. Далее, открыть программу (или написать) в notepad2 (для примера, он в архиве. Но можете использовать свой редактор), и нажать Ctrl-S, Ctrl-L. Программа, скомпилируется, соберется trd и запустится. (надо чтоб trd был ассоциирован с эмулятором)

Из пожеланий: сделать пометку чтоб переменная не объявлялась в конце. Например:
var a:integer;notdef;
А то в некоторых примерах надо после компиляции идти в фаил и убирать вручную.

- - - Добавлено - - -

Также, пример demo_z компилируется с ошибкой. Две метки имеют одинаковое название, наверное в кодах блоков if/then/else что-то перепуталось.

А вообще, отличный проект, я как-то раньше не обращал на него внимание.

Andrew771
03.03.2016, 21:03
Также, пример demo_z компилируется с ошибкой. Две метки имеют одинаковое название, наверное в кодах блоков if/then/else что-то перепуталось.
это я уже исправил в версии 0.906. При множественных and и or генерировалась повторная метка. Сейчас исправлено.

Andrew771
04.03.2016, 11:41
Andrew771, можешь сделать поддержку запуска из коммандной строки, чтоб входной фаил PRG фаил передавать в качестве параметра.
Например:
zxpascal.exe game.prg

и на выходе будет game.asm

сделал.



Нашел почему не работает ввод чисел - сжасм интерпретирует sub a,48 как sub a,a:sub a,48
Надо заменить все вхождения просто на sub 48

сделал.

Обновил версию до 0.907 в первом посте.
Исходник 0.907 выложил тут (http://zx-pk.ru/showthread.php?t=54&page=14&p=810433&viewfull=1#post810433).

Oleg N. Cher
05.08.2016, 12:20
Обязательно компилятор опробую и что-нибудь напишу. Очень давно ищу подобное, попадаются только монстры типа Си или Оберона с компиляторами из 1000 файлов. А тут - один фаил. Всё по спектрумовски.Но вот, кстати, это не совсем верно. Вот вам проект транслятора Оберона в Си, один exe-файл (Bin/ofront+.exe), юзайте себе на здоровьице:

https://github.com/Oleg-N-Cher/OfrontPlus

Можно пробовать скрещивать с SDCC. Процедуры у Andrew771 вшиты внутрь хорошие, я даже присмотрюсь к выводу спрайтов, но лучше бы он их делал как внешние библиотеки. А вот язык никакой, это мне напоминает недо-Си Raydac'а, и ведь останется таковым. Оберон в ZXDev позволяет намного больше, намного.

P.S. Неприятно всё-таки, что дезу разводите. Я даже XDevLite попытался сделать всего одним exe-файлом. Получилось. Только смарт-линкер в виде отдельной exe'шки.

Andrew771
07.08.2016, 21:20
А вот язык никакой, это мне напоминает недо-Си Raydac'а, и ведь останется таковым. Оберон в ZXDev позволяет намного больше, намного.
Это да, я не спорю. Я его делал прежде всего для написания игр, так что всё лишнее, на мой взгляд, отбросил.

Сегодня обновил до версии 0.908 в первом посте.

Исправлены баги:
- устранено зацикливание FOR при конечном счетчике 255 (спасибо Oleg N. Cher за наводку);
- иногда неверно записывались в память ячейки двумерных массивов, исправлено.

А также новое:
- теперь из командной строки или из файла BAT можно запускать со многими параметрами компиляции: вывод без/с атрибутами, вывод на обычный/виртуальный экран текста, спрайтов, карт, проверка/игнорирование краев спрайтов. См. мануал в архиве;
- улучшена оптимизация для расчета в памяти ячеек массивов. Например, если вызываются подряд ячейки a[i,j] и a[i,j+k], то расчет адреса в памяти для ячейки a[i,j+k] берется смещением на k от адреса a[i,j], а не заново расчетом i*a1+j+k.

Alex Rider
07.08.2016, 22:03
Я его делал прежде всего для написания игр
А будет развитие в сторону канонического Паскаля? Ибо вот это вот "для написания игр" отталкивает. А отталкивает тем, что намекает на кучу ограничений, который надо прочитать, выучить и не забывать при разработке.

Andrew771
07.08.2016, 22:18
Не могу обещать пока, т.к. занят написанием игры (http://zx-pk.ru/threads/262-strategii-realnogo-vremeni-na-zx-spectrum.html?p=881235&viewfull=1#post881235) сейчас. Собстно, и хочу проверить, реально ли написать серьезную игру на подобно-Паскале. :)

AzAtom
08.08.2016, 14:29
Andrew771, интересный проект.

Почему вы решили компилировать в ассемблерный текст, который затем ещё раз надо компилировать? Не проще ли сразу генерировать исполняемый код?
Ваш подход может помочь только в одном случае, если программист захочет доработать ваши процедуры или заменить их на свои.

Компромиссный вариант: В зависимости от флага (галка/параметр командной строки либо директива компилятора) генерировать ассемблерный код как сейчас, или сразу исполняемый код.

И ещё предложение ввести директиву компилятора {$ORG xxxxx}, указывающую по какому адресу компилировать исполняемый код.

- - - Добавлено - - -

И думаете ли об оптимизации? Например, в циклах вставлять тело процедур вместо вызовов процедур. Это полезно, если вызываемые процедуры небольшие, а сам цикл выполняется много раз, тогда программа будет гораздо быстрее исполняться.

Oleg N. Cher
08.08.2016, 14:49
Уважаемые,

хотя я не пользуюсь данным компилятором, я за развитие в сторону канонического Borland Turbo Pascal, поэтому в своё время и советовал Андрею взять в исходниках компилятор Turbo Pascal v3.0 для Z80 и начать его развивать, но он пошёл по своему пути. Что же, это его решение и выбор. Но вообще молодец, здорово, что проект продвигается, респект.

Andrew771
08.08.2016, 23:03
Почему вы решили компилировать в ассемблерный текст, который затем ещё раз надо компилировать? Не проще ли сразу генерировать исполняемый код?
Ваш подход может помочь только в одном случае, если программист захочет доработать ваши процедуры или заменить их на свои.
Можно было бы. Только тогда надо забыть о пользовательских процедурах на ассемблере, иначе мне придется еще писать и кросс-ассемблер. :) В принципе, насколько я знаю, можно сделать BAT-ник, в котором две команды:
- кросс-компиляция Паскаля в Асм (это ZX Like Pascal умеет);
- запуск кросс-ассемблера (например, sjasm) и подсовывание ему асмовского файла.
Знающие люди, надеюсь, напишут тут, как это сделать.

В отдаленном будущем планируется сделать родной (не кросс) Паскаль для Спектрума. Причем да, более приближенный к оригинальному Паскалю. Тем более, это позволит компилировать исходник компилятора самим компилятором, как учит Н.Вирт. Не на ассемблере же его писать. :)



И думаете ли об оптимизации? Например, в циклах вставлять тело процедур вместо вызовов процедур. Это полезно, если вызываемые процедуры небольшие, а сам цикл выполняется много раз, тогда программа будет гораздо быстрее исполняться.
Оптимизации многие есть. А вот раскрытие циклов не стал делать, т.к. посчитал, что для вывода спрайтов достаточно встроенных моих процедур (там раскрытие циклов сделано уже в асмовском коде), а для остального вроде и не надо + отжирает память.



я за развитие в сторону канонического Borland Turbo Pascal, поэтому в своё время и советовал Андрею взять в исходниках компилятор Turbo Pascal v3.0 для Z80 и начать его развивать, но он пошёл по своему пути
По-видимому, придется. Т.к. изобретать велосипед - неблагодарное дело. Просто, это мой первый блин COM-ом, хотел сам написать, чтоб прочувствовать. На самом деле, это нелегко написать полноценный компилятор, подтверждение тому - постоянно всплывающие баги, так что лучше пользоваться наработками опытных. Я до сих пор не могу сделать поддержку хотя бы параметров процедур - головоломка. Кстати, пробовал брать полный исходник Оберона из книги Вирта "Построение компиляторов" и переделать на Паскаль, но пока тоже не осилил.

- - - Добавлено - - -


И думаете ли об оптимизации?
Моя статья по генерации кода и оптимизациям ZX Like Pascal есть тут (http://zx-pk.ru/threads/5125-info-guide.html?p=815815&viewfull=1#post815815) или тут (http://dgmag.in/N15/DowngradeN15b.pdf)

AzAtom
09.08.2016, 09:29
Andrew771, а что с ORG? Если его надо менять, то батником не обойтись. Хочется одну вещь попробовать сделать, но адрес мне другой нужен. Удобно, если в паскалевском исходнике уже указано куда компилировать, а не менять в ASM каждый раз.

- - - Добавлено - - -

И ещё пожелание менять расширение. Т.е., из "program.prg" делать "program.asm".

- - - Добавлено - - -


придется еще писать и кросс-ассемблер
Ну там гораздо легче - одна строка преобразуется в одну команду. :)

Oleg N. Cher
09.08.2016, 14:05
От Олега Комлева, соавтора XDev:

Сообщение для Андрея Шарина (Andrew771)
В версии ZX Like Pascal v.0.908 такая же ошибка, как в реализации FOR для MSX-BASIC на Ямахе: есть проверка попадания на границу, но нет проверки на первоначальное нахождение нач.значения за границей. Поэтому любой цикл FOR выполняется хотя бы 1 раз, даже если начальное значение заведомо превышает конечное (например, "for a:=247 to 0 do write(a,' ');" напечатает 247).

- - - Добавлено - - -


пробовал брать полный исходник Оберона из книги Вирта "Построение компиляторов" и переделать на ПаскальМ-м-м. А зачем - с Оберона на Паскаль? Т.е. зачем делать лишнюю работу? В чём замес, так сказать? (сборка мусора здорово упрощает написание, да и не только в этом преимущества. Ты давно ловил непонятный баг, когда прога просто вылетает? Я недавно. Но на Обероне такие вещи легче ловятся, чаще всего Оберон-компиляторы написаны настолько хорошо, что бага ловится и исправляется за секунды. Например, легко ловишь неверную метку в CASE. Или обращение по NIL-указателю. Или срабатывает ASSERT. Но это стиль, так надо научиться писать. Паскаль/Си не поощряют такой стиль, к сожалению, хотя он там конечно возможен.

Если таки собираешься брать за основу ТурбоПаскаль (есть и другие варианты, мне как-то Серж Атанцов выслал с пол-десятка компиляторов Паскаля, довольно интересных и уже на Дельфи, и переписывать не нужно), то возьми исходник TP 3.0 для Z80, он на асме. И исходник TP 6.0 для DOS (в сети есть), он на Паскале+TurboVision (IDE)+асм (компилятор). И по мотивам этих двух проектов и двигайся. Где-то в сети я видел компилер TP, переписанный на Паскаль, с подробными комментариями.

В нативном компиляторе прям на самом Спеке смысла вообще не вижу. Ты хочешь сделать хороший компилятор или поиграться? ;-)

s_kosorev
09.08.2016, 15:28
И исходник TP 6.0 для DOS (в сети есть)
Вы эти исходники смотрели?
Как можно предлагать за базу брать исходники компилятора под дос на ассемблере для 8086 для переноса на z80 ?

Oleg N. Cher
09.08.2016, 16:18
Я не предлагаю переписывать весь код на Z80, только кодогенератор _для_ Z80. Главное - принцип. А подобрать аналоги команд можно. Для начала. Потом оптимизация. И понеслось.

s_kosorev
09.08.2016, 18:38
Это все тянет на проект по сложности не уступающи zx like pascal

Oleg N. Cher
09.08.2016, 18:55
На гораздо сложнее тянет.

Eltaron
09.08.2016, 18:56
Можно было бы. Только тогда надо забыть о пользовательских процедурах на ассемблере, иначе мне придется еще писать и кросс-ассемблер. :)
Есть ещё третий вариант - выводить не ассемблерный код, а уже скомпилированный, но в виде релоцируемого объектного модуля. Разумней всего в формате .rel от SDCC.
Тогда к нему можно будет прилинковывать ассемблерные вставки, собранные SDCC-шным же ассемблером.

Но вообще нет ничего странного в том, чтобы получать на выходе компилятора асмовый исходник. Более того, практически все компиляторы, которые я встречал, работали именно так. Вот прямо начиная с HITech C для CP/M и заканчивая gcc и clang. Просто у современных компиляторов этап ассемблирования скрыт.

Oleg N. Cher
09.08.2016, 19:04
Я, по мере доработки транслятора в Си, Ofront+, иногда ловлю себя на мысли, что сам бы так не написал. Да, увы, наши человеческие возможности ограничены. Кто-то развит лучше нас в какую-то свою сторону. Конечно TP сложнее, так и мощнее ведь.

Кроме того, я призываю не ограничиваться TP. Если в TP что-то плохо, нужно иметь смелость отказаться от этого, даже в ущерб совместимости, хотя бы в виде компромисса (ключики -oldSyntax, -newSyntax). Если в Паскале есть проблемы (лишние begin'ы), я не останавливаюсь на Паскале, а иду дальше. Если в Обероне есть проблемы (мало возможностей), я не останавливаюсь на Обероне, а иду дальше. Даже такой сравнительно простой проект как транслятор Оберона в Си (а есть мнение, что Оберон - почти Hello World в мире языков программирования) требует действительно большого ментального напряжения. Что уж говорить про компиляторы с более сложных языков.

Andrew771
10.08.2016, 21:14
Andrew771, а что с ORG? Если его надо менять, то батником не обойтись. Хочется одну вещь попробовать сделать, но адрес мне другой нужен. Удобно, если в паскалевском исходнике уже указано куда компилировать, а не менять в ASM каждый раз.
Ты имеешь в виду первоначальный адрес паскалевской программы или чтобы можно было в любом месте вставить ORG несколько раз? Если хочешь вставить в свои асмовские процедуры после последнего END Паскаля, то смело можешь вставлять, кросс-ассемблер правильно скомпилирует. А если внутри паскалевского кода, то зачем? Сделать мне не трудно. :)

- - - Добавлено - - -


И ещё пожелание менять расширение. Т.е., из "program.prg" делать "program.asm".
Это - пережиток от первой версии, когда быстро набросал, всё руки не доходят.

- - - Добавлено - - -


От Олега Комлева, соавтора XDev:
Сообщение от Saferoll
Сообщение для Андрея Шарина (Andrew771)
В версии ZX Like Pascal v.0.908 такая же ошибка, как в реализации FOR для MSX-BASIC на Ямахе: есть проверка попадания на границу, но нет проверки на первоначальное нахождение нач.значения за границей. Поэтому любой цикл FOR выполняется хотя бы 1 раз, даже если начальное значение заведомо превышает конечное (например, "for a:=247 to 0 do write(a,' ');" напечатает 247).
Это уже не буду делать, т.к. ухудшит быстродействие. Пусть будет на совести программиста ошибочный счетчик. У меня много где нет "защиты от дурака" - например, проверки выхода за границы массивов, строк. Проверка границ спрайтов - опционально по флагу. Просто, если делать проверки, ухудшит быстродействие.

- - - Добавлено - - -


В нативном компиляторе прям на самом Спеке смысла вообще не вижу. Ты хочешь сделать хороший компилятор или поиграться? ;-)
Больше второе - поиграться. Особенно хочется создать самокомпилируемый компилятор. В ZX Like Pascal для этого не хватает всего лишь малость - процедуры с параметрами и локальными переменными. Тогда можно будет сделать нативный ZX Like Pascal на ZX Like Pascalе. :)

AzAtom
10.08.2016, 21:33
Если хочешь вставить в свои асмовские процедуры после последнего END Паскаля, то смело можешь вставлять, кросс-ассемблер правильно скомпилирует.
После твоего компилятора получается ASM с первой командой "org 23900", вот чтобы его менять можно было из исходного PRG файла. Например, чтобы до первого begin поставить директиву {$ORG xxxxx} и чтобы это потом оказалось в ASM файле. А в середине паскалевской программы даже не знаю, надо ли это...

Andrew771
10.08.2016, 21:50
После твоего компилятора получается ASM с первой командой "org 23900", вот чтобы его менять можно было из исходного PRG файла.
ок, приделаю в следующей версии 0.909.

Q-Master
11.08.2016, 21:16
Но вообще нет ничего странного в том, чтобы получать на выходе компилятора асмовый исходник. Более того, практически все компиляторы, которые я встречал, работали именно так. Вот прямо начиная с HITech C для CP/M и заканчивая gcc и clang. Просто у современных компиляторов этап ассемблирования скрыт.

Вообще для двух последних, если я все верно помню, высказывание не является действительностью. Ни тот ни другой ассемблер не используют и не генерируют, причем давно. Оба генерируют некий промежуточный код, который унифицирован для всех используемых платформ. На его основе генерируется сразу компилированный код, без промежуточной трансляции в текст или еще какие промежуточные представления.

Eltaron
11.08.2016, 21:26
Вообще для двух последних, если я все верно помню, высказывание не является действительностью. Ни тот ни другой ассемблер не используют и не генерируют, причем давно.
:)


$ sudo mv /usr/bin/as /usr/bin/as1
$ gcc a.c
gcc: error trying to exec 'as': execvp: No such file or directory



Оба генерируют некий промежуточный код, который унифицирован для всех используемых платформ.
Ну да, именно так компиляторы и работают. Ещё Hitech C так работал. Там первым этапом был синтаксический разбор и преобразование в какой-то промежуточный код, вторым - запуск аллокатора регистров и всякого сопутствующего для получения ассемблерного исходника.
У clang так вообще два таких преобразования происходит. Сперва в LLVM, потом, когда станет нужно - в асм. Но у него это "стало нужно" может и после окончательной линковки уже случиться.

AzAtom
12.08.2016, 15:41
Andrew771, из мануала:
Random(x) - Случайное число от 0 до x включительно. x может быть также арифметическим выражением.
Может, правильнее выдавать не включительно, как делает тот же турбопаскаль от борланда? Тогда будет меньше проблем с переносом кода оттуда, например.

Процедуры допустимы только без параметров и локальных переменных.
Ждём их поддержки. По крайней мере, переменные цикла должны быть локальными, чтобы исключить повторное использование имени.

AzAtom
13.08.2016, 12:04
Возникла такая идея по облегчению разработки, чтобы каждый раз не собирать образ для спектрума. Сделать язык синтаксически совместимым с турбопаскаль, тогда можно сделать модуль, реализующий твои специфические функции вроде работы со спрайтами, и подключив его спокойно делать игру на PC и отлаживать алгоритмы и т.д. Потом уже можно убрать этот модуль и скомпилировать для спектрума.
Если интересно, могу помочь в написании такого модуля.

- - - Добавлено - - -

Правда, для такого придётся переработать подход.
- Ассемблерные процедуры перенести из конца программы и сделать возможность ассемблерных вставок.
- Коды спрайтов и карт можно заполнять при инициализации массивов в разделе var, например.

AzAtom
15.08.2016, 18:17
Начал делать этот модуль, только для Delphi. Столкнулся с неопределённостью. В инструкции функция описана, например Delay(<x>); и непонятно какого типа переменную она может принимать. Лучше описывать в виде Delay(x:byte);, как пишут в помощи по тому же turbo pascal или delphi.

Oleg N. Cher
15.08.2016, 22:41
AzAtom, если Вам нужен инструментарий для разработки под Спек и другие платформы на одном языке, посмотрите ZXDev, ссылка в подписи. Я приватно щас кое-что скину, буквально вчера начал набрасывать.

- - - Добавлено - - -

Именно так, кстати, всё и реализовано, как Вы предлагаете. Язык синтаксически совместим для разных платформ, есть поддержка ZX, можно делать модули, совместимые по интерфейсу, но различные по реализациям, то есть можно спокойно делать игру на PC, отлаживать алгоритмы, а потом скомпилировать для спектрума.

Есть возможность ассемблерных вставок, коды спрайтов и карт можно задавать в константых массивах.

Andrew771
15.08.2016, 23:01
Начал делать этот модуль, только для Delphi. Столкнулся с неопределённостью. В инструкции функция описана, например Delay(<x>); и непонятно какого типа переменную она может принимать. Лучше описывать в виде Delay(x:byte);, как пишут в помощи по тому же turbo pascal или delphi.
Везде используется тип word, если не указан явно диапазон значений. Все арифметические выражения <arithmetic expression> 16-битные, т.е. тип word.


Возникла такая идея по облегчению разработки, чтобы каждый раз не собирать образ для спектрума. Сделать язык синтаксически совместимым с турбопаскаль, тогда можно сделать модуль, реализующий твои специфические функции вроде работы со спрайтами, и подключив его спокойно делать игру на PC и отлаживать алгоритмы и т.д. Потом уже можно убрать этот модуль и скомпилировать для спектрума.
Если интересно, могу помочь в написании такого модуля.
Да, идея классная, я тоже над ней думал в начале разработки. Было бы очень удобно. Но требует большого количества человеко-часов, у меня столько нет сейчас. И вообще, сейчас занят написанием игры (http://zx-pk.ru/threads/262-strategii-realnogo-vremeni-na-zx-spectrum.html?p=881235&viewfull=1#post881235) на этом Паскале, хочется попробовать в деле.

AzAtom
15.08.2016, 23:07
Oleg N. Cher, вообще, есть идеи сделать кое-что довольно сложное, поэтому, хотелось бы поддержки указателей и прочего. Просто паскаль мне знаком и поэтому эта тема привлекла внимание. Интересные штуки вы прислали.

Andrew771
15.08.2016, 23:09
Именно так, кстати, всё и реализовано, как Вы предлагаете. Язык синтаксически совместим для разных платформ, есть поддержка ZX, можно делать модули, совместимые по интерфейсу, но различные по реализациям, то есть можно спокойно делать игру на PC, отлаживать алгоритмы, а потом скомпилировать для спектрума.
Проблема в том, что полных библиотек в ZXDev нет, нужно самому дописывать на ассемблере. Как, например, уже сейчас вывести спрайт?
Я же создал полную библиотеку, чтобы юзер ничего сам не писал на ассемблере. Как правило, он и не может, т.к. наша аудитория - люди, знающие только языки высокого уровня: Бейсик, Паскаль.

AzAtom
15.08.2016, 23:15
Везде используется тип word, если не указан явно диапазон значений.
Т.е., например функции работы с окнами, где указано "от 0 до 31" и т.д. имеют тип byte, а остальные word?


Было бы очень удобно.
Сегодня начал, набросал базовые функции очистки экрана, установки аттрибутов и прочих и вывод прямых спрайтов. Завтра буду делать отзеркаленные и окна может успею. С ассемблерными вставками я похоже погорячился. На PC их не получится писать как есть, и пока не вижу способа их реализовать кроссплатформенно.

Пока получилось запустить ваш пример из "demo_sprites.PRG". Исходник выглядит вот так:

program TestZXPas;

{$APPTYPE CONSOLE} // Эта директива для работы команд ввода/вывода.
uses
windows, ZXPas in 'ZXPas.pas';

var
x,y:byte;
SPRITE01:array[0..60]of byte = (6, 0,0, 63, 96,204,152,145,163,130,139,
0,1, 192, 96, 48, 24,200,200, 88, 80,
1,0, 143,199, 97, 44, 43, 41, 45, 45,
1,1, 208,208,176, 96,160,176,208,144,
2,0, 45, 35, 47, 51, 20, 23, 16, 31,
2,1, 48,160,160, 96, 96,160, 32,224);

SPRITE02:array[0..60]of byte = (6, 0,0, 0, 63, 96,204,144,145,163,130,
0,1, 0,192, 96, 48, 24,200,200, 88,
1,0, 139,143,199, 97, 44, 47,109, 91,
1,1, 80,208,208,176, 96,160,176,144,
2,0, 83, 88,103, 87, 72, 99, 60, 3,
2,1, 16, 48,176, 24,104,200, 56,192);

begin
// Инициализация модуля ZXPas
ZXPas.init;
while not ZXInitialized do
sleep(10);
// Далее можно писать программу для ZX Like Pascal

border(0);
textbackground(0);
textcolor(6);
// clrscr;
VirtScreenClear;
textcolor(3);
writeln('xxx');
SpritePutClear(sprite01,7+2,25-14);
SpritePutOr(sprite02,7+3,25-13);
SpritePutXor(sprite02,7+4,25-12);

SpritePutMirrorClear(sprite01,17+2,20-14);
SpritePutMirrorOr(sprite02,17+3,20-13);
SpritePutMirrorXor(sprite02,17+4,20-12);{}

VirtScreenPut;

// Ожидание закрытия графического окна и затем завершение программы
repeat
sleep(100);
until not ZXInitialized;
ZXPas.Deinit;
end.

Oleg N. Cher
15.08.2016, 23:17
Oleg N. Cher, вообще, есть идеи сделать кое-что довольно сложное, поэтому, хотелось бы поддержки указателей и прочего. Просто паскаль мне знаком и поэтому эта тема привлекла внимание. Интересные штуки вы прислали.Благодарю.

AzAtom, поддержка указателей в ZXDev безусловно имеется. Как типизированных, так и нетипизированных. Есть модуль SYSTEM, который реализует набор низкоуровневых операций. Оказываю консультации, отвечаю на вопросы. Есть форум для поддержи и рассылка. Сам удивляюсь почему этим почти никто не пользуется. ;-)


Проблема в том, что полных библиотек в ZXDev нет, нужно самому дописывать на ассемблере.Информация устарела. Есть довольно симпатичные библиотечки, не хуже твоих.


Как, например, уже сейчас вывести спрайт?Как минимум, несколькими способами. Есть модуль GrSpr, есть кое-что в Best40.



Я же создал полную библиотеку, чтобы юзер ничего сам не писал на ассемблере. Как правило, он и не может, т.к. наша аудитория - люди, знающие только языки высокого уровня: Бейсик, Паскаль.Знающий чел портирует туда чего угодно, даже с минимальным знанием асма и максимальным желанием. В крайнем случае попросит помощи. Есть также мнение, что всего сразу не предусмотришь. Ты сформировал библиотеку, куда добавил всё нужное тебе, ну а кто поручится, что юзеру не понадобится что-то ещё?

Andrew771
15.08.2016, 23:17
Random(x) - Случайное число от 0 до x включительно. x может быть также арифметическим выражением.
Может, правильнее выдавать не включительно, как делает тот же турбопаскаль от борланда? Тогда будет меньше проблем с переносом кода оттуда, например.
Думал над этим, переделать легко. Просто, считаю с самого начала, как только начал изучать Бейсик и Паскаль, что правильнее полный диапазон включительно. Такая вот самодеятельность :)
Я кстати еще по другому реализовал оператор read/readln - если юзер вводит неверное значение или не того типа, то прога не отваливается с ошибкой (это меня бесит во всех ЯВУ), а перезапрашивает значение заново, т.е. продолжает работу. Для игр особенно важно.

По другому сделана readkey - опрашивает сразу до двух одновременно нажатых клавиш.


Процедуры допустимы только без параметров и локальных переменных.
Ждём их поддержки. По крайней мере, переменные цикла должны быть локальными, чтобы исключить повторное использование имени.
Это планируется. И планируется поддержка записей еще.

AzAtom
15.08.2016, 23:20
Вот скомпилированная программа с использованием этого модуля. Дополню другие функции и тогда можно выложить исходник.
57869

Andrew771
15.08.2016, 23:24
Т.е., например функции работы с окнами, где указано "от 0 до 31" и т.д. имеют тип byte, а остальные word?
они тоже имеют тип word, но если введешь или получится значение вне диапазона 0..31, то последствия с программой могут быть любыми - грязь на экране, зависание и т.д. Проверок выхода за диапазон нигде нет (ни в окнах, ни в массивах, ни в строках и т.д.), чтобы не ухудшать быстродействие. Теоретически, можно доделать и опционально прикрутить, но нужно время.

AzAtom
15.08.2016, 23:27
Andrew771, кстати, read/readln/write/writeln пока тоже не вижу вменяемого способа реализации из-за их возможности принимать разное количество параметров. Свои процедуры паскаль так не позволяет оформлять. :( Поэтому, у меня они идут стандартные и используют консоль.

Если есть желание, то можно ввести функцию TextOut(x,y,string); по примеру как в windows, вот её легко в графике реализовать.

Andrew771
15.08.2016, 23:28
Информация устарела. Есть довольно симпатичные библиотечки, не хуже твоих.


Как минимум, несколькими способами. Есть модуль GrSpr, есть кое-что в Best40.
Тогда отл!


Знающий чел портирует туда чего угодно, даже с минимальным знанием асма и максимальным желанием. В крайнем случае попросит помощи. Есть также мнение, что всего сразу не предусмотришь. Ты сформировал библиотеку, куда добавил всё нужное тебе, ну а кто поручится, что юзеру не понадобится что-то ещё?
Ну для этого я тоже позволяю ассемблерные вставки оператором Asm. Но считаю, что должен быть базовый набор процедур уже встроен, чтобы можно было создать почти любую игру, ничего не делая на ассемблере.

Oleg N. Cher
15.08.2016, 23:28
Это планируется. И планируется поддержка записей еще.Ну вот. А в ZXDev уже есть записи, и локальные переменные, и параметры, и чего там тока нету. ;-)

Андрей, все ведь понимают - сложную работу делаешь. Но разработка модулей для готовой среды и языка - это одно, а подтягивание среды-языка к нуждам юзерским - совсем разные по сложности вещи. И то, и другое сложно, но дорабатывать твой Паскаль кроме тебя никто не будет, помяни моё слово. А разработать процедуры вывода спрайта для своей же игры и (даже!) прибегнуть при этом к асму - совсем другая петрушка, радующая сердце спектрумиста.

AzAtom
15.08.2016, 23:29
если введешь или получится значение вне диапазона 0..31, то последствия с программой могут быть любыми - грязь на экране, зависание и т.д. Проверок выхода за диапазон нигде нет (ни в окнах, ни в массивах, ни в строках и т.д.), чтобы не ухудшать быстродействие.
Вот как, а я ввёл в каждой проверку. Значит, при отладке программа может правильно работать, а на спеке может глючить. Тогда я тоже уберу проверки.
Кстати, проверку выхода спрайта за пределы экрана кто осуществляет? Функция или тоже сам программист?

Oleg N. Cher
15.08.2016, 23:32
Но считаю, что должен быть базовый набор процедур уже встроен, чтобы можно было создать почти любую игру, ничего не делая на ассемблере.Это невозможно, уважаемый! :-) Всего на свете не предусмотришь. Способов вывода спрайта бывает как минимум сто! ;-)

Да, богатые библиотеки это наше всё. Очень жаль, что я делаю их для ZXDev почти в одиночку.

Andrew771
15.08.2016, 23:35
Кстати, проверку выхода спрайта за пределы экрана кто осуществляет? Функция или тоже сам программист?
Это есть. Опционально можно включить флажок.

- - - Добавлено - - -


Да, богатые библиотеки это наше всё. Очень жаль, что я делаю их для ZXDev почти в одиночку.
дык я тоже в одиночку делал. Кое-что содрал у других и вставил, большую часть сам написал.

AzAtom
15.08.2016, 23:37
Предварительный результат http://zx-pk.ru/threads/24967-zx-like-pascal.html?p=882124&viewfull=1#post882124


Andrew771, какие алгоритмы растворения экрана и генерации звука? Хорошо бы их тоже реализовать в модуле.

Andrew771
15.08.2016, 23:38
Вот скомпилированная программа с использованием этого модуля. Дополню другие функции и тогда можно выложить исходник.
TestZXPas.rar
посмотрел, классно. То, о чем я мечтал, ты реализуешь. :)

AzAtom
15.08.2016, 23:41
Думаю насчёт реализации флагов вроде вывода на виртуальный экран, использования атрибутов... Нормально будет, если в модуль их можно будет передавать через параметры процедуры Init?

Andrew771
15.08.2016, 23:42
Andrew771, какие алгоритмы растворения экрана и генерации звука? Хорошо бы их тоже реализовать в модуле.
Идеи содрал из книги "Как написать игру на ассемблере" Капульцевичей, там алгоритмы расписаны. Страницы щас не вспомню, надо искать, заглядывать.

- - - Добавлено - - -


Думаю насчёт реализации флагов вроде вывода на виртуальный экран, использования атрибутов... Нормально будет, если в модуль их можно будет передавать через параметры процедуры Init?
Да, пусть.

AzAtom
16.08.2016, 08:46
Andrew771, ещё вопросы.
- При зеркалировании спрайта как находишь максимальный номер блока? Я не придумал ничего лучше, чем пройтись по спрайту и поискать максимальный номер.
Либо можно принять соглашение, что последним должен описываться самый правый нижний блок и координаты брать из него.

- Функция ReadKey возвращает код кнопки или символа из таблицы в мануале? Если нажаты 3 кнопки как быть? Например, право-вверх + "огонь".

Andrew771
16.08.2016, 09:12
- При зеркалировании спрайта как находишь максимальный номер блока? Я не придумал ничего лучше, чем пройтись по спрайту и поискать максимальный номер.
да, я так и делаю.


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



- Функция ReadKey возвращает код кнопки или символа из таблицы в мануале? Если нажаты 3 кнопки как быть? Например, право-вверх + "огонь".
Спектрум не позволяет больше 2х клавиш за раз читать. Джойстик вроде позволяет, но он не поддерживается пока.

- - - Добавлено - - -


Функция ReadKey возвращает код кнопки или символа из таблицы в мануале?
код кнопки.

AzAtom
16.08.2016, 09:56
Джойстик вроде позволяет, но он не поддерживается пока.
Кемпстон, который через отдельный порт, позволяет в любой комбинации нажимать все 5 кнопок, они просто выведены на 5 битов считываемого байта. Может, лучше заранее предусмотреть 3 нажатые кнопки, а при обработке клавиатуры возвращать только 2 кнопки? Или думаешь ввести отдельную функцию для джойстика?

Eltaron
16.08.2016, 10:13
Спектрум не позволяет больше 2х клавиш за раз читать.
http://pinkie.mylittlefacewhen.com/media/f/rsz/mlfw8608_small.jpg

AzAtom
16.08.2016, 10:25
Кстати да, не подумал сразу. В одном ряду клавиш в левой и правой половине клавиатуры можно читать до 5 одновременно нажатых клавиш.

Andrew771
16.08.2016, 10:29
Спектрум не позволяет больше 2х клавиш за раз читать.
Хотя я не прав, вспомнил, как играли втроем в игры на одной клавиатуре и жали по много кнопок, всё работало. :) В одном полуряду наверно нельзя больше двух.
Тогда readkey что ль сделать многокнопочную (штук на 10) плюс джойстик :)

Eltaron
16.08.2016, 10:33
Кстати да, не подумал сразу. В одном ряду клавиш в левой и правой половине клавиатуры можно читать до 5 одновременно нажатых клавиш.
ага
А две кнопки объективно мало. Если нажать вправо-вверх для движения по диагонали, то стрелять при этом уже невозможно.

Andrew771
16.08.2016, 10:35
Из книги "Как написать игру на ассемблере" (http://zxpress.ru/book_articles.php?id=1029):

(Из-за упрощенной аппаратной реализации клавиатуры, примененной в ZX Spectrum, достоверно (в общем случае) можно определить одновременное нажатие не более двух каких-либо клавиш - Примеч. ред.)
Это я еще тогда запомнил, но видимо это поклёп :)

Eltaron
16.08.2016, 10:38
Хотя я не прав, вспомнил, как играли втроем в игры на одной клавиатуре и жали по много кнопок, всё работало. :) В одном полуряду наверно нельзя больше двух.
Тогда readkey что ль сделать многокнопочную (штук на 10) плюс джойстик :)
в идеале вообще не так должно быть
сначала ReadKeyboard() для чтения всех 8 полурядов и джойстика в буфер
А потом все сравнения if IsPressed(KeyLeft) then то, else IsPressed(KeyRight) then это. IsPressed ничего не опрашивает, просто в буфер смотрит.
Но упадет быстродействие, надо смотреть.

- - - Добавлено - - -


Это я еще тогда запомнил, но видимо это поклёп :)
В оригинале опрос клавы через внутренности ULA проходит вроде, может там какие-то мутки. Но вообще похоже на гон.

Andrew771
16.08.2016, 10:39
Это уже явно не Паскалевские команды.

AzAtom
16.08.2016, 10:42
В турбопаскале ReadKey ждёт нажатия клавиши, поэтому делали так
if KeyPressed then ReadKey.
И ReadKey возвращает по одной нажатой клавише. Вряд ли тут так будет удобно, это нужно будет отдельный буфер создавать для учёта нажатых клавиш.
Думаю, сейчас удобнее - сразу прочитал коды нажатых клавиш и пошёл обрабатывать. Только хорошо бы их штуки 3 или 4 считывать одновременно.

Andrew771
16.08.2016, 10:43
Сейчас у меня сделано так - readkey читает все клавиши и коды двух первых нажатых заносит в две разные переменные типа byte. А юзер хочет, может их потом проверить или не проверять, по одной или обе. Можно просто увеличить количество этих переменных.

AzAtom
16.08.2016, 10:46
В оригинале опрос клавы через внутренности ULA проходит вроде, может там какие-то мутки. Но вообще похоже на гон.
Просто считывается значение порта. Кнопки сидят на решётке и если нажать 3 кнопки на углах одного квадрата, то определится, что и четвёртая нажата, в этом и проблема.
Клавиатуры для PC спроектированы так, что могут однозначно определить одновременное нажатие 3 клавиш, 2 из которых могут быть управляющие.

Andrew771
16.08.2016, 11:16
Andrew771, какие алгоритмы растворения экрана и генерации звука? Хорошо бы их тоже реализовать в модуле.
Растворение - эффект Thaw отсюда (http://zxpress.ru/book_articles.php?id=1026)
Звук - эффект Explos отсюда (http://zxpress.ru/book_articles.php?id=1031)

- - - Добавлено - - -

Я на выходных тогда попробую сделать readkey с 10 клавишами (а может и кемпстон в придачу) и плюс, что раньше говорил, установку начального адреса компиляции юзером.

AzAtom
16.08.2016, 11:31
Andrew771, с массивами у меня загвоздка. Не получается как у тебя.

Функция WindowGet куда копирует окно? В отдельный буфер в памяти?

- - - Добавлено - - -

И если 2 раза подряд её применить, прежняя запомненная картинка затрётся?

Andrew771
16.08.2016, 11:49
Andrew771, с массивами у меня загвоздка. Не получается как у тебя.
что не получается?



Функция WindowGet куда копирует окно? В отдельный буфер в памяти?
Да, в отдельный буфер памяти. В область виртуального экрана. (Кстати, нельзя использовать виртуальный экран и эту команду одновременно в программе, будет портиться виртуальный экран).



И если 2 раза подряд её применить, прежняя запомненная картинка затрётся?
да, затрётся.

AzAtom
16.08.2016, 11:58
что не получается?
Делаю новый тип type bytearray = array of byte; В итоге получается тип динамического массива и объявить переменную var a:bytearray[0..10]; уже не получается. Либо делаю тип type bytearray = array[0..65535]of byte и тоже переменную можно объявить только типа bytearray без указания его размера.
В общем, надежда только на то, что переделаешь типы массивов как в турбо/дельфи паскале, либо придётся делать по 2 блока объявления массивов, для отладки под модуль ZXPas и под компиляцию для спектрума. Неудобно.


В область виртуального экрана. (Кстати, нельзя использовать виртуальный экран и эту команду одновременно в программе, будет портиться виртуальный экран).
Понятно. А то я уже третий буфер создал было. Сделаю, чтобы копировалось в то же место виртуального экрана, откуда берётся на видимом экране.

Andrew771
16.08.2016, 12:21
В общем, надежда только на то, что переделаешь типы массивов как в турбо/дельфи паскале, либо придётся делать по 2 блока объявления массивов, для отладки под модуль ZXPas и под компиляцию для спектрума. Неудобно.
ок. Тоже заношу в список, что сделать в ближайшие дни. Сделаю, как в нормальном Паскале.

- - - Добавлено - - -


bytearray
кстати, сейчас не bytearray, а arraybyte.
Но скоро этого не будет. Будет нормальный array[1..x] of byte :)

AzAtom
16.08.2016, 12:22
Andrew771, может, я немного и надоем, но будет много вопросов и не получается сразу все задать.

- При прокрутке окна WindowScrollLeft и другие, аттрибуты не трогать вне зависимости от флага?
- Флаг "окна с атрибутами" влияет только на WindowGet и WindowPut?

Andrew771
16.08.2016, 12:25
- При прокрутке окна WindowScrollLeft и другие, аттрибуты не трогать вне зависимости от флага?
атрибуты вообще не трогаются никогда. Т.к. непонятно, когда их трогать (скроллинг на 1 пиксель происходит).



- Флаг "окна с атрибутами" влияет только на WindowGet и WindowPut?
да, только на них.

AzAtom
16.08.2016, 12:42
Andrew771, прокрутка окон осуществляется только на видимом экране?

Andrew771
16.08.2016, 12:44
Andrew771, прокрутка окон осуществляется только на видимом экране?
да.

AzAtom
16.08.2016, 17:32
Выяснилось, что с ReadKey(key1, key2); работать неудобно, потому, что искомый код может оказаться в key1 или key2 и нужно их оба проверять. Если их будет 10, то совсем можно будет зашиться. Нужно что-то другое придумать.

Не реализовал функции ArrayClear - ищу способ, Asm - команды другие, так просто не получится её реализовать, MapSearch - толком не понял, что она ищет.
Остальное, вроде, готово. Пересмотрю код, использование флагов и завтра, наверное, уже смогу показать.

Eltaron
16.08.2016, 18:56
Это уже явно не Паскалевские команды.
То есть если команду назвать паскальным названием, то она автоматически становится паскальной? Хех.
Вообще-то паскальный ReadKey через буфер и работает.
А то, что сейчас - это вообще перловая команда. (key1, key2) = get_any_two_pressed_keys_in_random_order() :)

Andrew771
16.08.2016, 21:33
Выяснилось, что с ReadKey(key1, key2); работать неудобно, потому, что искомый код может оказаться в key1 или key2 и нужно их оба проверять. Если их будет 10, то совсем можно будет зашиться. Нужно что-то другое придумать.
Не нужно обе проверять, если только одна клавиша, а только первую переменную key1, т.к. асмовская процедура заполняет всегда сначала key1, если хотя бы одна клавиша нажата.
С 10-ю да, нужно подумать. Может, сортировать коды по возрастанию в буфере клавиш... Но это замедлит чтение.
Вернуться к конструкции if KeyPressed then ReadKey? Т.е. KeyPressed определяет, нажато ли хоть одно что-нибудь, а ReadKey уже медленная процедура для 10 клавиш.

- - - Добавлено - - -


Не реализовал функции ArrayClear - ищу способ
Это просто обнуление числового массива или заполнение пустыми строками строкового массива. На асме я сделал через команду ldir, чтобы юзер не писал свою медленно работающую пошлость for i:=1 to i_max do a[i]:=0;



MapSearch - толком не понял, что она ищет.
В ней куча опций. Ищет заданное значение клетки или диапазон значений клеток в области клеток карты (карта - двумерный массив типа byte).

AzAtom
17.08.2016, 09:40
Не нужно обе проверять, если только одна клавиша, а только первую переменную key1
А если 2? Например, мы можем идти и начать стрелять, тогда в key1 код "вправо", а в key2 код "огонь", а можем просто стрелять, тогда в key1 уже код "огонь". Можем пойти стреляя, тогда в key1 код "огонь", а в key2 код "вправо". Можем перестать стрелять и код "вправо" переместиться в key1. В общем, пока не однозначно.



Это просто обнуление числового массива или заполнение пустыми строками строкового массива.
Это понятно, но в дельфи в процедуру не передаются двумерные массивы напрямую. Это можно обойти, конечно, но тогда будет написано по другому, например я сделал тестовую программу, где пришлось написать MapSet(map[0,0],mapspr,0,0,32,24); вместо MapSet(map,mapspr,0,0,32,24);

- Далее, в дельфи объявленные переменные не обязательно идут друг за другом, поэтому, все спрайты карты пришлось объединить в один большой массив.

- Вдруг выяснилось, что если захочется попробовать спрайты с атрибутами и без них, то придётся править все спрайты, что неудобно. Почему бы не сделать все спрайты с атрибутами, а при сброшенном флаге "спрайты с атрибутами" просто не копировать атрибуты. Да, это будет на 10% больше места занимать, но будет гораздо удобнее.

- Ещё задумал написать генератор спрайтов. Можно будет загрузить в него 1 битную картинку, а она выдаст её в текстовом виде для вставки в исходник программы. Или такой уже есть?

- - - Добавлено - - -

Сейчас у меня вот, что получилось 57888.

- - - Добавлено - - -

Кнопки 1 и 2 показывают цифры 1 и 2, кнопки 0 и пробел - выход из программы.

Alex Rider
17.08.2016, 12:10
А если 2? Например, мы можем идти и начать стрелять, тогда в key1 код "вправо", а в key2 код "огонь", а можем просто стрелять, тогда в key1 уже код "огонь". Можем пойти стреляя, тогда в key1 код "огонь", а в key2 код "вправо". Можем перестать стрелять и код "вправо" переместиться в key1. В общем, пока не однозначно.
Сделайте уже метод ReadKey как в Паскале, чтобы возвращал только одну кнопку, и function CheckKeys(Keys: string): Word, в которой в Keys передаются проверяемые кнопки в виде строки символов (например, "MQAOP"), а в результате установлены биты нажатых кнопок (например, для вверх-вправо-огонь - %11001). Тогда управление в игре можно будет хранить в строках (хоть у пользователя запрашивай, хоть константами забивай, особенно, если для джойстика придумать символы тоже) и проверять единообразно-безобразно.

s_kosorev
17.08.2016, 13:36
А почему нельзя просто допрашивать кнопки в матрице. Всякие ReadKey нужны для определения факта нажатия но не удержания

- - - Добавлено - - -

IsKeyPressed нужна функция

AzAtom
17.08.2016, 14:47
Есть пара идей на счёт ReadKey, не знаю какая лучше/удобнее.

- В ReadKey передаётся массив из 3-5 элементов (нужно решить и принять соглашение о количестве), оттуда возвращается с заполненными кодами нажатых клавиш. Программа просматривает массив на предмет нужных кодов. Например, проверка нажатия вправо ищет в массиве код соответствующей клавиши и возвращает 1 или 0 по результатам поиска, и т.д. Если надо набирать текст, то можно просматривать массив в поисках первого ненулевого значения и его принимать за нажатую клавишу.

- Ввести функцию SetKeyBuffer, которой передаётся массив из 3-5 элементов (нужно решить и принять соглашение о количестве), его адрес запоминается и обработчик клавиатуры автоматически заносит туда коды. Программе не нужно вызывать ReadKey, просто обрабатывает массив как в предыдущем случае.

- Наиболее близко к классическому паскалю, где-то есть буфер клавиатуры, он заполняется обработчиком клавиатуры по нажатию и отжатию клавиш. Функция ReadKey возвращает код нажатой и отжатой клавиши из этого буфера, можно в 2 разных переменных, в одной код клавиши, в другой флаг отжатия. Тогда программе нужно будет в цикле вызывать ReadKey до тех пор, пока key <>0 и соответственно обрабатывать полученные коды.

Reobne
17.08.2016, 15:08
Для проверки нажатости:
GetKeyState(VirtualKeyCode:word):boolean;
Определить константы для каждой клавиши:
ZXK_1=$f701; // старший байт порта FE и маска
Можно сделать константу и для эникей.
И ещё GetVirtualKeyCode:word, для удобства написания кода выбора игроком кнопок управления. Он вернёт код нажатой сейчас клавиши, в готовом формате для GetKeyState.

Oleg N. Cher
17.08.2016, 15:11
Я вот только не пойму зачем пихать все эти функции опроса клавы внутрь самого Паскаля, а потом говорить, что-де это не паскалевская команда. Делайте уже внешним модулем, или как. Поддержка модулей-то имеется?

Reobne
17.08.2016, 15:32
Oleg N. Cher, Иногда модульность вредна. Человеческое сознание не беспредельно. Человеческое внимание ограничено. Заставлять программиста помнить названия модулей, каждый раз перечислять их в начале программы, может стать занудной бюрократической особенностью языка. :)

AzAtom
17.08.2016, 17:20
Сделал генератор спрайтов 57974.

Обновлено.

Oleg N. Cher
17.08.2016, 17:32
Reobne, никто не заставляет ту самую модульность излишне пользовать. Просто в случае ZX Like Pascal, получается, невозможно разработать свою библиотеку, остаётся только надеяться убедить Andrew добавить то да сё в язык. Разве это хорошо? А хорошо ли иметь исходник всего в виде одной простыни? Это 70-е.

Именно потому, что человеческое сознание не беспредельно, а человеческое внимание ограничено, хорошо мыслить интерфейсами и писать хорошо структурированные, тематически закрытые модули, которые не экспортируют наружу ничего лишнего.


Заставлять программиста помнить названия модулей, каждый раз перечислять их в начале программы, может стать занудной бюрократической особенностью языка.Гораздо более занудной и бюрократической особенностью языка может стать то, что непонятно какая сущность откуда приходит, что является частью языка, что библиотеки. Это я наблюдал, к примеру, в PureBasic. Да будет также известно, что в TurboPascal графика и другие особенности реализованы библиотечно.

В общем, плохо когда не видно какие модули юзает твоя программа. Или твой модуль. Непонятны его зависимости, о них только догадываться остаётся, допокуда внимательно реализацию не изучишь. Вопрос приоритетов. Для больших проектов это очень плохо, для средних тоже. Вот для поиграться - это да, всё равно.

Andrew771
17.08.2016, 21:01
Сделал генератор спрайтов ZXSprGen v1.0.rar.
классно! Только не на чем проверить, бросил бы в дистрибутив какую-нибудь тестовую картинку. Если суперский, то буду поставлять вместе с дистрибутивом ZX Like Pascal :)
До этого времени для конвертации спрайтов я рекомендовал пользоваться моей утилитой (http://zx-pk.ru/threads/24967-zx-like-pascal.html?p=794106&viewfull=1#post794106). Я ей сам пользуюсь всегда. Но твой конвертер наверно еще удобнее, посмотрю, перейду.

Насчет опроса клавиш - предложения разные и хорошие, повод поразмышлять. Пока ничего не решил. Но нужно что-то простое.
Побитовых операций нету, так что не всё можно.

- - - Добавлено - - -


Вдруг выяснилось, что если захочется попробовать спрайты с атрибутами и без них, то придётся править все спрайты, что неудобно. Почему бы не сделать все спрайты с атрибутами, а при сброшенном флаге "спрайты с атрибутами" просто не копировать атрибуты. Да, это будет на 10% больше места занимать, но будет гораздо удобнее.
10% - это для памяти Спектрума непозволительно много. И так спрайты большую часть памяти занимают, а тут еще отгрызется 10% - пару-тройку килобайт. Лучше не надо.

- - - Добавлено - - -


Сейчас у меня вот, что получилось TestZXPas02.rar.
классно! Исходник бы паскалевский приложил, чтоб прочувствовать :)

- - - Добавлено - - -


Просто в случае ZX Like Pascal, получается, невозможно разработать свою библиотеку, остаётся только надеяться убедить Andrew добавить то да сё в язык. Разве это хорошо? А хорошо ли иметь исходник всего в виде одной простыни? Это 70-е.
Ассемблерные вставки можно делать сколько угодно, для этого есть оператор Asm. В Zdemo2 я вставил процедуру вывода карты 4х4 знакоместа например.
Также можно редактировать саму библиотеку libasm.lib - это обычный текстовый файл (правда, не забыть сохранить тогда резервную копию на всяк.случай).
Вот оператор свой нельзя вставить. :)
А чем плоха простыня, в которой всё сразу под рукой, и Паскаль, и асм, и данные все?

Oleg N. Cher
17.08.2016, 21:24
Тем, что когда она становится неподьёмной - ты устаёшь её листать, глаза разбегаются. Человеческое восприятие устроено так, что воспринимает информацию ограниченными порциями.

Именно Вирт считал и считает модульность большим шагом вперёд, и именно за её отсутствие критиковали старый виртовский Паскаль апологеты Си (например, в статье "Почему Паскаль не является моим любимым языком программирования"). Модульность выводит мышление на новый уровень, когда ты мыслишь межмодульным взаимодействием, интерфейсами и их иерархией, а не тем, какой регистр у тебя портится внутри вот этой машинной процедуры.

Наконец, удобно при проектировании больших систем. Я сейчас не о твоём Паскале, Андрей. В случае написания игры, возможно, тебе модули и не нужны, в силу специфики мышления. Но то тебе.

- - - Добавлено - - -

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

s_kosorev
17.08.2016, 21:50
Поддержка модулей-то имеется?
А в pascal модульности и не было, был include

Oleg N. Cher
17.08.2016, 22:12
Ну да, в виртовском Паскале так и было. В TP модульность появилась начиная с версии 4 (или 5?).

Дополню ещё. Модули - это базовая единица декомпозиции. Любой электронщик грамотно обоснует почему лучше иметь модульную и блочную конструкцию, чем схемный хаос. Насколько модули это хорошо при проектировании и для дальнейшего ремонта и обслуживания. Правда, это бесполезно объяснять радиолюбителю, паяющему схему из двух транзисторов. Андрей, не в обиду.

Концепт модульности происходит из желания разделить задачу на подзадачи. Разложить всё по полочкам, упорядочить. Процедура - это элементарная единица, а модуль - композитная, составная. Из-за нарушения принципов модульности мы имеем уродливые монолитные решения в IT, которые потребляют много памяти. Взять dll. Это самодостаточная единица? Нет. Чтобы её заюзать - нужен сишный хидер или биндинг. То есть там есть набор вызовов, а описатели параметров и проч. вынесены отдельно. Всё хранится не вместе, из-за чего получаем рассинхронизацию (старый биндинг отстаёт от новой версии). Разумеется, есть целая куча причин, по которым в электронике модульности достичь проще, чем в программировании.

AzAtom
18.08.2016, 09:00
Только не на чем проверить
Можно той картинкой из твоего архива.


бросил бы в дистрибутив какую-нибудь тестовую картинку
Бросил и обновил архив http://zx-pk.ru/threads/24967-zx-like-pascal.html?p=882316&viewfull=1#post882316.
Ещё хорошая идея в твоей программе, указывать сколько байт получилось в массиве.

- - - Добавлено - - -


Исходник бы паскалевский приложил, чтоб прочувствовать


program TestZXPas;

{$APPTYPE CONSOLE} // Эта директива для работы команд ввода/вывода.
uses
windows, ZXPas in 'ZXPas.pas';

var
x,y:word;
k1,k2:byte;

GG1 :array[0..240]of byte = (24,
0,2, 15, 7, 3, 3, 7, 29,246,155,
0,3, 252,254,255,234,255,245,255,255,
0,4, 0, 0, 0, 0, 0,128,128,128,
1,1, 3, 7, 6, 14, 15, 31, 63, 63,
1,2, 237,119,183,191,127,237,246,123,
1,3, 227,240,248,248,252,252,254, 95,
1,4, 128, 0, 0, 0, 0, 0, 0, 0,
2,1, 127,126,124, 63, 63, 31, 15, 7,
2,2, 104,223,254,253, 94,255,245,239,
2,3, 1,255, 71,255,127,234,103,243,
2,4, 12,255,255,170,255,224,224,128,
2,5, 64,240,240,188,224, 64, 56, 0,
3,1, 3, 0, 0, 0, 0, 1, 1, 1,
3,2, 31,255,255,255,255,252,252,252,
3,3, 248,252,254,255,255,255,127, 31,
3,4, 0, 0, 0, 0,128,192,224,240,
4,1, 1, 1, 3, 7, 14, 29, 51,103,
4,2, 120,184,112,240,240,224,192,128,
4,3, 15, 3, 1, 1, 0, 0, 0, 0,
4,4, 184, 88,176,248,184,184,216, 92,
5,0, 0, 0, 0, 1, 1, 1, 1, 1,
5,1, 206,220,248,240,112,248,254,127,
5,4, 108, 44, 60, 60, 46,127,127,103,
5,5, 0, 0, 0, 0, 0,128,224,240);

ball1:array[0..40]of byte = (4,
0,0, 3, 15, 31, 51,103,111,255, 0,
0,1, 224,248,252,254,255,255,255, 0,
1,0, 255,111,103, 51, 19, 15, 7, 0,
1,1, 255,255,254,254,252,248,240, 0);

mapspr:array[0..41*5-1]of byte = (
4, // Стена
0,0, 0, 0, 0, 0, 0, 0, 0, 0,
0,1, 0, 0, 0, 0, 0, 0, 0, 0,
1,0, 0, 0, 0, 0, 0, 0, 0, 0,
1,1, 0, 0, 0, 0, 0, 0, 0, 0,
4, // Кирпич
0,0, 85, 1, 1,255, 85, 16, 16,255,
0,1, 85, 1, 1,255, 85, 16, 16,255,
1,0, 85, 1, 1,255, 85, 16, 16,255,
1,1, 85, 1, 1,255, 85, 16, 16,255,
4, // Основание колонны
0,0, 36, 36, 36, 36, 36, 36, 36, 36,
0,1, 36, 36, 36, 36, 36, 36, 36, 36,
1,0, 36, 36, 36, 36, 72,136,136,255,
1,1, 36, 36, 36, 36, 18, 17, 17,255,
4, // Середина колонны
0,0, 36, 36, 36, 36, 36, 36, 36, 36,
0,1, 36, 36, 36, 36, 36, 36, 36, 36,
1,0, 36, 36, 36, 36, 36, 36, 36, 36,
1,1, 36, 36, 36, 36, 36, 36, 36, 36,
4, // Верхушка колонны
0,0, 127,144,136, 72, 36, 36, 36, 36,
0,1, 254, 9, 17, 18, 36, 36, 36, 36,
1,0, 36, 36, 36, 36, 36, 36, 36, 36,
1,1, 36, 36, 36, 36, 36, 36, 36, 36);

map:array[0..15,0..11]of byte = (
(4,3,3,3,3,3,3,3,3,3,2,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(0,0,0,0,0,0,0,0,0,0,0,1),
(4,3,3,3,3,3,3,3,3,3,2,1));

dig0:array[0..10]of byte = (1, 0,0, 0, 28, 34, 42, 42, 34, 28, 0);
dig1:array[0..10]of byte = (1, 0,0, 0, 24, 56, 24, 24, 24, 60, 0);
dig2:array[0..10]of byte = (1, 0,0, 0, 60, 66, 2, 28, 32,126, 0);

begin
// Инициализация модуля ZXPas. Флаги соответствуют галкам компилятора.
ZXPas.init(true,true,false,true,true,true,true,tru e);
// Далее можно писать программу для ZX Like Pascal

border(0);
textbackground(0);
textcolor(7);
clrscr;
VirtScreenClear;

MapSet(map[0,0],mapspr,0,0,32,24);

x:=4;
y:=1;
repeat
VirtScreenClear;
MapPut(0,0);
SpritePutClear(ball1,10,x);
SpritePutClear(GG1,x,16);
SpritePutClear(ball1,12,2);
ReadKey(k1,k2);
if (k1=49) or (k2=49) then SpritePutClear(dig1,4,4) else SpritePutClear(dig0,4,4);
if (k1=50) or (k2=50) then SpritePutClear(dig2,6,4) else SpritePutClear(dig0,6,4);
VirtScreenPut;
Delay(1);
x:=x+y;
if (x>19) or (x<4) then y:=-y;
until (k1=48) or (k2=48) or (k1=32) or (k2=32);

ZXPas.Deinit;
end.


- - - Добавлено - - -


а тут еще отгрызется 10% - пару-тройку килобайт.
Это да... Но с другой стороны, много ли игр двухцветные, а по сути одноцветные? Обычно только часть спрайтов может быть без своих атрибутов и принимать другие атрибуты. А спрайты ГГ, врагов и подобные будут разноцветные, так что, впустую потратится не 2-3 КБ, а гораздо меньше. Думаю, это приемлемо. По крайней мере, есть повод подумать над этим.

- - - Добавлено - - -

Так, почти половину модуля ZXPas мне придётся переписать, нужно ещё учесть флаги для работы со спрайтами с атрибутами и процедуры более понятно написать. Так что, пока выкладывать нечего.

AzAtom
19.08.2016, 16:52
Есть идея насчёт ReadKey. Нужно сделать её похожей на стандартную турбопаскалевскую. Пусть будет буфер на 4 кода. Обработчик прерываний опрашивает клавиатуру и найденную клавишу помещает в первую свободную (=0) ячейку буфера. Автоповтор тоже так же реализуется. При отпускании тоже помещается код клавиши, но с флагом release. Так же, ещё должны быть флаги модифицирующих клавиш капс и символ шифт. Флаги возвращаются в отдельной переменной. Вызов выглядит так Readkey(key,flag);
После чтения кода процедура прокручивает буфер вперёд, обнуляя последний код. Если ничего не нажато, то возвращается код 0. Так удобнее, чем использовать конструкцию if KeyPressed then ReadKey(); Программа просто читает и обрабатывает коды клавиш, пока key возвращается не нулевой. Это хорошо подойдёт для набора текста, ввода имени в турнирную таблицу и т.д.

Вторая часть идеи. Тут предлагали дать доступ к портам, но можно по другому. Программа создаёт массив из 10 байт и вызывает функцию SetKeyBuffer(keys); Теперь обработчик прерывания видит, что задан буфер клавиш и читает порты клавиатуры и считанное заносит в этот буфер в соответствующие байты. Т.е., получаем в байтах массива нажатые кнопки с каждой полустроки клавиатуры. В 9 и 10 байты занести считанное значение порта джойстика. В итоге, всё под рукой и можно легко узнать какая клавиша нажата. Можно даже в обработчике инвертировать считанный байт, чтобы установленный бит означал нажатую клавишу. Ну это не обязательно.
В конце программа вызывает функцию ReleaseKeyBuffer;, которая обнуляет свой указатель на массив и обработчик прерывания более не заполняет его.

Oleg N. Cher
19.08.2016, 17:24
Посмотрите как устроен буферизованный ввод с клавиатуры в ZXDev. Применяется буфер на 8 клавиш, обработчик повешен на прерывание, поэтому пользователь может нажать и отпустить клавишу между опросами, её нажатие всё равно будет зафиксировано. Также работает автоповтор.

• https://github.com/Oleg-N-Cher/XDev/blob/master/ZXDev/Lib/C/Input.c

Это примерно то же, что предлагает AzAtom.

Ещё есть универсальная процедура опроса управления, опрашивает джойстики и QAOPSpace, возвращая все (одновременно) нажатые кнопки в виде битового поля. Это для игр. Разумеется, чудес не бывает, и ей присущи все аппаратные ограничения Спектрума на одновременное число нажатых клавиш.

• https://github.com/Oleg-N-Cher/XDev/blob/master/ZXDev/Lib/C/Control.c

AzAtom
22.08.2016, 12:00
Обновил генератор спрайтов. http://zx-pk.ru/threads/24967-zx-like-pascal.html?p=882316&viewfull=1#post882316

Теперь
- графически отображает выделенный спрайт для удобного разрезания картинки,
- в конце массива пишет количество получившихся байт,
- добавлена возможность преобразования спрайта в текстовом виде обратно в картинку и её сохранение.

- - - Добавлено - - -

Ещё идея насчёт спрайтов.

На настоящий момент нет поддержки анимации. Чтобы например ГГ ходил нужно задать несколько отдельных спрайтов и печатать их по очереди.
Предлагаю сделать мультиспрайт, который является одним массивом, но содержит подряд несколько спрайтов, подобно тому, как я здесь (http://zx-pk.ru/threads/24967-zx-like-pascal.html?p=882356&viewfull=1#post882356) объединил спрайты карты.
Спрайты должны быть одинакового размера в байтах. В массиве байты 0 и 1 содержат 16 битное число - размер одного спрайта в байтах. Емнип, спрайты могут состоять из 255*11+1 = 2806 байт, поэтому, одним байтом не обойтись.
Спрайты имеют номера от 0 и выше. В процедуры вывода спрайтов ввести ещё один параметр - номер выводимого спрайта, например SpritePutClear(<sprite name>,<sprite index>,<x>,<y>);
Тогда мультиспрайт анимации ГГ может содержать, например:
0 - исходное положение (стоит),
0, 1, 2, 3 - фазы хождения,
0, 4, 5 - фазы приседания,
0, 4, 6 - фазы прыжка,
0, 7 - фазы стрельбы,
0, 4, 8 - фазы умирания.
При желании можно несложно сделать кучу фаз движений, как в "Принц Персии".
Мультиспрайт гранаты может содержать фазы её вращения при полёте, мультиспрайт бочки может содержать фазы взрыва.

Спрайты карты тоже можно задать как один мультиспрайт с кучей спрайтов. И чтобы не плодить разных функций можно оставить только мультиспрайты.
Можно даже не переделывать названия функций.
Думаю, удобно получится, а размер увеличится всего на 2*(количество мультиспрайтов) байт, т.е., не так уж и много.

Andrew771
23.08.2016, 11:01
Предлагаю сделать мультиспрайт, который является одним массивом, но содержит подряд несколько спрайтов
Классная идея. Теперь тогда можно сделать единый формат для спрайтов и спрайтов карт. Только размер каждого спрайта в мультиспрайте вот думаю, сделать одинаковыми или может быть различным (для экономии памяти, чтобы не хранить пустые знакоместа). Можно вообще сделать прямоугольными, тогда координаты каждого знакоместа не надо хранить. Но могут попадаться пустые знакоместа - 8-9 байт лишнего хранения на каждое.

Про начальный адрес компиляции 23900 думал. Не буду всё-таки делать его изменение из программы, т.к. будет хаос. Виртуальный экран занимает свою область памяти. А еще когда будут введены параметры процедур, нужно будет под стек серьезно память расширить. Лучше пусть компилятор это распределяет, а не пользователь. Да и зачем сдвигать 23900, планируется на Бейсике еще что-то писать до Паскаля? :)
Если уж так надо, меняй адрес компиляции вручную в скомпилированном файле, как сейчас.

Чтение клавиатуры. Думаю, сделать процедуру без параметров Readkey, которая заполняет буфер нажатых клавиш (пусть будет 10). А потом можно проверять переменную key, нажата ли какая-либо клавиша из буфера или нет:

Readkey;
if key='q' and key='p' then ... {движение вверх-вправо}

Спрайт-генератор включу в дистрибутив ZX Like Pascal, удобный.

AzAtom
23.08.2016, 15:36
Я тут подумал, даже не нужно указывать размер спрайта в байтах, он же просто вычисляется 1+количество знакомест*размер знакоместа (10 или 11 в зависимости от наличия атрибута). Просто главное, чтобы размеры в байтах были одинаковые, иначе скорость вычисления смещений может замедлится заметно.


Только размер каждого спрайта в мультиспрайте вот думаю, сделать одинаковыми или может быть различным (для экономии памяти, чтобы не хранить пустые знакоместа)
Ну у тебя же знакоместо может находится в любом месте спрайта и они не должны быть прямоугольными. Просто при прыжке спрайт может быть более высоким и там будут нарисованы руки, при стрельбе может торчать сбоку знакоместо с оружием, при беге знакоместо будет содержать ноги. Главное, чтобы количество знакомест было одинаковым в одном мультиспрайте.


Да и зачем сдвигать 23900, планируется на Бейсике еще что-то писать до Паскаля?
Я хотел один проект сделать, который должен жить и работать с 32768. :) А до него ещё одну программу уместить. В общем, 2 программы, одновременно, одна с нынешнего адреса, вторая с 32768.


Спрайт-генератор включу в дистрибутив ZX Like Pascal, удобный.
Спасибо. Конечно, тут напрашивается и некий редактор, но тогда проще будет прикрутить к готовому редактору сохранение в текстовом виде. :)

- - - Добавлено - - -

Ещё идея про клавиши. Обработчик клавиатуры опрашивает клавиатуру и складывает в специальный массив все нажатые кнопки, хоть 10, хоть 20 штук. Туда входят и кнопки джойстика.

Программисту доступны функции:
- функция function ReadKey(flag:byte):byte;, которая возвращает код нажатой клавиши и во флаге признаки нажатых шифтов. Коды всегда соответствуют большим буквам как в таблице из мануала. По анализируя флаг программа уже может сделать прописные буквы и т.д. Можно организовать как буфер, т.е., при нажатии программа считывает код один раз, при автоповторах тоже по одному разу. Как в турбопаскале, в общем.

- функция function KeyPressed:boolean; - аналог турбопаскалевской функции.

- функция function KeyPressed(key:byte):boolean; - возвращает, нажата ли сейчас клавиша с кодом в key, ищет во всём массиве, это должно быть быстро, вроде и команда такая есть у процессора.

Кнопкам джойстика тоже надо дать коды.

В результате, программу можно писать так:
В программе есть переменные для кодов клавиш, например kleft, kright, kup,kdown,kfire,kexit:byte;
раздел переопределения управляющих клавиш может выглядеть так:
TextOut(5,5,'Нажмите "Налево"'); потом kleft:=ReadKey(kflag);, и т.д.

А во время игры просто проверка нажатия влево: if KeyPressed(kleft) then begin ... end; и так для каждой нужной клавиши.

Так думаю программисту будет проще, не нужно самому ковыряться в массивах и буферах с кучей кода и клавиатура с джойстиком программой видятся совершенно одинаково.

Reobne
23.08.2016, 16:11
if key='q' and key='p' then
Это антинаучно! :)

AzAtom
23.08.2016, 17:40
Ещё хорошо бы спектрум-специфические функции реализовать в отдельном модуле, функции работы со спрайтами, с экраном, вывод звука, ввод с клавиатуры. И тогда мы могли бы назвать модули одинаково и можно будет в дельфи компилировать под windows, в турбопаскаль компилировать под DOS, а в ZX Like Pascal компилировать под спектрум и всё это вообще без изменения кода.
Хорошо бы, и у тебя ввести процедуры Init и Deinit, тогда можно будет без изменения кода перекомпилировать. В принципе, в дельфи получается и без них, но тогда флаги не передать.

- - - Добавлено - - -


Спрайт-генератор включу в дистрибутив ZX Like Pascal, удобный.
Перекачай, исправил пару небольших ошибок. http://zx-pk.ru/threads/24967-zx-like-pascal.html?p=882316&viewfull=1#post882316

- - - Добавлено - - -

Andrew771, можешь расписать принцип работы функции MapSearch? Мне осталось реализовать её и SounfEffect, тогда можно будет пробовать компилировать и в delphi и в zx like pascal.

Reobne
23.08.2016, 17:48
функция function ReadKey(flag:byte):byte;, которая возвращает код нажатой клавиши
Я-бы посоветовал не перегружать ReadKey таким образом. ReadKey уже описана в мануалах и привычна. Она возвращает была ли нажата и возможно давно отжата клавиша. А нам нужно узнать давится-ли клавиша прямо сейчас. Если не понравилось моё GetKeyState (http://zx-pk.ru/threads/24967-zx-like-pascal.html?p=882305&viewfull=1#post882305), придумайте новое, может KeyDown?
И всётаки считаю лучшим вариант с виртуальными кодами:
Есть текстовой слой, связка KeyPressed и ReadKey; для ввода текста, с нужным регистром. Всё чётко, научно и без граблей.
(Возможно добавить процедуры инициализации клавиатуры, процедуры обслуживания по таймеру 50 герц)

И есть слой "кнопочный", ближе к железу; для игрового процесса;
GetKeyState(VirtualKeyCode:word):boolean;

Например "IF GetKeyState(VirtualKeyCode) then ", где VirtualKeyCode 16-битная константа, должно компилится в
LD A,HI(VirtualKeyCode)
IN A,($FE)
AND LO(VirtualKeyCode)
JP NZ,SKIP_NNN

И GetVirtualKeyCode:word вернёт код нажатой сейчас клавиши, в готовом формате для GetKeyState.[/QUOTE]
Например TextOut(5,5,'Нажмите "Налево"'); kleft:=ReadKey(kflag); wkleft:=GetVirtualKeyCode; TextOut(5,15,kleft);
И в игре вызывать её:
IF GetKeyState(wkleft) then
LD HL,(wkleft)
LD A,H
IN A,($FE)
AND L
JP NZ,SKIP_NNN

Andrew771
23.08.2016, 21:49
Ещё хорошо бы спектрум-специфические функции реализовать в отдельном модуле, функции работы со спрайтами, с экраном, вывод звука, ввод с клавиатуры. И тогда мы могли бы назвать модули одинаково и можно будет в дельфи компилировать под windows, в турбопаскаль компилировать под DOS, а в ZX Like Pascal компилировать под спектрум и всё это вообще без изменения кода.
Это я изначально не планировал, думал только под Спектрум. Сейчас Oleg N.Cher поругается.


Andrew771, можешь расписать принцип работы функции MapSearch?
В мануале описан, цитирую:


MapSearch(<x>,<y>,<id element>,<id condition>,<distance>,<value variable>,<x variable>,<y variable>)

Поиск элемента (значения клетки) на карте вокруг исходной клетки <x>,<y> карты. Параметры карты должны быть предварительно заданы в операторе MapSet.
<x> - горизонтальная координата исходной клетки карты, может быть <arithmetic expression>.
<y> - вертикальная координата исходной клетки карты, может быть <arithmetic expression>.
<id element> - значение элемента (клетки карты), которое необходимо найти, может быть <arithmetic expression>.
<id condition> - условие поиска элемента (0 – равно значению элемента, 1 – не равно значению элемента, 2 – меньше значения элемента, 3 – больше или равно значению элемента), может быть <arithmetic expression>.
<distance> - расстояние в клетках от исходной клетки карты, может быть <arithmetic expression>.
<value variable> - имя переменной типа Byte, в которую запишется количество найденных элементов (если не найдены, то 0).
<x variable> - имя переменной типа Byte, в которую запишется горизонтальная координата ближайшего найденного элемента (если не найдены, то 0).
<y variable> - имя переменной типа Byte, в которую запишется вертикальная координата ближайшего найденного элемента (если не найдены, то 0).
Т.е., поиск определенного значения клетки карты вокруг клетки с координатами x,y на расстоянии distance в прямоугольной области. Можно просто искать конкретное значение клетки, а можно все не равные этому значению, или все клетки с бОльшим значением, или все клетки с меньшим значением. Нужно указать имена переменных <value variable>, <x variable>, <y variable>, куда запишется найденное количество подходящих клеток, удовлетворяющих условию поиска, а также ближайшие к искомой клетке координаты клетки с подходящим значением.
Например, найти вокруг клетки с координатами 12,16 в прямоугольной области 10х10 клеток значение клетки 8:
MapSearch(12,16,8,0,10/2,value,x,y)
После выполнения в value запишется количество найденных клеток со значением 8, а в x,y - ближайшая клетка со значением 8.

- - - Добавлено - - -


Я-бы посоветовал не перегружать ReadKey таким образом. ReadKey уже описана в мануалах и привычна. Она возвращает была ли нажата и возможно давно отжата клавиша. А нам нужно узнать давится-ли клавиша прямо сейчас. Если не понравилось моё GetKeyState, придумайте новое, может KeyDown?
да, пока думаю. Оптимальное не найдено, но хочется что-то простое.
Имеется буфер с заполненными нажатыми клавишами. Нужно проверить конкретную клавишу, есть ли она там. Всё.

AzAtom
25.08.2016, 12:38
поиск определенного значения клетки карты вокруг клетки с координатами x,y на расстоянии distance в прямоугольной области.
Ага, так понятнее.

Насчёт звука вопрос. Если передать в SoundEffect(0,0,0); это же будет самый длинный звук, да? Сколько секунд длится самый длинный звук?


И GetVirtualKeyCode:word вернёт код нажатой сейчас клавиши, в готовом формате для GetKeyState.
Т.е., чтобы VirtualKeyCode код содержал и адрес порта? Ну что-то в этом есть, да, но это привязка к конкретному железу, виртуальные коды могут быть несовместимые или обязательно для всех спектрумов одинаковые?


Если не понравилось моё GetKeyState, придумайте новое
В принципе, я тоже похожее предложил, только использовать не виртуальный 2 байтовый код клавиши, а 1 байтный вроде скан-кода клавиши, где не учитываются регистры букв, всё равно столько клавиш нет, кодов хватит и на джойстики тоже.
Читать не именно в текущий момент, а обработчик прерывания опрашивает клавиатуру и заполняет некий буфер. Функция KeyPressed(key:byte):boolean; ищет уже в этом массиве. Команда CPIR поможет. Правда, такая система занимает больше времени, но коды клавиш могут быть одинаковые для любой реализации клавиатуры и джойстиков.

- - - Добавлено - - -


Имеется буфер с заполненными нажатыми клавишами. Нужно проверить конкретную клавишу, есть ли она там. Всё.
Тоже думаю, что так будет лучше. Надо только добавить коды джойстиков.

- - - Добавлено - - -

Andrew771, про MapSearch. Если найдено 2 удовлетворяющие условиям ячейки, например, слева и справа на расстоянии 1, координаты которой будут возвращены? А если справа и справа-сверху, то которые координаты будут возвращены?

Reobne
25.08.2016, 16:38
В принципе, я тоже похожее предложил ...
Я всё это так сразу и понял.
А сам кажется остался непонят. Говорю, лучше новое название придумать. Говорю, KeyPressed лучше не перегружать (https://ru.wikipedia.org/wiki/%D0%9F%D0%B5%D1%80%D0%B5%D0%B3%D1%80%D1%83%D0%B7%D 0%BA%D0%B0_%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D0%B4%D1 %83%D1%80_%D0%B8_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0 %B8%D0%B9). А то кто нибудь найдёт/помнит описание оригинального KeyPressed и удивится. Грабли, как-бы ударили по лбу, и вместо дела человек сидит с открытым ртом. Граблей лучше не делать. Ведь не трудно придумать новое название. KeyDown(%влево%) - кнопка внизу. Всё сразу понятно.

А второй мой тезис о том, что мне не очень нравится, если компилятор за меня решит, что надо обязательно опрашивать все клавиши, складывать их в массив, чтобы потом использовать только 5-7 элементов из 40. Навязанная расточительность.
Программисты ZX обычно имеют представление о клавиатуре. Она же описана во многих книжках. Приятно применить свои знания. Приятно самому написать процедуру прерывания, на новом паскале. Опросить только нужные клавиши. Запомнить их там, где хочешь сам. ИМХО, конечно.

AzAtom
25.08.2016, 17:01
KeyPressed лучше не перегружать
Я специально предложил такое название, чтобы было с перегрузкой. Помнит KeyPressed - пусть его пишет, будет делать то же самое, что и в турбо, а новая версия позволит уточнить, нажата ли конкретно эта клавиша.


Приятно самому написать процедуру прерывания, на новом паскале.
Ещё и опрос с обработчиком прерывания самому писать? Ну его... :)


мне не очень нравится, если компилятор за меня решит, что надо обязательно опрашивать все клавиши, складывать их в массив, чтобы потом использовать только 5-7 элементов из 40.
Ну бейсик так изначально делает и ничего. :)

- - - Добавлено - - -

Andrew771, кстати, тригонометрических функций не предвидится? В играх ведь и по синусоиде захочется пустить врагов и прочих товарищей...

Andrew771
26.08.2016, 11:40
На этих выходных буду делать корректировки. На прошлых не успел.


Приятно самому написать процедуру прерывания, на новом паскале.
Ещё и опрос с обработчиком прерывания самому писать? Ну его...
Да, это доверять пользователю нельзя. Т.к. многие не знают асма.



Andrew771, кстати, тригонометрических функций не предвидится? В играх ведь и по синусоиде захочется пустить врагов и прочих товарищей...
Неа. Таблицы в массивах создавай. А то так и до 3D дойдем :) Неэффективно это на ЯВУ.

- - - Добавлено - - -


Andrew771, про MapSearch. Если найдено 2 удовлетворяющие условиям ячейки, например, слева и справа на расстоянии 1, координаты которой будут возвращены? А если справа и справа-сверху, то которые координаты будут возвращены?
не помню. Нужно залезть в асмовскую процедуру в библиотеке и посмотреть, сейчас на работе, некогда.

- - - Добавлено - - -


Насчёт звука вопрос. Если передать в SoundEffect(0,0,0); это же будет самый длинный звук, да? Сколько секунд длится самый длинный звук?
то же

Reobne
26.08.2016, 11:55
>>Приятно самому написать процедуру прерывания, на новом паскале.
Да, это доверять пользователю нельзя. Т.к. многие не знают асма.
Ты имеешь ввиду, не знают прерываний?
Ведь асм знать не обязательно. Вот на delphi, не нужно знать ассемблер, чтобы бросить на форму компонент Timer, и написать на паскале его событие onTimer.
ZX программер знает про 50 герц прерывания. Я почти уверен. Про него даже в википедии должно быть написано.

AzAtom
02.09.2016, 16:40
Наконец, решил попробовать скомпилировать свою программу и скормить программу эмулятору спектрума.
Компилятор ZX Like Pascal выдал asm файл, передаю его sjasm, он вроде компилирует, пишет 3 прохода, 0 ошибок и ничего не выводит в файл. Кто чем компилировал и получилось?

- - - Добавлено - - -

Оказывается, в начале ASM файла надо вставить тип железа вида "DEVICE ZXSPECTRUM128", а в конце ASM файла надо вставлять команду "savesna" или подобную. .sna файл не заработал на эмуляторе, пару спрайтов отобразил, двигается медленнее, чем надо, а при нажатии на клавиши спек перезагружается.

Мне бы .tap собрать. Как это сделать?

Andrew771
02.09.2016, 16:54
Это надо спрашивать у тех, кто пользуется sjasm. Я пользуюсь эмулятором со встроенным ассемблером EmuZWin.

AzAtom
02.09.2016, 18:10
Ну вот, там тоже неправильно.

Приложил картинки, так должно быть 58040, так получилось 58041. Исходник:


program TestZXPas;

var
x,y,ggx,ggy:word;
k1,k2:byte;
bally,balldy,balldir:word;
bx,by,bcnt:word;
map:arraybyte[24,32];

begin

border(0);
textbackground(0);
textcolor(7);
clrscr;
VirtScreenClear;

MapSet(MAP,MAPSPRA,0,0,32,24);

x:=4;
y:=1;
bally:=4;
balldy:=1;
balldir:=1;
ggx:=2;
ggy:=16;
bx:=0;
by:=30;
bcnt:=0;
repeat
ReadKey(k1,k2);
if (bally>19) or (bally<4) then begin
if balldir=1 then balldir:=2
else balldir:=1;
end;
if (k1=80) or (k2=80) then
ggx:=ggx+1;
if (k1=79) or (k2=79) then
ggx:=ggx-1;
if ggx+5>29 then
ggx:=29-5;
if ggx < 2 then
ggx:= 2;

MapPut(0,0);
SpritePutClear(ball3a,12,2);
SpritePutMirrorClear(ball3a,16,2);
SpritePutClear(COLORSA,14,5);
SpritePutClear(ball3a,10,bally);
SpritePutAnd(GG1MA2,ggx,ggy);
SpritePutOr(GG1A,ggx,ggy);
{ TextOut(2,0,'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
TextOut(2,1,'0123456789+-=<>');
TextOut(20,2,'TEXT TEST');}

if (k1=32) or (k2=32) then
if bcnt=0 then begin
by:=ggy+2; {// Пуля на 2 знакоместа ниже ГГ}
bx:=ggx+6; {// И на 6 знакомест правее ГГ}
bcnt:=20;
end;
if bcnt<>0 then begin
SpritePutAnd(BULLET1M,bx,by);
SpritePutOr(BULLET1,bx,by);
if bx<32 then
bx:=bx+2;
bcnt:=bcnt-1;
end;
if (k1=50) or (k2=50) then SpritePutClear(DIG2A,6,4) else SpritePutClear(DIG0A,6,4);
if (k1=49) or (k2=49) then SpritePutClear(DIG1A,4,4) else SpritePutClear(DIG0A,4,4);
VirtScreenPut;
Delay(1);
if balldir=1 then bally:=bally+balldy;
if balldir=2 then bally:=bally-balldy;
until (k1=48) or (k2=48) or (k1=69) or (k2=69){ or not ZXInitialized};
ScreenThaw;
Delay(20);

end.

GG1A
DEFB 36
DEFB 0,0, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 0,1, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 0,2, #04, #0F,#07,#03,#03,#07,#1D,#F6,#9B
DEFB 0,3, #04, #FC,#FE,#FF,#EA,#FF,#F5,#FF,#FF
DEFB 0,4, #04, #00,#00,#00,#00,#00,#80,#80,#80
DEFB 0,5, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 1,0, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 1,1, #04, #03,#07,#06,#0E,#0F,#1F,#3F,#3F
DEFB 1,2, #04, #ED,#77,#B7,#BF,#7F,#ED,#F6,#7B
DEFB 1,3, #04, #E3,#F0,#F8,#F8,#FC,#FC,#FE,#5F
DEFB 1,4, #04, #80,#00,#00,#00,#00,#00,#00,#00
DEFB 1,5, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 2,0, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 2,1, #04, #7F,#7E,#7C,#3F,#3F,#1F,#0F,#07
DEFB 2,2, #04, #68,#DF,#FE,#FD,#5E,#FF,#F5,#EF
DEFB 2,3, #04, #01,#FF,#47,#FF,#7F,#EA,#67,#F3
DEFB 2,4, #04, #0C,#FF,#FF,#AA,#FF,#E0,#E0,#80
DEFB 2,5, #04, #40,#F0,#F0,#BC,#E0,#40,#38,#00
DEFB 3,0, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 3,1, #04, #03,#00,#00,#00,#00,#01,#01,#01
DEFB 3,2, #04, #1F,#FF,#FF,#FF,#FF,#FC,#FC,#FC
DEFB 3,3, #04, #F8,#FC,#FE,#FF,#FF,#FF,#7F,#1F
DEFB 3,4, #04, #00,#00,#00,#00,#80,#C0,#E0,#F0
DEFB 3,5, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 4,0, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 4,1, #04, #01,#01,#03,#07,#0E,#1D,#33,#67
DEFB 4,2, #04, #78,#B8,#70,#F0,#F0,#E0,#C0,#80
DEFB 4,3, #04, #0F,#03,#01,#01,#00,#00,#00,#00
DEFB 4,4, #04, #B8,#58,#B0,#F8,#B8,#B8,#D8,#5C
DEFB 4,5, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 5,0, #04, #00,#00,#00,#01,#01,#01,#01,#01
DEFB 5,1, #04, #CE,#DC,#F8,#F0,#70,#F8,#FE,#7F
DEFB 5,2, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 5,3, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 5,4, #04, #6C,#2C,#3C,#3C,#2E,#7F,#7F,#67
DEFB 5,5, #04, #00,#00,#00,#00,#00,#80,#E0,#F0

GG1MA2
DEFB 36
DEFB 0,0, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 0,1, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FE,#FC
DEFB 0,2, #04, #E0,#F0,#F8,#F8,#F0,#00,#00,#00
DEFB 0,3, #04, #01,#00,#00,#00,#00,#00,#00,#00
DEFB 0,4, #04, #FF,#FF,#7F,#FF,#7F,#3F,#3F,#3F
DEFB 0,5, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 1,0, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 1,1, #04, #F8,#F0,#F0,#E0,#E0,#C0,#80,#80
DEFB 1,2, #04, #00,#00,#00,#00,#00,#00,#00,#00
DEFB 1,3, #04, #00,#04,#03,#03,#01,#01,#00,#00
DEFB 1,4, #04, #3F,#7F,#FF,#FF,#FF,#FF,#FF,#73
DEFB 1,5, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#BF
DEFB 2,0, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 2,1, #04, #00,#00,#00,#80,#80,#C0,#E0,#F0
DEFB 2,2, #04, #00,#00,#00,#00,#00,#00,#00,#00
DEFB 2,3, #04, #00,#00,#00,#00,#00,#00,#00,#00
DEFB 2,4, #04, #00,#00,#00,#00,#00,#00,#0F,#1F
DEFB 2,5, #04, #0F,#07,#03,#01,#03,#07,#83,#C7
DEFB 3,0, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 3,1, #04, #F8,#FC,#FE,#FE,#FE,#FC,#FC,#FC
DEFB 3,2, #04, #00,#00,#00,#00,#00,#00,#01,#01
DEFB 3,3, #04, #00,#01,#00,#00,#00,#00,#00,#80
DEFB 3,4, #04, #7F,#FF,#FF,#7F,#3F,#1F,#0F,#07
DEFB 3,5, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 4,0, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 4,1, #04, #FC,#FC,#F8,#F0,#E0,#C0,#80,#00
DEFB 4,2, #04, #03,#03,#07,#07,#07,#0F,#1F,#3F
DEFB 4,3, #04, #E0,#F0,#FC,#FC,#FE,#FE,#FE,#FF
DEFB 4,4, #04, #03,#03,#07,#03,#03,#03,#03,#01
DEFB 4,5, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 5,0, #04, #FE,#FE,#FE,#FC,#FC,#FC,#FC,#FC
DEFB 5,1, #04, #00,#01,#03,#07,#07,#01,#00,#00
DEFB 5,2, #04, #7F,#FF,#FF,#FF,#FF,#FF,#FF,#7F
DEFB 5,3, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 5,4, #04, #01,#81,#81,#81,#80,#00,#00,#00
DEFB 5,5, #04, #FF,#FF,#FF,#FF,#7F,#1F,#0F,#07

BULLET1
DEFB 1
DEFB 0,0, #07, #00,#00,#00,#7C,#7C,#00,#00,#00

BULLET1M
DEFB 1
DEFB 0,0, #07, #FF,#FF,#81,#81,#81,#81,#FF,#FF

BALL3A
DEFB 6
DEFB 0,0, #01, #00,#07,#1F,#3F,#33,#67,#7F,#7F
DEFB 0,1, #02, #00,#E0,#F8,#FC,#FC,#FE,#FE,#FE
DEFB 0,2, #03, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 1,0, #04, #00,#7F,#6F,#27,#33,#1F,#07,#00
DEFB 1,1, #05, #00,#FE,#FE,#FC,#FC,#F8,#E0,#00
DEFB 1,2, #06, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF

COLORSA
DEFB 8
DEFB 0,0, #00, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 0,1, #01, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 0,2, #02, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 0,3, #03, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 0,4, #04, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 0,5, #05, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 0,6, #06, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF
DEFB 0,7, #07, #FF,#FF,#FF,#FF,#FF,#FF,#FF,#FF

MAPSPRA
DEFB 4
DEFB 0,0, 7, 0, 0, 0, 0, 0, 0, 0, 0
DEFB 0,1, 7, 0, 0, 0, 0, 0, 0, 0, 0
DEFB 1,0, 7, 0, 0, 0, 0, 0, 0, 0, 0
DEFB 1,1, 7, 0, 0, 0, 0, 0, 0, 0, 0
DEFB 4
DEFB 0,0, 7, 85, 1, 1,255, 85, 16, 16,255
DEFB 0,1, 7, 85, 1, 1,255, 85, 16, 16,255
DEFB 1,0, 7, 85, 1, 1,255, 85, 16, 16,255
DEFB 1,1, 7, 85, 1, 1,255, 85, 16, 16,255
DEFB 4
DEFB 0,0, 7, 36, 36, 36, 36, 36, 36, 36, 36
DEFB 0,1, 7, 36, 36, 36, 36, 36, 36, 36, 36
DEFB 1,0, 7, 36, 36, 36, 36, 72,136,136,255
DEFB 1,1, 7, 36, 36, 36, 36, 18, 17, 17,255
DEFB 4
DEFB 0,0, 7, 36, 36, 36, 36, 36, 36, 36, 36
DEFB 0,1, 7, 36, 36, 36, 36, 36, 36, 36, 36
DEFB 1,0, 7, 36, 36, 36, 36, 36, 36, 36, 36
DEFB 1,1, 7, 36, 36, 36, 36, 36, 36, 36, 36
DEFB 4
DEFB 0,0, 7, 127,144,136, 72, 36, 36, 36, 36
DEFB 0,1, 7, 254, 9, 17, 18, 36, 36, 36, 36
DEFB 1,0, 7, 36, 36, 36, 36, 36, 36, 36, 36
DEFB 1,1, 7, 36, 36, 36, 36, 36, 36, 36, 36


_MAP
DEFB 4,3,3,3,3,3,3,3,3,3,2,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 0,0,0,0,0,0,0,1,1,1,1,1
DEFB 0,0,0,0,0,0,0,1,1,1,1,1
DEFB 0,0,0,0,0,0,0,1,1,1,1,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 0,0,0,0,0,0,0,0,0,0,0,1
DEFB 4,3,3,3,3,3,3,3,3,3,2,1

DIG0A
DEFB 1, 0,0, 7, 0, 28, 34, 42, 42, 34, 28, 0

DIG1A
DEFB 1, 0,0, 7, 0, 24, 56, 24, 24, 24, 60, 0

DIG2A
DEFB 1, 0,0, 7, 0, 60, 66, 2, 28, 32,126, 0


Andrew771, что тут может быть не так? Вроде массивы верно заданы.

- - - Добавлено - - -

Andrew771, да, предлагаю кроме write ввести ещё и TextOut(x,y:word;text:string); В принципе, я его реализовал в своём модуле, используя твой шрифт. Только пока забыл верхнюю и нижнюю строки символа заполнить нулём. :)

Как разберусь с этим кривым выводом, тогда можно будет модуль тоже показывать миру.

- - - Добавлено - - -

Название карты меня смущает, но вроде делал, как в примере.

Andrew771
04.09.2016, 22:03
1. Размер массива map для карты неверен (должен быть 16х12 клеток, если на весь экран, т.к. каждая клетка 2х2 знакоместа).
2. В процедуре MapSet два последних параметра должны быть 16,12 - столько клеток карты умещается на весь экран.
3. Формат спрайтов карты неверный, см. в мануале.
4. Данные карты почему-то перевернуты на бок. Должно быть 12 строк по 16 байт.
5. Процедура MapPut должна быть с 1,1, а не 0,0. Указываются координаты (индексы) клетки в массиве. А индексов 0,0 не бывает.

AzAtom
05.09.2016, 00:04
3. Формат спрайтов карты неверный, см. в мануале.
А, проглядел. Значит, надо будет ввести это дело и в генератор спрайтов.
Спрайты поправил, теперь карта вся чёрная получилась независимо от заданных атрибутов.


4. Данные карты почему-то перевернуты на бок. Должно быть 12 строк по 16 байт.
Учту в модуле. Делал так, потому что в паскале при задании двумерного массива в памяти идут подряд элементы [0,0], [0,1], [0,2], потом [1,0], [1,1], [1,2], ... а в модуле двумерный массив передаётся в виде одномерного, вот так и решил вопрос. Переделаю под одномерный, его даже будет проще задавать.

Andrew771
05.09.2016, 13:48
Andrew771, что тут может быть не так? Вроде массивы верно заданы.

Спрайты поправил, теперь карта вся чёрная получилась независимо от заданных атрибутов.
Еще ошибка - MapPut должна быть с 1,1, а не 0,0. Указываются координаты (индексы) клетки в массиве. А индексов 0,0 не бывает.

AzAtom
05.09.2016, 14:23
Andrew771, ааа, вот почему карта не отображалась :) Теперь работает. Внесу соответствующие изменения и комментарии в модуль.

Обнаружились проблемы.
- Частота кадров очень низкая получается на спектруме. Даже не знаю, что тут можно сделать.
- После примерно минуты работы той моей тестовой программы спектрум виснет/перезагружается.

- - - Добавлено - - -

Andrew771, хорошо бы объявление массивов сделать как на турбопаскале. Можно ввести ограничение, чтобы первый элемент всегда указывался 1 и размерность не больше 2, иначе компилятор будет выдавать ошибку. Плюс добавить инициализацию массива при объявлении. Тогда не нужно будет спрайты и карты пихать после end., и разработка с моим модулем тоже упроститься, не нужно будет переносить код спрайтов туда-сюда, плюс не нужно будет в .asm файле убирать повторное объявление массива карты.

Andrew771
07.09.2016, 17:12
- Частота кадров очень низкая получается на спектруме. Даже не знаю, что тут можно сделать.
Если на экране мало спрайтов двигается между кадрами, то может проще не использовать виртуальный экран, а стирать спрайт на старом месте и выводить на новом (команды WindowGet и WindowPut).


- После примерно минуты работы той моей тестовой программы спектрум виснет/перезагружается.
Фиг знает, нужно искать причину. Стек не переполняется? Память не расходуется полностью?



Andrew771, хорошо бы объявление массивов сделать как на турбопаскале. Можно ввести ограничение, чтобы первый элемент всегда указывался 1 и размерность не больше 2, иначе компилятор будет выдавать ошибку. Плюс добавить инициализацию массива при объявлении. Тогда не нужно будет спрайты и карты пихать после end., и разработка с моим модулем тоже упроститься, не нужно будет переносить код спрайтов туда-сюда, плюс не нужно будет в .asm файле убирать повторное объявление массива карты.
Это да, остается найти время. Еще хотел сделать единый формат спрайтов и спрайтов карт.



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

AzAtom
07.09.2016, 21:37
Стек не переполняется? Память не расходуется полностью?
Думаю нет. Использую только функции из zx like pascal, сам со стеком или памятью не работаю.


Еще хотел сделать единый формат спрайтов и спрайтов карт.
Классно будет.

Видел твою заготовку-тест для игры Z, классно. Только карты там 4х4 знакоместа и под них дополнительно процедура написана. Может, лучше ввести их в стандартную поставку? Например, назвать MapSet2 (или 2x2), MapSet4 (или 4x4), MapPut2, MapPut4 соответственно.


стирать спрайт на старом месте и выводить на новом (команды WindowGet и WindowPut).
Можно попробовать, но так будет мерцание.
Теоретически можно как-то продумать, чтобы восстановление прежнего фона, запоминание фона на новом месте и вывод нового спрайта производились одновременно, т.е., восстановили байт фона, запомнили байт фона в новом месте, вывели байт спрайта и т.д.

Ещё можно помечтать о реализации сцены, когда координаты спрайтов задаются в самих спрайтах, устанавливается окно просмотра и вызывается процедура вывода, которая побайтово или посимвольно выводит байты именно видимых в этом месте (знакоместе) спрайтов.

Reobne
08.09.2016, 05:43
Стек не переполняется? Память не расходуется полностью?
Если правда интересна:), надо просто взять, и посмотреть в отладчике.
Выложите снапшот, все вместе посмотрим.

AzAtom
08.09.2016, 11:07
Интересно. Вот снапшот58105.

- - - Добавлено - - -

На спектруме я делаю CLEAR 24888, меняю в асме ORG 24900, компилирую и запускаю.
23900, как исходно в программе, не получается. Если сделать CLEAR 23888, то потом не хватает памяти выполнить команду запуска.

Reobne
08.09.2016, 17:17
По адресу $6257 стоит PUSH, и то что что он PUSHает уже не POPается.

- - - Добавлено - - -

Для ориентировки:
LD HL,(7533H) ;6231 2A3375
INC HL ;6234 23
LD (7533H),HL ;6235 223375
LD A,4FH ;6238 3E4F
LD HL,7537H ;623A 213775
CP (HL) ;623D BE
JP NZ,6244H ;623E C24462
JP 624DH ;6241 C34D62
; 6244 - jump/call references:
; JP from 623EH
LD A,4FH ;6244 3E4F
LD HL,7538H ;6246 213875
CP (HL) ;6249 BE
JP NZ,6254H ;624A C25462
; 624D - jump/call references:
; JP from 6241H
LD HL,(7533H) ;624D 2A3375
DEC HL ;6250 2B
LD (7533H),HL ;6251 223375
; 6254 - jump/call references:
; JP from 624AH
LD HL,(7533H) ;6254 2A3375
PUSH HL ;6257 E5 <--------***ТУТ!***---------
LD HL,0005H ;6258 210500
LD DE,001DH ;625B 111D00
EX DE,HL ;625E EB
AND A ;625F A7
SBC HL,DE ;6260 ED52
JP NC,626DH ;6262 D26D62
POP DE ;6265 D1
ADD HL,DE ;6266 19
LD HL,0018H,GET_CHAR ;6267 211800
LD (7533H),HL ;626A 223375
; 626D - jump/call references:
; JP from 6262H
LD HL,(7533H) ;626D 2A3375
LD DE,0002H ;6270 110200
EX DE,HL ;6273 EB
AND A ;6274 A7
SBC HL,DE ;6275 ED52
JP Z,6283H ;6277 CA8362
JP C,6283H ;627A DA8362
LD HL,0002H ;627D 210200
LD (7533H),HL ;6280 223375
; 6283 - jump/call references:
; JP from 6277H, 627AH
LD A,01H ;6283 3E01
LD (7517H),A ;6285 321775
LD (7518H),A ;6288 321875
CALL 6F2AH ;628B CD2A6F

AzAtom
09.09.2016, 22:25
Так вот оно что, я только количество PUSH и POP проверил, совпадало. Т.е., получается команды
JP NC,626DH ;6262 D26D62
POP DE ;6265 D1
нужно поменять местами?

- - - Добавлено - - -

Чуть позже попробую.

- - - Добавлено - - -

Andrew771, нашли ошибку.
Код, который нашёл Reobne соответствует участку в сгенерированном asm:

L16
L17
ld hl,(_GGX)
push hl
ld hl,5
ld de,29
ex de,hl
and a
sbc hl,de
jp nc,L18
pop de
add hl,de
L19
ld hl,24
ld (_GGX),hl


и его исходный код на паскале:

if ggx+5>29 then
ggx:=29-5;


Я-то попробую попроще написать, но ошибка налицо.

- - - Добавлено - - -

Переделал на

if ggx>29-5 then
ggx:=29-5;


теперь генерирует

L16
L17
ld hl,(_GGX)
ld de,29
ex de,hl
and a
sbc hl,de
jp nc,L18
ld de,5
and a
sbc hl,de
L19
ld hl,24
ld (_GGX),hl

что тоже неправильно, потому что надо сравнивать сразу с 24, а 5 вообще не к месту. В общем, ошибка при вычислении выражений в условии.

Ещё раз переделал на

if ggx>24 then
ggx:=24;

Теперь, вроде, правильно сгенерировал код. Единственное, осталось непонятно, зачем загружать не в нужные регистры и затем обменивать их содержимое для сравнения.

- - - Добавлено - - -

Ещё есть пожелание программу завершать не "jp $", а просто "ret".

- - - Добавлено - - -

Нарушен порядок вычисления выражений. Написал if (ggx+5)>29 then ggx:=29-5; и тоже правильно сгенерировал код, загрузил переменную, добавил к ней 5 и сравнил с 29. Надо чтобы сначала вычислялись выражения, затем проводилось сравнение.

AzAtom
14.09.2016, 17:35
Написал на этом паскале процедуру рисования линии и к нему на асме процедуру точки. Всего получилось заполнение экрана 192 линий по 256 точек за 12,4 сек, что соответствует 883 такта на пиксель. Сама процедура точки получилась 315 тактов, она без табличная, адрес "вычисляется" переставлением битов. Больше 500 тактов на пиксель в самом скомпилированном алгоритме линии тоже многовато, но там понятно, под переменные используются не регистры, а память.

- - - Добавлено - - -

Andrew771, планируется ли поддержка мыши?
Можно автоматически устанавливать минидрайвер, который обновляет 3 переменные в памяти, а программа может получить состояние мыши с помощью процедуры ReadMouse(X,Y,B:byte);, где X и Y координаты, а B содержит биты нажатых кнопок, например, бит 0 это левая, бит 1 правая, а бит 2 средняя кнопки.

blackmirror
15.09.2016, 16:32
Написал на этом паскале процедуру рисования линии и к нему на асме процедуру точки. Всего получилось заполнение экрана 192 линий по 256 точек за 12,4 сек, что соответствует 883 такта на пиксель. Сама процедура точки получилась 315 тактов, она без табличная, адрес "вычисляется" переставлением битов. Больше 500 тактов на пиксель в самом скомпилированном алгоритме линии тоже многовато, но там понятно, под переменные используются не регистры, а память.
Очень жаль, что в сообщении нет этого замечательного кода, но если использовать алгоритм Брезенхема, то результаты будут в несколько раз лучше. Судя по наброску на псевдокоде, который не очень сложно перевести на асм, большую часть переменных, необходимых для рисования линии, вполне можно распихать по регистрам. Вычислять для каждой точки адрес в памяти не потребуется, и общее быстродействие без особых усилий можно довести до 150 тактов на точку плюс тактов 500 на вычисления переменных в начале функции:

DRAW_LINE(X1,Y1,X2,Y2):

IF Y2<Y1 //рисовать линию будем с того конца, у которого Y меньше
SWAP(X1,X2)
DY = ABS(Y2-Y1)
Y1 = MIN(Y1,Y2)

IF X2<X1 //правим команды вращения маски и изменения указателя после метки INC_or_DEC
INC_or_DEC = DEC_X
ELSE
INC_or_DEC = INC_X
DX = ABS(X2-X1)

CNT = MAX(DX,DY) //количество точек которые нужно нарисовать
HL = COO_TO_ADR(X1,Y1) //вычисляем байт в котором сидит первая точка
PT = 1 SHL (X1&7) //вычисляем маску точки
ER = 0 //устанавливаем ошибку в ноль

GOTO SET_PT_1

INC_Y:
ER -= DX //корректируем ошибку
H += 1 //смещаемся по Y
IF H AND 7 //в 7 случаях из 8 можно будет нарисовать точку без дальнейшей коррекции
GOTO SET_PT_1
H -= 8 //корректируем указатель и переходим в следующую строку знакомест
L += 32
IF L AND 224
GOTO SET_PT_1
H += 8 //переходим в следующий блок из 8 строк

SET_PT_1:
(HL) |= PT //рисуем точку
IF CNT=0 //проверяем не закончилась ли линия
GOTO EXIT
CNT -= 1
IF ER>=DX //проверяем, можно ли дальше двигаться вдоль оси Y
GOTO INC_Y

INC_or_DEC: //код настроенный в начале процедуры на уменьшение или увеличение X
RRC PT or RLC PT //сдвиг маски
IF CY
INC L or DEC L //изменение указателя
ER+=DY //коррекция ошибки
IF ER>=DX //проверка не нужно ли сместиться по оси Y
GOTO INC_Y

SET_PT_2:
(HL) |= PT //рисуем точку
IF CNT=0 //проверяем не закончилась ли линия
GOTO EXIT
CNT-=1
GOTO INC_or_DEC //переходим у следующей точке

EXIT:

AzAtom
15.09.2016, 16:40
blackmirror, конкретно на этом паскале вот:


procedure DrawLine;
begin
dx:=0;
if (x1-x2)<$8000 then dx:=x1-x2;
if (x2-x1)<$8000 then dx:=x2-x1;
dy:=0;
if (y1-y2)<$8000 then dy:=y1-y2;
if (y2-y1)<$8000 then dy:=y2-y1;

if (x2-x1)<$8000 then dx1:=1 else dx1:=$FFFF;
if (y2-y1)<$8000 then dy1:=1 else dy1:=$FFFF;

if dx>dy then begin
y:=dx / 2;
for i:=dx downto 0 do begin
asm(PUTPIXELA);
y:=y+dy;
if y>dx then begin
y1:=y1+dy1;
y:=y-dx;
end;
x1:=x1+dx1;
end;
end else begin
y:=dy / 2;
for i:=dy downto 0 do begin
asm(PUTPIXELA);
y:=y+dx;
if y>dy then begin
x1:=x1+dx1;
y:=y-dy;
end;
y1:=y1+dy1;
end;
end;
end;


От привычного паскаля отличается тем, что в функции и процедуры параметры не передаются (надеюсь, что только пока не передаются) и для этого используются глобальные переменные X1,Y1,X2,Y2. Процедура адаптирована на использование целочисленных переменных с разрядностью 16 бит, хотя, наверное хватит и 8 бит, если координаты не превышают 0-255. Позже попробую.
Процедура точки PUTPIXELA на асме, берёт координаты из переменных X1 и Y1.

blackmirror
15.09.2016, 17:24
AzAtom, получается, что алгоритмы почти совпадают, а меньшая эффективность только из-за использования паскаля и 16 разрядных переменных. Вообще отсутствие указателей и оператора goto сильно мешает написать эффективный алгоритм рисования линии на чистом паскале. В такой ситуации проще весь алгоритм делать на асме, а не только рисование точки.

AzAtom
16.09.2016, 09:41
blackmirror, интересный вариант. Есть замечания.


PT = 1 SHL (X1&7) //вычисляем маску точки
ER = 0 //устанавливаем ошибку в ноль
Старший бит на экране находится слева, поэтому надо PT = 80h SHR (X1&7),
и ошибку надо в половину смещения: ER = MIN(DX, DY) DIV 2, иначе, линия будет ниже настоящей и последовательные линии будут с длинными ступеньками на стыках.

AzAtom
30.09.2016, 13:18
Наконец, дописал некоторые функции и немного намарафетил свой модуль. Написан по описанию компилятора ZX Like Pascal версии 0.908. 58374
Модуль сделан на Delphi 4.
Имеющиеся несоответствия описаны в самом начале модуля.
- Не реализованы функции write, writeln, read, readln. При их использовании происходит ввод-вывод через консоль и необходима директива компилятора {$APPTYPE CONSOLE}.
- Плохо реализована функция очистки массива. Скорее всего, будет нормально очищать одномерный массив и первую строку двумерного массива.
- Функция SoundEffect выдаёт немного более быстрый звук, чем получается на эмуляторе. Возможно, это связано с тем, что я не учитываю остановки процессора (wait). Так же, продолжительность одного эффекта ограничивается 10 секундами. По алгоритму максимальная длительность звукового эффекта может превышать 10 минут.


Реализованы дополнительные функции, отсутствующие в ZX Like Pascal:
-function ZXInitialized:boolean; // Возвращает true, если графическое окно создано и можно выводить графику.
-procedure TextOut(x,y:word;text:string); // Вывод текста по указанным координатам знакоместа.
-procedure PutPixel(x,y,e:word); // Установка точки по координатам X,Y. E=0 бит сбрасывается, E=1 бит устанавливается.
-procedure Line(x1,y1,x2,y2:word); // Рисование линии от X1,Y1 до X2,Y2. Биты всегда устанавливаются.
-procedure ReadMouse(var x,y,b:word); // Возвращает координаты мыши 0<=X<=255, 0<=Y<=191 и нажатые кнопки в виде 00000MRL.

Так же, в архиве программа, использующая данный модуль и скомпилированный исполняемый файл для windows.

Коротко принцип работы.
Для работы используются 2 массива по 6912 байт, соответствующие экрану настоящего Spectrum. Один является аналогом реального экрана, второй аналог виртуального экрана и все графические функции работают в соответствии с принципами Spectrum.
При инициализации модуля запоминаются режимы работы, которые должны соответствовать установленным галкам компилятора ZX Like Pascal. Так же, запускается вспомогательный поток, в котором создаётся окно и таймер, срабатывающий каждые 32 мс.
По сообщению от таймера происходит преобразование массива с реальным экраном spectrum в windows bitmap, который, затем, отображается на экране.

Andrew771
16.08.2017, 23:47
Обновил версию до 0.909, в первом посте.
Теперь можно:
- инициализировать значения переменных и массивов при объявлении;
- выводить карты не только по 2х2 знакоместа на клетку, но и по 1х1 знакоместо на клетку;
- заменены непривычные ArrayType[N] на стандартные паскалевские Array[1..N] of Type.

Также добавлен Генератор спрайтов ZxSprGen V.2.0.1 от AzAtom, спасибо еще раз огромное тебе!

- - - Добавлено - - -


Нарушен порядок вычисления выражений. Написал if (ggx+5)>29 then ggx:=29-5; и тоже правильно сгенерировал код, загрузил переменную, добавил к ней 5 и сравнил с 29. Надо чтобы сначала вычислялись выражения, затем проводилось сравнение.
Да, со скобками нужно писать. В логических выражениях сейчас всё читается слева направо, если не стоят скобки.

Smalovsky
23.08.2017, 14:55
Когда будет поддержка типов записей?

Andrew771
29.08.2017, 12:39
Когда-нибудь :) Опять времени стало мало на разработку.
А вообще, в ближайших изменившихся планах - поддержка 8-битных вычислений без типа Word (опционально) вместо нынешних 16-битных и для Byte, и для Word.
16-битные вычисления расходуют больше памяти и меньше по быстродействию, но в большинстве динамичных игр Word не нужен или мало используется. Кстати, записи тоже будут тормозить расчет адресов, поэтому отложены на светлое будущее.

Bolt
15.03.2018, 18:30
Когда будет поддержка типов записей?
У меня уже есть :) Работает, правда, всё это очень медленно, но мы и над этим когда-нибудь поработаем :)


type
tPoint=record x,y:byte; end;

procedure putpixel(const point:tPoint);
var
x,y,a:word;
begin
x:=point.x;
y:=point.y;
a:=((y and 7) shl 8) + ((y and $38) shl 2) + ((y and $c0) shl 5);
a:=a+$4000+(x shr 3);
mem[a]:=mem[a] or (128 shr (x and 7));
end;

procedure test_rec;
var
i:byte;
pnt:tPoint;
begin
for i:=1 to 100 do
begin
pnt.x:=i*2;
pnt.y:=i;
putpixel(pnt);
end;
end;

begin
// ...
test_rec;
// ...
end.
64631

Andrew771
15.03.2018, 22:51
Класс! Будем ждать твой компиль тоже, хотца свои наработки на Спек перекомпилировать, где типов записей полно.

ALKO
05.04.2018, 16:01
Забыл, какую тулзу юзал от Эндрю771, которая перегоняла BMP-шки в подпрограмму отрисовки спрайтов и шестнадцатиричных данных.
Напомните, плиз.

- - - Добавлено - - -

Хотя вон смотрю есть некий ZxSprGen, пощупаю его.

Andrew771
05.04.2018, 17:03
Рекомендую ZxSprGen от AzAtom, он полностью подходит.

- - - Добавлено - - -

А моя тулза тут (http://zx-pk.ru/threads/24967-zx-like-pascal.html?p=794106&viewfull=1#post794106)

ALKO
07.04.2018, 00:30
Странно.
Лоде руннер запустился нормально.
А demo_sprites выдаёт следующее (все галочки включены при компиляции в асм. В качестве асм в машинные коды использую EmuZwin)
https://pp.userapi.com/c845418/v845418434/1eb81/hOF1PgaLvdY.jpg

- - - Добавлено - - -

Адреса пробовал как дефолтный, так и org 30000

Andrew771
07.04.2018, 15:11
Судя по формату спрайтов, атрибуты спрайтов должны быть выключены.

Bolt
07.04.2018, 15:41
Andrew771, можно перенести твою библиотеку и адаптировать некоторые демки из ZX Like Pascal для bm-pascal? :)

Andrew771
07.04.2018, 16:14
Конечно можно.

ALKO
10.04.2018, 13:35
Эх сложна, не осиливаю я.
https://pp.userapi.com/c845124/v845124563/25a09/G4E1mQim990.jpg

Даже готовая демка глючит.
От пасцалевого синтаксиса отвык.

Bolt
10.04.2018, 16:02
; копирование вирт.экрана на реальный
; вход: нет
; выход: нет

put_virt ld a,54
LD HL,addr_virt_screen
LD DE,16384
put_virt_01 dup 128
LDI
edup
dec a
jp nz,put_virt_01
RET


Почему так, а не один большой ldir?

Shiny
10.04.2018, 16:39
Почему так, а не один большой ldir?

16 тактов против 21, наверное.

AzAtom
10.04.2018, 16:50
Так быстрее. LDI 16 тактов для пересылки 1 байта, LDIR 21 такт для пересылки 1 байта. Правда, памяти уходит на это 256 байт. :(

Andrew771
10.04.2018, 17:40
Так быстрее. LDI 16 тактов для пересылки 1 байта, LDIR 21 такт для пересылки 1 байта. Правда, памяти уходит на это 256 байт.
Подтверждаю.


Эх сложна, не осиливаю я.
Есть bat-ник для демо Z, где все флаги выставлены как надо.
А еще необходимо после компиляции стереть повторные объявления массивов в файле ASM. В исходнике PRG написано, каких. Это было так, пока я не сделал инициализацию при объявлении массивов, но исходник Z пока не успел заменить. После замены залезать в ASM уже не надо будет, заменю.

Bolt
10.04.2018, 18:39
Мне и bat-ник не помогает. Один раз как-то оно запустилось, но не помню что именно я делал.

Andrew771
10.04.2018, 23:28
Ок, перепроверю Z.

- - - Добавлено - - -

Тут лежит исходник ZX Like Pascal, в нем, кажется, обновленный Z, где не нужно ничего колдовать: http://zx-pk.ru/threads/54-podderzhim-sajt-iskhodnikov!.html?p=810433&viewfull=1#post810433

ALKO
11.04.2018, 08:41
Есть bat-ник для демо Z
Компилил через БАТ-ник

Andrew771
11.04.2018, 11:03
Компилил через БАТ-ник
Возьми обновленный исходник Z тут (http://zx-pk.ru/threads/54-podderzhim-sajt-iskhodnikov!.html?p=810433&viewfull=1#post810433) в исходниках ZX Like Pascal, он должен без проблем запускаться.

Bolt
25.04.2018, 18:29
Задам вопрос в этой теме.
Меня в demo_z.prg смущает этот код:


if y_put>(y_map_scr-y_max_obj)
then y_min_lim:=y_map_scr-y_max_obj
else y_min_lim:=1;

При запуске y_map_scr=3, y_max_obj=5.
Результат вычитания в скобках отрицательный, результат сравнения будет true и в переменную y_min_lim, которая типа byte, запишется "отрицательное" число 254.
А дальше сравнение


... and (y_put>=y_min_lim) and ...

которое даст false и вывод спрайта не произойдёт.
Объясни, пожалуйста, как это работает в твоём компиляторе.

Andrew771
26.04.2018, 12:14
Результат вычитания в скобках отрицательный
В ZX Like Pascal нет отрицательных чисел, интерпретируется как положительное. Компилируется в код:


L18
ld a,(_Y_PUT)
ld l,a
ld h,0
push hl
ld a,(_Y_MAP_SCR)
ld l,a
ld h,0
ld de,5
and a
sbc hl,de
pop de
and a
sbc hl,de
jp nc,L19

Bolt
26.04.2018, 17:58
В ZX Like Pascal нет отрицательных чисел, интерпретируется как положительное.
Вон оно чо... :)

Andrew771
26.04.2018, 18:06
Ну насколько я помню, в TurboPascal, если тип переменных в выражениях byte или word, тоже нет отрицательных чисел, а проворачивается. Например, 5-6=255, насколько помню :)
А ты можешь тогда ввести функцию abs:


if y_put>abs(y_map_scr-y_max_obj)
then y_min_lim:=y_map_scr-y_max_obj
else y_min_lim:=1;

Shiny
26.04.2018, 18:13
для справочки: как HitechC обходится:


main()
{
int xm=-127;
int ym=96;

if (xm>ym) xm=-xm;

}

RAM:80F7 ld (ix+0FEh), 81h ; 'Á'
RAM:80FB ld (ix+0FFh), 0FFh
RAM:80FF ld (ix+0FCh), 60h ; '`'
RAM:8103 ld (ix+0FDh), 0
RAM:8107 ld e, (ix+0FEh)
RAM:810A ld d, (ix+0FFh)
RAM:810D ld l, (ix+0FCh)
RAM:8110 ld h, (ix+0FDh)
RAM:8113 call sub_813D ; if (xm>ym) xm=-xm;
RAM:8116 jp p, loc_812B
RAM:8119 ld e, (ix+0FEh) ; xm=-xm
RAM:811C ld d, (ix+0FFh)
RAM:811F ld hl, 0
RAM:8122 or a
RAM:8123 sbc hl, de
RAM:8125 ld (ix+0FEh), l
RAM:8128 ld (ix+0FFh), h
RAM:812B
RAM:812B loc_812B: ; CODE XREF: sub_80F4+22j

;
RAM:813D sub_813D: ; CODE XREF: sub_80F4+1Fp
RAM:813D ld a, h
RAM:813E xor d
RAM:813F jp m, loc_8145
RAM:8142 sbc hl, de
RAM:8144 ret
RAM:8145 ; ---------------------------------------------------------------------------
RAM:8145
RAM:8145 loc_8145: ; CODE XREF: sub_813D+2j
RAM:8145 ld a, h
RAM:8146 and 80h ; 'À'
RAM:8148 sbc hl, de
RAM:814A inc a
RAM:814B ret

Andrew771
09.05.2018, 20:45
Свежий исходник демо игры Z на ZX Like Pascal тут (http://zx-pk.ru/threads/262-strategii-realnogo-vremeni-na-zx-spectrum.html?p=963214&viewfull=1#post963214)

Bolt
12.05.2018, 13:50
Текущее демо Z и исходник на ZX Like Pascal (http://zx-pk.ru/threads/24967-zx-like-pascal.html). Т.к. теперь появилась инициализация массивов при объявлении, экономится много места в памяти, еще есть 13 кб свободных примерно.
Напиши, пожалуйста, как распределена память и как там 13 килобайт свободных осталось. 14 килобайт экраны, таблиц и спрайтов килобайт 18, остаётся 16 килобайт для кода. Он что, в 3 килобайта уместился?

Andrew771
14.05.2018, 20:39
23900-32506: скомпилированная программа на Паскале
32507-33253: процедура вывода карты клеток 4х4 знакоместа на Асме
33254-45440: спрайты
45441-48314: скомпилированная библиотека
48315-52409: карта
52410-53524: переменные и массивы
53525-57343: СВОБОДНАЯ ОБЛАСТЬ
57344-65xxx: виртуальный экран и таблица отраженных байтов

Да, промахнулся я. Осталось менее 4 кб, виртуальный экран забыл.

Bolt
14.05.2018, 21:01
Хоть что-то осталось, у меня пока в 48 совсем не помещается.
Кроме исключения повторного вычисления индекса массива какие ещё оптимизации есть в ZX Like Pascal? У меня фантазия не работает после переписывания кодогенератора :) Отдохнуть надо.

Andrew771
14.05.2018, 21:07
Нужно делать 8-битный Паскаль :)
В статье журнала "Downgrade" №15 оптимизации, которые делал, описал (http://dgmag.in/N15/DowngradeN15b.pdf).

Bolt
14.05.2018, 21:14
Нужно или исходник переделать, там повторов много, или сделать чтобы оптимизатор повторяющиеся части заменял на подпрограммы.

Bolt
15.05.2018, 19:03
Сколько ещё по объёму исходного кода на Паскале надо добавить, чтобы demo_z стало игрой? Я так понял, оставшихся 4 килобайт недостаточно?
Спрашиваю чтобы понять, если я, допустим, сожму имеющийся код до 48 килобайт, на сколько надо будет его ещё оптимизировать.

Andrew771
18.05.2018, 17:52
Думаю, кода раза в 3 больше будет. Так что нынешние 9кб, занимаемые скомпилированной программой, многовато. Уже думаю, как в 8-бит перевести выражения для типа byte, буду реализовывать, хорошо бы ужать хотя бы в 1,5 раза.

ALKO
04.10.2019, 10:02
По поводу асм-процедур не совсем понятно.
Есть основное тело программы begin end
Внутри него можно сделать асм-вставку?
А ещё лучше - вызовом процедуры. Правда я уже и не помню правил объявления процедур в пасцале. В начале 00ых ещё маялся им.

Пожелание на будущее (если у компилятора вообще будет будущее), помимо процедур попиксельного скролла добавить скролл познакоместный. Желательно с указанием скроллируемой области ректангла и учётом атрибутов.
Синхронизация с кадровой развёрткой тоже не помешала бы.
А также вывод спрайта с маской с точностью до пикселя.

Утилита СпрайтГен - понимаю, распознавание цвета с последующей конвертацией в атрибуты довольно геморное занятие. Но можно было бы хотя бы шпаргалку в виде набора палитр ink/paper, щёлкая по которым оно бы выдавало десятичный код на каждое знакоместо спрайта.
А то приходится в бейсике через PEEK смотреть (эдакая "пипетка").

В пасцале же для совсем уж ленивых можно было бы задефайнить коды клавиш под более человеческий вид, но если это сложно, то пусть будет как есть.

Без отрицательных чисел сложновато.
Хотя бы однобайтовую -128..127 хотелось бы.

AY + 128k тоже очень не хватает. Хотя бы AY. Интеграцию треков из вортекса, и саунд эффектов.

- - - Добавлено - - -

Алсо, для нубья вроде меня, довольно перспективный компиль. Функционала бы в него побольше.
PutPixel, например, шустрое рисование прямых/окружностей с алгоритмом Брезенхэма, НЕ-ПЗУшные-тормозные-процедурки.
Да с заливкой. Вывод текста с символами 8х8 тоже нужон, имхо. А ещё лучше - разный формат символов -16х8, 8х16.
Приспособить под TMX карты. Добавить алгоритмы сжатия картинок.
Было бы почти идеально.
Ах да, полезной функцией было бы и простое указание цвета атрибута в заданном месте.
Да так, шоб оно плазму 32х24 плавно вытягивало.

А то пробовал z88dk пощупать, так дальше настройки дело не ушло. только винт зря загадил.
Поэтому нубью и остаётся что на AGD однотипного бадыля штамповать, да на бейсике убер-тормозные мини-аркады.
А мастера ассемблера только шлют/посылают "приветы" через свои демосцены со скроллом текста.

- - - Добавлено - - -

> хотелка не треснет?

Нет, не треснет.:v2_dizzy_king:

ZX_NOVOSIB
04.10.2019, 10:36
А мастера ассемблера только шлют/посылают "приветы" через свои демосцены со скроллом текста.
Ну а что им - мастерам - ещё остается делать? Игры писать что ли? Не барское это дело (Хотя Барский возможно возразит)


Поэтому нубью и остаётся что на AGD однотипного бадыля штамповать, да на бейсике убер-тормозные мини-аркады.
А мастера ассемблера только шлют/посылают "приветы"
А что если... "нубью" и "мастерам" как-то скооперироваться? Разделение труда, так сказать. Хотя не, бред какой-то :)

ALKO
04.10.2019, 10:50
А что если... "нубью" и "мастерам" как-то скооперироваться? Разделение труда, так сказать. Хотя не, бред какой-то :)

Вот-вот. Я сию тенденцию заметил и на Сеге.
Там конечно СДК всяко удобнее спектрумских утилит, но тоже далека до идеала. Даже банальные платформеры уровня марео вынуждают заниматься изобретением велосипеда.
Тогда как более прошаренные типочки выжимают в дермосценах / играх-недоделках графон уровня 32-ух биток. Но сорсы при этом жыдят. Мол, сами догадайтесь, как мы это зафигарили.
А ведь там си компилятор (причём полноценный GCC), то есть ни что не мешало прикрутить готовые библиотеки. Но фиг вам.

Andrew771
04.10.2019, 12:14
По поводу асм-процедур не совсем понятно.
Есть основное тело программы begin end
Внутри него можно сделать асм-вставку?
А ещё лучше - вызовом процедуры.
Вызов процедуры на Асме:

Asm(NAME)
Имя процедуры обязательно заглавными буквами.
Само тело процедуры после последнего END программы.
Можно обращаться из асма к переменным, заданным в Паскале. Для этого ставим нижнее подчеркивание и далее имя заглавными буквами. Например, в Паскале есть переменная value. В асме ее вызываем по имени _VALUE

- - - Добавлено - - -


Пожелание на будущее (если у компилятора вообще будет будущее), помимо процедур попиксельного скролла добавить скролл познакоместный. Желательно с указанием скроллируемой области ректангла и учётом атрибутов.
Синхронизация с кадровой развёрткой тоже не помешала бы.
А также вывод спрайта с маской с точностью до пикселя.
Учту. Но на далекое будущее.


Утилита СпрайтГен - понимаю, распознавание цвета с последующей конвертацией в атрибуты довольно геморное занятие. Но можно было бы хотя бы шпаргалку в виде набора палитр ink/paper, щёлкая по которым оно бы выдавало десятичный код на каждое знакоместо спрайта.
А то приходится в бейсике через PEEK смотреть (эдакая "пипетка").
А посчитать смещение адреса от начала спрайта невозможно?



В пасцале же для совсем уж ленивых можно было бы задефайнить коды клавиш под более человеческий вид, но если это сложно, то пусть будет как есть.
Таблицу символов и клавиш см. в pdf-мануале в конце.


Без отрицательных чисел сложновато.
Хотя бы однобайтовую -128..127 хотелось бы.
Тоже думал над этим.


AY + 128k тоже очень не хватает. Хотя бы AY. Интеграцию треков из вортекса, и саунд эффектов.
Обычно, для AY вставляю скомпилированный в редакторах AY код в исходник Паскаля в виде отдельной асм-процедуры.

Остальные хотелки тоже учту в далеком будущем. :)

ALKO
04.10.2019, 12:21
Таблицу символов и клавиш см. в pdf-мануале в конце.
Да, знаю. Просто для удобства дефайны предлагаю.


А посчитать смещение адреса от начала спрайта невозможно?

Не понимаю, как это решит проблему? СпрайтГен понимает только монохром, а атрибуты приходится вручную вбивать.

Bolt
04.10.2019, 12:52
Да, знаю. Просто для удобства дефайны предлагаю.
Что в данном случае есть "дефайн"? В Си и в Паскале это разные вещи.

Andrew771
04.10.2019, 12:53
Не понимаю, как это решит проблему? СпрайтГен понимает только монохром, а атрибуты приходится вручную вбивать.
Добавь атрибуты сразу в этом же текстовом файле, а на Спек переноси уже скомпилированный полностью спрайт.

Bolt
04.10.2019, 13:09
А что если... [...] как-то скооперироваться? Разделение труда, так сказать. Хотя не, бред какой-то :)
Да, бред. Мои предложения и просьбы игнорятся напрочь. А я один не могу вытянуть транслятор, оптимизатор, рантайм, тестирование и всё остальное. Адаптацию либ из ZX Like Pascal вообще не осилил, а автору, похоже, пофиг. Хочет Andrew771 пилить свой ни с чем не совместимый "Паскаль" - ну, ок.

ALKO
04.10.2019, 13:14
Добавь атрибуты сразу в этом же текстовом файле, а на Спек переноси уже скомпилированный полностью спрайт.

Я так и делаю, но я не об этом...

- - - Добавлено - - -


Что в данном случае есть "дефайн"? В Си и в Паскале это разные вещи.

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

Oleg N. Cher
04.10.2019, 13:23
Развели тут плодить поделки, понимаешь. Конечно же не потянуть всё одному, надо понимать свои силы.

Я вот не пойму зачем ещё один свой неповторимый Паскаль, если есть ACK?


ACK Modula-2 is part of the Amsterdam Compiler Kit which is (according to the homepage) "a cross-platform compiler and toolchain suite that is small, portable, extremely fast, and extremely flexible. It targets a number of low-end machines including the Z80, 8086 and 80386, but there are many other code generators available. It supports several languages, including ANSI C, Pascal and Modula-2, and contains integrated runtime libraries including a libc. The ACK runs on Unix systems; most development happens on Linux". Originally the whole kit was written by Andrew Tanenbaum and Ceriel Jacobs. You can get more information by reading the online manpage and the About the ACK page. UPDATE: I installed Bochs and a Diskimage from Bochs download page to find out some details. The image available at the time of writing (08/10/04) includes the Modula-2 Compiler which seems to work as expected. It's a PIM3 Compiler.

Bolt
04.10.2019, 13:23
Переопределить кодовые значения клавиш в символьные, шоб не тыкаться в таблицу каждый раз.


const
c_key_code_space=32;
c_key_code_enter=13;
c_key_code_0=48;

и т.д. Для подавляющего большинства здесь присутствующих непосильная задача, они будут ждать пока это сделают за них. Вот и вся "кооперация".

ALKO
04.10.2019, 14:14
. Я вот не пойму зачем ещё один свой неповторимый Паскаль, если есть ACK?

Неповторимый паскаль в один экзешник, ничего лишнего. Документация по-рузски, а для меня, как для патриота Рашки, это важный аспект. Всё предельно просто.
Да и акцент нативно больше на игроделии. А в том ACK, как я понимаю, надо приаттачивать сторонние либы от Можон Твинс, или чё там.

Andrew771
04.10.2019, 14:53
Мои предложения и просьбы игнорятся напрочь. А я один не могу вытянуть транслятор, оптимизатор, рантайм, тестирование и всё остальное. Адаптацию либ из ZX Like Pascal вообще не осилил, а автору, похоже, пофиг. Хочет Andrew771 пилить свой ни с чем не совместимый "Паскаль" - ну, ок.

Конечно же не потянуть всё одному, надо понимать свои силы.

Да и акцент нативно больше на игроделии
Да, я именно для написания игр делал, поэтому ограничения. Я думаю сейчас, что и 16 бит многовато, нужно было делать 8 бит. А уж 32 бита совсем излишне, жрет памяти много и медленно работает.
Bolt, а что за адаптация либ? Какая моя помощь нужна?
Оптимизацию, которую я делал, подробно описал в статье (http://dgmag.in/N15/DowngradeN15b.pdf)
Еще подробнее и больше (но не для Спектрума)- в книге Н.Вирт "Построение компиляторов", 2010.
Ты спрашивал про вычисление выражений, помнится. Я в них не особо пока разобрался, только основное, которое у тебя уже есть.

ALKO
04.10.2019, 15:09
. Я думаю сейчас, что и 16 бит многовато, нужно было делать 8 бит.

Я не эксперт, но мне кажется, 16 бит в редких случаях таки нужны.
Как минимум для подсчёта очков.
Хм.. для параллакс скролла, возможно.
Всяко бывает.

Bolt
04.10.2019, 15:35
Да, 32 бита не нужны, отрицательные не нужны, аргументы не нужны... Может пусть пишущий игру сам решает по поводу быстродействия?

Кстати, а кто-нибудь вообще видел через какой костыль у меня сейчас реализовано деление? А задумался почему именно так?

Подпрограммы привести к "настоящему" Паскалю. Пример см. в файлах, это то, из чего я пытался собрать demo_z.pas.
70232
70231


procedure MapSet(p1,p2:pointer; a3,a4,a5,a6:byte);
begin
asm
ld e,(&&p1+0)
ld d,(&&p1+1)
ld (map_addr_array),de

ld e,(&&p2+0)
ld d,(&&p2+1)
ld (map_addr_sprites),de

ld a,(&&a3)
ld (map_xscr),a

ld a,(&&a4)
ld (map_yscr),a

ld a,(&&a5)
ld (map_width_scr),a

ld a,(&&a6)
ld (map_height_scr),a

ld a,64
ld (map_xmax_array),a
ld a,64
ld (map_ymax_array),a
end;
end;

И с выражениями проблема, некоторые опираются на то, что в компиляторе нет 32 бит и отрицательных чисел. Этакий Си-стайл, когда "250+10" может выдать и 260, и 4, и вообще что угодно.

Andrew771
04.10.2019, 15:41
Для подсчета очков (и прочего) думаю ввести тип longint, но для него отдельные команды (сложение, вычитание, вывод на экран, возможно умножение, деление). В обычных выражениях только тип byte.

- - - Добавлено - - -


Подпрограммы привести к "настоящему" Паскалю. Пример см. в файлах, это то, из чего я пытался собрать demo_z.pas.
Ок, дома посмотрю. Сейчас на работе не могу.

ALKO
04.10.2019, 16:15
.Может пусть пишущий игру сам решает по поводу быстродействия?

Действительно. Что мешает реализовать весь диапазон ? И удобных но медленных типов/процедурок, и быстрых но кастрированных под самый мозжечок. А там уже в зависимости от ситуации, чтоб у пользователя был выбор.

- - - Добавлено - - -

А кстати, табличная тригонометрия планируется?
В SGDK на сеге такая имеется, и довольно шустро крутит синусоиды по экрану. Есть конечно свои лимиты на фиксированную запятую дробной части. Но всё равно относительно удобно и высокоуровнево.
https://media.giphy.com/media/l3978usXXBk93TYly/giphy.gif

- - - Добавлено - - -

... правда у сеги проц с полноценными 32бита регистрами...

Andrew771
04.10.2019, 16:43
А кстати, табличная тригонометрия планируется?
С этим пока проблемы. Я проводил исследование на Спектруме - выводил 500-700 линий одновременно по быстрым алгоритмам линий, описанным на форуме. Подумывал писать автогонки на векторной графике. Но скорость вывода даже по оптимальным алгоритмам не устроила. Это еще без расчета координат линий :(
А как сделана игра Micronaut One (https://www.youtube.com/watch?v=v8gtajpc89s), для меня загадка. Может, кто растолкует? Вот хочу типа ее, но еще больше детализации.

ALKO
04.10.2019, 17:18
В микронауте пренебрегли сдвигом перспективы по двум осям.
Частая практика для быстрых преобразований 3д в декартовы координаты. По этой же причине нельзя поднять голову в думе, и нет наклонных плоскостей. По этой же причине нельзя свернуть назад в роад раш или кавасаки на сеге.

Сам алгоритм рендеринга стен Микронаута, имхо, схож с рендерингом полигональной дороги Роад Раш.

Чуть подробнее написано в статье:
http://www.extentofthejam.com/pseudo/

Поначалу растолковывают про растровые эффекты. А чуть ниже про полигоны.

Andrew771
04.10.2019, 17:27
ALKO, спасибо большое! Буду теперь изучать.

ALKO
04.10.2019, 17:31
. Вот хочу типа ее, но еще больше детализации.

Типа неё но с ещё большей детализацией - это уже Star Strike 2.
Там аналогичная болячка - камера может смотреть только вперёд, если её попытаться развернуть, то пространство вывернет наизнанку. Зато хитрым образом камера получает свободу в режиме дуэли. А всё потому что вокруг ничего кроме звёзд, и, собственно, самого противника, которого на дальних дистанциях не сильно заметно карёжит.

- - - Добавлено - - -

Кстать, в выше упомянутом Кавасцаки на сеге сей артефакт заметен на резких поворотах. Из-за чего пространство забавно скукоживается с одной стороны, и раскукоживается с другой.
Ну а наклоны камеры там растровым эффектом сделаны - построчный скролл, тоже частая практика на сеге. То есть всеми способами сводится к минимуму количество вычислений на каждую вершину полигона.

Oleg N. Cher
05.10.2019, 11:26
Неповторимый паскаль в один экзешник, ничего лишнего. Документация по-рузски, а для меня, как для патриота Рашки, это важный аспект. Всё предельно просто.Эк вы размечтались, батенька.


А в том ACK, как я понимаю, надо приаттачивать сторонние либы от Можон Твинс, или чё там.А, ну оно конечно проще наклепать самому компилятор и либы, чем приаттачить к ACK'у либы, да уж.

ALKO
05.10.2019, 13:23
А, ну оно конечно проще наклепать самому компилятор и либы, чем приаттачить к ACK'у либы, да уж.

Ну вот к примеру ща делаю демку мини-игры (на основе своего гипотетического самого масштабного проекта, когда-либо (не)существовавшего на спектруме - речь о Техно-Алкесе (https://zx-pk.ru/threads/30330-ishchu-zhelayushchikh-vystupit-v-roli-programmista/page9.html) ), так вот, мне понадобился познакоместный скролл.
Я скачал Supercode с WOSa, дизассемблировал нужную мне процедурку, воткнул в этот недо-паскаль. Всего-то делов.:v2_dizzy_priest:

Конечно костыли, НО - если бы автор не отвлекался на создание очередной настолки уровня крестики-нолики, а продолжал развивать проект, то было БЫ всё максимально удобно, чем где-либо.

- - - Добавлено - - -

Только вот сам пасцаль на фоне тех же си-подобных языков нифига не удобен.

Bolt
05.10.2019, 14:13
Чем именно Паскаль неудобен?