Просмотр полной версии : LASER BASIC 2
Oleg N. Cher
07.09.2016, 01:47
Всем привет. Есть мысль разработать оптимизированный набор процедур - аналогов команд LASER BASIC.
Я пока набросал универсальную подпрограмму вывода познакоместного спрайта с атрибутами. Требуется ваша помощь (особенно обращаюсь к Destr'у, AzAtom'у и Reobne). Код тестировал на спрайтах разного размера. По-моему, получилось довольно хорошо.
Конструктивная критика (баги? ускорить без серьёзного увеличения размера?)
Нужно модифицировать, чтобы можно было выводить спрайты с выходом за пределы экрана (как по X, так и по Y).
Вообще философский момент. Я кинулся кодить, но потом понял, что реализовал формат, не совместимый с оригинальным LASER BASIC'ом. Там сперва спрайт выводится весь по ширине, потом следующая пиксельная линия и т.д. А у меня получилось так: выводится первое знакоместо целиком, потом второе, и так на ширину линии, потом преход к следующей знакоместной строке. Чтобы я не занимался мазохизмом, скажите, пожалуйста, есть ли выверенные методики вывода подобных спрайтов, которые диктуют наиболее удачный формат для быстрого вывода? Берём в расчёт то, что самый внутренний цикл в моей реализации крутится 8 раз (выводим знакоместо), а в лазерной - количество, равное ширине спрайта (выводим строку). То есть мой вариант формата во внутреннем цикле оптимальнее лазерного для спрайтов, ширина которых меньше восьми знакомест.
Так что есть альтернатива: или слегка модифицировать формат и написать перекодировщик. Или остаться на старом лазерном формате. Это вопрос, на который я ещё себе не ответил.
Атрибуты бы целенаправленно не хотелось вставлять вперемешку с блоками пикселей, хотя такой вариант я тестировал. Но решено, что у нас останется возможность выводить спрайты без атрибутов, и тогда, если они в конце, их вывод просто легче отрезать, чем обходить атрибутные данные доп. кодом.
Критикуем, господа.
/*********************/
/* LASER BASIC 2 */
/* by Oleg N. Cher */
/* zx.oberon2.ru */
/*********************/
extern unsigned int Laser2_SPRT_ADR; // Sprite file start address
/* Спрайты хранятся в памяти в следующем формате:
Байт 1 - номер спрайта.
Байт 2 - младший байт размера спрайта (9*HGT*LEN+3).
Байт 3 - старший байт размера спрайта.
Байт 4 - длина спрайта.
Байт 5 - высота спрайта.
8*HGT*LEN - данные о состоянии
пикселей.
HGT*LEN - атрибуты.
ИТОГО: 9*HGT*LEN+5 байтов.
*/
/*--------------------------------- Cut here ---------------------------------*/
void Laser2_ATOF (void)
{
__asm
LD A, #0xC9 ; "RET"
LD (Laser2_ATOF_IN), A
__endasm;
} //Laser2_ATOF
/*--------------------------------- Cut here ---------------------------------*/
void Laser2_ATON (void)
{
__asm
LD A, #0xED ; "LD DE,(ADDR) ED5BXXXX"
LD (Laser2_ATOF_IN), A
__endasm;
} //Laser2_ATON
/*--------------------------------- Cut here ---------------------------------*/
void Laser2_PTBL (signed char col, signed char row, unsigned char spn) __naked {
__asm
POP HL
POP BC ; C = col; B = row
POP DE ; E = spn
PUSH DE
PUSH BC
PUSH HL
XOR A ; NOP
JP _Laser2_PUT_SPRITE
__endasm;
} //Laser2_PTBL
/*--------------------------------- Cut here ---------------------------------*/
void Laser2_PTOR (signed char col, signed char row, unsigned char spn) __naked {
__asm
POP HL
POP BC ; C = col; B = row
POP DE ; E = spn
PUSH DE
PUSH BC
PUSH HL
LD A, #0xB6 ; OR (HL)
JP _Laser2_PUT_SPRITE
__endasm;
} //Laser2_PTOR
/*--------------------------------- Cut here ---------------------------------*/
void Laser2_PTXR (signed char col, signed char row, unsigned char spn) __naked {
__asm
POP HL
POP BC ; C = col; B = row
POP DE ; E = spn
PUSH DE
PUSH BC
PUSH HL
LD A, #0xAE ; XOR (HL)
JP _Laser2_PUT_SPRITE
__endasm;
} //Laser2_PTXR
/*--------------------------------- Cut here ---------------------------------*/
void Laser2_PTND (signed char col, signed char row, unsigned char spn) __naked {
__asm
POP HL
POP BC ; C = col; B = row
POP DE ; E = spn
PUSH DE
PUSH BC
PUSH HL
LD A, #0xA6 ; AND (HL)
JP _Laser2_PUT_SPRITE
__endasm;
} //Laser2_PTND
/*--------------------------------- Cut here ---------------------------------*/
void Laser2_PUT_SPRITE (void) __naked {
// A: mode; C: col; B: row; E: spn
__asm
.globl Laser2_ATOF_IN
LD (SPRT_MODE_IN$), A ; Set draw mode
; Процедура расчёта адреса экрана из координат
; Вход: C=x, B=y
; Выход: HL = адрес видеопамяти
LD A, B
AND #7
RRCA
RRCA
RRCA
OR C
LD L, A
LD A, B
AND #24
OR #0x40
LD H, A ; 14 байт, 53 такта
LD (SCR_ADR_IN$+1), HL
LD HL, (_Laser2_SPRT_ADR)
FIND_BY_N_IN$: LD A, (HL) ; N of a sprite
OR A
RET Z
INC HL
CP E ; spn
JR Z, SPRT_FOUND_IN$
LD C, (HL)
INC HL
LD B, (HL)
ADD HL, BC ; + offset to next sprite
JR FIND_BY_N_IN$
SPRT_FOUND_IN$: INC HL
INC HL
LD C, (HL) ; length of sprite
INC HL
LD B, (HL) ; height of sprite
LD (SPRT_HGT_LEN_IN$+1), BC
INC HL
SCR_ADR_IN$: LD DE, #0 ; adr of sprite (up left corner)
SPRT_HLINE_IN$: LD A, E ; Begin of loop on charlines
LD (SCR_LOBYTE_IN$+1), A
PUSH BC
LD B, #8
SPRT_CHAR_IN$: LD A, (HL)
SPRT_MODE_IN$: NOP ; NOP | AND (HL) | OR (HL) | XOR (HL)
LD (DE), A
INC HL
INC D
DJNZ SPRT_CHAR_IN$
LD B, #8 ; Draw 8 bytes (one charline)
LD A, D
SUB A, B
LD D, A
INC E ; Next screen line
DEC C
JR NZ, SPRT_CHAR_IN$
SCR_LOBYTE_IN$: LD A, #0
ADD #0x20 ; Next charline
LD E, A ; If carry then jump to next third of screen
JR NC, CONTIN_1_3_IN$
LD A, D ; Next third of screen
ADD B
LD D, A ; DE := DE + 0x0800
CONTIN_1_3_IN$: POP BC
DJNZ SPRT_HLINE_IN$ ; End of loop on charlines (the same third)
Laser2_ATOF_IN: ; RET
LD DE, (SCR_ADR_IN$+1)
LD A, D ; Calculate attribute address
RRCA
RRCA
RRCA
AND #3
OR #0x58
LD D, A
SPRT_HGT_LEN_IN$: LD BC, #0
LD A, #32
SUB A, C ; 32 - len
LD (SPRT_HGT_DIS_IN$+1), A
DRAW_ATRLINE_IN$: PUSH BC ; Begin of loop on charlines
LD B, #0
LDIR
LD A, E
SPRT_HGT_DIS_IN$: ADD #0
LD E, A
LD A, C
ADC D
LD D, A
POP BC
DJNZ DRAW_ATRLINE_IN$
RET
__endasm;
} //Laser2_PUT_SPRITE
модифицировать формат и написать перекодировщик
Поддерживай тот формат который уже есть.
Выводить по линиям - это как-бы уже по умолчанию стандарт.
По знакоместам - это для других типов спрайтов (типа как в Popeye или TrapDoor). Но там можно обойтись банальным PRINT.
null_device
09.09.2016, 02:13
Основной "спотыкач" лазер-бейсика, невозможность работы в нем, на 128К машине (без принудительного перехода в 48К режим). Он, вроде как использует для своих нужд буфер принтера, чем портит системные переменные.
Oleg N. Cher
09.09.2016, 02:47
Destr, а если по знакоместам быстрее? Ведь на практике большинство спрайтов имеют ширину меньше 8 символов, а имеет смысл в первую очередь оптимизировать внутренний цикл.
null_device, оригинальный LASER BASIC я вообще не рассматриваю как серьёзный инструмент для разработки - на сегодняшний день есть более совершенные средства, генерирующие настоящий машинный код (в отличие от интерпретатора или компилятора LASER BASIC в пи-код). Поэтому я беру только принцип.
Библиотека Raydac & Michailov [HVG] (есть реализация для SDCC и ZXDev) не использует буфер принтера и даже умеет выводить графику на второй экран (#C000).
Когда-то делал процедуру универсальную для спрайтов, она здесь http://zx-pk.ru/threads/20554-vyvodim-sprajt-s-proverkoj-granits-ekrana.html
Код, и пример работы во вложении к теме.
Формат спрайта 8 строк спрайта, строка атрибутов, ... , ...
Oleg N. Cher
09.09.2016, 15:17
drbars, благодарю. Посмотрел код, правда, не знаю, как он может быть мне полезен. Разве что присмотрюсь к деталям реализации отсечения невидимой части спрайта.
Основное преимущество при построчном выводе спрайта - возможность пользоваться командами типа LDI или разворачивать цикл вывода как-то иначе. Когда же в универсальной процедуре вывода спрайта используется логическая операция (AND/OR/XOR), смысла её разворачивать как бы и нет, я же не демки собираюсь писать. LDI в этом случае тоже не шибко поможет. Правильно я рассуждаю?
Что касается размещения данных атрибута среди блоков пикселей. Да, это эффективнее, чем выводить их потом, но только если всегда используется вывод с атрибутами. В случае же LASER BASIC'овского PTBL/PTXR/PTOR/PTND это не всегда так.
Alcoholics Anonymous
10.09.2016, 03:05
Hi Oleg,
void Laser2_PTBL (signed char col, signed char row, unsigned char spn) __naked {
__asm
POP HL
POP BC; C = col; B = row
POP DE; E = spn
PUSH DE
PUSH BC
PUSH HL
XOR A; NOP
JP _Laser2_PUT_SPRITE
__endasm;
} // Laser2_PTBL
Does oberon have function pointers? If not you can use callee convention to save some bytes in your binaries:
void Laser2_PTBL (signed char col, signed char row, unsigned char spn) __naked __z88dk_callee {
__asm
POP HL
POP BC; C = col; B = row
dec sp
POP DE; D = spn
push hl
XOR A; NOP
ld e,d ; E = spn
JP _Laser2_PUT_SPRITE
__endasm;
} // Laser2_PTBL
I had to do something weird in there because of the three bytes but with this in place calls to your subroutine will no longer have pops afterward.
If you do need function pointers, you have to resort to some trickery as sdcc is not fully capable of function calls through pointers with fastcall or callee linkage.
drbars, благодарю. Посмотрел код, правда, не знаю, как он может быть мне полезен. Разве что присмотрюсь к деталям реализации отсечения невидимой части спрайта.
Основное преимущество при построчном выводе спрайта - возможность пользоваться командами типа LDI или разворачивать цикл вывода как-то иначе. Когда же в универсальной процедуре вывода спрайта используется логическая операция (AND/OR/XOR), смысла её разворачивать как бы и нет, я же не демки собираюсь писать. LDI в этом случае тоже не шибко поможет. Правильно я рассуждаю?
Что касается размещения данных атрибута среди блоков пикселей. Да, это эффективнее, чем выводить их потом, но только если всегда используется вывод с атрибутами. В случае же LASER BASIC'овского PTBL/PTXR/PTOR/PTND это не всегда так.
Полезность в общем принципе работы, блок расчета отсечения частей. Думаю цикл можно свернуть и сделать с любой логикой, что самой собой замедлит вывод.
Атрибут помещен строками в тело спрайта затем, чтобы не делать повторного расчета отсечения для атрибута и не городить лишний цикл. Если у тебя спрайт цветной, а нужно вывести ч/б, то проще не выводить эту строку.
Oleg N. Cher
11.09.2016, 04:24
Для перехода к следующей строке атрибутов спрайта за пределами экрана можно вычислить смещение с отсечением, и прибавлять это число. И его же, умноженное на 8, мы будем использовать, чтобы отсечь невидимые блоки пикселей, там в целом всё довольно эффективно можно сделать. Я закодирую и покажу.
Кстати, оптимизировал чуть-чуть подпрограмму в первом посте темы. И набросал конвертер спрайтов из лазерного формата.
Alcoholics Anonymous, yes, Oberon has function pointers (procedure variables):
VAR p: PROCEDURE (i: INTEGER): REAL;
Oleg N. Cher
11.09.2016, 20:22
58208 с прыгающим инопланетным чудиком. Вывод за пределами экрана пока не реализован. Бинарь занимает 986 байт, из них:
661 байт - массив спрайтов (4 фазы чудика, 5x4 знакомест каждая, без атрибутов).
123 байта - основная подпрограмма вывода спрайта Laser2_PUT_SPRITE_INSCR.
202 байта - остальной код (в т.ч. процедуры установки цветов, задержки, инициализации и т.д.)
MODULE Laser2Demo; (*$MAIN*)
(* LASER BASIC 2 Demo for Sinclair ZX Spectrum 48 Kb *)
(* Copyright (C) 2016 Oleg N. Cher, VEDAsoft Oberon Club *)
IMPORT gr := Laser2, b := Basic;
(* Пример взят из книги "Как написать игру для ZX Spectrum" *)
CONST
FrameSizeBytes = 5(*hdr*) + 8*20(*data*) ;
TYPE
Sprites = ARRAY FrameSizeBytes * 4 (*frames*) + 1 OF CHAR;
CONST
Chudik = Sprites ( ... ); (* Данные спрайтов поскипаны *)
VAR
x, phase: SHORTINT;
BEGIN
b.Init;
b.COLOR(b.Bright + b.Black*b.Paper + b.Yellow); b.BORDER(b.Black); b.CLS;
gr.InitSpritesAr(Chudik); gr.ATOF;
FOR x := -2+2 TO 30-2 BY 2 DO
FOR phase := 1 TO 4 DO gr.PTBL(x, 5, phase); b.PAUSE(5) END;
END;
b.Quit
END Laser2Demo.
Старый вариант этой же демки (на библиотеке Raydac/Michailov, со сделанной мною смартлинковкой) занимает 2686 байт.
Думаю, это хороший результат. Для дерзновенных предлагаю оптимизировать процедуру вывода ещё сильнее. ;-)
В планах реализовать вывод спрайтов за пределами экрана. Потом ещё несколько подпрограмм: скроллинг окон, атрибутов и т.д. Все процедуры из набора LASER BASIC реализовывать не планирую, только нужные (мне).
- - - Добавлено - - -
Сделал процедуру для выбора экрана (по адресу), чтобы иметь возможность выводить на второй экран, да и вообще в виртуальный экран в памяти. Сначала хотел назвать SCRN, сообразно стилю LASER BASIC, но отказался от этого, назвал SetScreen. Так новая, не входящая в набор ранее, процедура будет заметнее, ибо коррелирует с InitSprites, InitSpritesEx и InitSpritesAr.
Конвертер спрайтов LASER BASIC в LASER BASIC 2 будет включен в дистрибутив ZXDev (с исходниками). Конвертирует на уровне исходного текста, но не бинаря. Пока понимает только Оберон, планирую добавить Си. Утилита очень сырая, нет никакой обработки ошибок, но всё, что нужно, она делает, а больше пока не требуется.
http://i.piccy_.info/i9/17dc85d4a42337406c94360e67263957/1473556818/27982/1065564/ConvSpr.png
Типичный модуль ресурсов игры на Обероне может выглядеть так (сам инициализируя LASER BASIC 2):
MODULE Rsrc; (** Resource *)
IMPORT Laser2;
TYPE
SpritesT = ARRAY SpriteSize OF CHAR;
CONST
Spr1* = 1; (* Константа - номер спрайта, экспортируется, т.е. её видно извне *)
Spr2* = 2;
(* ... *)
Sprites = SpritesT ( ... );
BEGIN
Laser2.InitSpritesAr(Sprites)
END Rsrc.
MODULE MyGame; (*$MAIN*)
IMPORT Laser2, Rsrc;
...
BEGIN
...
Laser2.PTBL(x, y, Rsrc.Spr2);
...
END MyGame.
Barmaley_m
11.09.2016, 23:36
А мне кажется более перспективным поменять формат, если это необходимо для повышения быстродействия. Написать перекодировщик - не проблема. Зато будет в целом быстрее работать. Совместимость со старым лазер-бейсиком как бы особо никому не нужна. Либо программа пишется с нуля (и тогда старый формат не имеет значения), либо все равно придется ее серьезно переделывать, и формат спрайтов окажется не такой уж большой сложностью.
Oleg N. Cher
12.09.2016, 00:36
Справедливо, и я согласен. Для того и поменял. Такты, правда, не считал, но более чем уверен, что скорость познакоместного вывода спрайтов всегда выше, чем построчного, для ширины < 8 и, как минимум, не ниже для > 8. Но с уточнением: если при выводе используется логическая операция. И, как следствие, нельзя использовать LDI или вывод стеком.
Кто-нибудь поделится подпрограммами для пиксельного скроллинга знакоместных окошек? Интересует прямой и циклический скроллинг, с буфером или без, горизонтальный на 1, 2, 4 и 8 пикселей и вертикальный на 1. Без атрибутов. Можно конечно взять процедуры Лазер Бейсика как есть, но надо хотя бы посмотреть, насколько они эффективны. Это как бы следующий этап моей работы (над игрой).
Также наверное интересует зеркалирование (эффект mirror) знакоместных окошек.
P.S. Процедурка PutSprite вроде удачная получилась, да? По кр. мере никто не ругался и не обзывал код ламерским. ;-) Даже мудрый жерри (Destr хело!), который пробегал мимо, не к ночи буде упомянут. ;-)
А вывод спрайтов с прозрачными знакоместами будет? Как в книге "как написать игру".
Лучше всего обычные спрайты хранить и выводить столбцами, в таком случае получим хорошее сжатие упаковщиками.
SPRT_CHAR_IN$: LD A, (HL)
SPRT_MODE_IN$: NOP ; NOP | AND (HL) | OR (HL) | XOR (HL)
LD (DE), A
Тут берётся байт спрайта, затем делается наложение байта спрайта самого на себя?
Наложение на экран делается иначе. Взятый байт экрана, накладывается на байт спрайта и возвращается на экран.
Oleg N. Cher
12.09.2016, 14:52
drbars, издеваетесь? Это просто опечатка в логике. Вот что значит код не тестировать. Исправим.
Вывод спрайтов с прозрачными знакоместами не планируется. Я прикинул, что мне нужны такие процедуры:
ATON ATOF PTBL PTOR PTND PTXR
INVM
INVV MIRV SETV CLSV
WL1V WR1V WL4V WR4V WL8V SL1V SR1V SL4V SR4V SL8V SR8V
WCRV SCRV
AWLV
Разве что кто-то ещё присоединится к разработке. Я ещё тогда говорил Руслану, автору игр про мышек, в теме про "что-то вроде лазер бейсик" про потенциал данного подхода, но он куда-то исчез. Испугался большого размера пристёгнутой целиком библиотеки. Ну вот, а теперь мы это исправили.
Я переписал спрайтовую демку, выложенную SfS в теме Спрайты, ps/2 и куча утилит (http://zx-pk.ru/threads/23473-sprajty-ps-2-i-kucha-utilit.html), заменив его процедуру на свою, получается и экономия байтиков, и рост скорости вывода:
DemoSpr 7520 байт
DemoSpr2 7461 байт
58211
Такты не знаю как мерять. Если кто займётся, было бы интересно сравнить.
SfS, я оптимизировал Ваш спрайтовый вывод в двух местах. Там DEC B: JR NZ нужно изменить на DJNZ. И при переходе к следующему знакоместу можно использовать INC L вместо INC HL, получится быстрее. Ну а то, что там построчно выводится, так упс. Просто берите мою процедуру, это самое удачное в этом весе, что я встречал. ;-)
Да, ещё там как-то странно вычисляется адрес атрибутов, но спишем это на возможность работы со вторым экраном.
- - - Добавлено - - -
Исправил. (https://github.com/Oleg-N-Cher/XDev/commit/e93e4ba559a120f6596a68b2c2fbaa824393d014)
Oleg N. Cher
14.09.2016, 05:13
Реализовал INVM, INVV, SETV и CLSV.
В принципе, всё, что мне было нужно, есть здесь:
http://zxpress.su/book_articles.php?id=1026http://zxpress.su/book_articles.php?id=1027
Но я не стал передирать код буквально, а переосмыслил. И, думаю, мои процедуры при самом незначительном росте размера обходят приведённые в книге "Как написать игру на ассемблере для ZX Spectrum" по скорости. Хотя такты, опять же, точно не считал.
Oleg N. Cher, я думаю в процедуру отрисовки спрайта стоит добавить возможность зеркалирования используя таблицу в 256 байт. Для игр это необходимо.
LD HL,MIRROR_TAB ; Таблица зеркалирования (адрес кратен 256)
LD B,#00
MIRR_L1 LD A,L
LD C,#08
MIRR_L2 RLA
RR E
DEC C
JR NZ,MIRR_L2
LD (HL),E
INC L
DJNZ MIRR_L1
RET
Зеркальный вывод байта спрайта LD:
LD B,high MIRROR_TAB
LD C,(HL)
DEC L
LD A,(BC)
LD (DE),A
INC E
Зеркальный вывод байта спрайта OR:
LD B,high MIRROR_TAB
LD A,(DE)
DEC E
LD C,A
LD A,(BC)
OR (HL)
LD (HL),A
INC L
А будет LASER BASIC 2 совместим с LASER BASIC хотя бы на уровне исходных кодов?
Оригинальный LB был когда-то широко распространён и описан в ранней Р.Ф. в литературе, имевшей широкое хождение.
Если, напротив, общего останется - одно название, то зачем его вообще "заимствовать"?
Первый LB, кажется, мог быть использован просто как компилятор чистого Spectrum Basic. Только, опять же, кажется, не работал корректно на 128k-машине, на 48k не давал использовать User Defined Graphics (режим Graph (CS + 9))...
Будет ли LASER BASIC 2 компиляторм Spectrum Basic'а, но лишённым этих ограничений оригинала?
- - - Добавлено - - -
А будет LASER BASIC 2 совместим с LASER BASIC хотя бы на уровне исходных кодов?
Имею в виду - на уровне интерпретатора.
- - - Добавлено - - -
оригинальный LASER BASIC я вообще не рассматриваю как серьёзный инструмент для разработки - на сегодняшний день есть более совершенные средства, генерирующие настоящий машинный код (в отличие от интерпретатора или компилятора LASER BASIC в пи-код). Поэтому я беру только принцип.
А как работал LASER Compiler - компилил пи-код вместе с интерпретатором - ну если говорить упрощённо, для людей весьма далёких от низкого уровня, таких как я и ещё с полдюжины людей здесь? Об этом ли говорилось в литературе года 92-94-го, когда писали, что существующие на тот момент компиляторы приписывают себя или свою часть, содержащую определённые процедуры, к самому скомпилированному коду, а также ни один из известных на тот момент в России компиляторов не поддерживал полностью полный набор инструкций интерпретатора Spectrum Basic? Почти дословно так писали в "Диалектах Бейсика для ZX Spectrum", "Как написать игру для ZX Spectrum на языке BASIC" и т.п.
А как работал LASER Compiler - компилил пи-код вместе с интерпретатором - ну если говорить упрощённо, для людей весьма далёких от низкого уровня, таких как я и ещё с полдюжины людей здесь?
очень похоже что после `компиляции` исходный текст программы практически неменяется. скорее он более быстро (по сравнению с родными процедурами) обрабатывается.
Oleg N. Cher только сотрясает воздух, показать что-то уровня HeartBroken или Venturama он не способен,
а эти игры практически целиком на скомпиленном бейсике, компилятор 83его года !!!
а авторы книжек вероятно не знали про HisoftBasic http://www.worldofspectrum.org/infoseekid.cgi?id=0008249
вот игра сделанная на нём http://www.worldofspectrum.org/infoseekid.cgi?id=0018540
Oleg N. Cher
15.09.2016, 00:31
А будет LASER BASIC 2 совместим с LASER BASIC хотя бы на уровне исходных кодов?Нет.
Первый LB, кажется, мог быть использован просто как компилятор чистого Spectrum Basic. Только, опять же, кажется, не работал корректно на 128k-машине, на 48k не давал использовать User Defined Graphics (режим Graph (CS + 9))...Вертикальный скроллинг оригинального LB использует буфер принтера для своей работы. В версии Михайлова/Мазницы, а также в LASER BASIC 2 это исправлено и есть возможность задавать экран или буфер для графического вывода.
Будет ли LASER BASIC 2 компиляторм Spectrum Basic'а, но лишённым этих ограничений оригинала?Нет. Я не вижу смысла разрабатывать компилятор Бейсика. LB2 как графическую библиотеку можно использовать из Оберона, Си и ассемблера.
А как работал LASER Compiler - компилил пи-код вместе с интерпретатором - ну если говорить упрощённо, для людей весьма далёких от низкого уровня, таких как я и ещё с полдюжины людей здесь?Там пристёгивался большой кодовый блок, а операторы Бейсика и Лазер Бейсика компилировались в его вызовы, по-моему, в шитый байт-код с прямой или косвенной адресацией, хотя я не уверен. Это уже не столь интересно, ибо: a) сильно медленнее машкода; b) пристёгиваются все графические подпрограммы, даже неиспользуемые.
Если, напротив, общего останется - одно название, то зачем его вообще "заимствовать"?Я заимствую название, ибо народ падок до слов и названий - от слова "Паскаль" млеет, а от слова "Оберон" морщится. Хотя по сути это почти одно и то же. А вообще - имею право, как автор. Я беру название LASER BASIC чтобы показать полную преемственность при работе с графикой. По сути же это не язык, не интерпретатор, просто графический движок. Как его ещё назвать, если он по сути и есть Лазер Бейсик, начиная с названий процедур и заканчивая логикой их работы?
Я не понимаю, почему вы вцепились в интерпретатор или псевдокомпилятор, ровно также как и в Бейсик. Вы в курсе, что основное достоинство языка Бейсик в том, что его интерпретатор помещался в довольно маленькое ПЗУ. Но это было ценно тогда, сегодня в этом смысла нет. Потому что есть более совершенные средства разработки, дающие чистый машкод очень недурного качества, выбирающие и пристёгивающие к вашей программе из всего кода только нужный. И всё это делается само нажатием одной кнопки. Да и языки есть покрасивше, поструктурнее.
- - - Добавлено - - -
goodboy, мели-мели языком, я вообще не гейммейкер. А ты небось лопатой копать соревноваться с экскаватором заманаешься. Кстати, это надо ещё доказать, что эти игры "практически целиком на скомпиленном бейсике, компилятор 83его года !!!", потому что это баян, такой же как "Буратина на лазер бейсике". Проверяется элементарно, за две минуты в дебаггере.
- - - Добавлено - - -
если говорить упрощённо, для людей весьма далёких от низкого уровня, таких как я и ещё с полдюжины людей здесь?Как раз для таких людей я и разрабатывал ZXDev, в основном. Но, правда, потом оказалось, что людям весьма далёким от низкого уровня нужны крутые библиотеки на асме, а асмеры не хотят их писать, потому что сильно круты, чтобы это курить, и заняты своими ништякамии, кто-то микрухи паяет, кто-то кодит какую-то одному ему понятную фигню, как-то так.
надо ещё доказать, что эти игры "практически целиком на скомпиленном бейсике, компилятор 83его года !!!", потому что это баян, такой же как "Буратина на лазер бейсике". Проверяется элементарно, за две минуты в дебаггере.
смотри на-здоровье, все игры от ShawBrothers. на чистом асме только вывод спрайтов
Oleg N. Cher
15.09.2016, 00:42
Инфа где-то об этом есть? Я давно утверждал, кстати, что на Обероне можно писать хорошие игры, особенно если будут хорошие библиотеки для работы с ними из этого самого Оберона, так что это только подтверждает мои идеи.
goodboy, я понимаю, что вам хочется чтобы я писал игры, и вы меня так подзуживаете, но все люди разные и делают то, что считают нужным. Если я и буду писать игры, то явно не для того, чтобы вы млели. Я вообще считаю что геймеры избалованы редкостно, пытаться им угодить - себе дороже. И труден хлеб, полученный с игромейкерства, и достаётся с каждым годом всё труднее.
А библиотечки себе попишу, почему нет. И с народом потрындю, здесь есть интересные люди, дают хорошие советы, показывают перспективу, смотрят на вещи под другим углом зрения.
Oleg N. Cher, goodboy проводил исследование кода из игр 3show brothers. Нашлось 100% совпадение с кодом компилятора mcoder.
Oleg N. Cher, goodboy, не вздумайте ссориться - не хватало только очередной форумной войны. :D :v2_dizzy_army:
- - - Добавлено - - -
Я заимствую название, ибо народ падок до слов и названий - от слова "Паскаль" млеет, а от слова "Оберон" морщится. Хотя по сути это почти одно и то же. А вообще - имею право, как автор.
Ой, поспорили бы с Вами западники.) Насчёт того, имеете ли право.
Моральное право - только разве с угла зрения российской морали. Но это строго говоря. Лично мне чаще как-то всё равно до прав английского бизнеса.
- - - Добавлено - - -
Я не понимаю, почему вы вцепились в интерпретатор или псевдокомпилятор, ровно также как и в Бейсик. Вы в курсе, что основное достоинство языка Бейсик в том, что его интерпретатор помещался в довольно маленькое ПЗУ. Но это было ценно тогда, сегодня в этом смысла нет. Потому что есть более совершенные средства разработки, дающие чистый машкод очень недурного качества, выбирающие и пристёгивающие к вашей программе из всего кода только нужный. И всё это делается само нажатием одной кнопки. Да и языки есть покрасивше, поструктурнее.
Я понимаю, на ПК знаю несколько О.О.П. Я.В.У.
Почему BASIC? Да народ любит не то что круче, а то, на что он больше времени потратил. От того же и Спектрум любят, кстати.)
Здесь BASIC знают и что-то не слишком маленькое на нём делали почти все. То же и на Западе. Там басечников больше, чем ассемблерщиков. Это здесь быть басечником - чуть ли не за позор порой считают. Часто и работу с любым ЯВУ на Спектруме не одобряют.
Но это уже в сторону.
BASIC родной, понятный и легендарный для людей здесь и там. Ещё раз: народ любит не то что круче, а то, на что он больше времени потратил. Отсюда войны на писишных форумах: что круче - Java, C# или растерявший популярность Delphi, Object Pascal. Своя рубашка ближе к телу.
Кстати, помимо Laser Basic и Laser Compiler, был ещё Laser Genius. Кажется это был пакет - ассемблер, редактор, дебаггер и т.п.
Можно использовать слово Laser, но зачем цепляться к слову Basic?
- - - Добавлено - - -
Может быть лучше что-то типа "LASER Studio" или "LASER IDE"?
Где-то в форуме было, bugsy тоже корпел над своей версией LASER BASIC 2 по юности.
Oleg N. Cher
16.09.2016, 01:12
Учитываю критику, пусть будет без слова Basic, просто пакет графических процедур Laser 2. Кстати, сам модуль и называется Laser2 изначально, просто комменты поправлю.
Я согласен с Вами насчёт ностальгии. Люди любят утолять её тем, что им приносило удовольствие и на что были потрачены силы и время. Я не исключение, поэтому кодирую для Спектрума и переписываю игры, но меня замучал перфекционизм, поэтому я переписываю всего несколько игр, но дотошно и годами. Конечно это не то, от чего бы затащился гудбой. Но зачем меня провоцировать? Я же его не обвиняю в том, что он плохой боксёр или, к примеру, биатлонист. Ну ведь бесит же. И я не устану объяснять свою позицию: каждый относится по-разному к компу. Для железячника это набор деталей. Для программиста - площадка его деятельности и рабочее место. Для домохозяйки это способ посплетничать в соцсетях. И т.д. Так же люди относятся и к играм. Для программиста игр игры это его деятельность. Для меня игры (некоторые) это произведения искусства. Я ими восхищаюсь, пытаюсь повторить. Но разрабатывать крутые игры с нуля - это вне моих интересов. Мои интересы - это языки программирования, трансляция и т.п. Ещё раз: я не обязан разрабатывать игры, так зачем брать на слабо? Берите и делайте сами, раз вам хочется. Делайте на Бейсике, делайте на чём угодно. Ну а в моём меню сегодня Оберон. С лазерным прицелом. ;-)
Что касается западной модели купить слово, обозвать его "слово (R)", и чтобы все остальные не имели права ничего им называть - это их дрянное капиталистическое уродство. Когда продаются слова - значит что-то в обществе не так. Но это сугубо моё мнение. Ваше при вас, не собираюсь развивать эту тему.
ZX_NOVOSIB
16.09.2016, 10:00
Oleg N. Cher только сотрясает воздух, показать что-то уровня HeartBroken или Venturama он не способен,
а эти игры практически целиком на скомпиленном бейсике, компилятор 83его года !!!
goodboy, мели-мели языком, я вообще не гейммейкер. А ты небось лопатой копать соревноваться с экскаватором заманаешься.
Я давно утверждал, кстати, что на Обероне можно писать хорошие игры, особенно если будут хорошие библиотеки для работы с ними из этого самого Оберона, так что это только подтверждает мои идеи.
goodboy, я понимаю, что вам хочется чтобы я писал игры, и вы меня так подзуживаете, но все люди разные и делают то, что считают нужным. Если я и буду писать игры, то явно не для того, чтобы вы млели. Я вообще считаю что геймеры избалованы редкостно, пытаться им угодить - себе дороже. И труден хлеб, полученный с игромейкерства, и достаётся с каждым годом всё труднее.
Но зачем меня провоцировать? Я же его не обвиняю в том, что он плохой боксёр или, к примеру, биатлонист. Ну ведь бесит же. И я не устану объяснять свою позицию: каждый относится по-разному к компу. Для железячника это набор деталей. Для программиста - площадка его деятельности и рабочее место. Для домохозяйки это способ посплетничать в соцсетях. И т.д. Так же люди относятся и к играм. Для программиста игр игры это его деятельность. Для меня игры (некоторые) это произведения искусства. Я ими восхищаюсь, пытаюсь повторить. Но разрабатывать крутые игры с нуля - это вне моих интересов. Мои интересы - это языки программирования, трансляция и т.п. Ещё раз: я не обязан разрабатывать игры, так зачем брать на слабо? Берите и делайте сами, раз вам хочется. Делайте на Бейсике, делайте на чём угодно. Ну а в моём меню сегодня Оберон. С лазерным прицелом. ;-)
Oleg N. Cher , у меня идея! :rolleyes: Возьми чужие красивые спрайты, чужие звуковые эффекты и... нет, конечно не делай крутую игру, ты же не геймейкер. Но сделай просто демо-игру, без смысла, без сюжета, без тонн графики. Просто пару экранов (или скроллинг), главный герой имеет полоску энергии и жизни, главным героем можно управлять, его движения анимированы, на экране перемещающиеся враги, столкновения с ними вызывают потерю энергии, а затем и жизни. Пусть ГГ имеет возможность чем-нибудь стрелять во врагов. Столкновения объектов отслеживается и сопровождается звуками. Всё это плавно и красиво. В итоге ты и времени/сил затратишь в сто раз меньше, чем если бы ты делал настоящую игру уровня вышеупомянутой HeartBroken, но и люди наконец перестанут к тебе постоянно приставать и обвинять в сотрясании воздуха, будет достигнут некий компромис. И волки будут сыты и овцы целы ;)
На обероне можно повторить буратино? ) Если да, то быть может можно взять графику и повторить, просто одну стартовую улицу, не всю игру конечно.
Oleg N. Cher
16.09.2016, 20:18
Резонное предложение, просто мне это не интересно - браться за что-то новое, когда лежит куча незаконченных проектов. В XDev тоже много хвостов. Кто будет делать экспорт константных массивов, рефакторинг компилятора, убирать лимит на длину строк, добавлять возможность сохранять исходники в разных кодировках, адаптировать сборщик мусора для 64 бит? Вы, что ли, господа? ;-) Нет. То-то же. Потому что это слишком специфично. И вам неинтересно. А я знаю, что кроме меня это вряд ли кто-то сделает.
Скажу, что мне интересно. Интересно посмотреть как будут делать игры на ZXDev. Интересно пообщаться с гейммейкерами, которые будут делать игру, поконсультировать их, в процессе узнать, что нужно доделать в ZXDev, чтобы было круто. По сути то ZXDev это отличная база для ностальгии, просто без Бейсика. Там можно программить как на Supercode. Или как на Laser. Или как на Паскале. Я утоляю ностальгию по Спектруму, ТурбоПаскалю, Дельфи, Модуле-2 и низкоуровневому кодингу с помощью всего-навсего Оберона и ZXDev. И по сути Оберон очень близок к QuickBasic. Это действительно так. Просто Квик больше завязан на DOSе, а Оберон наоборот - более платформенно нейтрален, но проще и мощнее Квика. Можно ностальгировать без Бейсика, господа. Да, книг по этому делу нет. Но это увы. Есть статья. Читайте. Пишите сами. Спрашивайте вопросы. Предлагайте библиотеки и процедуры. Не всё же мне самому делать?
- - - Добавлено - - -
Несколько, правда, непонятно, что должна показать такая поделка: что ZXDev как средство разработки мощнее компилятора Бейсика 83его года? Так, по-моему, это очевидно. Или нет? И, раз графические процедуры в играх 3show brothers такие мощные, неплохо бы узнать что они делают и как устроены. Впрочем, я что-то очень сомневаюсь, что HeartBroken на Бейсике.
Впрочем, не возражаю против такого эксперимента. Начать нужно с адаптации графической библиотеки Вячеслава Медноногова - Graphic Library v1.1 (http://zxpress.su/article.php?id=9972) для ZXDev. Мне нужен доброволец, который хочет этим заняться. Знание ассемблера желательно в самом минимальном объёме. Готов оказать поддержку онлайн в удобном для вас формате, таким образом, сделаем эту адаптацию вместе. Доброволец научится и будет уже сам адаптировать код. Потом прикладная часть, что уже не так интересно.
Да, была мысль адаптировать к ZXDev также графический движок Grax (Fairlight). Всё руки не доходят. :-(
Smalovsky
16.09.2016, 22:11
Библиотеки - это хорошо. Только где взять редакторы спрайтов( кроме редакторов лазер и мега бейсиков) для них? Для писи нужны редакторы, так как уже популярны кросс-компиляторы( общеринятый компилятор си к примеру;-)). Вся программа - код и данные делаются на писи, затем собираются в образ с помощью утилит.
Bedazzle
16.09.2016, 22:21
графический движок Grax (Fairlight).
После дефлорации ХОТМ было бы интересно его распотрошить, но боюсь, что не хватит познаний в математике осознать как устроено.
Oleg N. Cher
16.09.2016, 22:57
Ну хотя бы повторить как есть, не особо вникая. Хотя piotr433 же переписал его на Си (http://zx-pk.ru/showthread.php?t=13827), так что это стало сильно проще.
Smalovsky, да есть редакторы на ПИСИ. и конвертеры есть, и утилиты. Не пойму в чём проблема. Если бы Вы сказали, к примеру, что художников и музыкантов нет. Вот это было бы грустно. Но редакторы - их валом, бери какой хочешь. Мотайте до раздела "Работа с ZX графикой на PC":
http://trd.speccy.cz/pcutilz.php
Bedazzle
16.09.2016, 23:06
Хотя piotr433 же переписал его на Си (http://zx-pk.ru/showthread.php?t=13827)
Скорее так (http://zx-pk.ru/threads/26129-grax-%E2%80%94-graficheskij-dvizhok-igry-fairlight.html)
Smalovsky
17.09.2016, 08:43
Oleg N. Cher, редакторы вроде есть, только они редактируют экран, а не спрайты. Нужен редактор для спрайтов.
Bedazzle
17.09.2016, 09:00
Oleg N. Cher, редакторы вроде есть, только они редактируют экран, а не спрайты. Нужен редактор для спрайтов.
Такое (http://www.zx-modules.de/zxpaintbrush/zxpaintbrush.html) есть. Вот чего реально не хвает - возможности делать анимированные спрайты.
Alex Rider
17.09.2016, 12:40
Учитываю критику, пусть будет без слова Basic, просто пакет графических процедур Laser 2. Кстати, сам модуль и называется Laser2 изначально, просто комменты поправлю.
Переименовать тему чтобы больше не было претензий к названию?
Alex Rider, Предлагаю: "LASER SPRITES LIBRARY 2 для ZXDev"
- - - Добавлено - - -
Или для SDCC ?
Oleg N. Cher
17.09.2016, 21:40
Но Laser это не только спрайты, это же вообще графический движок. Пусть тема называется как есть, я же вас на неё ловлю. ;-) Есть мысль сделать для Бейсик-людей таблицу соответствия операторов ZX-Basic процедурам и операторам Оберона. Не завалялась ни у кого табличка операторов ZX-Basic в Excel или Word, на основе которой можно это сделать?
Тогда все увидят, что Оберон - это правильный Бейсик, с веткой ELSE, с циклом WHILE, с процедурами и т.п. Чего я и добиваюсь, потому что люди очень цепляются за слова, иногда скрадывая за ними суть.
- - - Добавлено - - -
Reobne, и для ZXDev, и для SDCC.
Smalovsky
17.09.2016, 22:46
Игровое меню. Лень заполнять служебное окно. Пока от спрайтов отказываюсь в пользу UDG, так как нет редактора спрайтов.
58249
Лень заполнять служебное окно
сделай его одним цветом с бордюром,
будет не-так бросаться в глаза
Oleg N. Cher
18.09.2016, 05:19
Реализовал AWLV, SL8V, SR8V, WL8V, WR8V и PTNV. Осталось сделать зеркалирование, горизонтальные сдвиги на 1 и 4 бита, вертикальные сдвиги и вывод спрайта за пределами экрана. На чём план-минимум будем считать выполненным. Остальное по запросу.
PTNV - это новая операция: инверсный вывод спрайта. Ранее в Лазере приходилось сначала инвертировать спрайт в памяти, выводить и инвертировать опять, чтобы вернуть в исходное состояние. Теперь вывод инверсного спрайта так же эффективен, как и обычного (4 такта на CPL против 4-х на NOP).
Насчёт зеркалирования. Уверен, что буфер не нужен. Логика такая: есть зеркалируемая область, построчно берём первый и последний байт картинки, зеркалим и меняем местами, т.е. на место первого записываем зеркальный последний, на место последнего зеркальный первый, далее берём два следующих байта и т.д. Последний (средний) байт может оказаться один, если длина строки непарная, тогда мы его просто зеркалим.
В связи с чем вопрос: чтобы поменять в байте порядок битов на обратный (отзеркалить) можно ли действовать эффективнее, чем в этой процедурке?
; Подпрограмма зеркального отображения байта в аккумуляторе
MIRV0 RLA
RR B ;отображенный байт получится в B
RLA
RR B
RLA
RR B
RLA
RR B
RLA
RR B
RLA
RR B
RLA
RR B
RLA
RR B
RET
В связи с чем вопрос: чтобы поменять в байте порядок битов на обратный (отзеркалить) можно ли действовать эффективнее, чем в этой процедурке?
Да, таблицей... :v2_dizzy_facepalm:
Игровое меню. Лень заполнять служебное окно. Пока от спрайтов отказываюсь в пользу UDG, так как нет редактора спрайтов.
Pr.7z
А как же: http://vtrdos.ru/system.php#s28
или нужен на пц?
Oleg N. Cher
18.09.2016, 14:27
drbars, это не моя процедура :-) Это из книжки "Как написать игру на ассемблере".
По поводу хранения спрайта строками. Фактически переход к следующему байту строки это INC L (INC E), а к следующему байту столбца - INC H (INC D). Равнозначно. От постолбцового вывода выигрыш на спрайтах маленького размера, < 8. На практике таких спрайтов большинство. И наоборот - для вывода больших спрайтов-пейзажей обычно не требуется особая скорость (если требуется - применяются совсем другие методы). Потому что по столбцам во внутреннем цикле гарантированно выводится 8 байт, а по строкам меньше. А LDI использовать нельзя - у нас логические операции.
Oleg N. Cher, следующий этап — сохранение фона перед выводом спрайта, и при последующем выводе восстановление и новое сохранение. В случае использования логических наложений, особенно с маской это обязательно.
Oleg N. Cher
18.09.2016, 15:46
Знаю, drbars. Но тут для меня начинается высшая математика и что-то непостижимое. Есть люди, которые самыми неприхотливыми средствами делают настоящие чудеса, я могу только восторгаться или мечтать повторить. С масочными спрайтами работал только один раз, это был вывод пушечного ядра в игре SeaFight, и делался он точками, притом процедурой в ПЗУ.
Oleg N. Cher, вот пример... вывод спрайта с маской без таблиц движения. Делал для игры, но потом переписал под табличный способ.
http://zx-pk.ru/threads/23544-vyvod-sprajta-po-x-y.html
Alex Rider
19.09.2016, 16:58
я же вас на неё ловлю. ;-)
:v2_thumb:
- - - Добавлено - - -
чтобы поменять в байте порядок битов на обратный (отзеркалить) можно ли действовать эффективнее, чем в этой процедурке?
А эффективнее по памяти или по скорости? По скорости таблица вне конкуренции - 32 такта на байт.
- - - Добавлено - - -
Но тут для меня начинается высшая математика и что-то непостижимое.
Чем-то помочь, рассказать?
- - - Добавлено - - -
Oleg N. Cher, следующий этап — сохранение фона перед выводом спрайта, и при последующем выводе восстановление и новое сохранение.
Для этого в библиотеке надо поддержать непрямоугольные спрайты, иначе для фигуристых спрайтов будет работать очень медленно и жрать пямять. Вот тут как бы и начинается специфика Спектрума: в одних играх спрайты прямоугольные и такие извращения будут тормозить, в других нудна поддержка непрямоугольных спрайтов, в результате общие библиотеки неэффективны, каждый пишет своё с учетом 1000 и одного нюанса.
Oleg N. Cher
19.09.2016, 21:27
Alex Rider, я обязательно воспользуюсь любезным предложением помочь с матчастью: туда дальше вынесу на общую разработку пару своих идей игр, просто не надеюсь, что кто-то захочет присоединиться, из-за чего интерес не очень сильный. А так - художник нужен, музыкант, возможно, хард-кодер ассемблерщик. Но двигаться конечно планирую в своём контексте, т.е. писать на Обероне.
То, что есть специфика, и её надо учитывать - никакой библиотекой не поправишь. И так в любом деле. В книге "Как написать игру на ассемблере" есть вывод спрайтов произвольной конфигурации. И процедура там приводится очень простая. Но она так проста лишь только потому, что там координаты для вывода спрайта знакоместа вшиты в сам спрайт, в каждое его знакоместо. Если там хранить смещения и прибавлять к ним при выводе реальные координаты, пересчитывая их в адреса экрана и атрибутов, угадайте что будет? Правильно - будет довольно тормознуто.
Я просто не собираюсь писать игры со всякими фигурными спрайтами, масками и прочим, отсюда и такой скромный круг задач, которые я перед собой ставлю. Выше головы не прыгнешь - пусть игры делают те, у кого талант. Я со своей стороны буду совершенствовать ZXDev.
Про зеркалирование: конечно интереснее оптимизировать по скорости, но если табличка будет 256 байт, а у меня в игре всего один спрайт, который нужно зеркалить, и он шириной 2 знакоместа, то тут начинается стрельба по воробьям. :) В целом же было бы интересно сделать максимально эффективно по скорости, разумно по памяти, но без таблицы.
На обероне можно повторить буратино? ) Если да, то быть может можно взять графику и повторить, просто одну стартовую улицу, не всю игру конечно.ZX_NOVOSIB, как видим, желающих клонировать Буратино не наблюдается. Никому не интересно. :)
P.S. Кстати, я адаптировал к ZXDev пару процедур атрибутного скроллинга из Supercode. То есть, Supercode намечен. Присоединяйтесь.
+ ZXDev/Lib/Supercode. Attribute_Scr_Left (#39) & Attribute_Scr_Right (#40). (https://github.com/Oleg-N-Cher/XDev/commit/c9afe3220b1cb95f0f4c072a0c4c043cb7f7ed13)
http://i.piccy_.info/i9/b6d3ca53436019bed0a81c89024d4291/1474309563/20768/1065564/Supercode.png
Bedazzle
20.09.2016, 11:52
Про зеркалирование: конечно интереснее оптимизировать по скорости, но если табличка будет 256 байт, а у меня в игре всего один спрайт, который нужно зеркалить, и он шириной 2 знакоместа, то тут начинается стрельба по воробьям.
Так может дать возможность выбора разработчику - скорость или размер?
- - - Добавлено - - -
Если нужно развернуть не один байт, а изображение спрайта в памяти,
то обработать попарно можно так (для простоты только внутренний цикл):
col_mirror_loop:
dec hl
ld a, (de)
ld c, (hl)
; ------------------
; byte mirroring
; ------------------
DUP 8
rla
rr c
EDUP
; ------------------
rla
ld (de), a
ld (hl), c
inc de
djnz col_mirror_loop
Alex Rider
20.09.2016, 14:15
Alex Rider, я обязательно воспользуюсь любезным предложением помочь с матчастью: туда дальше вынесу на общую разработку пару своих идей игр, просто не надеюсь, что кто-то захочет присоединиться, из-за чего интерес не очень сильный.
Я больше про рассказать что-нить более понятным языком. Возможно по Skype, возможно, с реализацией в прямом эфире. Сам писать не хочу.
Oleg N. Cher
20.09.2016, 17:44
Слышали анек про работника кроватного завода, который тащил детальки и собирал дома - то автомат получается, то пистолет. ;-) Так и я, не пойдёт мне эта теория впрок. Максимум, что я могу, это написать с её помощью что-то, положить такую процедуру бережно в либу и сдувать с неё пыль. Но к дизайну либы хорошо бы если бы приложил руку более опытный гейммейкер.
drbars, Bedazzle, благодарю. С миррорингом более или менее всё ясно.
Я реализовал AWRV, SL1V, SR1V, WL1V, WR1V. Байтовый (на 8 точек) и битовый (на 1 точку) скроллинг - обычный и циклический - проблем не вызвал. Больше вопросов вызывает горизонтальный скроллинг на 4 бита. Есть идея, как сделать его оптимально? Навскидку приходит на ум только побитовый сдвиг 4 раза и потом логическое наложение AND #F : OR x ( AND #F0 : OR x ).
Bedazzle
20.09.2016, 18:05
Навскидку приходит на ум только побитовый сдвиг 4 раза
Ещё как вариант использовать
https://i.imgur.com/SIevaIz.png
Oleg N. Cher
21.09.2016, 00:34
Да, действительно. Лучше этих команд ничего и не придумаешь. Годится. :)
void Laser2_SL4V (unsigned char col, unsigned char row, unsigned char len, unsigned char hgt) __z88dk_callee
{
__asm
POP DE
POP BC ; C = col; B = row
CALL _Laser2_XYtoScr
POP BC ; C = len; B = hgt
PUSH DE
LD A, C
DEC A
ADD L
LD L, A
SL4V_HLINE$: PUSH BC
LD D, #8
LD E, L
SL4V_ROLL_LINE8$: LD B, C
XOR A
SL4V_ROLL_LINE$: RLD
DEC L
DJNZ SL4V_ROLL_LINE$
LD L, E
INC H
DEC D
JR NZ, SL4V_ROLL_LINE8$
LD A, L
ADD #0x20 ; Next charline
LD L, A ; If carry then jump to next third of screen
JR C, SL4V_CONT_1_3$
LD A, H
SUB #8 ; HL := HL - 0x0800
LD H, A
SL4V_CONT_1_3$: POP BC
DJNZ SL4V_HLINE$ ; End of loop on charlines (the same third)
__endasm;
} //Laser2_SL4V
Oleg N. Cher
22.09.2016, 00:46
Реализовал SL4V, SR4V, WL4V, WR4V, MIRV и MARV. Зеркалирование экрана использует код, предложенный Bedazzle (http://zx-pk.ru/threads/26921-laser-basic-2.html?p=885725&viewfull=1#post885725). Для зеркалирования атрибутов удалось использовать команду LDI. Такты не считал, но думаю, получилось хорошо.
58292
Мне остался только вертикальный скроллинг окна (вверх и вниз) на произвольное кол-во пикселей, обычный и циклический. И писать его не хочется, с удовольствием слямзил бы готовый.
- - - Добавлено - - -
Всё-таки посчитал такты. Неа, LDI здесь не эффективнее. Такой расклад.
MARV_MIRR_LINE$: LD A, (DE) ; 7
LDI ; 16
DEC L ; 4
LD (HL), A ; 7
INC L ; 4
DEC DE ; 6
DEC E ; 4
DJNZ MARV_MIRR_LINE$ ; 48t, 8 bytes
MARV_MIRR_LINE$: LD A, (DE) ; 7
LD C, (HL) ; 7
LD (HL), A ; 7
LD A, C ; 4
LD (DE), A ; 7
INC L ; 4
DEC E ; 4
DJNZ MARV_MIRR_LINE$ ; 40t, 7 bytes
Зеркалирование экрана использует код, предложенный Bedazzle (http://zx-pk.ru/threads/26921-laser-basic-2.html?p=885725&viewfull=1#post885725)
Удалил более быстрый и короткий пример.
Oleg N. Cher
22.09.2016, 04:19
drbars, код Bedazzle зеркалит сразу 2 байта одним махом. Чего и требуется.
Если я что-то не так понял, прошу объяснить, а не удалять.
- - - Добавлено - - -
drbars, ваш пример оптимальнее для зеркалирования одного байта, и с этим никто даже не собирался спорить. А тут сразу два байта. Если вы внимательно подумаете, то поймёте, что в моём случае (зеркалится окно) код Bedazzle оптимальнее.
Так что зря удалили.
Bedazzle
22.09.2016, 06:47
код Bedazzle оптимальнее.
Мной он только выковырян.
Oleg N. Cher
22.09.2016, 12:48
drbars, ну что это за "барышня обиделась"? Восстановите посты, могут кому-то пригодиться. В т.ч. и мне потом, мало ли.
Господа, у кого-то они остались в кэше браузера? Запостите. (У меня нет, долбанный Chrome)
Bedazzle
22.09.2016, 14:28
Господа, у кого-то они остались в кэше браузера?
эти?
; mirror byte (example 2)
; 17 bytes, 66 t.
LD C,A
RLCA
RLCA
XOR C
AND %10101010
XOR C
LD C,A
RLCA
RLCA
RLCA
RRC C
XOR C
AND %01100110
XOR C
; Результат = reg A.
Так же, если проблема со свободными регистрами можно использовать только аккумулятор.
18 bytes
LD A,(HL)
RLCA
RLCA
XOR (HL)
AND %10101010
XOR (HL)
LD (HL),A
RLCA
RLCA
RLCA
RRC (HL)
XOR (HL)
AND %01100110
XOR (HL)
LD (HL),A
Oleg N. Cher
22.09.2016, 14:43
Вот моя процедура зеркалирования окна. Если вы видите как её оптимизнуть (не для демостроя, без таблиц), то милости прошу. У нас техническая тема, так что по возможности без эмоций, ладно?
void Laser2_MIRV (unsigned char col, unsigned char row, unsigned char len, unsigned char hgt) __z88dk_callee
{
__asm
POP DE
POP BC ; C = col; B = row
CALL __Laser2_XYtoScr
POP BC ; C = len; B = hgt
PUSH DE
LD A, C
LD (MIRV_WIDTH$+1), A
INC A
SRL A
LD (MIRV_WIDTH_DIV2$+1), A
MIRV_HLINE$: PUSH BC ; Begin of loop on charlines
LD A, #8
MIRV_LINE8$: EX AF, AF
LD (MIRV_SCR_ADR$+1), HL
LD A, L
MIRV_WIDTH$: ADD #0
LD E, A
LD D, H
MIRV_WIDTH_DIV2$: LD B, #0
MIRV_COL_MIRROR$: DEC E
LD A, (DE)
LD C, (HL)
; ------------------
; 2 bytes mirroring
; ------------------
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
; ------------------
RLA
LD (DE), A
LD (HL), C
INC L
DJNZ MIRV_COL_MIRROR$
MIRV_SCR_ADR$: LD HL, #0
INC H
EX AF, AF
DEC A
JR NZ, MIRV_LINE8$
LD A, L
ADD #0x20 ; Next charline
LD L, A ; If carry then jump to next third of screen
JR C, MIRV_CONT_1_3$
LD A, H
SUB #8 ; HL := HL - 0x0800
LD H, A
MIRV_CONT_1_3$: POP BC
DJNZ MIRV_HLINE$ ; End of loop on charlines (the same third)
__endasm;
} //Laser2_MIRV
Oleg N. Cher
25.09.2016, 02:49
Сделал вывод спрайта с отсечением невидимой части, не помещающейся на экране. Кода понадобилось дофига прилично (+ байт 300). В приложенном архиве чудик, выбегающий из-за экрана и убегающий туда же, и двигающийся большой спрайт, которым можно рулить QAOP.
58322
Дайте верт. скроллинг знакоместного окна на произвольное к-во пикселов, ну плиз! Так вломы писать! %) Может кто-то расковыривал SCROLL и SCROLLW из Mega Basic (http://zxpress.su/book_articles.php?id=43)?
- - - Добавлено - - -
В Laser2 можно иметь спрайты размером превышающие размер экрана. Как с этим обстоят дела в оригинальном Laser Basic - не знаю. Скорее всего, тоже можно.
Oleg N. Cher
28.09.2016, 15:31
Как может выглядеть PIXEL_ADD, адаптированный для работы с экраном (буфером), размещённым по произвольному адресу?
22B0 LD B,A
22B1 AND A
22B2 RRA
22B3 SCF
22B4 RRA
22B5 AND A
22B6 RRA
22B7 XOR B
22B8 AND A,F8H
22BA XOR B
22BB LD H,A
22BC LD A,C
22BD RLCA
22BE RLCA
22BF RLCA
22C0 XOR B
22C1 AND A,C7H
22C3 XOR B
22C4 RLCA
22C5 RLCA
22C6 LD L,A
22C7 LD A,C
22C8 AND A,07H
22CA RET
Oleg N. Cher
10.10.2016, 22:36
Искомый PIXEL_ADD, адаптированный для работы с экраном (буфером), размещённым по произвольному адресу.
; Вычисляем в HL адрес байта в экранной области
ld a,(_X1) ; 13
ld c,a ; 4
rra ; 4
rra ; 4
rra ; 4
and #1F ; 7
ld l,a ; 4
ld a,(_Y1) ; 13
ld b,a ; 4
and #38 ; 7
rla ; 4
rla ; 4
or l ; 4
ld l,a ; 4
ld a,b ; 4
and #07 ; 7
ld h,a ; 4
ld a,b ; 4
and #C0 ; 7
rra ; 4
rra ; 4
rra ; 4
or h ; 4
ScrHighByte: or #40 ; 7
ld h,a ; 4
ret ; 10Старший байт адреса экрана (или буфера) пишется подпрограммой настройки по адресу ScrHighByte+1.
В Laser2 я использую модифицированную версию этого кода, чтобы задавать Y в пикселях, а X в знакоместах, так что код получается проще.
Благодарю AzAtom'а за эту процедуру.
Искомый PIXEL_ADD, адаптированный для работы с экраном (буфером), размещённым по произвольному адресу.
; Вычисляем в HL адрес байта в экранной области
ld a,(_X1) ; 13
ld c,a ; 4
rra ; 4
rra ; 4
rra ; 4
and #1F ; 7
ld l,a ; 4
ld a,(_Y1) ; 13
ld b,a ; 4
and #38 ; 7
rla ; 4
rla ; 4
or l ; 4
ld l,a ; 4
ld a,b ; 4
and #07 ; 7
ld h,a ; 4
ld a,b ; 4
and #C0 ; 7
rra ; 4
rra ; 4
rra ; 4
or h ; 4
ScrHighByte: or #40 ; 7
ld h,a ; 4
ret ; 10Старший байт адреса экрана (или буфера) пишется подпрограммой настройки по адресу ScrHighByte+1.
В Laser2 я использую модифицированную версию этого кода, чтобы задавать Y в пикселях, а X в знакоместах, так что код получается проще.
Благодарю AzAtom'а за эту процедуру.
выделенное жирным надо заменить на
ScrHighByte: add a,#40 ; 7
иначе адрес не произвольный
Oleg N. Cher
25.10.2016, 11:23
Хочу подвести итоги по проекту.
Проект Laser 2 успешно доведён до требуемой кондиции и показал себя в работе хорошо и стабильно. Я реализовал-таки вертикальный нециклический скроллинг вверх и вниз. И ещё циклический скроллинг вверх (с буфером) на 1 пиксель. Перевёл порт игры на Laser 2, и бинарь стал меньше примерно на килобайт.
http://i.piccy_.info/i9/cf309ff1a0416b54dfbe12f979682411/1477383059/5078/1081357/Laser2.png
Вроде выигрыш и маловатый, но это же графический движок с кодом высокой плотности. Да, ещё заметил, что Laser 2 заметно быстрее спрайты отрисовывает, чем Laser Михайлова/Мазницы. То, что он и быстрее, и компактнее - это ему плюс. А в дополнение в нём ещё и процедуры хорошо друг от друга изолированы, т.е. отдельно взятый вывод спрайтов или отдельный скроллинг не тянет с собой пол-движка (как в Laser).
Конечно в Laser 2 возможности Laser Basic реализованы далеко не полностью, но жизнь научила не программировать впрок, и того, что сделано, мне вполне достаточно для порта игры Дурак со взгляда перфекциониста. У меня просьба. Если будете что-то делать в этом направлении, давайте скоординируем все изменения. Если будете применять Laser 2 в своих проектах, напишите мне. Это же интересно, в конце концов. :-)
Ещё отличие Laser 2 от Laser: нет никакой проверки координат на выход за пределы экрана. Конечно при выводе спрайтов это учтено (в режиме OUT_OF_SCREEN спрайт может выходить за границы экрана), но во всех остальных случаях никаких проверок не производится. Это сделано для ускорения графического вывода.
Самая свежая версия библиотеки Laser 2 живёт здесь:
https://github.com/Oleg-N-Cher/XDev/blob/master/ZXDev/Lib/C/Laser2.hhttps://github.com/Oleg-N-Cher/XDev/blob/master/ZXDev/Lib/C/Laser2.c
Oleg N. Cher
26.10.2016, 00:14
Благодарю! И спасибо всем, кто участвовал в обсуждении.
Игорь, между прочим, именно ваш Laser и сподвиг меня в итоге на порт Дурака, из чего вылился проект ZXDev.
А вот как выглядит интерфейс для работы с Laser 2 на языке Оберон:
DEFINITION Laser2; (* non-portable *)
(***************************)
(* LASER 2 Graphic Engine *)
(* Coded by Oleg N. Cher *)
(* zx.oberon2.ru/forum *)
(***************************)
TYPE
ADR = LONGINT;
BUFFER = ARRAY OF CHAR;
SPRITES = ARRAY OF CHAR;
UBYTE = INTEGER;
(* New procedures: *)
PROCEDURE SCRL (adr: ADR) (* Init sprites *) ;
PROCEDURE SCRLv (adr: ADR) (* in variable *) ;
PROCEDURE SCRLa (buf: BUFFER) (* in array *) ;
PROCEDURE SPRT (adr: ADR) (* Init sprites *) ;
PROCEDURE SPRTv (adr: ADR) (* in variable *) ;
PROCEDURE SPRTa (sprites: SPRITES) (* array *) ;
PROCEDURE SCRN (adr: ADR) (* Set screen *) ;
(* Synonyms for the new procedures: *)
PROCEDURE InitScroll (adr: ADR) ;
PROCEDURE InitScrollV (adr: ADR) (* in var *) ;
PROCEDURE InitScrollA (buf: BUFFER) ;
PROCEDURE InitSprites (adr: ADR) ;
PROCEDURE InitSpritesV (adr: ADR) (* in var *) ;
PROCEDURE InitSpritesA (sprites: SPRITES) ;
PROCEDURE SetScreen (adr: ADR) ;
(* Sprite manipulations: *)
PROCEDURE ATOF ;
PROCEDURE ATON ;
PROCEDURE INVM (spn: UBYTE) ;
PROCEDURE PTBL (col, row: SHORTINT; spn: UBYTE) ;
PROCEDURE PTND (col, row: SHORTINT; spn: UBYTE) ;
PROCEDURE PTNV (col, row: SHORTINT; spn: UBYTE) ;
PROCEDURE PTOR (col, row: SHORTINT; spn: UBYTE) ;
PROCEDURE PTXR (col, row: SHORTINT; spn: UBYTE) ;
(* Screen windows processing: *)
PROCEDURE CLSV (col, row, len, hgt: UBYTE) ;
PROCEDURE INVV (col, row, len, hgt: UBYTE) ;
PROCEDURE MIRV (col, row, len, hgt: UBYTE) ;
PROCEDURE SDNV (col, row, len, hgt, npx: UBYTE) ;
PROCEDURE SUPV (col, row, len, hgt, npx: UBYTE) ;
PROCEDURE SL1V (col, row, len, hgt: UBYTE) ;
PROCEDURE SL4V (col, row, len, hgt: UBYTE) ;
PROCEDURE SL8V (col, row, len, hgt: UBYTE) ;
PROCEDURE SR1V (col, row, len, hgt: UBYTE) ;
PROCEDURE SR4V (col, row, len, hgt: UBYTE) ;
PROCEDURE SR8V (col, row, len, hgt: UBYTE) ;
PROCEDURE WL1V (col, row, len, hgt: UBYTE) ;
PROCEDURE WL4V (col, row, len, hgt: UBYTE) ;
PROCEDURE WL8V (col, row, len, hgt: UBYTE) ;
PROCEDURE WR1V (col, row, len, hgt: UBYTE) ;
PROCEDURE WR4V (col, row, len, hgt: UBYTE) ;
PROCEDURE WR8V (col, row, len, hgt: UBYTE) ;
PROCEDURE WU1V (col, row, len, hgt: UBYTE) ;
(* Attribute windows processing: *)
PROCEDURE AWLV (col, row, len, hgt: UBYTE) ;
PROCEDURE AWRV (col, row, len, hgt: UBYTE) ;
PROCEDURE MARV (col, row, len, hgt: UBYTE) ;
PROCEDURE SETV (col, row, len, hgt: UBYTE) ;
END Laser2.
Oleg N. Cher
26.12.2016, 02:49
Исправил досадную ошибку в CLSV и INVV (https://github.com/Oleg-N-Cher/XDev/commit/4baf8b499e7cf5a18a8214d474e3b8775264136c), связанную с некорректным вычислением адреса нижней строки знакомест.
Также пересобрал игру Бега мышей с помощью библиотеки Laser2 (http://zx.oberon2.ru/forum/viewtopic.php?f=10&t=190&p=1848#p1848). Интересно, что я делал ранее прогноз (http://zx.oberon2.ru/forum/viewtopic.php?f=10&t=190) и, как выяснилось, оказался прав:
Скомпилированная игра «Бега мышей» занимает сейчас 13 кб, и это очень много. Оптимизировать её по размеру кода можно в десятке направлений. Мой прогноз: в рамках технологии ZXDev её размер после оптимизации будет не больше 3,5 кб. И такая оптимизация желательна не только для уменьшения размера этой игры. Сама возможность оптимизации должна показать скептикам на практике переход от макета, подготовленного очень быстро, до эффективного компактного релиза.
Ну вот, сегодня всех обрадую: с библиотекой Laser2 игра стала весить 3175 байт. После hrust'а 2607 байт. Это не предел конечно, есть ещё возможности для мелких оптимизаций.
Oleg N. Cher
11.01.2017, 05:52
Тема «Графический движок Laser 2 (на концепте Laser Basic)» на Оберон-форуме:
http://zx.oberon2.ru/forum/viewtopic.php?f=10&t=298
Вот моя процедура зеркалирования окна. Если вы видите как её оптимизнуть (не для демостроя, без таблиц), то милости прошу. У нас техническая тема, так что по возможности без эмоций, ладно?
void Laser2_MIRV (unsigned char col, unsigned char row, unsigned char len, unsigned char hgt) __z88dk_callee
{
__asm
POP DE
POP BC ; C = col; B = row
CALL __Laser2_XYtoScr
POP BC ; C = len; B = hgt
PUSH DE
LD A, C
LD (MIRV_WIDTH$+1), A
INC A
SRL A
LD (MIRV_WIDTH_DIV2$+1), A
MIRV_HLINE$: PUSH BC ; Begin of loop on charlines
LD A, #8
MIRV_LINE8$: EX AF, AF
LD (MIRV_SCR_ADR$+1), HL
LD A, L
MIRV_WIDTH$: ADD #0
LD E, A
LD D, H
MIRV_WIDTH_DIV2$: LD B, #0
MIRV_COL_MIRROR$: DEC E
LD A, (DE)
LD C, (HL)
; ------------------
; 2 bytes mirroring
; ------------------
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
RLA
RR C
; ------------------
RLA
LD (DE), A
LD (HL), C
INC L
DJNZ MIRV_COL_MIRROR$
MIRV_SCR_ADR$: LD HL, #0
INC H
EX AF, AF
DEC A
JR NZ, MIRV_LINE8$
LD A, L
ADD #0x20 ; Next charline
LD L, A ; If carry then jump to next third of screen
JR C, MIRV_CONT_1_3$
LD A, H
SUB #8 ; HL := HL - 0x0800
LD H, A
MIRV_CONT_1_3$: POP BC
DJNZ MIRV_HLINE$ ; End of loop on charlines (the same third)
__endasm;
} //Laser2_MIRV
http://www.retroprogramming.com/2014/01/fast-z80-bit-reversal.html
Oleg N. Cher
17.05.2024, 02:20
Надо миррорить два байта, а не один, как по твоей ссылке, жерри.
Lethargeek
18.05.2024, 20:52
Вот моя процедура зеркалирования окна. Если вы видите как её оптимизнуть (не для демостроя, без таблиц),
что за утырочная мания объявлять всё, что не по нраву, "демостроем" с негативным оттенком
в играх зеркалирование табличное сплошь и рядом, даже в довольно древних
да и таблица-то всего лишь 256 байт
Oleg N. Cher
18.05.2024, 21:39
Демострой это определённой набор подходов и принципов, при которых ложат болт на нормальное использование памяти и забивают целые килобайты инструкциями типа LDI, шобы было "во фреймчик". А мне была нужна универсальная библиотека. Да и 256 байт это тоже память.
Lethargeek
18.05.2024, 21:48
Демострой это определённой набор подходов и принципов, при которых ложат болт на нормальное использование памяти и забивают целые килобайты инструкциями типа LDI, шобы было "во фреймчик". А мне была нужна универсальная библиотека. Да и 256 байт это тоже память.
только вот табличное зеркалирование - норма тех времён, когда и демок-то еще не было (хотя фреймовость местами уже была)
Oleg N. Cher
18.05.2024, 21:49
Ладно, не возражаю. В XDev такие штуки могут быть устроены опционально. Благодаря сишному препроцессору.
Держитесь, пацаны. Через несколько дней вас будут обращать в Оберон.
Oleg N. Cher
19.05.2024, 13:21
Аминь
Демострой это определённой набор подходов и принципов, при которых ложат болт на нормальное использование памяти и забивают целые килобайты инструкциями типа LDI, шобы было "во фреймчик". А мне была нужна универсальная библиотека. Да и 256 байт это тоже память.
А все от задачи зависит.
Если критично оптимизация по памяти это одно.
Но где-то критично быстродействие кода.
Я тут как-то ради быстродействия (не на спеке) сделал таблицу размером в 2ГБ. И всех это устроило, потому что иначе быстродействия не хватало. И ничего.
Oleg N. Cher
19.05.2024, 18:55
Да ясен пень, я ж и не спорю. Если всех всё устраивает
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot