PDA

Просмотр полной версии : Пишу шедевр для «Вектора 06Ц»



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

ivagor
03.08.2020, 18:53
lxi sp,im_stek ; временный указатель стека для прерываний
Он должен быть не на экране, где его шторка портит, а где-нибудь в свободном месте. Если это поправить, то работает как предыдущая версия.

metamorpho
03.08.2020, 19:22
Он должен быть не на экране, где его шторка портит, а где-нибудь в свободном месте. Если это поправить, то работает как предыдущая версия.

ivagor, спасибо !!
Исправил - получилось

KTSerg
03.08.2020, 19:25
Накатал счетчик вывода спрайтов.
Считает сколько раз за 10 секунд выводятся спрайты.
В данной версии, прерывания и вывод спрайта по алгоритму jerri.
Результат в hex.

Какой алгоритм воткнуть для сравнения?

Заменил программку.

Верхний результат вывод спрайтов по алгоритму jerri, нижний результат мой кривой алгоритм (по 4 строки в цикле).

metamorpho
03.08.2020, 19:45
Это что за 10 секунд почти 5 тысяч спрайтов выводит ?

Вот этот для сравнения проверь.


;================================================= =========
;Вывод квадратика 24x24 точки в сразу в три плоскости для статичных объектов
; вход HL - куда на экран выводить DE - адрес графики
SpriteC3qa:
PUSH H
PUSH D
PUSH B

MOV A,H ; сохраняем начало столбик X плоскость (1) куда выводим графику
STA pozic_xP1
MOV A,L
STA pozic_y; сохраняем начало строки Y куда выводим графику
mvi a,3
STA PLAST

LXI B,2000h
;====================== строка 1
fumbingo:
LDAX D ; загружаем акумулятор А содержимым графики
MOV M,A ; выводим в экран по адресу "HL" байт графики
INX D ; DE=DE+1 увеличиваем адрес откуда брать графику
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 2
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 3
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 4
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 5
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 6
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 7
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 8
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 9
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 10
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 11
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 12
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 13
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 14
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 15
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 16
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 17
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 18
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 19
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 20
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 21
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 22
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 23
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

DCR L ; ==================== строка 24
LDA pozic_xP1
MOV H,A ; адрес плоскости 1
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 2
LDAX D
MOV M,A
INX D
DAD B ; адрес плоскости 3
LDAX D
MOV M,A
INX D

LDA PLAST ; счётчик столбиков (всего 3)
dcr a
jz rimikoq ; если все три столбика нарисованы выходим из подпрограммы

STA PLAST
; следующий столбец X
LXI H,pozic_xP1
inr M
mov H,M
LDA pozic_y
MOV L,A ; восстанавливаем Y
jmp fumbingo

rimikoq:
;=============
POP B
POP D
POP H

RET ;иначе - выйти из п/п вывода квадратиков

KTSerg
03.08.2020, 20:46
...
Вот этот для сравнения проверь.
...

Фух, справился ;)
Верхние, как в прошлой версии. Нижний результат алгоритма metamorpho.

jerri
03.08.2020, 20:52
Фух, справился ;)
Верхние, как в прошлой версии. Нижний результат алгоритма metamorpho.

почему мой выдает больше?
вроде твой эффективней?

KTSerg
03.08.2020, 21:00
почему мой выдает больше?
вроде твой эффективней?
твой алгоритм успевает за 10 секунд вывести 1320h спрайтов,
14С4h - спрайтов моего алгоритма.
0BD0h - спрайтов алгоритм metamorpho.

jerri
03.08.2020, 21:26
твой алгоритм успевает за 10 секунд вывести 1320h спрайтов,
14С4h - спрайтов моего алгоритма.
0BD0h - спрайтов алгоритм metamorpho.

как хранит данные твой алгоритм?

у тебя же здесь процедуры на 24 линии раскатанные?

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


твой алгоритм успевает за 10 секунд вывести 1320h спрайтов,
14С4h - спрайтов моего алгоритма.
0BD0h - спрайтов алгоритм metamorpho.

как хранит данные твой алгоритм?



KTSerg,
добавь вот этот вот спрайтовый дроппер


;вывод спрайта в системе битпланов Вектор 06
;ширина спрайта -24
;на входе
;bc адрес спрайта
;de aдрес на экране
;E-Y D-X

drop24
ld hl,0
add hl,sp
ld (sprite_sp0),hl
ld h,b
ld l,c
ld c,(hl)
inc hl
ld b,(hl)
inc hl
ld sp,hl

;задаем Y в L
ld l,e
;задаем X в A
ld a,d ;битплан1
add a,#20
ld e,a ;битплан2
add a,#20 ;битплан3
drop240
dup 12

ld h,d
;рисуем на первом плане
ld (hl),c
inc h
ld (hl),b
inc h
pop bc
ld (hl),c
;переход на второй битплан
ld h,e
;рисуем на втором плане
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc
;переход на третий битплан
ld h,a
;рисуем на третьем плане
ld (hl),c
inc h
ld (hl),b
inc h
pop bc
ld (hl),c
;переходим на следующую строку
inc l
;возвращаемся на первый план
ld h,d
;повторяем цикл рисования
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc
;переход на второй битплан
ld h,e
;рисуем на втором плане
ld (hl),c
inc h
ld (hl),b
inc h
pop bc
ld (hl),c
;переход на третий битплан
ld h,a
;рисуем на третьем плане
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
;выбираем следующую пару байтов для цикла рисования
pop bc
edup

org $-1
sprite_sp
ld sp,#3131
sprite_sp0 equ $-2
ret

KTSerg
03.08.2020, 21:54
Накатал тот алгоритм про который писал ранее, в котором старший байт адреса на экране не вычисляется при переходе к следующей плоскости а вычислен заранее и хранится в регистре.
За 10 секунд этот алгоритм вывел 1558h спрайтов.


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

Полностью раскатанных нет.
Алгоритм тот выводит 4 строки за цикл. Данные хранятся ужасно.
Если байты в спрайте пронумеровать, то за один цикл выводятся байты с 1-го по 36-ой, и при выводе 4-ёх строк расположены они в плоскостях следующим образом:
в первой плоскости:
20 21 24
19 22 23
2 3 6
1 4 5
во второй плоскости:
29 28 25
30 27 26
11 10 7
12 9 8
в третьей плоскости;
32 33 36
31 34 35
14 15 18
13 16 17

вот, как-то так... :)

jerri
03.08.2020, 22:00
KTSerg, вот в этом варианте как раз я вычисляю адреса 3х плоскостей и перехожу по ним быстро
сам спрайт раскатан, потому как регистров под счетчик нет.

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



в первой плоскости:
20 21 24
19 22 23
2 3 6
1 4 5
во второй плоскости:
29 28 25
30 27 26
11 10 7
12 9 8
в третьей плоскости;
32 33 36
31 34 35
14 15 18
13 16 17

вот, как-то так... :)

ужас, правда если со стека берешь то можно нормально класть

2b 3b 6b
1с 4c 5c

KTSerg
03.08.2020, 22:06
KTSerg, вот в этом варианте как раз я вычисляю адреса 3х плоскостей и перехожу по ним быстро
сам спрайт раскатан, потому как регистров под счетчик нет.

Вот не знаю чем заменить "dup 12" и "edup"

jerri
03.08.2020, 22:13
Вот не знаю чем заменить "dup 12" и "edup"

повторить 12 раз кусок от dup до edup
и там последний pop bc убирается конструкцией org $-1

KTSerg
03.08.2020, 22:33
повторить 12 раз кусок от dup до edup
и там последний pop bc убирается конструкцией org $-1
Перед edup , случайно не пропущено inr l ?

в цикле, почему-то медленнее получилось чем предыдущая версия.
Результат 12D0h.
Цикл буду завтра, т.е. уже сегодня вечером разворачивать, глаза уже не видят ни чего... :(

jerri
03.08.2020, 23:03
Перед edup , случайно не пропущено inr l ?

в цикле, почему-то медленнее получилось чем предыдущая версия.
Результат 12D0h.
Цикл буду завтра, т.е. уже сегодня вечером разворачивать, глаза уже не видят ни чего... :(


;вывод спрайта в системе битпланов Вектор 06
;ширина спрайта -24
;на входе
;bc адрес спрайта
;de aдрес на экране
;E-Y D-X

drop24
ld hl,0
add hl,sp
ld (sprite_sp0),hl
ld h,b
ld l,c
ld c,(hl)
inc hl
ld b,(hl)
inc hl
ld sp,hl

;задаем Y в L
ld l,e
;задаем X в A
ld a,d ;битплан1
add a,#20
ld e,a ;битплан2
add a,#20 ;битплан3
drop240
dup 12

ld h,d
;рисуем на первом плане
ld (hl),c
inc h
ld (hl),b
inc h
pop bc
ld (hl),c
;переход на второй битплан
ld h,e
;рисуем на втором плане
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc
;переход на третий битплан
ld h,a
;рисуем на третьем плане
ld (hl),c
inc h
ld (hl),b
inc h
pop bc
ld (hl),c
;переходим на следующую строку
inc l

;возвращаемся на первый план
ld h,d
;повторяем цикл рисования
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc
;переход на второй битплан
ld h,e
;рисуем на втором плане
ld (hl),c
inc h
ld (hl),b
inc h
pop bc
ld (hl),c
;переход на третий битплан
ld h,a
;рисуем на третьем плане
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
inc l
;выбираем следующую пару байтов для цикла рисования
pop bc

edup

org $-1
sprite_sp
ld sp,#3131
sprite_sp0 equ $-2
ret

ага inr l пропущен

KTSerg
04.08.2020, 04:26
Не выдержала душа поэта... с утреца всё перелопатил.

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

Jerri_c:
lxi d,a_test_spr ; адрес спрайта на экране
lxi b,tab_spr0 ; адрес спрайта
push h ; сохранить счетчик
;
call drop24 ; вывод спрайта
;
pop h восстановить счетчик
inx h ; увеличение счетчика выводов спрайта на экран
;
lda StopFlag ; читаем флаг остановки
ora a ; проверка флага
jnz Jerri_c


И результат немного поменялся:
Оригинальный вариант алгоритма Jerri - 1380h
Вариант Jerri, с заранее вычисленными адресами битпланов, и полностью развёрнутый (без циклов) - 1603h

Мой оригинальный алгоритм - 151Eh
Мой с заранее вычисленными адресами битпланов - 15B2h

Алгоритм metamorpho, совсем не использующий стек - 0С0Сh
Алгоритм metamorpho, совсем не использующий стек и с обычным прерыванием в которои нет защиты стека - 0С0Eh

Во вложении сам тест и его исходник.

ivagor
04.08.2020, 05:44
Если здесь (https://zx-pk.ru/threads/31954-pishu-shedevr-dlya-%C2%ABvektora-06ts%C2%BB.html?p=1075244&viewfull=1#post1075244) добавить змейку по плоскостям, то еще -16 тактов на каждый edup. Варианты с циклами тоже можно ускорить и даже если без плоскостной змейки, но с ней выигрыш будет заметнее.

jerri
04.08.2020, 09:18
Если здесь (https://zx-pk.ru/threads/31954-pishu-shedevr-dlya-%C2%ABvektora-06ts%C2%BB.html?p=1075244&viewfull=1#post1075244) добавить змейку по плоскостям, то еще -16 тактов на каждый edup. Варианты с циклами тоже можно ускорить и даже если без плоскостной змейки, но с ней выигрыш будет заметнее.

За счёт чего 16 тактов?
Переход между любыми адресами 1 команда.

ivagor
04.08.2020, 09:25
-2 команды, каждая по 8 тактов, итого 16 тактов.

jerri
04.08.2020, 09:27
-2 команды, каждая по 8 тактов, итого 16 тактов.Какие именно?

ivagor
04.08.2020, 09:36
Сейчас 3 перехода между плоскостями на каждую строку, условно можно их назвать в 1, 2 и 3 плоскость. При змейке по плоскостям достаточно в 1й строке двух переходов: во 2 и 3 плоскость и во второй строке два перехода: во 2 и 1 плоскость.

jerri
04.08.2020, 10:13
Сейчас 3 перехода между плоскостями на каждую строку, условно можно их назвать в 1, 2 и 3 плоскость. При змейке по плоскостям достаточно в 1й строке двух переходов: во 2 и 3 плоскость и во второй строке два перехода: во 2 и 1 плоскость.Ты уверен? переход между битпланами сейчас занимает также 1 байт. Также как и движение в сторону.

ivagor
04.08.2020, 11:08
Набросал упомянутый ранее вариант, надеюсь принципиальных ошибок нет. Стоит отметить, что порядок вывода очень своеобразный, конвертер графики надо делать аккуратно.

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

Скопипастил у jerri описание и не поправил: D - не совсем X, это X+старшая половина адреса начальной плоскости.

jerri
04.08.2020, 11:25
Набросал упомянутый ранее вариант, надеюсь принципиальных ошибок нет. Стоит отметить, что порядок вывода очень своеобразный, конвертер графики надо делать аккуратно.

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

Скопипастил у jerri описание и не поправил: D - не совсем X, это X+старшая половина адреса начальной плоскости.Принципиальной разницы от моего последнего варианта не увидел.

Команда внесения данных +
команда перехода +
если надо снятие со стека данных.

Отличие необоснованно замороченный формат.

К вечеру выложу полноценную процедуру с контролем высоты спрайта.

ivagor
04.08.2020, 11:30
Принципиальной разницы от моего последнего варианта не увидел.
Тут будет решать тот, кто будет использовать - принципиальны ему -8 тактов на строку или нет.

jerri
04.08.2020, 11:31
Тут будет решать тот, кто будет использовать - принципиальны ему -8 тактов на строку или нет.Нет там -8 тактов на строку.

ivagor
04.08.2020, 11:49
Нет там -8 тактов на строку.
Есть. Если следующее сообщение будет "Нет", то отвечать не вижу смысла.

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

Конкретные цифры. Вариант jerri - 412 тактов на блок из двух строк, у меня - 396 тактов на блок из двух строк.

CodeMaster
04.08.2020, 11:51
Нет

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

jerri
04.08.2020, 15:03
Есть. Если следующее сообщение будет "Нет", то отвечать не вижу смысла.

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

Конкретные цифры. Вариант jerri - 412 тактов на блок из двух строк, у меня - 396 тактов на блок из двух строк.

ага рисуем так



бп0 0<<
бп1 >>0
бп2 >>0
v
бп2 0<<
бп1 >>0
бп0 >>0
v


-2 команды за счет перехода по текущему плану на линию вниз.

+ на 192 такта меньше моей
- для спрайтов нужен весьма интересный конвертер.

metamorpho
04.08.2020, 19:15
Пришлось повозиться с разными моментами при переходе на метод вывода спрайтов, который предложил Jerri (спасибо что посоветовал).
Но похоже усилия стоили того - скорость прибавилась явно.
На данный момент переделаны основные подпрограммы вывода спрайтов (остались ещё некоторые специфические).
Циклы ещё не разворачивал. Смотрите (rom) - "стресс-тест" для подпрограммы вывода спрайта - 10 движущихся объектов + герой + монетки.
Скорость анимации можно ускорить за счёт уменьшения паузы. При передвижении влево вправо у главного героя иногда проскальзывают мерцания (это код где в строке 4 байта выводятся). Но в целом вроде нормально.

CodeMaster
04.08.2020, 19:27
Смотрите (rom) - "стресс-тест" для подпрограммы вывода спрайта
Можно также выкладывать периодически видео с промежуточными результатами, для тех кто просто следит за темой?

ivagor
04.08.2020, 19:40
metamorpho, много спрайтов - это хорошо, но в последней версии стало более заметно мерцание/моргание "вертолетов". В принципе оно и в 13 было, но там их было меньше и не так бросалось в глаза.

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

Сделал Size 2:1 и вроде стало нормально (мигания "вертолетов" так не вижу), пардон, похоже ложная тревога.
В процедурах вывода спрайтов можно убрать лишние завершающие mov h,a по адресам 5425h и 5489h

metamorpho
04.08.2020, 20:50
Можно также выкладывать периодически видео с промежуточными результатами, для тех кто просто следит за темой?

Хорошо, периодически буду выкладывать видео :)


https://youtu.be/tBFvSYAkl5s

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


В процедурах вывода спрайтов можно убрать лишние завершающие mov h,a по адресам 5425h и 5489h

ivagor, спасибо за подсказку !!

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

(Возможно эту мысль уже писали, но может нет) может кому-то пригодится - я обнаружил, что при равёртывании цикла (в выводе спрайта по методу Jerri) освобождается регистр E.
И это можно использовать вот как:
в начале mvi e,40h
и вместо sui 40h (при возвращении на первый план) использовать sub e
эта команда на 4 такта меньше чем sui

jerri
04.08.2020, 21:55
(Возможно эту мысль уже писали, но может нет) может кому-то пригодится - я обнаружил, что при равёртывании цикла (в выводе спрайта по методу Jerri) освобождается регистр E.
И это можно использовать вот как:
в начале mvi e,40h
и вместо sui 40h (при возвращении на первый план) использовать sub e
эта команда на 4 такта меньше чем sui


вот тебе процедура с переменной высотой спрайта
с развернутым выводом по упрощенному методу

здесь все три регистра D E A заняты под указатели на битпланы.




;вывод спрайта в системе битпланов Вектор 06
;ширина спрайта -24
;на входе
;bc адрес спрайта
;de aдрес на экране
;E-Y D-X
;a-высота спрайта /2 1-12

drop24
dec a
add a,a
ld hl,table_high
add a,l
ld l,a
adc a,h
sub l
ld h,a
ld a,(hl)
inc hl
ld h,(hl)
ld l,a
ld (drop_exec),hl

ld hl,0
add hl,sp
ld (sprite_sp0),hl
ld h,b
ld l,c
ld c,(hl)
inc hl
ld b,(hl)
inc hl
ld sp,hl

;задаем Y в L
ld l,e
;задаем X в A
ld a,d ;битплан1
add a,#20
ld e,a ;битплан2
add a,#20
;битплан3
jp #c3c3
drop_exec equ $-2

table_high
dw drop_240
dw drop_241
dw drop_242
dw drop_243
dw drop_244
dw drop_245
dw drop_246
dw drop_247
dw drop_248
dw drop_249
dw drop_24a
dw drop_24b
drop24b
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop24a
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop249
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop248
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop247
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop246
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop245
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop244
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop243
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop242
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop241
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
pop bc
inc l
drop240
ld h,d
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,e
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,a
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c
inc l

ld h,d
ld (hl),b
inc h
pop bc
ld (hl),c
inc h
ld (hl),b
pop bc

ld h,e
ld (hl),c
inc h
ld (hl),b
pop bc
inc h
ld (hl),c

ld h,a
ld (hl),b
pop bc
inc h
ld (hl),c
inc h
ld (hl),b
sprite_sp
ld sp,#3131
sprite_sp0 equ $-2
ret

73220

кто там автор pretty asm?
добавьте туда конструкцию DUP/EDUP

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

а замирание врагов при упирании в стену я смотрю так и не устранил?

KTSerg
05.08.2020, 05:40
Хорошо, периодически буду выкладывать видео :)
...
Не могу вспомнить, в какой игрушке был аналогичный эффект, чем меньше на экране остается подвижных объектов, тем быстрее они начинают двигаться... :)

Это не вопрос.

jerri
05.08.2020, 05:45
Не могу вспомнить, в какой игрушке был аналогичный эффект, чем меньше на экране остается подвижных объектов, тем быстрее они начинают двигаться... :)

