Нету конкретной задумки. Есть понимание, что просмотр клеток лабиринта в ZXOOM, полей в Эрудите и карты в будущей стратегии - это одно и тоже. Вывод текстов и спрайтов везде одинаков. А раз так, то можно это обобщить в ЯВУ.
Andrew771, ну так и тебе не чужда тяга к универсальности. :) Если наваяешь игру, которая меня заинтересует, можем попробовать доказать на практике, что универсальность ей никак не повредит. Спортируем её в рамках ZXDev на Оберон и другие платформы. Включая ZX, кодогенерация SDCC пойдёт ей только на пользу.
Насчёт ReadLn. Можно реализовать только Backspace, курсоры и буфер. Курсоры и буфер будут опциональными, т.е. если они не нужны в проекте, то и код лишний не будет включен. Именно к такому подходу надо стремиться. К универсальности, функциональности и компактности. Имхо.
Задумка игры такая (ищи мои посты там): http://zx.pk.ru/showthread.php?t=914...t=civilization
В 48к всё, что там описано, не поместится. Да и делать очень долго, может интерес пропасть. Поэтому пока есть планы сделать стратегию в стиле Древней Руси или Римской Империи без науки и изменения строев, и юниты только соответствующие эпохе. За год можно наклепать, если не лениться. Сейчас у меня хандра, ничего не делаю, даже апдейт для Эрудита почти готовый не могу закончить. :)
Если сначала создать ЯВУ, а потом только писать, то сроки явно затянутся. Дилемма.
Readln в играх для Спека, которые я знаю, всегда был только с backspace и более ничего. Ну если на Бейсике, то был еще курсор. А вот буфер - это уже писюканство.
В писюке есть еще буфер клавиатуры - гадость ужасная, до сих пор бесит.
Андрей, есть 2 противоположных подхода к программированию на Спектруме, да и не только на нём.
Первый. Это тупейший транслятор (компилятор или ассемблер) и умнейший и энергичнейший кодинг. Алгоритмы абсолютно втиснуты в архитектуру процессора, обкромсаны до частного их варианта использования, подходящего только для этого конкретного случая. Чего-то лишнее (расширения, универсальность) убраны, ибо это потери. Код экономится до байтика, такты проца тоже. Шикарный кодинг может вызвать восхищение среди таких же кодеров. Реализация крайне ориентирована на конкретные платформу и процессор. Ничего плохого в таком кодинге нет. Эффективность и компактность, быстроту никто не отменял. Проблемы начинаются когда надо понять устройство алгоритма, расширить его функциональность или портировать его на другой процессор/язык/платформу.
Первый путь был мне очень мил где-то в году 1996-м, году появления компилятора Coloss и игры SeaFight. Ничего более наглядного и красивого, чем Coloss, в плане низкоуровневого языка-инвалида для Спектрума (замены ассемблеру) я не встречал. А, вру. Встречал. Это язык Metal Владимира Кладова. Где-то на этом форуме о нём рассказывал Владимир.
Может я бы как-то более с энтузиазмом отнёсся к твоим идеям недопаскаля, но таких игрушечных компиляторов я уже делал не один десяток. Сперва QuickForth для ZX (на базе HL ZX Forth), потом Coloss для Спектрума (на Спектруме), потом Coloss для Доса (на Паскале), потом Coloss для Доса на Coloss’е (метатранслятор весил около 2 кб). Потом Coloss для Винды на Дельфи. Потом делал Паскаль. Делал маленький кроссплатформенный компилятор Оберона. Исходники к сожалению погибли. Надо ещё повспоминать, было что-то ещё. Просто хочу сказать, что всегда найдётся тот, кому будут нужны записи в недоязыке.
К тому же реализовать полностью вот хотя бы даже Оберон – это не так уж и много работы. Очень советую тебе вдумчиво изучить проект Оберс. Это транслятор Оберона-2 в текст на макроассемблере NASM. Т.е. примерно такого же уровня штучка, что ты задумал. Можно переделать его для Спектрума. Наверное. Но это вполне себе серьёзная реализация, хоть сейчас садись и делай на нём многозадачную операционную систему для защищённого 32-битного режима. Недостаток: практически нет оптимизации. Достоинство: бинарник транслятора весит 25 Кб. Согласись, реальный даже для Спека объём. Теперь чуть критики, надеюсь, ты не обидишься. Вынос проекта на общее обсуждение предполагает насыщение новыми идеями. Ты довольно закрыт для идей со стороны. Вот как задумал, так и не пожертвовал ни одной своей идеей. Трудно будет работать в команде, разве что твой авторитет будет абсолютным.
Второй подход. Это абсолютно умный, практически идеальный компилятор (а ведь оно того стоит, потрудиться чтобы он появился), нагляднейшая форма представления алгоритмов, включая графику, таблицы и прочие возможности визуализации. Это гибкая настройка свойств алгоритма и свойств низкоуровневых компонентов. Это совместимость между различными платформами, включая ретро. Для Спека предполагается сделать много компонентов (на асме), с возможностью гибкого их конфигурирования, язык высокого уровня с сверхнизким оверхедом и совместимые снизу вверх библиотеки для различных платформ. Сейчас мне гораздо ближе по духу вот такой второй способ. Хотя идеальной кодогенерации для Z80 нет и не предвидится, всё равно работать для таких идей представляется интересным. Появляются новые возможности. Лёгкое понимание и модификация алгоритмов. Разворачивание их на любую платформу (автоматически), быстрая работа с низкой сложностью, высокий уровень, хорошие перспективы для платформ, котоые ещё даже не реализованы. В этом смысле я вижу очень хорошую перспективу для Оберон-технологий, правда, к ним надо ещё приложить руку конечно.
Я буду сейчас заниматься другими проектами и платформами. Считайте, что на ZXDev забил. Ввиду почти полного отсутствия интереса и помощи.
Посмотрел я Coloss и встроенный язык в эмулятор EmuZWin - это всего лишь замена названий команд ассемблера, но принципиально ничего не облегчает. Ну буду я писать a=7 вместо ld a,7 , что это меняет?
Вот еще пример из твоего языка Coloss:
Почему присваивать нужно обязательно 87=alpha, а не alpha=87?Код:{ 87 = alpha ‘ LD A,87 ‘
‘ LD (alpha),A ‘
** = beta ‘ ADD A ‘
‘ LD (beta),A ‘
alpha + beta ‘ LD A,(alpha) ‘
‘ LD HL,beta ‘
‘ ADD (HL) ‘
= alpha = ! ‘ LD (alpha),A ‘
‘ RST 10h ‘
ret ‘ RET ‘
## alpha , beta ; ‘ alpha: DW 0 ‘
‘ beta: DW 0 ‘
Из всего написанного лично у меня наибольший внутренний протест вызывает вывод символа по RST 10h конструкцией “{ = !”
Была мысль сделать вывод с помощью потоков... не совсем удачная. Обратите внимание на скромную открывающуюся фигурную скобку в самом начале проги. Ей не соответствует закрывающая. И не должна. Вся эта программа написана в малом (байтовом) представлении. И если вдруг мы захотим работать не с байтами, а словами, и с HL вместо A, зачем писать не “alpha + beta”? Т.е. “{“ переход в байтовый формат; ”}” соответственно в формат слов. Вещественной арифметики, встроенной в компилятор, к сожалению пока нет. Нужно писать быструю библиотеку, калькулятор Спека по RST 28h ОЧЕНЬ медленный.
Итак, во что превратится наша прожка, если изменить скобку:
} 87 = alpha ‘ LD HL,87 ‘
‘ LD (alpha),HL ‘
** = beta ‘ ADD HL,HL ‘
‘ LD (beta),HL ‘
alpha + beta ‘ LD HL,(alpha) ‘
‘ LD DE,(beta) ‘
‘ ADD HL,DE ‘
= alpha = ! ‘ LD (alpha),HL ‘
‘ CALL WRITENUM ‘
ret ‘ RET ‘
## alpha , beta ; ‘ alpha: DW 0 ‘
‘ beta: DW 0 ‘
В большом (словарном) представлении конструкция “} = !” уже выводит не символ по коду в A, а число, находящееся в HL. Вывод производится с помощью процедуры writenum, к-рая находится в стандартной библиотеке COLOSS.COL.
Непонятно, что означает **=beta. А почему нельзя написать beta=alpha*2? А потом alpha=alpha+beta ? А потом print alpha?
И почему скобка открывается, но не закрывается. Тогда замени ее другим чем-нибудь, оператором установки режима "байты/слова" например.
Пойми, что если исходный код состоит из закорючек и если компилируемый код не оптимален, то проще писать либо на Бейсике, либо на Ассемблере, т.к. они стандартны и известны. Оберон будет лучше Coloss, т.к. он стандартен и известен.
Полной оптимизации кода из ЯВУ часто не удается достигнуть, а для Спектрума это очень важно. Иначе получается встроенный Бейсик. Так зачем широко известный каждому спектрумисту Бейсик менять на малоизвестный Оберон?
Сейчас оптимален и используется как основной язык Ассемблер. Нужна ему более лучшая замена. Замена не названиям ассемблерных команд, а целым ассемблерным конструкциям и процедурам. Это уже есть, называется "макросы ассемблера". Нужно стандартизировать эти макросы, назвать операторами из известного ЯВУ и по возможности подогнать под конструкции ЯВУ. Т.е. идти снизу вверх, от кодов к операторам ЯВУ, а не традиционно от операторов ЯВУ к кодам.
Я не стану утверждать, что Coloss кажется мне верхом совершенства. Это замена асму для краткости. Coloss более лаконичен и более нагляден. Но не во всём. Сейчас мне некоторые вещи в нём видятся уродливыми, теперь я бы стал делать иначе. Например, я обозначал { % как регистр C, { = [[]] } как присваивание LD (BC),A - сейчас я предпочёл бы { C и = [BC]
Придраться есть к чему. Но в Coloss'е трансляция атомарная, как в асме. Соответственно транслятор примитивнейший, а код можно получить идеальный. Да, Coloss можно и нужно пересмотреть. Это безусловно. Но я этим заниматься не буду.
В рамках проекта XDev успешно собран экспериментальный мидлет на Компонентном Паскале. Меня тут уверяли, что пуребасик это крайне качественный продукт, так вот, господа, время показывает, что мощь Оберонов значительно превосходит наши с вами представления о них. На Оберонах возможно то, что пуребасику и не приснится. Анонсирую игру Dash с открытыми исходниками, целевые платформы (пока) — ZX Spectrum, J2ME и MS DOS. Возможно, в дальнейшем будет поддержана Amiga, Win32/64, UNIX/Linux и др. платформы.
Планируются также эксперименты по разработке софта на КП для Android. Желающих попробовать освоить это направление рад видеть в аське, мейле и у себя на форуме.
Обращаю ваше внимание, что Компонентный Паскаль — это правильное надмножество языков Оберон-1 и Оберон-2, а это значит что можно вести разработку игры практически на одном языке, и её логика будет представлять собою единые исходники, собираемые для разных платформ. Иллюстрирую это своим проектом Dash (для MS DOS: язык Оберон-1/компилятор Oberon-M; для J2ME: язык Компонентный Паскаль/компилятор GPCP; и для ZX Spectrum: язык Оберон-2/транслятор Ofront/SDCC). Проект только недавно начал переносить под версионный контроль, поэтому сами понимаете.
Недавно с интересом узнал, что в своё время для компьютера Amiga много писали на модульных языках. Существовал даже Amiga Modula & Oberon Klub (AMOK), который зарелизил более сотни с лишним флоппи дисков с исходниками на Модуле и Обероне. Всё это доступно для скачивания. Подробнее об этом в теме Amiga и модульные языки.
Добавил платформу ZX Spectrum. Покритикуйте, пожалуйста, процедуру вывода тайлов GrTiles.PutTile — размер 16x12 (без атрибутов) на предмет скорости. Понимаю, что кардинально можно ускорить, запретив прерывания и воспользовавшись методом вывода через стек, но пока решено использовать режим IM 2.
В Unreal Spectrum этот trd не грузится.
Oleg N. Cher, адрес на экране из hl принципиально забирать?
---------- Post added at 22:57 ---------- Previous post was at 22:55 ----------
в ix обработка ошибок?Цитата:
PUSH IX
LD IX,#0
ADD IX,SP
#endif
LD A,#0x1E
CP A,4(IX) ; x
RET C ; IF x <= 30 THEN RETURN
LD C,5(IX) ; y
CP A,C
RET C ; IF y
---------- Post added at 23:04 ---------- Previous post was at 22:57 ----------
я бы перепахал таблицу
ускорил бы на 48 тактовЦитата:
ld a,(ix+4)
add a,(hl)
ld c,a
inc l
ld b,(hl)
inc hl
ld a,(de)
ld (bc),a
inc de
inc c
ld a,(de)
ld (bc),a
inc de
А я проверил в Spectaculator 6, и тоже не грузится. В принципе, trd-шник создан старой ещё досовской утилитой Медноногова bin2trd, от которой я давно хочу избавиться. Однако сгенеренные ею trd-шки открываются в, начиная со старинного же Шалаева и заканчивая FUSE и EmuZWin. Исходников bin2trd у меня нет, и с форматом я не знаком. Надо разбираться.
Зато данный казус простимулировал работу над моей собственной утилитой MakeZX. Планирую скоро зарелизить первую версию. Вероятно, поддержки формата TRD в версии 1.0 не будет, а может и вообще не будет. Разве что мне поможет кто-то более опытный, ведь утилита будет полезна не только для ZXDev, но и для SDCC (а может и ещё применения найдутся).
Интерфейс для работы с TRD будет выглядеть, скорее всего, так:Работа с диском будет осуществляться так (с лентой аналогично):Код:DEFINITION DiskTRD;
TYPE
DiskFile = RECORD (* OBJECT *)
error-: BOOLEAN; (* Is error after ReCreate, SaveBasic, SaveCode or Finalize? *)
END;
PROCEDURE (VAR trd: DiskFile) ReCreate (diskName: STRING);
PROCEDURE (VAR trd: DiskFile) SaveBasic (
name: STRING; startLine, dataLength: INTEGER; VAR data: ARRAY OF BYTE);
PROCEDURE (VAR trd: DiskFile) SaveCode (
name: STRING; startAddr, dataLength: INTEGER; VAR data: ARRAY OF BYTE);
PROCEDURE (VAR trd: DiskFile) Finalize;
END DiskTRD.
Конечно же непринципиально, можно забирать из любой пары.Код:PROCEDURE CreateTrdDisk;
VAR
trd: DiskTRD.DiskFile; data: ARRAY 2 OF BYTE;
BEGIN
data[0] := CHR(243); data[1] := CHR(175); (* First 2 bytes of ROM. *)
trd.ReCreate("mydisk.trd");
trd.SaveCode("ROM", 0, 2, data);
trd.Finalize;
IF trd.error THEN IO.WriteStr("Disk creating error") END;
END CreateTrdDisk;
Не совсем. IX в начале процедуры мы настраиваем чтобы таскать параметры из стека, которые были положены туда примерно так:Но мы проверяем не вышли ли координаты за пределы экрана. В конце работы над игрой эти проверки, если понадобится, можно убрать.Код:LD HL, tileAddr
PUSH HL
LD HL, tileCoords
PUSH HL
CALL _GrTiles_PutTile
jerri, интересная мысль! Благодарю.