Это не вопрос.
Любые где нет контроля скорости.
Например galaxian

metamorpho
05.08.2020, 07:32
вот тебе процедура с переменной высотой спрайта
с развернутым выводом по упрощенному методу здесь все три регистра D E A заняты под указатели на битпланы.

Спасибо!!


а замирание врагов при упирании в стену я смотрю так и не устранил?

Это есть в списках багов, которые я буду устранять, но позже.


Любые где нет контроля скорости.

Какие есть варианты контроля скорости на Вектор ?

jerri
05.08.2020, 07:44
Какие есть варианты контроля скорости на Вектор ?

Счётчик на прерываниях
каждое прерывание прибавляет счётчик
В основном цикле проверяешь значение и если оно больше заданного значения
Например 3 то обнуляешь и запускаешь обработку объектов и освежение экрана.
Если меньше то ждёшь.
Это стабилизирует скорость игры.

Другой вариант (обработки объектов в прерывании) я тебе писал ранее
Но с твоим способом вывода спрайтов он не совместим.

KTSerg
05.08.2020, 08:44
Счётчик на прерываниях
каждое прерывание прибавляет счётчик
В основном цикле проверяешь значение и если оно больше заданного значения
Например 3 то обнуляешь и запускаешь обработку объектов и освежение экрана.
Если меньше то ждёшь.
Это стабилизирует скорость игры.
...
Для начала, можно легко определить, сколько перываний происходит за время отрисовки всего экрана.
В эмуляторе например, можно поставить метки остановки (брекпоинт) на самое начало отрисовки экрана, и в начало прерываний.
А потом запускать программу, и смотреть, на каких метках она останавливается.

jerri
05.08.2020, 09:21
Для начала, можно легко определить, сколько перываний происходит за время отрисовки всего экрана.
В эмуляторе например, можно поставить метки остановки (брекпоинт) на самое начало отрисовки экрана, и в начало прерываний.
А потом запускать программу, и смотреть, на каких метках она останавливается.Счетчик делается не для определения скорости, а для ее контроля.
Скорость в ситуациях, если на экране один герой и когда на экране много объектов, не должна существенного отличаться.

KTSerg
05.08.2020, 09:52
Счетчик делается не для определения скорости, а для ее контроля.
Скорость в ситуациях, если на экране один герой и когда на экране много объектов, не должна существенного отличаться.
Да, но первоначально нужно иметь представление, сколько прерываний происходит за время обновления полного экрана с максимальной загрузкой подвижными объектами. Что-бы не поставить счетчик слишком маленький, или слишком большим.
Хотя дело вкуса, можно и наугад значение счетчика начать контролировать, а потом методом "научного тыка" подгонять, искать нужное значение.

jerri
05.08.2020, 11:10
Да, но первоначально нужно иметь представление, сколько прерываний происходит за время обновления полного экрана с максимальной загрузкой подвижными объектами. Что-бы не поставить счетчик слишком маленький, или слишком большим.
Хотя дело вкуса, можно и наугад значение счетчика начать контролировать, а потом методом "научного тыка" подгонять, искать нужное значение.Это не вопрос вкуса, это вопрос дизайна
Идеальное движение на 1 точку за фрейм
Медленнее медленно,
Быстрее быстро.

Если героя смещать на 2 точки то идеально будет выглядеть смещение раз в 2 фрейма.

CodeMaster
05.08.2020, 11:28
Хотя дело вкуса, можно и наугад значение счетчика начать контролировать, а потом методом "научного тыка" подгонять, искать нужное значение.
Думацо, так всегда и делали. Количество врагов и NPC проще методом научного тыка подобрать. Отсюда, видимо, иногда и случаются накладки с динамикой, когда на 5 уровнях подобрали, но не всё учли и где-то дальше это вылазит боком.

jerri
05.08.2020, 11:32
Думацо, так всегда и делали. Количество врагов и NPC проще методом научного тыка подобрать. Отсюда, видимо, иногда и случаются накладки с динамикой, когда на 5 уровнях подобрали, но не всё учли и где-то дальше это вылазит боком.Именно, при этом обычно на синхронизацию со временем тоже клали болт, и в результате включение турбо режима превращает многие игры в неиграбельное торопилово.

S_V_B
05.08.2020, 15:06
Нужно сразу определиться с максимальным количеством врагов на экране и сколько ты реально можешь вывести за фрэйм. Далее как я писал выше можешь чередовать их вывод чет-нечет чтобы удвоить кол-во выводимых объектов. В самом прерывании инкриментируй счетчик который проверяешь перед апдейтом. (если объектов мало - ждешь среднего значения которое вычислил экспериментально.. тогда никакое турбо не ускорит).

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

Счетчик покажет тебе сколько прерываний занимает игровой цикл... если меньше -ждешь.

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

Да и естественно выводим (в прерывании) только объекты которые сдвинулись. Тогда все будет ОК.

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

На экран выводи хотя бы счетчик игрового цикла .. тогда будет понятна динамика между экранами (примерно).

Black Cat / Era CG
05.08.2020, 18:43
Я не шарю, но что если для "недостающих" врагов выводить "пустой" спрайт?

S_V_B
05.08.2020, 19:01
Я не шарю, но что если для "недостающих" врагов выводить "пустой" спрайт?
Зачем??? Ты же разделил основной цикл игры и прерывание - в основном цикле мнеяешь в списке состояние, а в обработчике прерывания ..выводишь.
Зачем тратить лишнее время... как в глупых книжках :) (обязательно нужно перерисовать все... будет лагать.. Мы же пишем ШЕДЕВР :))

KTSerg
05.08.2020, 20:28
...
Зачем тратить лишнее время... как в глупых книжках :) (обязательно нужно перерисовать все... будет лагать.. Мы же пишем ШЕДЕВР :))
Действительно, зачем тратить процессорное время на перерисовку пустых спрайтов (отсутствующих врагов), когда можно значительно эффективнее потратить его (лишнее время) на ожидание флага синхронизации времени/скорости...
Или это был сарказм, про тратить лишнее время?
Тогда пардон, я его не понял...

jerri
05.08.2020, 22:25
Black Cat / Era CG, S_V_B, KTSerg, metamorpho,

стоп стоп стоп, итак как вариант. каждый фрейм рисуем ГГ + часть врагов - чтобы хватило на фрейм
допустим максимальное количество врагов получается x/y=3 фрейма.

значит движем героя со скоростью 1 точка во фрейм(но выводим с точностью до 2х точек). а все враги движутся в 1.5-3 раза медленнее чем ГГ.

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

Хотя конечно я бы предпочел асинхронный вывод и обработку врагов на прерывании.

metamorpho
06.08.2020, 20:36
Сделал новый объект - птичку, вставил графику + добавил ещё немного другой графики и памяти уже нету.
rom получился больше 32 Кб и при запуске завис. Как-то я нерасчитал :)
Придётся либо птичку убрать либо что-то другое что хотел внедрить в игру.
См. (rom) с птичкой для истории :) (похоже птичку уберу - слишком много весит).

PPC
06.08.2020, 20:48
Сделал новый объект - птичку, вставил графику + добавил ещё немного другой графики и памяти уже нету.
rom получился больше 32 Кб и при запуске завис. Как-то я нерасчитал :)
Придётся либо птичку убрать либо что-то другое что хотел внедрить в игру.
См. (rom) с птичкой для истории :) (похоже птичку уберу - слишком много весит).
Не отчаивайтесь так, "птичку жалко" (с) - у Вектора есть ещё похер в похеровницах, рекомендую присмотреться к квазидиску в смысле всю графику туда. Удачи!

jerri
06.08.2020, 20:50
Сделал новый объект - птичку, вставил графику + добавил ещё немного другой графики и памяти уже нету.
rom получился больше 32 Кб и при запуске завис. Как-то я нерасчитал :)
Придётся либо птичку убрать либо что-то другое что хотел внедрить в игру.
См. (rom) с птичкой для истории :) (похоже птичку уберу - слишком много весит).

а что на размер ROM есть ограничения?

PPC
06.08.2020, 20:58
а что на размер ROM есть ограничения?
Ограничения нет, но с адреса 0x8000 видeопамять, плоскости. Автор хочет все 16 цветов, он сам писал об этом, все 4 видеоплоскости.
Решение: графику в квазидиск (всю). Там есть разные варианты доступа, рекомендую в области со стековым доступом. Тут помогут...

PS. Только придётся сопрягаться с CP/M, графику закачивать, но это - technicality. Хотя, можно и с мафона, можно даже сделать с мафона custom ROM loader. Но c CP/M проще.

PPS. Есть ещё вариант: во время загрузки основного кода custom лодером настроить квазидиск так, чтобы открылся доступ "как память". Если совместимость со старыми квазидисками не важна, и рассчитывать на доработку Баркаря, квазидиск можно размапить на доступ "как память" прямо c адреса 0x8000, и гнать с мафона навалом...
Тогда CP/M не нужна. Правда, в реале не у всех может быть Баркарь... это проверяется. А можно для совместимости гнать лодером в стандартное окно 0xA000-0xDFFF, и потом мувнуть хоть в адрес 0 банка квазидиска...всё равно на экран стеком выводить. А области "как память" оставить для драйверов/подгружаемых оверлеев с кодом.

metamorpho
06.08.2020, 22:07
....рекомендую присмотреться к квазидиску в смысле всю графику туда. Удачи!


PS. Только придётся сопрягаться с CP/M, графику закачивать, но это - technicality. Хотя, можно и с мафона, можно даже сделать с мафона custom ROM loader. Но c CP/M проще.
PPS. Есть ещё вариант: во время загрузки основного кода custom лодером настроить квазидиск так, чтобы открылся доступ "как память". Если совместимость со старыми квазидисками не важна, и рассчитывать на доработку Баркаря, квазидиск можно размапить на доступ "как память" прямо c адреса 0x8000, и гнать с мафона навалом...
Тогда CP/M не нужна. Правда, в реале не у всех может быть Баркарь... это проверяется. А можно для совместимости гнать лодером в стандартное окно 0xA000-0xDFFF, и потом мувнуть хоть в адрес 0 банка квазидиска...всё равно на экран стеком выводить. А области "как память" оставить для драйверов/подгружаемых оверлеев с кодом.


PPC, спасибо за информацию, буду знать!!
Эта игра точно без квазидиска будет - чтобы была чисто классика Вектор-06Ц без всяких добавок.
Ну а потом (если ещё вдохновение найдёт) посмотрим.

KTSerg
07.08.2020, 05:24
PPC, спасибо за информацию, буду знать!!
Эта игра точно без квазидиска будет - чтобы была чисто классика Вектор-06Ц без всяких добавок.
Ну а потом (если ещё вдохновение найдёт) посмотрим.
Значит нужно внимательнее на спрайты посмотреть. Либо компактнее их расположить в памяти, либо глянуть на возможность совмещения, хотя это будет зависеть от порядка следования байтов в спрайтах.
Ещё, я уже спрашивал, но не запомнил, получил ли ответ.
Сколько цветов используется в каждом из спрайтов?
Я не о количестве возможных, понятно, что их 8, а о реально используемых цветах в картинках?
Если в каких-то спрайтах их не больше 4-ёх, может сократить для этих спрайтов сипользование до 2-ух плоскостей?
Это конечно не для всех объектов подойдёт... но места занимать будут меньше, скорость вывода на экран - выше...

metamorpho
07.08.2020, 09:17
Либо компактнее их расположить в памяти

"компактнее их расположить в памяти" - это как например ?


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

"возможность совмещения" - а это что такое ?


Сколько цветов используется в каждом из спрайтов?
Я не о количестве возможных, понятно, что их 8, а о реально используемых цветах в картинках?
Если в каких-то спрайтах их не больше 4-ёх, может сократить для этих спрайтов сипользование до 2-ух плоскостей?
Это конечно не для всех объектов подойдёт... но места занимать будут меньше, скорость вывода на экран - выше...

Вот эта идея понятна, но практически все спрайты задействуют все три плоскости.

KTSerg
07.08.2020, 10:30
...
"возможность совмещения" - а это что такое ?
Т.к. для каждого объекта есть несколько спрайтов, с разными фазами перемещения, то есть вероятность, что конец у одного из спрайтов может совпадать с началом другого спрайта. Соответственно, их можно совместить, просто начало одного из спрайтов формально находится на информации принадлежащей другому спрайту. Это маловероятно, но возможно.


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

jerri
07.08.2020, 11:04
"компактнее их расположить в памяти" - это как например ?


у тебя есть на 3х плоскостях по 2 полоски справа и слева.
или можешь направо сдвинуть.

это еще 1.5 кб

S_V_B
07.08.2020, 19:21
Вы не думали... считаь спрайты не в плоскостях а просто в XY... че тупите-то (или у 8 ми битных все плохо)

jerri
07.08.2020, 19:32
Вы не думали... считаь спрайты не в плоскостях а просто в XY... че тупите-то (или у 8 ми битных все плохо)Ты чего сказать то хотел?

S_V_B
07.08.2020, 19:40
У вас 8ми биток свои плоскости ... не бейти меня ногами.. зкран вериткально порезан................ беда, но это тоже решабельно.. (я приобрел ATARI 65XE)

jerri
07.08.2020, 20:05
У вас 8ми биток свои плоскости ... не бейти меня ногами.. зкран вериткально порезан................ беда, но это тоже решабельно.. (я приобрел ATARI 65XE)Ща поясню
Экран вектора имеет высоту 256 и состоит из 32 вертикальных ленточек.

Далее вектор позволяет до 16 цветов из палитры 256.
цветная точка собирается из 4 значений выбираемых из 4х битпланов, также как на амиге.

В итоге экран может занимать от 8 до 32 кб
Тут вот где-то выше я ссылки кидал.

metamorpho
09.08.2020, 07:57
1 . Хотел уточнить нижеприведённый музыкальный шедевр он же чисто на ВИ53 проигрывается ?

2. Есть идея сделать музыку следующим образом:
- на эмуляторе загрузить "Бейсик" и там набрать и отредактировать мелодию
- далее вставить эту мелодию в ассемблер

Но какой код нужно вставить в обработку прерывания, чтобы проигрывать эту мелодию ?
Может у кого есть готовый вариант.



https://www.youtube.com/watch?v=90QSOHiBKgk

metamorpho
09.08.2020, 16:37
Загрузил Векторовский Бейсик попробовал там сделать мелодию, столкнулся с тем что оттуда нельзя скопировать строку и туда нельзя вставить строку (почему-то сразу я не подумал об этом). Похоже этот вариант пока на полочку положу :)

В этой игре хочется сделать музыку на ВИ53, т.е. биперная и АY музыка не подойдёт.
До этого svofski давал несколько ссылок по музыке - из них для ВИ53 похоже подходит только вот это
https://zx-pk.ru/threads/29077-igraem-melodii-na-vi53.html
Каким-то образом SegaBoy конвертирует MIDI мелодии.
ivagor ты переносил этот Апогеевский плеер (SegaBoy) на Вектор, а можешь исходник дать (если конечно остался), чтобы мне посмотреть как проигрывать подобные мелодии. Возможно мне там получится что-то понять :)

jerri
09.08.2020, 19:32
metamorpho, плеер из RiseOut можно выдернуть. Но вот музыку надо для него гдето писать.
Если для Вектора есть трекеры можно комунибудь музыку заказать.

svofski
09.08.2020, 20:22
Про трекеры не знаю, но один из проверенных простых способов добычи музыки для ви53 — конвертация midi, или abc.

jerri
09.08.2020, 21:15
Про трекеры не знаю, но один из проверенных простых способов добычи музыки для ви53 — конвертация midi, или abc.А плеер где?
А формат какой?

SegaBoy
09.08.2020, 21:56
А плеер где?
А формат какой?
А мелодию какую?
Плеер можно написать если что, да и формат придумать.

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

metamorpho, какую мелодию будем конвертировать?

metamorpho
10.08.2020, 09:36
SegaBoy, я ещё не выбрал мелодию.
Насколько я понял твой метод позволяет конвертировать под ВИ53 форматы Midi, ABC, NSF ("Денди").

А ещё какие варианты форматов можно конвертировать твоим методом ?
Например форматы:
sid (с компьютера Commodore 64)
ay,ym,asc,stc,pt2 (ZX Spectrum)
sap (Atari)
snd (MSX)

их можно конвертировать под ВИ53 ?

metamorpho
10.08.2020, 22:06
SegaBoy, вот эти две мелодии (первые которые в них)

SegaBoy
10.08.2020, 23:47
SegaBoy, я ещё не выбрал мелодию.
Насколько я понял твой метод позволяет конвертировать под ВИ53 форматы Midi, ABC, NSF ("Денди").

А ещё какие варианты форматов можно конвертировать твоим методом ?
Например форматы:
sid (с компьютера Commodore 64)
ay,ym,asc,stc,pt2 (ZX Spectrum)
sap (Atari)
snd (MSX)

их можно конвертировать под ВИ53 ?
Я только из миди делаю. Если можно конвертировать из вышеперечисленных форматов в трёхканальное миди, то да.

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


SegaBoy, вот эти две мелодии (первые которые в них)
Завтра посмотрю и отпишу.

metamorpho
11.08.2020, 11:00
Я только из миди делаю. Если можно конвертировать из вышеперечисленных форматов в трёхканальное миди, то да.


Да некоторые из этих форматов конвертируются в Midi.

А как получить из миди то что нам нужно ? Где там данные искать ?

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

Как сделать качественное рандомное число ?
Например я вставил в программу обработки прерывания такой код:
LXI H,random
inr m
Но такой код выдаёт не очень рандомные числа, в них есть закономерность-одинаковость inr.

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

Есть у кого-нибудь наработки на ассемблере эффекта разлетания частиц в стороны - как от взрыва ?
Допустим есть центр спрайта и от него разлетаются как от взрыва точки или может спрайты 8х8.
Или же эффект что спрайт постепенно "съезжает" внутрь самого себя и исчезает ?

KTSerg
11.08.2020, 11:21
...
Как сделать качественное рандомное число ?
Например я вставил в программу обработки прерывания такой код:
LXI H,random
inr m
Но такой код выдаёт не очень рандомные числа, в них есть закономерность-одинаковость inr.
...
Попробуй использовать (например складывать) со значением какого-то регистра, который в твоей основной программе используется как счетчик... я бы ещё (до кучи) попробовал использовать регистр состояния...

svofski
11.08.2020, 16:15
Как сделать качественное рандомное число ?
Никак, но есть способы худо-бедно изобразить его подобие. LFSR из примера с мандрилом дает перемешанную последовательность чисел от 1 до 65535, имеет периодичность 65535.


; выход:
; HL - число от 1 до 65535
rnd16:
lxi h,65535
dad h
shld rnd16+1
rnc
mvi a,00000001b ;перевернул 80h - 10000000b
xra l
mov l,a
mvi a,01101000b ;перевернул 16h - 00010110b
xra h
mov h,a
shld rnd16+1
ret

KTSerg
11.08.2020, 19:34
Никак, но есть способы худо-бедно изобразить его подобие. LFSR из примера с мандрилом дает перемешанную последовательность чисел от 1 до 65535, имеет периодичность 65535.
...
По мне так вполне себе красивый "rnd" получается. Не знаю, скорее всего после завершения цикла, последовательность полностью повторится, и с этим нужно как-то отдельно бороться ...

metamorpho
11.08.2020, 20:57
svofski, спасибо!!
Твой способ получения rnd работает.

SegaBoy
11.08.2020, 21:23
А как получить из миди то что нам нужно ? Где там данные искать ?

Есть такой онлайн конвертер Binary MIDI file to text (MF2T/T2MF format) conversion (http://flashmusicgames.com/midi/mid2txt.php). С помощью него можно получить текстовое представление миди-файла.

Вот например начало из Flying Dragon:


77 On ch=1 n=69 v=127
77 Pb ch=1 v=8192
77 Par ch=1 c=11 v=92
77 On ch=2 n=64 v=127
77 Pb ch=2 v=8192
77 Par ch=2 c=11 v=92
77 On ch=3 n=57 v=90
77 Pb ch=3 v=8145
78 Par ch=2 c=11 v=86
78 Pb ch=3 v=8192
79 Par ch=2 c=11 v=73
79 Pb ch=3 v=8145
80 Par ch=2 c=11 v=56
80 Pb ch=3 v=8192
81 Par ch=2 c=11 v=0
81 Off ch=3 n=57 v=0
84 Off ch=1 n=69 v=0
84 Off ch=2 n=64 v=0

Каждая строка начинается с числа - это номер события (или в данном случае кадра). Затем одна из команд события: On - включить канал, Off - выключить канал, Pb - изменить высоту ноты (pitch bend), Par - изменить громкость в канале. Далее номер канала (ch=x). В командах On/Off затем идёт номер ноты (n=x) и уровень громкости (v=x). В команде Par обычно стоит с=11 (не знаю что это) и в конце всегда v=0 (что соответствует нулевой громкости). И наконец в команде Pb указано значение относительно ноты используемой в последней команде On.

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

metamorpho, что-то я с наскоку не смог одолеть ни Excitebike, ни Flying Dragon - какие-то там бульки и всплески не в кассу постоянно слышны (ну в смысле после моей конвертации). Совсем не простые для меня мелодии оказались, Кастлвания намного легче даётся )))

metamorpho
11.08.2020, 21:34
SegaBoy, спасибо за информацию!!
А вот это текстовое представление миди-файла ты как в ручную обрабатываешь
или есть какая-то программа преобразующая в данные для ассемблера ?
Или это текстовое представление миди-файла напрямую вставляется в ассемблер, а уже там програмно обрабатывается ?

SegaBoy
11.08.2020, 22:51
SegaBoy, спасибо за информацию!!
А вот это текстовое представление миди-файла ты как в ручную обрабатываешь
или есть какая-то программа преобразующая в данные для ассемблера ?
Или это текстовое представление миди-файла напрямую вставляется в ассемблер, а уже там програмно обрабатывается ?
Для наглядного изучения миди-файла я использую MidiEditor. Из получившегося текстового файла удаляю всё лишнее - заголовки, хвосты, многократно повторяющиеся фрагменты. Затем на этот текстовый файл натравливаю код, который выстраивает для меня данные пригодные уже для проигрывания в плеере на ассемблере. Соответственно сначала надо придумать как они, данные эти, будут устроены, а потом этот код написать. Так как у меня ничего кроме GameMaker Studio нету, то и пишу код я прямо в нём. А так можно использовать любую среду программирования или язык.

Вот к примеру из такого фрагмента (Super Mario Bros):


76 On ch=3 n=50 v=90
76 Pb ch=3 v=8160
77 On ch=1 n=66 v=127
77 Pb ch=1 v=8152
77 On ch=2 n=76 v=127
77 Pb ch=2 v=8122
84 Off ch=3 n=50 v=0
85 On ch=3 n=50 v=90
85 Pb ch=3 v=8160
86 Off ch=1 n=66 v=0
86 On ch=1 n=66 v=127
86 Pb ch=1 v=8152
86 Off ch=2 n=76 v=0
86 On ch=2 n=76 v=127
86 Pb ch=2 v=8122
93 Off ch=3 n=50 v=0
103 On ch=3 n=50 v=90

получаются следующие данные для плеера:


db 4, 3, 1
db 24, 6, 9, 7
db 224, 1
db 4, 3, 1
db 24, 6, 9, 7
db 224, 10

Формат данных (в текущей версии) следующий. Старшие три бита первого байта это флаги выключения каналов 1, 2 и 3. Следующие три бита флаги включения. Последние два бита (пока) не используются. Затем если установлен бит включения канала, то следующий байт это номер ноты. Последний байт это количество кадров которые надо подождать прежде чем проигрывать следующий фрагмент.
Алгоритм следующий - загружаем значение для ноты 3 в третий канал, ждём 1 кадр, загружаем значение для ноты 6 в первый канал, загружаем значение для ноты 9 во второй канал, ждём 7 кадров, выключаем каналы 1, 2 и 3, ждём 1 кадр и тд.

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

Вот примеры плеера для Апогея (можно запустить в эмуляторе).

metamorpho
12.08.2020, 09:40
SegaBoy, спасибо за подробные объяснения!!
Ещё немного и я сам научусь конвертировать :)

Возникли вопросы:
Что имеется ввиду под словами "ждём 7 кадров" ? Это длительность ноты ? Сколько длится 1 кадр ?

Правильно ли я понял что в "note_table_1" это значения частот используемых нот (частота канала) ?
И номер ноты соответствуют данным из этой таблицы ?
Но как составляется эта таблица, из каких данных "текстового представления миди-файла" она формируется ?
Ведь у нас в "текстовом представлении миди-файла" есть только номер ноты (n=x) и уровень громкости (v=x). Как это преобразуется ?

note_table_1:
dw 7216, 6811, 6430, 6070, 5409, 5107, 4821, 4551, 4057, 3616, 3414, 3223, 3043, 2713

KTSerg
12.08.2020, 09:57
...
note_table_1:
dw 7216, 6811, 6430, 6070, 5409, 5107, 4821, 4551, 4057, 3616, 3414, 3223, 3043, 2713
Всё значительно проще.
Это коэффициенты для частоты ноты. Они не записаны в Миди, т.к. они стандартны для конкретного устройства воспроизведения.
Т.к. тактовая ВИ53 1.5МГц, то делим 1500000 на 6430 (к примеру), и получаем частоту 233Гц - почти Ля-диез малой октавы.
Коэффициенты из этой таблицы записываются в регистры ВИ53, и он генерит запрошенную частоту - ноту.

x-code
12.08.2020, 14:40
Это коэффициенты для частоты ноты. Они не записаны в Миди, т.к. они стандартны для конкретного устройства воспроизведения.

Так такая конвертация, скорее всего, порежет все огибающие и все шумовые эффекты типа ударных.
Даже звуковой движок в игре Fatax умел больше :(

При конверсии ведь нужно учитывать не только высоту тона ноты, но и инструментом какого тембра она играется, и с каким эффектом (вибрато, тремоло и т.п.)

По-моему, на форуме уже когда-то публиковалась вполне достойная эмуляция AY на ВИ53 - вот в эту сторону я бы и смотрел при конверсии с ZX / Commodore / MSX.

KTSerg
12.08.2020, 14:52
Так такая конвертация, скорее всего, порежет все огибающие и все шумовые эффекты типа ударных.
Даже звуковой движок в игре Fatax умел больше :(

При конверсии ведь нужно учитывать не только высоту тона ноты, но и инструментом какого тембра она играется, и с каким эффектом (вибрато, тремоло и т.п.)

По-моему, на форуме уже когда-то публиковалась вполне достойная эмуляция AY на ВИ53 - вот в эту сторону я бы и смотрел при конверсии с ZX / Commodore / MSX.
"Давайте послушаем начальника транспортного цеха..." (с) ...
Нужно экспертное мнение спецов, занимавшихся плеерами для Вектора. Я даже представить себе не могу, сколько ресурсов процессорного времени нужно, чтобы на ВИ53 достойно эмулировать AY... на игру ресурсов не хватит... На заставке - может быть... во время игры - сомневаюсь...
Делать отдельный плеер с отдельной музыкой в игре, в которой и так для спрайтов уже памяти не хватает... сомнительный вариант...

jerri
12.08.2020, 14:54
"Давайте послушаем начальника транспортного цеха..." (с) ...
Нужно экспертное мнение спецов, занимавшихся плеерами для Вектора. Я даже представить себе не могу, сколько ресурсов процессорного времени нужно, чтобы на ВИ53 достойно эмулировать AY... на игру ресурсов не хватит... На заставке - может быть... во время игры - сомневаюсь...
Делать отдельный плеер с отдельной музыкой в игре, в которой и так для спрайтов уже памяти не хватает... сомнительный вариант...На спеке плеер занимает около 10000 тактов. Но это порядка 25 лет эволюции

На векторе кто-то вообще занимался звуком?

KTSerg
12.08.2020, 14:58
... На векторе кто-то вообще занимался звуком?
Первое, что увидел на второй странице тем для Вектора.
https://zx-pk.ru/threads/31546-trekernaya-semplernaya-muzyka-na-vektore.html
https://zx-pk.ru/threads/14607-quot-covox-dlya-vektor-06ts-quot.html
https://zx-pk.ru/threads/28132-bipernaya-muzyka-na-vektore-06ts.html

jerri
12.08.2020, 15:02
https://zx-pk.ru/threads/31546-trekernaya-semplernaya-muzyka-na-vektore.html
https://zx-pk.ru/threads/14607-quot-covox-dlya-vektor-06ts-quot.html
https://zx-pk.ru/threads/28132-bipernaya-muzyka-na-vektore-06ts.htmlЯ не эти частные случаи имею ввиду.
На спектруме есть линейка трекеров идущая от sound tracker и пришедшая в итоге к vortex tracker который в принципе плеер для ау и подходит и для бк и для msx

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

x-code
12.08.2020, 15:10
Я так понимаю для вот этой микросхемы в векторе никогда ничего подобного не создавалось?

Только вот это, насколько я знаю:
https://zx-pk.ru/threads/20691-muzyka-sergeya-novikova.html

В обсуждение приглашается ivagor, плотно занимавшийся ВИ53 на Векторе.

jerri
12.08.2020, 15:15
Только вот это, насколько я знаю:
https://zx-pk.ru/threads/20691-muzyka-sergeya-novikova.html

В обсуждение приглашается ivagor, плотно занимавшийся ВИ53 на Векторе.

я вот про это
http://hype.retroscene.org/blog/794.html

https://www.youtube.com/watch?time_continue=5&v=fWdxkp9FhTk&feature=emb_logo

это то в чем музыку пишут, к чему идет плеер.

SegaBoy
12.08.2020, 22:10
Что имеется ввиду под словами "ждём 7 кадров" ? Это длительность ноты ? Сколько длится 1 кадр ?

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

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



Правильно ли я понял что в "note_table_1" это значения частот используемых нот (частота канала) ?
И номер ноты соответствуют данным из этой таблицы ?
Но как составляется эта таблица, из каких данных "текстового представления миди-файла" она формируется ?
Ведь у нас в "текстовом представлении миди-файла" есть только номер ноты (n=x) и уровень громкости (v=x). Как это преобразуется ?

Как правильно указал KTSerg, это коэффициенты или константы для определённых частот (только от тактовой Апогея 1,77 МГц) которые и загружаются в каналы ВИ53. Таблица составляется пробеганием по всем нотам и пересчётом их в константы. Можно конечно так не делать и в данных плеера вместо однобайтового значения номера из таблицы сразу указывать двухбайтовое значение константы и посмотреть как лучше. Ну и плеер конечно изменить под это.

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

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

metamorpho, есть ещё какие nsf на примете чтобы попробовать из них конвертировать? Например мелодии из марио довольно прилично звучат без громкости и без огибающих. Может ещё какие-то более дружелюбными для портирования окажутся ))

KTSerg
13.08.2020, 08:57
Я поправил своё сообщение про коэффициенты. У Вектора ВИ53 тактируется частотой 1,5МГц.
Но суть та-же, нота после пересчёта коэффициента не меняется, только октава получилась другая.

metamorpho
13.08.2020, 13:11
SegaBoy, спасибо за объяснения!!

Ещё возниклм вопросы:
плеер (исходник на asm), который ты дал он же в теле основной программы работает (насколько я понял), а ещё в программе обработки прерываний должны обрабатываться нижеприведённые данные.
pit_cnt1_port equ $ec00
pit_cnt2_port equ $ec01
pit_cnt3_port equ $ec02
pit_ctrl_port equ $ec03
pit_init1 equ $3e
pit_init2 equ $7e
pit_init3 equ $be

Например на Векторе для вывода одного отдельного звука в программе обработки прерываний есть программирование таймера ВИ53:
MVI A,0B6H ; УСТАНОВИТЬ РЕЖИМ 3 ТАЙМЕРА ДЛЯ КАНАЛА 2, ЗАПИСЬ КОЭФ-
OUT 08 ; ФИЦИЕНТА ДЕЛЕНИЯ В ДВА БАЙТА - СНАЧАЛА МЛ. ПОТОМ СТ.
MOV A,M ; ВЗЯТЬ МЛАДШИЙ БАЙТ КОЭФФ. ДЕЛЕНИЯ И
OUT 09 ; ЗАПИСАТЬ В КАНАЛ 2 ТАЙМЕРА.
INX H ; ПЕРЕДВИНУТЬ УКАЗАТЕЛЬ НА СЛЕДУЮЩИЙ БАЙТ ПАРАМЕТРОВ.
MOV A,M ; ВЗЯТЬ СТАРШИЙ БАЙТ КОЭФФ. ДЕЛЕНИЯ И
OUT 09 ; ЗАПИСАТЬ В КАНАЛ 2 ТАЙМЕРА.

А в программе обработки прерываний как у тебя они обрабатываются ?
Или же на Апогее это по другому работает ?


....есть ещё какие nsf на примете чтобы попробовать из них конвертировать? Например мелодии из марио довольно прилично звучат без громкости и без огибающих. Может ещё какие-то более дружелюбными для портирования окажутся ))

Думаю если я найду мелодию, то она вновь может оказаться с проблемами :)

Спасибо, что помогаешь мне разобраться в этом вопросе.
Если у меня получиться, то я сам их конвертировать буду. Ну а если не получиться, то буду искать подходящую мелодию :)

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

Информация из справочника Черезова А. по Вектору-06Ц

; десятичные значения нот (частота канала для ноты)
note_table:
; контр-октава
dw 45872,43290,40872,38560,36408,34364,32432,30612,28 902,27273,25729,24311 ; до/до#/ре/ре#/ми/фа/фа#/соль/соль#/ля/ля#/си
; большая-октава
dw 22936,21645,20436,19280,18204,17182,16216,15306,14 451,13636,12876,12146 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; малая-октава
dw 11468,10823,10218,9646,9102,8591,8108,7653,7229,68 18,6438,6075 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 1-я октава
dw 5734,5415,5107,4823,4551,4296,4054,3827,3614,3409, 3219,3036 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 2-я октава
dw 2867,2708,2554,2412,2275,2147,2027,1913,1805,1705, 1609,1519 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 3-я октава
dw 1433,1353,1277,1205,1137,1074,1014,957,904,852,804 ,759 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 4-я октава
dw 717,677,639,602,569,537,507,472,452,426,402,380 ; до до# ре ре# ми фа фа# соль соль# ля ля# си

В музыкальной нотной грамоте я не грамотен.
Поэтому вопрос - почему в этой таблице на ноте ми и ноте си нету # ?

x-code
13.08.2020, 13:19
а ещё в программе обработки прерываний должны обрабатываться нижеприведённые данные.

Судя по всему, на Апогее порты отображены в адреса ОЗУ, поэтому первые четыре константы в этом коде - это Апогеевский аналог адресов Векторовских портов 08-11.
Три последние константы - это константы управляющих слов для инициализации каналов таймера. Почему для второго канала это $be, а не $b6 - возможно, на Апогее используется другой режим таймера.


А в программе обработки прерываний как у тебя они обрабатываются ?

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

Считай, что прерывание, это метроном, который тикает 50 раз в секунду. Зарядил канал таймера играть первую ноту - отсчитываешь нужное количество тактов метронома сообразно длительности ноты и выбранному темпу - затем программируешь канал таймера играть следующую ноту (или останавливаешь таймер, если нужна пауза).

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


В музыкальной нотной грамоте я не грамотен.
Поэтому вопрос - почему в этой таблице на ноте ми и ноте си нету # ?

Потому что диез (и бемоль) - это расстояние в полутон между нотами.
Знакомая же нам всем гамма до-ре-ми-фа-соль-ля-си, которую музыканты называют "до мажор", в плане разницы высоты звука между соседними нотами - это "тон, тон, полутон, тон, тон, тон, полутон"

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

metamorpho
13.08.2020, 13:30
Судя по всему, на Апогее порты отображены в адреса ОЗУ, поэтому первые четыре константы в этом коде - это Апогеевский аналог адресов Векторовских портов 08-11.
Три последние константы - это константы управляющих слов для инициализации каналов таймера. Почему для второго канала это $be, а не $b6 - возможно, на Апогее используется другой режим таймера.
.....

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


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

x-code, спасибо, теперь стало понятней !!

x-code
13.08.2020, 13:50
этот код плеера с Апогея и есть то что нужно вставлять
в программу обработки прерываний на Векторе (изменив управляющие команды для портов) ?

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

metamorpho
13.08.2020, 14:04
Немного новостей. Сейчас в целом различные моменты игры (кроме музыки) оформились.
Так что пока их откладываю в сторону и занимаюсь разработкой кода для проигрывания музыки.
Музыка (для ВИ53), оказалась наиболее специфичной и незнакомой темой для меня.
Но надеюсь с помощью тех кто мне помогает напишу код для музыки :)

А пока вот (rom) для тестов. Уровни ещё не шлифовал (просто наброски).
Некоторые из них непроходимы. Переключаться между уровнями можно клавишей "Тab".
Интересно ваше мнение насчёт эффекта при взятии монеты.
Первоначально была графика при гибели героя (аж семь кадров исчезания типа взрыва), но от этого пришлось отказаться т.к. памяти не хватает. Поэтому вместо графики, был написан эффект при гибели героя, который так себе получился, но есть планы его доработать до чего-то лучшего :)
Может у кого-то будут какие советы по игре - пишите.
Из "крупных" данных в игру осталось вставить музыку и заставку - надеюсь памяти хватит :)

metamorpho
13.08.2020, 16:13
SegaBoy, ещё 2 вопроса возникли.

--------------------------Вопрос 1-й.
Pb - изменить высоту ноты (pitch bend). В команде Pb указано значение относительно ноты используемой в последней команде On.
Как преобразуется нота с учётом Pb ?

Например
76 On ch=3 n=50 v=90
76 Pb ch=3 v=8160

здесь нота n=50 (допустим это 2-я октава нота до# её частота 2708 из таблицы частот для нот )
При преобразовании миди текста как Pb повлияет на эту ноту ? Изменит высоту ноты в какую сторону ?

-------------------------------Вопрос 2-й.
Вот таблица 84-х нот (их частот) для Вектора.
Как считаются ноты ? Т.е. n=1 (из миди текста) это соответствует какой ноте из таблицы для Вектора ?

note_table:
; контр-октава (12 нот)
dw 45872,43290,40872,38560,36408,34364,32432,30612,28 902,27273,25729,24311 ; до/до#/ре/ре#/ми/фа/фа#/соль/соль#/ля/ля#/си
; большая-октава
dw 22936,21645,20436,19280,18204,17182,16216,15306,14 451,13636,12876,12146 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; малая-октава
dw 11468,10823,10218,9646,9102,8591,8108,7653,7229,68 18,6438,6075 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 1-я октава
dw 5734,5415,5107,4823,4551,4296,4054,3827,3614,3409, 3219,3036 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 2-я октава
dw 2867,2708,2554,2412,2275,2147,2027,1913,1805,1705, 1609,1519 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 3-я октава
dw 1433,1353,1277,1205,1137,1074,1014,957,904,852,804 ,759 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 4-я октава
dw 717,677,639,602,569,537,507,472,452,426,402,380 ; до до# ре ре# ми фа фа# соль соль# ля ля# си

x-code
13.08.2020, 17:37
как Pb повлияет на эту ноту ? Изменит высоту ноты в какую сторону ?

Ответ - в спецификации MIDI. Параметр команды Pb - это 14-битное число от 0 до 16384.
При конверсии:

1. Это число нужно преобразовать в диапазон от -1 до 1. 8192 - это ноль, 16384 - это один, а 0 - это минус один. Всё, что между этими точками - вещественные числа в диапазоне от -1 до 1.
2. Умножить на количество полутонов в диапазоне pitch bend (обычно +/- два полутона, т.е. умножаем на 2)
3. Поделить на 12 (количество полутонов в октаве)
4. Возвести двойку в степень числа, полученного на шаге 3
5. Умножить базовую частоту ноты на результат шага 4

Привожу английский оригинал на всякий случай:


So, to manage the pitchbend data and use it to alter the pitch of a tone in a synthesizer we need to do the following steps.
1. Combine the MSB and LSB to get a 14-bit value.
2. Map that value (which will be in the range 0 to 16,383) to reside in the range -1 to 1.
3. Multiply that by the number of semitones in the ± bend range.
4. Divide that by 12 (the number of equal-tempered semitones in an octave) and use the result as the exponent of 2 to get the pitchbend factor (the value by which we will multiply the base frequency of the tone or the playback rate of the sample).

A pitchbend value of 8,192 (MSB 64 and LSB 0) will mean 0 bend, producing a pitchbend factor of 2(0/12) which is 1; multiplying by that factor will cause no change in frequency. Using the example message from above, a pitchbend of 12,280 will be an upward bend of 4,088/8191=0.499. That is, 12,280 is 4,088 greater than 8,192, so it’s about 0.499 of the way from no bend (8,192) to maximum upward bend (16,383). Thus, if we assume a pitchbend range setting of ± 2 semitones, the amount of pitch bend would be about 0.998 semitones, so the frequency scaling factor will be 2(0.998/12), which is about 1.059. You would multiply that factor by the fundamental frequency of the tone being produced by your synthesizer to get the instantaneous frequency of the note.

KTSerg
13.08.2020, 18:21
Перегнал плеер от Апогея, который выкладывал SegaBoy.
Пересчитал коэффициенты для Вектора.
Вот что получилось. С исходником.

metamorpho, в плеере таблицы оптимизированы, в них нет коэффициентов для нот, которые не используются в конкретной мелодии.

metamorpho
13.08.2020, 19:30
Ответ - в спецификации MIDI. Параметр команды Pb - это 14-битное число от 0 до 16384. При конверсии:
1. Это число нужно преобразовать в диапазон от -1 до 1. 8192 - это ноль, 16384 - это один, а 0 - это минус один. Всё, что между этими точками - вещественные числа в диапазоне от -1 до 1.
2. Умножить на количество полутонов в диапазоне pitch bend (обычно +/- два полутона, т.е. умножаем на 2)
3. Поделить на 12 (количество полутонов в октаве)
4. Возвести двойку в степень числа, полученного на шаге 3
5. Умножить базовую частоту ноты на результат шага 4

Вот это да ?!?!
Всё-таки кажется как-то попроще это должно быть.
Подождём ответ SegaBoy, узнаем что он делает с этим Pb.


Перегнал плеер от Апогея, который выкладывал SegaBoy.
Пересчитал коэффициенты для Вектора. Вот что получилось. С исходником.

KTSerg, огромное спасибо!!

SegaBoy
13.08.2020, 20:45
Вот это да ?!?!
Всё-таки кажется как-то попроще это должно быть.
Подождём ответ SegaBoy, узнаем что он делает с этим Pb.

Всё верно x-code расписал. Из описания выше формула получается следующая:


noteFreq * 2 ^ ((pitchBend - 8192) / 8191 * halfToneNum / 12)

где noteFreq это базовая частота ноты к которой применяем изменение pitchBend, а halfToneNum это количество полутонов на которое можно сдвинуть высоту ноты вверх или вниз. В описании выше оно указано как ±2, но может быть от ±2 до ±12 (я как раз использую ±12, правда я уже не помню как пришёл именно к такому значению).

SegaBoy
13.08.2020, 23:35
... Почему для второго канала это $be, а не $b6 - возможно, на Апогее используется другой режим таймера.
При установке режимов работы 2 или 3, третий бит может иметь любое значение. Поэтому $3e, $7e и $be равнозначны $36, $76 и $b6.

metamorpho
14.08.2020, 09:11
Эта невероятная Pb. Что-то я запутался в её вычислении.

К примеру в миди тексте дано следующее:
77 On ch=2 n=76 v=127
77 Pb ch=2 v=8122

Что означает в канал номер 2 загрузить ноту 76 + применить к этой ноте Pb

Я так понял параметр v=8122 (уровень громкости) всё же учитывается при конверсии ?
Иначе на основании чего вычислять Pb ?

По инструкции:
1. Это число нужно преобразовать в диапазон от -1 до 1.
0 - это минус один 8192 - это ноль 16384 - это один
Всё, что между этими точками - вещественные числа в диапазоне от -1 до 1.

Т.е. всё что от 0 до 8191 это Pb=-1 ?
А если ровно 8192 то это Pb=0 ?
А всё что от 8193 до 16384 это Pb=1 ?

И тогда получается что в данном случае Pb=-1 т.к. v=8122 т.е. меньше 8192

Правильно ли я понял ?

-----------------------------------

Всё верно x-code расписал. Из описания выше формула получается

следующая:


noteFreq * 2 ^ ((pitchBend - 8192) / 8191 * halfToneNum / 12)

где noteFreq это базовая частота ноты к которой применяем изменение pitchBend, а halfToneNum это

количество полутонов на которое можно сдвинуть высоту ноты вверх или вниз. В описании выше оно

указано как ±2, но может быть от ±2 до ±12 (я как раз использую ±12, правда я уже не помню как

пришёл именно к такому значению).


noteFreq * 2 ^ ((pitchBend - 8192) / 8191 * halfToneNum / 12)

noteFreq это понятно взять нужно из таблицы частот нот
pitchBend=-1 (в данном примере)
А как понять чему равен halfToneNum ? ±12
Он зависит от значения Pb ?
т.е. если Pb=0 тогда соответственно halfToneNum=0
если Pb=1 тогда соответственно halfToneNum=12
если Pb=-1 тогда соответственно halfToneNum=-12

И тогда получается что в данном случае halfToneNum=-12 т.к. Pb=-1

Правильно ли я понял ?
-------------------------------------

В результате получается
если Pb=0 тогда воздействия на ноту никакого не будет
если Pb=1 тогда если например была нота до#2-й октавы то она станет до#3-й октавы
если Pb=-1 тогда если например была нота до#2-й октавы то она станет до#1-й октавы

Т.е. при конверсии алгоритм такой:
если Pb=0 тогда пропускаем т.к. ничего не меняется
если Pb=1 тогда номер ноты=номер ноты+12
если Pb=-1 тогда номер ноты=номер ноты-12

Если это так то зачем нужны сложные формулы, если вместо Pb можно было сразу номер ноты записать.

====================================
Ещё вопрос определения ноты.

Вот таблица 84-х нот (их частот) для Вектора.
Как считаются ноты ?
Т.е. n=1 (из миди текста) это соответствует какой ноте из таблицы для Вектора ?
n=1 это "до" контр октавы или это "си" 4-й октавы ?


note_table:
; контр-октава (12 нот)
dw 45872,43290,40872,38560,36408,34364,32432,30612,28 902,27273,25729,24311 ;

до/до#/ре/ре#/ми/фа/фа#/соль/соль#/ля/ля#/си
; большая-октава
dw 22936,21645,20436,19280,18204,17182,16216,15306,14 451,13636,12876,12146 ; до до# ре ре# ми фа

фа# соль соль# ля ля# си
; малая-октава
dw 11468,10823,10218,9646,9102,8591,8108,7653,7229,68 18,6438,6075 ; до до# ре ре# ми фа фа# соль

соль# ля ля# си
; 1-я октава
dw 5734,5415,5107,4823,4551,4296,4054,3827,3614,3409, 3219,3036 ; до до# ре ре# ми фа фа# соль

соль# ля ля# си
; 2-я октава
dw 2867,2708,2554,2412,2275,2147,2027,1913,1805,1705, 1609,1519 ; до до# ре ре# ми фа фа# соль

соль# ля ля# си
; 3-я октава
dw 1433,1353,1277,1205,1137,1074,1014,957,904,852,804 ,759 ; до до# ре ре# ми фа фа# соль соль# ля

ля# си
; 4-я октава
dw 717,677,639,602,569,537,507,472,452,426,402,380 ; до до# ре ре# ми фа фа# соль соль# ля ля# си

x-code
14.08.2020, 10:29
Т.е. всё что от 0 до 8191 это Pb=-1 ?
А если ровно 8192 то это Pb=0 ?
А всё что от 8193 до 16384 это Pb=1 ?

Нет. Я не зря писал уточнение, что при приведении к диапазону -1..+1 получается вещественное число.

При исходной команде

77 Pb ch=2 v=8122
получается

(8122 - 8192) / 8191 ~= -0,0085
-0,0085 * 12 / 12 = -0,0085
2^-0,0085 ~= 0,9941

Это и есть наш искомый множитель частоты

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


Как считаются ноты ?
Т.е. n=1 (из миди текста) это соответствует какой ноте из таблицы для Вектора ?
n=1 это "до" контр октавы или это "си" 4-й октавы ?

Если правильно читаю спецификацию MIDI, то n выражается в полутонах, 60 соответствует ноте "до" первой октавы.
Соответственно, 61 - это до диез первой октавы, 59 - это си малой октавы (помним, что между "си" предыдущей октавы и "до" следующей всего один полутон)

metamorpho
14.08.2020, 10:56
Нет. Я не зря писал уточнение, что при приведении к диапазону -1..+1 получается вещественное число.
При исходной команде получается
(8122 - 8192) / 8191 ~= -0,0085
-0,0085 * 12 / 12 = -0,0085
2^-0,0085 ~= 0,9941
Это и есть наш искомый множитель частоты


Тогда получиться частота, которой нет в статичной Векторовской таблице нот
и значит нужно для каждой мелодии делать свою специфическую таблицу нот (частот) учитывая все варианты Pb.



Если правильно читаю спецификацию MIDI, то n выражается в полутонах, 60 соответствует ноте "до" первой октавы.
Соответственно, 61 - это до диез первой октавы, 59 - это си малой октавы (помним, что между "си" предыдущей октавы и "до" следующей всего один полутон)

В Векторовской статичной таблице нот всего 84 ноты и такие данные как-то не совместимы с этой таблицей. И что тогда делать ?

x-code
14.08.2020, 11:01
значит нужно для каждой мелодии делать свою специфическую таблицу нот (частот) учитывая все варианты Pb.

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

S_V_B
14.08.2020, 16:29
Кроме музыки, как насчет процедурных звуков... "пию...бубух.. и вжжжж".. очень интересно

SegaBoy
14.08.2020, 19:49
Тогда получиться частота, которой нет в статичной Векторовской таблице нот
и значит нужно для каждой мелодии делать свою специфическую таблицу нот (частот) учитывая все варианты Pb.
В Векторовской статичной таблице нот всего 84 ноты и такие данные как-то не совместимы с этой таблицей. И что тогда делать ?
У меня для каждой мелодии своя таблица - не одна какая-то общая или универсальная. Алгоритм такой - сначала добываем все задействованные ноты и применяем к ним Pb - столько и какие есть в конкретной мелодии. Не все какие бывают в природе, а только те что нужны для конкретного случая. Получаются разные частоты. Из этих частот вычисляем нужные константы - просто делим частоту каналов ВИ53 на значение частоты "нот". Затем можно оставить эти значения, но они двухбайтовые и часто повторяются. Поэтому и был выбран вариант с таблицей "нот" - хотя в данном случае правильнее будет таблицей констант.

KTSerg
15.08.2020, 07:18
У меня для каждой мелодии своя таблица - не одна какая-то общая или универсальная. ... Поэтому и был выбран вариант с таблицей "нот" - хотя в данном случае правильнее будет таблицей констант.
Кстати, понятно, что это универсальный алгоритм (отдельная таблица для каждого канала), и он не оптимален во всех случаях.
В тех двух мелодиях, что были выложены, и в которых я пересчитывал коэффициенты для Вектора, таблица второго канала почти полностью совпадала с таблицей первого канала. За небольшим исключением. И в данных случаях было бы компактнее сделать одну таблицу для всех трёх каналов, чтобы не дублировались коэффициенты.
Хотя это мелочь, (при общей таблице) экономилось-бы всего около десятка байт.

metamorpho
15.08.2020, 15:51
Как оказалось на Векторе отсутствуют какие-либо музыкальные редакторы. Поэтому в результате создания собственного плеера для музыки под ВИ53 появилось желание сделать хотя бы простенький нотный 3-х канальный музыкальный редактор, который мог бы выдавать код для вставки в ассебмлер. Но на его создание нужно время.
Попробовал создать конвертор текстового-миди файла, но тема оказалась не из лёгких.
Сделал простенький конвертор для миди-текстов и после конвертации у меня получилась "мелодия" не для слабых нервов :)
Оказалось это не очень похоже на автоматическую конвертацию из одного формата в другой. При конвертации Midi-текста нужно учесть много разных моментов + нужна ручная доработка отдельных моментов Midi мелодий. На создание качественного конвертора нужно время.
Поэтому на данный момент решил обратиться к профессионалу конвертации Midi для ВИ53- к SegaBoy.
SegaBoy, почитал твою тему про конвертацию и обнаружил что у тебя есть вот такая мелодия "Chōjin Sentai Jetman (04) Area C".
Есть ли у тебя её исходник на asm ? Можно ли мне её использовать в игре ?
И есть ли у тебя ещё какие-либо (не представленные в твоей теме про конвертацию) мелодии конвертированные тобой под Ви53 ?

SegaBoy
15.08.2020, 19:40
Кстати, понятно, что это универсальный алгоритм (отдельная таблица для каждого канала), и он не оптимален во всех случаях.
В тех двух мелодиях, что были выложены, и в которых я пересчитывал коэффициенты для Вектора, таблица второго канала почти полностью совпадала с таблицей первого канала. За небольшим исключением. И в данных случаях было бы компактнее сделать одну таблицу для всех трёх каналов, чтобы не дублировались коэффициенты.
Хотя это мелочь, (при общей таблице) экономилось-бы всего около десятка байт.
Использовал алгоритм что был под рукой - он для особо сложных случаев (типа Silver Surfer), где не хватает 256 значений на три канала и нужно на каждый канал по отдельной таблице. А так в старых версиях, на такие «простые» мелодии я использовал одну таблицу на три канала.

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


SegaBoy, почитал твою тему про конвертацию и обнаружил что у тебя есть вот такая мелодия "Chōjin Sentai Jetman (04) Area C".
Есть ли у тебя её исходник на asm ? Можно ли мне её использовать в игре ?
И есть ли у тебя ещё какие-либо (не представленные в твоей теме про конвертацию) мелодии конвертированные тобой под Ви53 ?
Я Джетмана конвертировал под аппаратную доработку с управлением уровня громкости. Попробую сделать в обычном режиме, тогда выложу результат и исходники.
Из не выложенных есть ещё Silver Surfer и ещё что-то.

SegaBoy
16.08.2020, 15:36
Эта невероятная Pb. Что-то я запутался в её вычислении.
Попробуй пока вообще не использовать Pb. Используй только On и Off. Например для super mario этого вполне достаточно для начала.

jerri
18.08.2020, 10:55
Немного новостей. Сейчас в целом различные моменты игры (кроме музыки) оформились.
Так что пока их откладываю в сторону и занимаюсь разработкой кода для проигрывания музыки.
Музыка (для ВИ53), оказалась наиболее специфичной и незнакомой темой для меня.
Но надеюсь с помощью тех кто мне помогает напишу код для музыки :)

А пока вот (rom) для тестов. Уровни ещё не шлифовал (просто наброски).
Некоторые из них непроходимы. Переключаться между уровнями можно клавишей "Тab".
Интересно ваше мнение насчёт эффекта при взятии монеты.
Первоначально была графика при гибели героя (аж семь кадров исчезания типа взрыва), но от этого пришлось отказаться т.к. памяти не хватает. Поэтому вместо графики, был написан эффект при гибели героя, который так себе получился, но есть планы его доработать до чего-то лучшего :)
Может у кого-то будут какие советы по игре - пишите.
Из "крупных" данных в игру осталось вставить музыку и заставку - надеюсь памяти хватит :)

эффект когда плывет палитра? а может чорный высветлять до белого и назад?

а если набор микровзрывов?

metamorpho
18.08.2020, 15:27
При взятии монеты эффект создаётся вот как - в программе обработки прерываний срабатывает следующее:
mvi a,251
out 02
С палитрой это не связано напрямую.
Чёрный до белого и назад кажется будет слишком контрастно (на мой взгляд).

Насчёт набора микровзрывов хорошая идея, попробую !!

metamorpho
18.08.2020, 20:02
Игра готова по всем пунктам, кроме музыки.
Осталось вставить музыку и может некоторые звуки изменить.
После различных оптимизаций кода и информации удалось неплохо сократить файл - на данный момент игра занимает 30756 байт
Можно ещё кое-что ужать но похоже этого хватит.

zx_
19.08.2020, 09:07
metamorpho, а картинки из игры, ака скриншоты
в первый пост

metamorpho
20.08.2020, 10:09
metamorpho, а картинки из игры, ака скриншоты
в первый пост

Сделаю, но только когда сделаю музыку для игры - тогда игра будет полностью готова.

KTSerg
20.08.2020, 10:15
Наткнулся в закромах на файл "Миссия невыполнима.mid", правда в ней только часть темы.

metamorpho
20.08.2020, 11:09
Наткнулся в закромах на файл "Миссия невыполнима.mid", правда в ней только часть темы.

KTSerg, не понял ты о чём ?

metamorpho
21.08.2020, 11:06
Написал простенький музыкальный редактор. К нему написал свой плеер. Возникла проблема не пойму почему так работает.
Плеер у меня обрабатывает три канала отдельно. Каждый канал отдельно работает правильно, но если их сразу три запускать то один играет, а два других "хрипят".
В чём может быть проблема ? Может есть какая-то особенность программирования каналов ВИ53 ?

KTSerg
21.08.2020, 12:22
... Плеер у меня обрабатывает три канала отдельно. Каждый канал отдельно работает правильно, но если их сразу три запускать то один играет, а два других "хрипят".
...
Без просмотра кода плеера сложно сказать что-то конкретное.

metamorpho
21.08.2020, 12:32
Без просмотра кода плеера сложно сказать что-то конкретное.

Вот код:


;
;-----------------------------------------------
; Super player 08.2020
;-----------------------------------------------
;
;==== Мой формат плеера:


;===================================
pit_init1 .equ 36h
pit_init2 .equ 76h
pit_init3 .equ 0b6h
timeron .equ 1h
;
;------------------------------------

.ORG 0100H
; =======================
M0000H: DI
XRA A
OUT 10H ;
;
MVI A,0C3H
STA 0000H ;
STA 0038H ;
LXI H,M0000H
SHLD 0001H
LXI H,vsync
SHLD 0039H
;
LXI SP,100H

end_program:

mvi a, pit_init1 ; отключить канал 1
out $08
mvi a, pit_init2 ; отключить канал 2
out $08
mvi a, pit_init3 ; отключить канал 3
out $08
;
lxi h, repeat_point1 ;
shld data_pointer1 ; инициализация канала 1
lxi h, repeat_point2 ;
shld data_pointer2 ; инициализация канала 2
lxi h, repeat_point3 ;
shld data_pointer3 ; инициализация канала 3
mvi a, 1 ;
sta wait_counter1 ;
sta wait_counter2
sta wait_counter3

ei

command_line:
jmp command_line
;
;============================================ Плеер в программе обработки прерываний
;
vsync:
push h
push d
push b
push psw


;======================= обработка канала 1
kanal1:
lxi h,wait_counter1 ; отрабатываем установленную длительность
dcr m
jnz kanal2 ; переход если длительность не равна нулю
; ===== иначе если равна нулю то загружаем следующие данные
read_command1:
lhld data_pointer1 ; читаем данные
mov a,m
inx h
shld data_pointer1
cpi 255 ; проверяем это не конец мелодии ?
jnz oktava_can1 ; если нет то идём на обработку данных

; если конец мелодии канала то глушим канал
mvi a, 36h ; отключить канал 1
out $08
lxi h, repeat_point1 ; перезапуск мелодии
shld data_pointer1
jmp kanal2 ; переход на канал 2

;================================================= === проверка октавы
oktava_can1:
; ==============отсеиваем только то что от 108-114
cpi 114
jnc dlina_can1 ; если больше 114 то уходим
cpi 108
jc dlina_can1 ; если меньше 108 то уходим

call oktavian ; возвращает в HL адрес октавы
shld oktava_counter1 ; установка октавы для канала

lhld data_pointer1 ; читаем данные
mov a,m
inx h
shld data_pointer1
;============================================== проверка это длительность ?
dlina_can1:
; ==============отсеиваем только то что от 101-107
cpi 107
jnc off_1 ; если больше 114 то уходим
cpi 101
jc off_1 ; если меньше 108 то уходим

call dlinachiz ; возвращает в A длительность канала
sta swait_counter1 ; установка длительности для канала

lhld data_pointer1 ; читаем данные
mov a,m
inx h
shld data_pointer1
;============================================== проверка это пауза ?
off_1:
cpi 100
jnz set_1
mvi a,36h ; выключить канал 1
out 08
lda swait_counter1 ; взять длительность канала
sta wait_counter1 ; установка текущей длительности для канала
jmp kanal2 ; переход на канал 2

;============================================== значит это НОТА 1-12
set_1:
lhld oktava_counter1 ; берём адрес октавы для ноты
lxi d, 0002h; вычисляем адрес ноты
rizunok1:
dcr a
jz wuwitron1 ; нашли адресс ноты
dad d
jmp rizunok1
wuwitron1:
mvi a,36h ; задать режим для канала 1 (включить канал)
out 08
mov a, m
out 0bH
inx h
mov a, m
out 0bH
lda swait_counter1 ; взять длительность канала
sta wait_counter1 ; установка текущей длительности для канала

;================================================= =============
;======================= обработка канала 2
;================================================= =============
kanal2:
lxi h,wait_counter2 ; отрабатываем установленную длительность
dcr m
jnz kanal3 ; переход если длительность не равна нулю
; ===== иначе если равна нулю то загружаем следующие данные
read_command2:
lhld data_pointer2 ; читаем данные
mov a,m
inx h
shld data_pointer2
cpi 255 ; проверяем это не конец мелодии ?
jnz oktava_can2 ; если нет то идём на обработку данных

; если конец мелодии канала то глушим канал
mvi a, 76h ; отключить канал 2
out $08
lxi h, repeat_point2 ; перезапуск мелодии
shld data_pointer2
jmp kanal3 ; переход на канал 2

;================================================= === проверка октавы
oktava_can2:
; ==============отсеиваем только то что от 108-114
cpi 114
jnc dlina_can2 ; если больше 114 то уходим
cpi 108
jc dlina_can2 ; если меньше 108 то уходим

call oktavian ; возвращает в HL адрес октавы
shld oktava_counter2 ; установка октавы для канала

lhld data_pointer2 ; читаем данные
mov a,m
inx h
shld data_pointer2
;============================================== проверка это длительность ?
dlina_can2:
; ==============отсеиваем только то что от 101-107
cpi 107
jnc off_2 ; если больше 114 то уходим
cpi 101
jc off_2 ; если меньше 108 то уходим

call dlinachiz ; возвращает в A длительность канала
sta swait_counter2 ; установка длительности для канала

lhld data_pointer2 ; читаем данные
mov a,m
inx h
shld data_pointer2
;============================================== проверка это пауза ?
off_2:
cpi 100
jnz set_2
mvi a,76h ; выключить канал 2
out 08
lda swait_counter2 ; взять длительность канала
sta wait_counter2 ; установка текущей длительности для канала
jmp kanal3 ; переход на канал 2

;============================================== значит это НОТА 1-12
set_2:
lhld oktava_counter2 ; берём адрес октавы для ноты
lxi d, 0002h; вычисляем адрес ноты
rizunok2:
dcr a
jz wuwitron2 ; нашли адресс ноты
dad d
jmp rizunok2
wuwitron2:
mvi a,76h ; задать режим для канала 2 (включить канал)
out 08
mov a, m
out 0aH
inx h
mov a, m
out 0aH
lda swait_counter2 ; взять длительность канала
sta wait_counter2 ; установка текущей длительности для канала

;================================================= =============
;======================= обработка канала 3
;================================================= =============
kanal3:
lxi h,wait_counter3 ; отрабатываем установленную длительность
dcr m
jnz end_int ; выход из прерываний если длительность не равна нулю
; ===== иначе если равна нулю то загружаем следующие данные
read_command3:
lhld data_pointer3 ; читаем данные
mov a,m
inx h
shld data_pointer3
cpi 255 ; проверяем это не конец мелодии ?
jnz oktava_can3 ; если нет то идём на обработку данных

; если конец мелодии канала то глушим канал
mvi a, 0b6h ; отключить канал 3
out $08
lxi h, repeat_point3 ; перезапуск мелодии
shld data_pointer3
jmp end_int ; выход из прерываний

;================================================= === проверка октавы
oktava_can3:
; ==============отсеиваем только то что от 108-114
cpi 114
jnc dlina_can3 ; если больше 114 то уходим
cpi 108
jc dlina_can3 ; если меньше 108 то уходим

call oktavian ; возвращает в HL адрес октавы
shld oktava_counter3 ; установка октавы для канала

lhld data_pointer3 ; читаем данные
mov a,m
inx h
shld data_pointer3
;============================================== проверка это длительность ?
dlina_can3:
; ==============отсеиваем только то что от 101-107
cpi 107
jnc off_3 ; если больше 114 то уходим
cpi 101
jc off_3 ; если меньше 108 то уходим

call dlinachiz ; возвращает в A длительность канала
sta swait_counter3 ; установка длительности для канала

lhld data_pointer3 ; читаем данные
mov a,m
inx h
shld data_pointer3
;============================================== проверка это пауза ?
off_3:
cpi 100
jnz set_3
mvi a,0b6h ; выключить канал 3
out 08
lda swait_counter3 ; взять длительность канала
sta wait_counter3 ; установка текущей длительности для канала
jmp end_int ; выход из прерываний

;============================================== значит это НОТА 1-12
set_3:
lhld oktava_counter3 ; берём адрес октавы для ноты
lxi d, 0002h; вычисляем адрес ноты
rizunok3:
dcr a
jz wuwitron3 ; нашли адресс ноты
dad d
jmp rizunok3
wuwitron3:
mvi a,0b6h ; задать режим для канала 3 (включить канал)
out 08
mov a, m
out 09H
inx h
mov a, m
out 09H
lda swait_counter3 ; взять длительность канала
sta wait_counter3 ; установка текущей длительности для канала


;=================================
end_int:
pop psw
pop b
pop d
pop h
;
ei
ret
;
;
;================================================= ===========
;---------------------------
; контр-октава (12 нот)
note_table1:
dw 45872,43290,40872,38560,36408,34364,32432,30612,28 902,27273,25729,24311 ; до/до#/ре/ре#/ми/фа/фа#/соль/соль#/ля/ля#/си
; большая-октава
note_table2:
dw 22936,21645,20436,19280,18204,17182,16216,15306,14 451,13636,12876,12146 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; малая-октава
note_table3:
dw 11468,10823,10218,9646,9102,8591,8108,7653,7229,68 18,6438,6075 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 1-я октава
note_table4:
dw 5734,5415,5107,4823,4551,4296,4054,3827,3614,3409, 3219,3036 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 2-я октава
note_table5:
dw 2867,2708,2554,2412,2275,2147,2027,1913,1805,1705, 1609,1519 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 3-я октава
note_table6:
dw 1433,1353,1277,1205,1137,1074,1014,957,904,852,804 ,759 ; до до# ре ре# ми фа фа# соль соль# ля ля# си
; 4-я октава
note_table7:
dw 717,677,639,602,569,537,507,472,452,426,402,380 ; до до# ре ре# ми фа фа# соль соль# ля ля# си


;================sound_data: .db
repeat_point1: db 111,104,1,2,3,4,5,6,7,8,9,10,11,12,255
repeat_point2: db 112,104,1,2,3,4,5,6,7,8,9,10,11,12,255
repeat_point3: db 113,104,1,2,3,4,5,6,7,8,9,10,11,12,255

;255,255,255,255,255,255,255,255,255,255,255,255,2 55,255,255

;---------------------------

data_pointer1: .dw 0 ; позиция в нотном массиве для канала 1
data_pointer2: .dw 0 ; позиция в нотном массиве для канала 2
data_pointer3: .dw 0 ; позиция в нотном массиве для канала 3

wait_counter1: .db 0 ; текущее вычисление длительность для канала 1
wait_counter2: .db 0 ; текущее вычисление длительность для канала 2
wait_counter3: .db 0 ; текущее вычисление длительность для канала 3

swait_counter1: .db 0 ; установленная длительность для канала 1
swait_counter2: .db 0 ; установленная длительность для канала 2
swait_counter3: .db 0 ; установленная длительность для канала 3

oktava_counter1: .db 0 ; установленная ОКТАВА для канала 1
oktava_counter2: .db 0 ; установленная ОКТАВА для канала 2
oktava_counter3: .db 0 ; установленная ОКТАВА для канала 3

;=======================================
; подпрограммы определения длительности
dlinachiz:
cpi 101
jnz ghtimin1
mvi a,255 ;------ 1 - full
ret
ghtimin1:
cpi 102
jnz ghtimin2
mvi a,128 ;------ 1/2
ret
ghtimin2:
cpi 103
jnz ghtimin3
mvi a,64 ;------ 1/4
ret
ghtimin3:
cpi 104
jnz ghtimin4
mvi a,32 ;------ 1/8
ret
ghtimin4:
cpi 105
jnz ghtimin5
mvi a,16 ;------ 1/16
ret
ghtimin5:
cpi 106
jnz ghtimin6
mvi a,8 ;------ 1/32
ret
ghtimin6:
cpi 107
rnz
mvi a,4 ;------ 1/64
ret
;=======================================
; подпрограммы определения октавы
oktavian:
cpi 108
jnz timin1
lxi h,note_table1 ; контр-октава
ret
timin1:
cpi 109
jnz timin2
lxi h,note_table2 ; большая-октава
ret
timin2:
cpi 110
jnz timin3
lxi h,note_table3 ; малая-октава
ret
timin3:
cpi 111
jnz timin4
lxi h,note_table4 ; 1-я октава
ret
timin4:
cpi 112
jnz timin5
lxi h,note_table5 ; 2-я октава
ret
timin5:
cpi 113
jnz timin6
lxi h,note_table6 ; 3-я октава
ret
timin6:
cpi 114
rnz
lxi h,note_table7 ; 4-я октава
ret
;==============================
.end

ivagor
21.08.2020, 12:46
Не уверен, решит ли это проблему хрипа, но задавать режим канала таймера при каждом изменении делителя - это лишнее. Надо один раз в начале инициализировать все три канала и в паузах соответствующий канал.

metamorpho
21.08.2020, 13:19
Не уверен, решит ли это проблему хрипа, но задавать режим канала таймера при каждом изменении делителя - это лишнее. Надо один раз в начале инициализировать все три канала и в паузах соответствующий канал.

Проблему не решило, но для себя сделал открытие в отсутствии необходимости каждую ноту задавать режим канала. Спасибо за совет.

ivagor
21.08.2020, 14:18
oktava_counterы нужно поменять с db на dw

metamorpho
21.08.2020, 14:33
oktava_counterы нужно поменять с db на dw

ivagor, спасибо большое - ПОМОГЛО !!
Автоматически скопировал при наборе и неподумал. А потом это же очевидно должно быть DW т.к. адресс два байта. Куда я смотрел не знаю ?
Да проблемы бывают кроются в чём-то более простом, а мы ищем их в сложном.
Зато я перерыл по теме ВИ53 журналы "Вектор-User", "Байты" и Черезова заодно посмотрел - искал там особенности программирования ВИ53, а тут банальное DW :)

Black Cat / Era CG
23.08.2020, 07:00
Вот Шедевр! http://sensi.org/scalar/ware/436/
Только коротковат :(

CodeMaster
23.08.2020, 09:56
Только коротковат
Было бы желание и сюжет, можно кучу подгрузок сделать, а тут, пока, минимализм.

Black Cat / Era CG
23.08.2020, 10:08
Я так понимаю игра очень поздняя.

metamorpho
24.08.2020, 21:52
Игра готова. Обновил первый пост.

CodeMaster
24.08.2020, 22:00
Игра готова.
Как можно добавить её сюда (http://sensi.org/scalar/)?

metamorpho
24.08.2020, 22:03
Как можно добавить её сюда (http://sensi.org/scalar/)?

Насколько я знаю это svofski добавляет туда.

CodeMaster
24.08.2020, 22:10
Тогда, попросим svofski в тему.

svofski
24.08.2020, 23:19
Вот!
http://sensi.org/scalar/ware/910

Чего-то мне кажется, что иногда мерцает. Или это спецэффект при съедании монетки?

ivagor
25.08.2020, 06:26
metamorpho, игрушка очень красивая, но для казуального меня сложноватая. Насчет эффекта при взятии монетки согласен со svofski - как-то не очень. И бывает артефакт, когда при скролле от вертолета остается фрагмент.

metamorpho
25.08.2020, 07:53
Чего-то мне кажется, что иногда мерцает. Или это спецэффект при съедании монетки?

Да мерцает - это такой спецэффект :)
svofski, спасибо за внесение в картотеку!!

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


metamorpho, игрушка очень красивая, но для казуального меня сложноватая. Насчет эффекта при взятии монетки согласен со svofski - как-то не очень. И бывает артефакт, когда при скролле от вертолета остается фрагмент.

ivagor, спасибо за отзыв!!
Да немного хардкора там есть :)
Насчёт эффекта - например могу сделать специальную версию без этого эффекта - если нужно :)
Про артефакт с вертолётом знаю, возможно позже исправлю, но сначала нужно понять откуда он растёт :)

Black Cat / Era CG
25.08.2020, 08:31
Игра готова. Обновил первый пост.
Пройдено! Клево, но очень коротко :)

metamorpho
25.08.2020, 09:09
Пройдено! Клево, но очень коротко :)

Black Cat / Era CG, спасибо за отзыв!!

svofski
25.08.2020, 12:07
svofski, спасибо за внесение в картотеку!!
Спасибо за то, что есть что вносить! Давай ещё =)

KTSerg
26.08.2020, 07:08
...
Ну вот и пройден путь - моя цель достигнута - завершено написание моего первого "шедевра" для Вектора.
...
- написан редактор уровней, ...
...

Добавить в игру метку с номером сборки.
Доработать Редактор уровней, чтобы он проверял на соответствие номера сборки и менял уровни в rom-файле игры.
Выложить Редактор в комплекте с игрой.
Возможно у народа появятся идеи по поводу новых уровней, поделятся своими версиями...

Это мои мысли вслух.

CodeMaster
26.08.2020, 09:34
Насчет эффекта при взятии монетки согласен со svofski - как-то не очень.
При том, что он не всегда возникает.

но для казуального меня сложноватая.
Не знаю, явно не хватает счётчика жизней и таймера на прохождение ;-)

Да немного хардкора там есть
9-й уровень непроходим в паре мест? Или надо искать фичи?

metamorpho
26.08.2020, 12:49
Спасибо за то, что есть что вносить! Давай ещё =)

Желание ещё сотворить для Вектора есть, как только появиться возможность....


Добавить в игру метку с номером сборки.
Доработать Редактор уровней, чтобы он проверял на соответствие номера сборки и менял уровни в rom-файле игры. Выложить Редактор в комплекте с игрой. Возможно у народа появятся идеи по поводу новых уровней, поделятся своими версиями...

Интересная идея.


При том, что он не всегда возникает....
Не знаю, явно не хватает счётчика жизней и таймера на прохождение ;-)
...........9-й уровень непроходим в паре мест? Или надо искать фичи?

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

ivagor
26.08.2020, 13:24
metamorpho, думаю попробовать портануть на другой комп, как к этому относишься? Не факт, что действительно начну что-то делать, но вдруг начну, а автор против.

metamorpho
26.08.2020, 14:04
metamorpho, думаю попробовать портануть на другой комп, как к этому относишься? Не факт, что действительно начну что-то делать, но вдруг начну, а автор против.

У меня есть мысли сделать порт (тоже возможно сделаю, а может и нет) на PC, Android (и может быть на ZX Spectrum).
На другие платформы я не против, а только за :)
А на какой комп портануть хочешь ?

ivagor
26.08.2020, 14:45
А на какой комп портануть хочешь ?
Орион-Про (с парой дополнительных плат) вроде должен потянуть. Еще из продвинутых неспектрумов должен бы потянуть Алесте, но там и проц помедленнее и я его хуже знаю.

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

Кстати, если говорить о забугорных компах или приставках на z80, то msx 2 подходит, а sega master system подходит просто идеально, но там тысячи своих любителей.

zx_
26.08.2020, 15:07
ivagor, на специалист ? )

ivagor
26.08.2020, 15:33
О специалисте проще будет думать, если metamorpho сделает версию для спека.

metamorpho
26.08.2020, 16:04
О специалисте проще будет думать, если metamorpho сделает версию для спека.

Да есть идея портануть на Спектрум, поскольку на втором месте после Вектора у меня идёт Спектрум - это мой второй компьютер из детства, а ещё там ведь конкурс :)
Если конечно игра подходит под правила конкурса, то я ещё могу успеть (если конечно разберусь с особенностями Спектрума). Хотя сдаётся мне что туда нужно делать более эффектную игру чтобы иметь шанс на приз :)

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


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

ivagor, если решишь портировать, то могу дать исходник (если с ним будет легче это сделать)

ivagor
26.08.2020, 16:12
Если посмотреть на yrgb 2019, то там binorium из призеров мог бы возможно посоревноваться с yazzie, но для этого имхо как минимум нужно очень удачно перерисовать/конверснуть графику с использованием мультиколора и написать крутые музоны для ay. Там все же ситуация намного более конкурентная, для вектора новую игрушку делают раз в несколько лет, а на спеке несколько в год.

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


ivagor, если решишь портировать, то могу дать исходник (если с ним будет легче это сделать)
Спасибо, но лучше не надо. Если я возьму исходник и ничего не сделаю, то получится неудобно.

Black Cat / Era CG
26.08.2020, 18:49
Игра коротенькая. Все легко проходится :)

CodeMaster
27.08.2020, 10:57
9-й уровень проходим....можно посмотреть видео-прохождение в первом посту.
Видео не работает на этом компе, но разобрался.

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

x-code
27.08.2020, 13:40
Да есть идея портануть на Спектрум

На Спектруме придётся повозиться с вертикальным скроллом (в отличие от Вектора, там нет аппаратной поддержки оного от слова "совсем") и с attribute clashing в вертикальном направлении - но, судя по видео (https://www.youtube.com/watch?v=VoHL-nskftc), игры, использующие вертикальный скролл, эту проблему как-то решали.

Это уже - не в обиду автору - не говоря о том, что для Спектрума ещё в годы его величия был тот же Cybernoid (https://www.youtube.com/watch?v=qJ2JJJGdIck), который по геймплею довольно похож на Binorium, за исключением протяжённых по вертикали уровней с плавной прокруткой.

ivagor
27.08.2020, 14:04
Если проводить параллели со спековскими играми, то я бы обратил внимание на old tower (https://www.youtube.com/watch?v=Q0jIODApwRY) Дениса Грачева

jerri
27.08.2020, 15:20
Если проводить параллели со спековскими играми, то я бы обратил внимание на old tower (https://www.youtube.com/watch?v=Q0jIODApwRY) Дениса ГрачеваМультиколор конечно рулит, но сильно сокращает игровое поле.
Надо выбрать или скорость или красота.

metamorpho
04.08.2021, 00:41
Сделал новую версию "Binorum"

Что изменено:
- подключена возможность управлять Джойстиком П (на кнопках - рестарт уровня / он же старт игры)
(спасибо ivagor, svofski, Improver за помощь с вопросами по Джойстику П)
- в заставке название игры преобразилось ( надеюсь в лучшую сторону) :)
- был убран (немного "глючный") спецэффект при взятии монеты

Позже (после того как пройдёт проверка на реальном Векторе) выложу новую версию в начало темы.

metamorpho
06.08.2021, 15:30
Проверка на реальном Векторе прошла успешно - можно скачать новую версию в первом посте в самом низу (вложения) - файл BinorumJP.

Также если можно, то прошу svofski заменить (или добавить) в Картотеке старую версию на новую.

svofski
06.08.2021, 16:07
прошу svofski заменить
Заменил.

Pyk
14.12.2021, 00:41
Обнаружил, что последняя версия игры не работает у меня в эмуляторе Emu80 (также как и в emu от b2m).
Логично было предположить, что проблема в добавленной поддержке джойстика, стал разбираться, но понимание не пришло.
В эмуляторе опрашивается порт B второго ППА (06h). Насколько я понимаю, разомкнутые контакты джойстика - это 1 в соответствующем разряде, нажатие кнопки либо отклонение джойстика приводит к появлению 0.
В Emu80 джойстик (пока) не эмулируется. Загрузчик по умолчанию программирует все 3 порта второго ППА на ввод, никаких подтягивающих резисторов на входах нет, стало быть, без подключенного джойстика из порта B считывается 0, что игра ошибочно воспринимает как нажатые клавиши джойстика.

Но как оно в таком случае работает на реале (без джойстика)? Что я не учитываю?

Ramiros
14.12.2021, 08:53
Загрузчик по умолчанию программирует все 3 порта второго ППА на ввод, никаких подтягивающих резисторов на входах нет, стало быть, без подключенного джойстика из порта B считывается 0, что игра ошибочно воспринимает как нажатые клавиши джойстика.

Но как оно в таком случае работает на реале (без джойстика)? Что я не учитываю?

С чего вы решили что будет 0? висящие в воздухе входа (т.е. затворы полевых транзисторов) работают как антена и отлично ловят наводки. Там скорее будет считываться 1, ну или шум.

Pyk
14.12.2021, 10:12
Ramiros, логично. Могу ошибаться, конечно, но почему-то мне запомнилось, что на моем Апогее в подобном случае из ВВ55 стабильно считывались нули... Проверю еще раз вечером...

Pyk
14.12.2021, 22:32
Ramiros, провел тесты на том, что было под рукой - Апогее. Там также имеется ВВ55, все входы/выходы которого просто выведены на внешний разъем. При программировании на ввод из портов стабильно считываются нули. Более того, именно этот эксперимент побудил меня изменить это поведение в Emu80. В версиях до 4.0.350 включительно из портов считывалось FF, и на них Binorum без проблем работает. В общем, насколько надежно полагаться на то, что без джойстика будет всегда считываться FF, я не знаю :( Может быть, поведение зависит от партии ВВ55 или разводки платы или еще чего-то? Кто-нибудь из форумчан может что-то подсказать?

Кстати, если порт запрограммирован на вывод и на нем установлено FF, то при перепрограммировании на ввод нули начинают считываться не сразу и не одновременно во всех разрядах, переходные процессы занимают некоторое время. Могу проиллюстрировать скриншотом с экрана Апогея, но тут это наверное будет оффтопик...

Pyk
15.12.2021, 00:38
Работу игры в следующей версии Emu80 восстановлю, а пока при желании можно взять версию 4.0.350 от 13 марта года из архива (https://emu80.org/distr/).

Ramiros
15.12.2021, 11:57
Pyk, Может зависит от ревизии, партии ВВ55-й? но игру проверили на реале и она работает. Вообще я считаю это косяк игры и игру по уму надо бы допилить, т.к. есть вероятность что не на всех Векторах она запустится.

parallelno
30.06.2022, 21:04
Круто!

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



echo "sprite: db64 $(base64 -w0 sprite.bin)" >> masterpiece.asm


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

Это для какого ассемблера? или это команды какого-то линовщика? Поясни пожалуйста.

Ищу способ инклудить бинарные файлы. но для Tasm не нашел такой команды. Только конверт в текст по типу DB XX, YY,..

svofski
30.06.2022, 21:44
parallelno, при сборке tasm-ом я просто склеиваю отдельные бинарные файлы в процессе сборки, проще всего. db64 - это фишка Прекрасма, в нем можно вставлять большие куски прямо в base64. Когда на скорую руку хочется какой-нибудь графики добавить, удобно.

parallelno
01.07.2022, 03:42
parallelno, при сборке tasm-ом я просто склеиваю отдельные бинарные файлы в процессе сборки, проще всего...

А как ты склеиваешь?

svofski
01.07.2022, 11:25
cat code.bin data.bin > test.rom, ну или copy/b head.bin+data.bin test.rom, в зависимости от системы. Смещение на приплюсованные данные легко вычисляется с помощью метки в конце ассемблерного файла.

parallelno
01.07.2022, 12:08
А если нужно два бинарных файла приклеить?

svofski
01.07.2022, 12:30
А если нужно два бинарных файла приклеить?

Так же, cat и copy можно сколько угодно файлов склеивать. Если несколько массивов данных на которые нужны ссылки, тут тяжелее. Тогда размеры файлов и смещения можно вычислить перед компиляцией основного модуля и передать их как параметры. Например вот тут так делается (наверное это трудночитаемый кусок, но суть в том, что ZSTART получается как 256+VMSIZE+STARTSIZE и потом -DZPU_CODE_START=$$ZSTART
https://gitlab.com/svofski/zpu8080/-/blob/master/common.mk#L117

Это все по своему красиво, но может быть неоправданно и если проще сконвертировать данные в db, которые включаются директивой include, то так лучше и сделать. Объемы-то все комически крохотные: самая громадная глыба данных, которую Вектор сможет охватить, современному компьютеру даже L2 кеш не завалит.

parallelno
01.07.2022, 13:48
А как передать в tasm параметры? Я не смог найти такое в мануале. Видел только что макрос можно для всяких ifdef передавать. Извини, не смог сходу разобраться в твоём билде по ссылке. Не умею пока в Мэйк файлы.

svofski
01.07.2022, 15:05
Параметр и макрос в тасме это одно и то же.

В коде пишем что-нибудь типа


lxi h, DATA_SIZE


а при вызове tasm добавляем (можно просто в батнике) -DDATA_SIZE=256, то есть
tasm -DDATA_SIZE=256 -b -t85 myprog.asm myprog.bin

parallelno
01.07.2022, 20:57
Параметр и макрос в тасме это одно и то же.

В коде пишем что-нибудь типа


lxi h, DATA_SIZE


а при вызове tasm добавляем (можно просто в батнике) -DDATA_SIZE=256, то есть
tasm -DDATA_SIZE=256 -b -t85 myprog.asm myprog.bin

О! За это огормное спасибо! Жалко что не было примера макросов в документации TASM.

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


Перед edup , случайно не пропущено inr l ?

в цикле, почему-то медленнее получилось чем предыдущая версия.
Результат 12D0h.
Цикл буду завтра, т.е. уже сегодня вечером разворачивать, глаза уже не видят ни чего... :(

команды dup и edup которые ты привел в своем коде из какого ассемблера?

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


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

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

Скопипастил у jerri описание и не поправил: D - не совсем X, это X+старшая половина адреса начальной плоскости.

Сравнил твой алгоритм с предыдущими. Твой чуть быстрее всех в тесте TKSerg.

Что-то картинка чмльно пожалась. Не разобрать, поэтому текстом. Добавил проценты от изначального варианта metamorpho. Наглядно видно сколько можно выжать при оптимизации. Крутые результаты, ребят! И спасибо за реализации.

jerri's original
137EH 4990 162%

jerri's precalced, unrolled
162EH 5678 184%

Serg's original
151CH 5404 175%

Serg's precalced, unrolled
15B0H 5552 180%

ivagor's unrolled
170EH 5902 191%

metamorpho's unrolled
0C0CH 3084 100%



77511

parallelno
02.07.2022, 06:43
Нашел небольшую ошибку в программе KTSerg

Два раза вызов процедуры для расчета адреса спрайта для последнего знака результата


call adr_tab
call adr_tab ; вычисление адреса спрайта


Корректный результат будет
jerri's original
137FH 4990 162%

jerri's precalced, unrolled
162FH 5678 184%

Serg's original
151EH 5404 175%

Serg's precalced, unrolled
15B8H 5552 180%

ivagor's unrolled
1707H 5895 191%

metamorpho's unrolled
0C0EH 3086 100%

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

Можно сказать что ничего не поменялось, но для чистоты эксперимента примвел %)

KTSerg
02.07.2022, 07:34
...
команды dup и edup которые ты привел в своем коде из какого ассемблера?
...
Они содержатся не в моём коде.
Судя по переписке
https://zx-pk.ru/threads/31954-pishu-shedevr-dlya-%C2%ABvektora-06ts%C2%BB.html?p=1075237&viewfull=1#post1075237
Я сам не знал что это такое, чтобы заменить чем-то соответствующим для Вектора.
Мнемоника команд кода в котором они были, очень похожа на мнемонику для Z80.

Поисковик дал такую ссылки:
https://zx-pk.ru/threads/447-sjasmplus-z80-kross-assembler.html?p=903843&viewfull=1#post903843
https://zx-pk.ru/threads/447-sjasmplus-z80-kross-assembler.html?p=904360&viewfull=1#post904360
http://zxpress.ru/article.php?id=14690

parallelno
02.07.2022, 22:50
Не выдержала душа поэта... с утреца всё перелопатил.

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

Jerri_c:
lxi d,a_test_spr ; адрес спрайта на экране
lxi b,tab_spr0 ; адрес спрайта
push h ; сохранить счетчик
;
call drop24 ; вывод спрайта
;
pop h восстановить счетчик
inx h ; увеличение счетчика выводов спрайта на экран
;
lda StopFlag ; читаем флаг остановки
ora a ; проверка флага
jnz Jerri_c


И результат немного поменялся:
Оригинальный вариант алгоритма Jerri - 1380h
Вариант Jerri, с заранее вычисленными адресами битпланов, и полностью развёрнутый (без циклов) - 1603h

Мой оригинальный алгоритм - 151Eh
Мой с заранее вычисленными адресами битпланов - 15B2h

Алгоритм metamorpho, совсем не использующий стек - 0С0Сh
Алгоритм metamorpho, совсем не использующий стек и с обычным прерыванием в которои нет защиты стека - 0С0Eh

Во вложении сам тест и его исходник.

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



StInt:
xthl ; обмен hl <-> ((sp))
shld im_ret+1 ; сохраним адрес возврата из прерывания
pop h
shld im_hl+1 ; сохраним значение HL при выхове прерывания
push psw
lxi h,2 ;\ вычисляем указатель стека
dad sp ;/
shld im_sp+1 ; сохраним указатель стека
pop psw
push b ;восстановим данные испорченные стеком

lxi sp,im_stek ; временный указатель стека для прерываний
push PSW
push b
push d


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



StInt:
xthl ; обмен hl <-> ((sp))
shld im_ret+1 ; сохраним адрес возврата из прерывания
pop h
shld im_hl+1 ; сохраним значение HL при выхове прерывания
lxi h,0 ;\ вычисляем указатель стека
dad sp ;/
shld im_sp+1 ; сохраним указатель стека
pop psw
push b ;восстановим данные испорченные стеком

lxi sp,im_stek ; временный указатель стека для прерываний
push b
push d


Поправь меня пожалуйста если ошибаюсь

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


Они содержатся не в моём коде.
Судя по переписке
https://zx-pk.ru/threads/31954-pishu-shedevr-dlya-%C2%ABvektora-06ts%C2%BB.html?p=1075237&viewfull=1#post1075237
Я сам не знал что это такое, чтобы заменить чем-то соответствующим для Вектора.
Мнемоника команд кода в котором они были, очень похожа на мнемонику для Z80.

Поисковик дал такую ссылки:
https://zx-pk.ru/threads/447-sjasmplus-z80-kross-assembler.html?p=903843&viewfull=1#post903843
https://zx-pk.ru/threads/447-sjasmplus-z80-kross-assembler.html?p=904360&viewfull=1#post904360
http://zxpress.ru/article.php?id=14690

Действительно ошибся. Спасибо за ссылки.

KTSerg
03.07.2022, 04:55
Пытаяс понять как работает твоя реализация прерываний нашел один избыточный кусочек кода как мне кажется:



StInt:
xthl ; обмен hl <-> ((sp))
shld im_ret+1 ; сохраним адрес возврата из прерывания
pop h
shld im_hl+1 ; сохраним значение HL при выхове прерывания
push psw
lxi h,2 ;\ вычисляем указатель стека
dad sp ;/
shld im_sp+1 ; сохраним указатель стека
pop psw
push b ;восстановим данные испорченные стеком

lxi sp,im_stek ; временный указатель стека для прерываний
push PSW
push b
push d


кажется что тут избыточно порталкивание PSW в стек и обратно. Как мне кажется его можно убрать, и заодним убрать смешение SP на 2 в команде DAD
...
Поправь меня пожалуйста если ошибаюсь
...
По бумажкам, которые у меня есть, команда "DAD rp" влияет на флаг "CY".
Возможно его пытался защитить от изменения на время выполнения операции "DAD SP".

KTSerg
03.07.2022, 07:34
Если в основной программе флаг CY ни где и ни как не используется, то видимо, скорее всего, его защиту в прерывании можно убрать.

ivagor
03.07.2022, 09:03
Если в основной программе флаг CY ни где и ни как не используется, то видимо, скорее всего, его защиту в прерывании можно убрать.
Лучше не надо, вдруг проц будет не 8080 (ну мало ли) и тогда еще и другие флаги от dad пострадают.

parallelno
03.07.2022, 11:04
О, точно. Не подумал об этом. Спасибо!

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

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

parallelno
04.07.2022, 19:57
Набросал упомянутый ранее вариант, надеюсь принципиальных ошибок нет. Стоит отметить, что порядок вывода очень своеобразный, конвертер графики надо делать аккуратно.

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

Скопипастил у jerri описание и не поправил: D - не совсем X, это X+старшая половина адреса начальной плоскости.

Спасибо за оптимизацию! Твой вариант самый быстрый.
Я его совсем незначительно ускорил (только в инициализации). примерно на 1,2% и сделал его чуточку понятнее для хранения данных (на мой вкус), хотя и далеко от идеала.

твой вариант


;----------------------------------------------------------------
; draw a sprite (24x24 pixels)
; author ivagor
; method: zig-zag, unrolled

; in:
; BC sprite data
; DE screen address (x,y)

.macro DRAW_EVEN_LINE_IVAGOR()
POP B
MOV M,C
DCR H
MOV M,B
DCR H
POP B
MOV M,C
MOV H,E
MOV M,B
INR H
POP B
MOV M,C
INR H
MOV M,B
MOV h,a
POP B
MOV M,C
INR H
MOV M,B
INR H
POP B
MOV M,C
DCR L
.endmacro


.macro DRAW_ODD_LINE_IVAGOR()
MOV M,B
DCR H
POP B
MOV M,C
DCR H
MOV M,B
MOV H,E
POP B
MOV M,C
INR H
MOV M,B
INR H
POP B
MOV M,C
MOV H,D
MOV M,B
INR H
POP B
MOV M,C
INR H
MOV M,B
DCR L
.endmacro

.function DS_ivagor
DrawSprite_ivagor:
; store SP
LXI H,0 ; (12)
DAD SP ; (12)
SHLD @restoreSP+1 ; (20)
; HL = BC
MOV H, B ; (8)
MOV L, C ; (8)
; BC = (HL), HL +=2
MOV C, M ; (8)
INX H ; (8)
MOV B, M ; (8)
INX H ; (8)
; SP = HL
SPHL ; (8)

; HL = DE
XCHG ; (4)
; D = screen X
MOV D, H ; (8)
; E = second screen X
MVI A, $20 ; (8)
ADD D ; (4)
MOV E, A ; (8)
; A = third screen X
MVI A, $20 ; (8)
ADD E ; (4)
; X += 2
INR H ; (8)
INR H ; (8)
; (160)
; screen format
; DRAW_EVEN_LINE_IVAGOR
; 1st screen buff : 3 <- 2 <- (1)
; 2nd screen buff : (4) -> 5 -> 6
; 3rd screen buff : (7) -> 8 -> 9
; y--
; DRAW_ODD_LINE_IVAGOR
; 3nd screen buff : 12 <- 11 <- 10
; 2nd screen buff : (13) -> 14 -> 15
; 1st screen buff : (16) -> 17 -> 18
; y--
; repeat

; HL = screen address (X + 2, Y)
; SP = sprite data + 2
; D - 1st screen buff X
; E - 2nd screen buff X
; A - 3rd screen buff X

; first line
MOV M,C
DCR H
MOV M,B
DCR H
POP B
MOV M,C
MOV H,E
MOV M,B
INR H
POP B
MOV M,C
INR H
MOV M,B
MOV h,a
POP B
MOV M,C
INR H
MOV M,B
INR H
POP B
MOV M,C
DCR L

DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
DRAW_ODD_LINE_IVAGOR()
DRAW_EVEN_LINE_IVAGOR()
; 24th line
MOV M,B
DCR H
POP B
MOV M,C
DCR H
MOV M,B
MOV H,E
POP B
MOV M,C
INR H
MOV M,B
INR H
POP B
MOV M,C
MOV H,D
MOV M,B
INR H
POP B
MOV M,C
INR H
MOV M,B

@restoreSP: LXI SP, TEMP_ADDR ; restore SP (12)
RET
.endfunction




;----------------------------------------------------------------
; draw a sprite (24x24 pixels)
; author: parallelno
; method: zig-zag
; in:
; BC sprite data
; DE screen address (x,y)
.macro DRAW_EVEN_LINE_PARALLELNO2(_moveOneLineDown = true)
POP B ; 1st screen space
MOV M,C
INR H
MOV M,B
INR H
POP B
MOV M,C
MOV H,E ; 2nd screen space
MOV M,B
DCR H
POP B
MOV M,C
DCR H
MOV M,B
MOV H,A ; 3rd screen space
POP B
MOV M,C
DCR H
MOV M,B
DCR H
POP B
MOV M,C
.if _moveOneLineDown == true
DCR L
.endif
.endmacro

.macro DRAW_ODD_LINE_PARALLELNO2(_moveOneLineDown = true)
MOV M,B ; 3rd screen space
INR H
POP B
MOV M,C
INR H
MOV M,B
MOV H,E ; 2nd screen space
POP B
MOV M,C
DCR H
MOV M,B
DCR H
POP B
MOV M,C
MOV H,D ; 1st screen space
MOV M,B
DCR H
POP B
MOV M,C
DCR H
MOV M,B
.if _moveOneLineDown == true
DCR L
.endif
.endmacro

.function DS_parallelno2
DrawSprite_parallelno2:
; store SP
LXI H, 0 ; (12)
DAD SP ; (12)
SHLD @restoreSP + 1 ; (20)
; SP = BC
MOV H, B ; (8)
MOV L, C ; (8)
SPHL ; (8)
; D, E, A are initial X for
; the 1st, the 2nd, the 3rd screen buffs
XCHG ; (4)
MVI A, 2 ; (8)
ADD H ; (4)
MOV D, A ; (8)
ADI $20 ; (8)
MOV E, A ; (8)
ADI $20 ; (8)
; (108) total
; screen format
; DRAW_EVEN_LINE_PARALLELNO2()
; 1st screen buff : 1 -> 2 -> 3
; 2nd screen buff : 4 <- 5 <- (6)
; 3rd screen buff : 7 <- 8 <- (9)
; y--
; DRAW_ODD_LINE_PARALLELNO2()
; 3nd screen buff : 12 -> 11 -> 10
; 2nd screen buff : 13 <- 14 <- (15)
; 1st screen buff : 18 <- 17 <- (16)
; y--
; repeat

; HL - 1st screen buff XY
; SP - sprite data
; D - 1st screen buff X + 2
; E - 2nd screen buff X + 2
; A - 3rd screen buff X + 2

DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2()
DRAW_EVEN_LINE_PARALLELNO2()
DRAW_ODD_LINE_PARALLELNO2( false)

@restoreSP: LXI SP, TEMP_ADDR ; restore SP (12)
RET
.endfunction

svofski
04.07.2022, 20:24
Как думаете, рисовать спрайты лучше сверху вниз или наоборот? Где будет меньше теаринг? При условии что мы не укладываемся в прирывание.
По-моему тут нельзя дать однозначного ответа. Рвать будет независимо от направления отрисовки. Важнее спланировать момент рисования спрайта относительно положения луча. Можно наверное даже сортировать спрайты так, чтобы успевать их выводить в нужном порядке.

parallelno
04.07.2022, 20:44
По-моему тут нельзя дать однозначного ответа. Рвать будет независимо от направления отрисовки. Важнее спланировать момент рисования спрайта относительно положения луча. Можно наверное даже сортировать спрайты так, чтобы успевать их выводить в нужном порядке.

Какой эмулятор точнее все эмулирует обновление экрана? Нужно чтоб потестировать теаринг.

svofski
04.07.2022, 21:06
VV и v06x точно, emu80v2 думаю тоже. b2m, когда я проверял последний раз, вел себя слегка девиантно, но не так существенно, чтобы повлиять на тестирование разрывов.

ivagor
04.07.2022, 21:21
совсем незначительно ускорил (только в инициализации)
Фишка варианта с
MOV C, M ; (8)
INX H ; (8)
MOV B, M ; (8)
INX H
в инициализации в том, что можно выводить спрайты стеком при разрешенных прерываниях по методу Медноногова. Но если прерывания запрещены, то конечно в этом нет необходимости.

parallelno
04.07.2022, 21:34
ivagor, в моем варианте прерывания тоже разрешены.

ivagor
04.07.2022, 22:03
А как восстанавливать испорченный фрагмент спрайта? Есть разные варианты, но я не увидел или не понял, какой именно здесь.

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

Если конкретнее, то проблема возникнет, если прерывание попадет в промежуток от SPHL до DRAW_EVEN_LINE_PARALLELNO2(). Вероятность этого не такая уж большая, чтобы проблема сразу проявилась, но при долгой работе это произойдет.

parallelno
05.07.2022, 01:45
Если мы ещё ничего не считали со стека, то sp указывает на начало спрайта. Если прерывание произойдет, то оно испортит те два байта перед данными спрайта, а это не страшно.

Sandro
05.07.2022, 05:31
А если прерывание произойдёт чуть позже, то адрес возврата затрёт спрайт. Использование регистров BC позволяет всегда хранить эти два байта на регистрах и восстановить их в обработчике прерывания.
А перед самым началом спрайта делается двухбайтовая дырка, из которой мы никогда ничего не читаем. Затрёт -- так затрёт.

Можно уж было дать и развёрнутое объяснение. Вас же и другие люди читают.

ivagor
05.07.2022, 07:05
Если прерывание произойдет, то оно испортит те два байта перед данными спрайта, а это не страшно.
Да, jerri предложил этот вариант в теме robotz (PPC). Точнее он предложил оставлять между спрайтами (минимум) по 2 байта. Просто переход от варианта с "любым" размещением спрайтов к "разреженному" произошел без комментария.

parallelno
05.07.2022, 08:50
Sandro, Извини пожалуйста. спасибо что дал развёрнутое объяснение. Но хочу уточнить что притензия не принимается, так как я отвечал не всем, а только
05ivagor

Да, jerri предложил этот вариант в теме robotz (PPC). Точнее он предложил оставлять между спрайтами (минимум) по 2 байта. Просто переход от варианта с "любым" размещением спрайтов к "разреженному" произошел без комментария.
В этой теме кажется кто-то написал о том что нужно держать 2 safety байта до данных. И KTSerg в этой теме выложил свой вариант исходника где так же это было. Поэтому я посчитал что вроде бы все уже этой используют. Сорян.

ivagor
18.07.2022, 22:36
Про артефакт с вертолётом знаю, возможно позже исправлю, но сначала нужно понять откуда он растёт
Базырь в новом v06x позволил увидеть механизм возникновения артефакта. В игре, как я понимаю, есть ограничение области рисования спрайта по высоте, если на него наезжает шторка. Если при движении главгероя по вертикали шторка наехала на спрайт врага, то под шторкой останется нестертый фрагмент. Пока его не видно, но когда главгерой сместится по вертикали обратно и врага в это время не будет рядом со шторкой, то из под нее проявится нестертый фрагмент. По моему разумению возможный вариант борьбы - разрешить рисование спрайта под шторкой, чтобы он продолжал затирать.

HardWareMan
19.07.2022, 07:01
Фишка варианта с
MOV C, M ; (8)
INX H ; (8)
MOV B, M ; (8)
INX H
в инициализации в том, что можно выводить спрайты стеком при разрешенных прерываниях по методу Медноногова. Но если прерывания запрещены, то конечно в этом нет необходимости.
MOV R,M занимает 7 тактов, а INX RP только 5. Почему указано 8? Там есть дополнительные такты ожидания?

ivagor
19.07.2022, 07:03
Вышеприведенный вариант можно наблюдать например на уровне 2. Но он не единственный, на каком-то из следующих уровней есть альтернативный вариант, но тоже связанный со шторкой. Тут движение главгероя не нужно, достаточно чтобы для вывода спрайта было всего лишь место под один тайл. Вертолет "бьется винтом" о препятствие сверху и там остается полоска от верхушки винта. Похоже на то, что под шторкой (которая тут снизу) не рисуются более нижние положения спрайта, которые должны были затереть предыдущие. Думаю тут тоже можно поправить расширив допустимую область рисования спрайтов под шторку.

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


Почему указано 8? Там есть дополнительные такты ожидания?
У вектора процессор тормозится видеоконтроллером, про это много раз написано в векторовских темах.

Pyk
20.07.2022, 22:55
Там есть дополнительные такты ожидания?
Да, на Векторе на выполнение любого цикла обращения к памяти требуется количество тактов, кратное 4.

ivagor
21.07.2022, 06:15
С одной стороны да, а с другой - у ПК8000 (в scr1/2) и 8002 (без включения "повышенной производительности процессора") тоже на каждое обращение к памяти/порту уходит кратное четырем число тактов, но у всех трех растактовки разные. По вектору информация есть в нескольких местах, и я делал свой вариант (https://www.sensi.org/~retrocomp/vector06c/v06cycl.html)