PDA

Просмотр полной версии : ЭТЮДЫ



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

krt17
15.05.2018, 20:27
генерация автомаски

Кто быстрее?
Че прям каждый фрейм генеришь?
Этож я так понимаю для статики, судя по and-or, а потом статику в код разворачиваешь?

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

Праздное любопытство, смотреть правда лень, а послушать не против :)

ZX_NOVOSIB
15.05.2018, 20:27
creator, да, но он кажется байт 57

jerri
15.05.2018, 20:54
Че прям каждый фрейм генеришь?
Этож я так понимаю для статики, судя по and-or, а потом статику в код разворачиваешь?

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

Праздное любопытство, смотреть правда лень, а послушать не против :)

ну вообщето сходные механизмы автогенерения маски использовались что в Thunderbirds(1-4) что в Venom Strikes Back
что в Heartland

krt17
15.05.2018, 21:13
ну вообщето сходные механизмы автогенерения маски
Эм, к алгоритму то какие вопросы, он прост как три копейки. Я просто слабо представляю как нормально двигать маску and-or, или без таблиц двигает???
Я задал два простых праздных вопроса.
Зачем быстро, если генерится не каждый фрейм?
Разворачивает ли статику в код для скорости?
jerri, хоть убей не пойму к чему твое утверждение под моей цитатой?

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

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

krt17
15.05.2018, 23:24
Посмотрел код, вопросов нет.:v2_smoke:

Знахарь
16.05.2018, 12:23
Насколько понимаю, есть еще 1 условие: надо рисовать так, чтобы оставалась в 1 точку рамка внутри рабочей области (в данном случае 16х16 пикс область, знач. рисовать желательно 14х14 точек). Тогда маске будет куда размещать обводочку на спрайтик. Иначе, если спрайтик впритык, то маска/обводочка не будет выноситься за пределы знакомест... DRBARS?

Shiny
16.05.2018, 13:46
Экспериментировал с римскими числами. на форумах написано, что максимальное число, которое может быть написано 3999. Но почему-то вышло 4999.65289

drbars
19.05.2018, 08:18
Эм, к алгоритму то какие вопросы, он прост как три копейки. Я просто слабо представляю как нормально двигать маску and-or, или без таблиц двигает???
Я предложил многоуважаемому %all% подумать над алгоритмом автомаски без сдвигов. Существуют способы анализа крайних битов, например, чтобы сделать "контур-маску" с заливкой внутри.


Посмотрел код, вопросов нет.:v2_smoke:

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

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


Насколько понимаю, есть еще 1 условие: надо рисовать так, чтобы оставалась в 1 точку рамка внутри рабочей области (в данном случае 16х16 пикс область, знач. рисовать желательно 14х14 точек). Тогда маске будет куда размещать обводочку на спрайтик. Иначе, если спрайтик впритык, то маска/обводочка не будет выноситься за пределы знакомест... DRBARS?

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

krt17
19.05.2018, 08:58
подумать над алгоритмом автомаски без сдвигов.
Тут вопрос переходит в плоскость заливки, а не жрущая такты и/или память заливка это мечта. Наверное проще сделать оптимизатор для графики с маской и паковать.

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

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


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

Знахарь
19.05.2018, 19:47
Некто Ticklish Jim/BIS в свое время занимался автомаской для Crime Santa Claus и писал статью по этому поводу вроде бы в ZX-POWER за 1998 год (вроде бы апрель).
В том числе он предлагал "покопаться в чешской игрушке TOWDIE" на предмет быстрого генератора автомаски.

Reobne
20.05.2018, 10:51
Знахарь,
Нагуглил я.

zxpress.ru
ZX Power #03
31 декабря 1997
Программирование
Ликбез - Автоматическое создание маски для спрайтов. (https://zxpress.ru/article.php?id=8041)

Там 3 метода. Первые 2 побитывые, а третий - (заморский баклажанный :v2_crazy:) тот самый со сдвигами.
А ещё игра упоминается, в которой быстрая но неполноценная маска. Сдвиги только по горизонтали.

ZX_NOVOSIB
27.06.2018, 08:33
Какой на асме аналог бейсик-процедуре:
10 IF INKEY$ > "" THEN GO TO 10

Т.е. какой процедурой можно отследить отпускание любой клавиши? Иными словами процедура выходит из цикла, только если ни одна клавиша не нажата.

Shiny
27.06.2018, 08:56
если я правильно понял, то:


wk:
xor a
in a,($FE)
cpl
and 31
jr z,wk

ZX_NOVOSIB
27.06.2018, 09:33
Шынни, "and 31" это как-то относится к управляющим кодам? Ведь до 31 идут управляющие коды, но там есть и исключение в виде 13 кода (клавиша ентер) :v2_conf3:

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

Если сделать and 12 вместо and 31, то тогда процедура и на ентер распространится? )

Reobne
27.06.2018, 10:02
"and 31" это как-то относится к управляющим кодам?
Нет! Не относится! 31 это пять двоичных единичек. А кнопки в Спектруме разбиты на восемь групп по пять. Вот к чему это относится!

Black Cat / Era CG
27.06.2018, 10:02
and 31
С порта 254 5 бит - 5 клавиш полуряда клавы, and 31 - это and %00011111.

DenisGrachev
27.06.2018, 10:32
Т.е. какой процедурой можно отследить отпускание любой клавиши? Иными словами процедура выходит из цикла, только если ни одна клавиша не нажата.



loop:
call 654
inc e
jr nz,loop

Shiny
27.06.2018, 10:56
короче так

ZX_NOVOSIB
27.06.2018, 12:34
если я правильно понял, то:


wk:
xor a
in a,($FE)
cpl
and 31
jr z,wk


Всё же NZ , а не Z ?

Shiny
27.06.2018, 12:42
ёклмн. Как работает клавиатура?
5 битов по портам отведены соответсвующим значениям: 1-не нажата, 0-нажата.

Например, проверяем нажатие клавиши А:

tt:
ld a,$FD
in a,($FE)
and 1
jr nz, tt

в примере A=0, поэтому чтение будет из всех портов.

cpl - инверсия
and 31 даст 0, если клавиша НЕ нажата, или не 0, если нажата.

Shiny
17.07.2018, 08:18
Камрады, нужна простая задачка - получить N*4/3. Есть мысли? я сов7 запутался.

Reobne
17.07.2018, 08:33
Умножь на константу 341 сдвигами, и возьми старший байт.

Shiny
17.07.2018, 10:25
выходит, проще лукап построить

Hacker Grey
09.10.2018, 14:15
Друзья. Помогите оптимизировать процедуру.
есть два числа одно от 0 до 64 второе от 0 до 63
нужно их перемножить и результат разделить на 64 (т.е. простую пропорцию сделать)

Просто много параллельно процедур пишу и время на раздумья тратить нету.
сейчас просто перемножаю процедурой 8бит*8бит=16бить и результат двигаю 4 раза впрао, но понимаю что это глупо и тормознуто.
Сначало 8 раз в одну сторону вращаю, потом 4 раза в другую.

; AC=C*В
XOR A
DUP 8
RR C
JR NC,$+3
ADD B
RRA
EDUP
RR C

rlc c : rlca : rlc c : rlca

быстро на ум пришло взять таблицу 64*64 в 4 килобайта. и один операнд сдвигать 2 раза во второй что бы получить смещение в табличке 16*256
Но предложите что нибудь со сдвигами и сложениями , вычитаниями, максимально быстрое .

blackmirror
09.10.2018, 19:13
DUP 6 и код после EDUP не понадобится
если дробная часть и округление не требуются, то RR C тоже не понадобится
если памяти не жалко, можно сделать 64 функции умножающие на числа от 0 до 63, тогда можно выкинуть команды условного перехода, а ADD B поставить там, где они нужны для данного множителя

Bedazzle
10.10.2018, 06:59
Друзья. Помогите оптимизировать процедуру.
есть два числа одно от 0 до 64 второе от 0 до 63
нужно их перемножить и результат разделить на 64 (т.е. простую пропорцию сделать)

Результат должен быть точным? Если сначала поделить оба числа, найти среднее, и умножить, всё можно в 8 бит крутить.

Shiny
10.10.2018, 09:09
Не очень понятна задача.
Для умножения попробовать старый индейский способ - по таблице квадратов.
для деления - использовать lut

krt17
10.10.2018, 10:20
a(0-63), b(0-64)
a*b/64=4*a*b/(64*4)=(4*a)*b/256
Все просто, 2 раза "add a" затем просто умножаете на b и берете старший байт.

Hacker Grey
10.10.2018, 14:13
2 раза "add a" затем просто умножаете на b и берете старший байт.
Ну так это тоже самое получается что и у меня. - "2 раза add a" - это два моих вращения. "просто умножаете на b" - это умножение 8бит на 8бит = 16 бит
Так у меня и сейчас работает. То же самое по скорости.

Я хочу умножение оптимизировать в 6 ротаций, вместо 8 влево и потом 2 вправо. как blackmirror предложил, Просто надо просчитать и попробовать, может сходу замена DUP 8 DUP 6 прокатит

char
10.10.2018, 19:13
надо что-то такое мутить:

if b=64 then exit ;a=a*64/64 :)

a*b/64 = ( (a+b)^2 - a^2 - b^2 ) / 2 / 64 = (a+b)^2 / 64 - a^2 / 64 - b^2 /64 + rra

need table x^2/64 (x=0..126) или возможно x^2/32 + rra:srl a

...или можь вообще так:
;(a+b)^2 - (a-b)^2 = a^2 + b^2 + 2*a*b - a^2 - b^2 + 2*a*b = 4*a*b

a*b/64 = ( (a+b)^2 - (a-b)^2 ) / 4 / 64 = ( (a+b)^2 / 128 - (a-b)^2 / 128 ) + rra

(используется предрасчитанная табличка x^2 / 128 )

...или вообще
a*b/64 = ( (a+b)^2 - (a-b)^2 ) посчитали в HL (двумя взятиями из таблицы) и старший байт забрали в A (это и есть / 4 / 64)
(используется предрасчитанная табличка x^2)



;
;mul_ac4:
;hl = (a+c)^2 - (a-c)^2 = a*c*4
ld h,sqr_tbl/256
sub c
ld l,a
add a,c
add a,c
ld c,(hl)
inc h
ld b,(hl)
ld l,a
ld a,(hl)
dec h
ld l,(hl)
ld h,a
sbc hl,bc
;/mul_ac4

ld a,h ;a = a*c*4/256 = a*c/64


...и как вариант возможной дальнейшей оптимизации, из таблицы не по 2 байта брать (16битное вычитание), а вначале по младшим байтам решение вынести - повлияют ли они на старшие (перенос), и уж потом из таблицы брать и вычитать старшие, с учетом переноса или его отсутствия



;a = a*c/64 = ( (a+c)^2 - (a-c)^2 ) / 256
ld h,sqr_tbl/256
sub c
ld l,a
ld b,(hl)
add a,c
add a,c
ld c,l
ld l,a
ld a,(hl)
sub b
inc h
ld a,(hl)
ld l,c
sbc a,(hl)


[при заполнении 512b sqr_tbl таблицы квадратов не забыть квадраты для отрицательных чисел]


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


получить N*4/3. Есть мысли?

взять стандартную процедуру побитного деления и раскрыть-расписать, учитывая, что делитель в данном конкретном случае - это просто два включенных бита / две ветки переходов, с невключенными остальными / пустыми ветками
3 = %00000011

Shiny
11.10.2018, 08:16
взять стандартную процедуру побитного деления и раскрыть-расписать, учитывая, что делитель в данном конкретном случае - это просто два включенных бита / две ветки переходов, с невключенными остальными / пустыми ветками
3 = %00000011

Да все уже, сделано. Вычисления длинные, к тому же это демо, решается lut размером 512 байт.

Shiny
21.11.2018, 12:53
Проверка на присутствие числа в диапазоне:


between: ; B.C=high/low, A=value
ld e,a
ld a,b
cp e
ret c
ld a,e
cp c
ret


Есть другие варианты?

Destr
21.11.2018, 16:52
Проверка на присутствие числа в диапазоне:
А типа такого не прокатит?


; In: B.C=high/low, A=value
; Out: флаг C=1 если число не в диапазоне
between:
cp b
ccf
ret c
cp c
ret

Shiny
12.01.2019, 19:40
Найдено в интернетах:

При устройстве на работу программистом столкнулся с интересной задачей следующего содержания:

«Напишите программу, которая выводит на экран числа от 1 до 100. При этом вместо чисел, кратных трем, программа должна выводить слово Fizz, а вместо чисел, кратных пяти — слово Buzz. Если число кратно пятнадцати, то программа должна выводить слово FizzBuzz. Задача может показаться очевидной, но нужно получить наиболее простое и красивое решение.»

пишите решения.

shurik-ua
12.01.2019, 23:09
var
s0: string;
begin
for i:=1 to 100 do begin
s0:='';
if (i mod 3) = 0 then s0:= 'Fizz';
if (i mod 5) = 0 then s0:= s0 + 'Buzz';
if s0 ='' then s0:= inttostr(i);
writeln(s0);
end;

Dexus
13.01.2019, 00:44
.org $8000
ld b,0
ld c,0
ld d,1
l1:
ld e,0
inc b
ld a,b
cp 3
jr nz,j1
ld b,0
ld hl,str_fizz
call print_strhl
inc e
j1:
inc c
ld a,c
cp 5
jr nz,j2
ld c,0
ld hl,str_buzz
call print_strhl
inc e
j2:
ld a,e
and a
jr nz,j3
call print_strnum
j3:
ld a,32
rst 16;lf
inc d
ld a,d
cp 101
jr nz,l1
ret

str_fizz: .db 'fizz',0
str_buzz: .db 'buzz',0

print_strhl:
push bc
push de
l2:
ld a,(hl)
and a
jr z,q1
rst 16
inc hl
jr l2
q1:
pop de
pop bc
ret

print_strnum:
push bc
push de
ld c,d
ld b,0
call 6683
pop de
pop bc
ret

shurik-ua
13.01.2019, 01:52
сурово )

Barmaley_m
13.01.2019, 03:34
Напишите программу, которая выводит на экран числа от 1 до 100. При этом вместо чисел, кратных трем, программа должна выводить слово Fizz, а вместо чисел, кратных пяти — слово Buzz. Если число кратно пятнадцати, то программа должна выводить слово FizzBuzz.Задача может показаться очевидной, но нужно получить наиболее простое и красивое решение
Задача действительно очевидная, а требование "простоты и красоты" переводит её в рубрику "угадай, что нравится автору". Быть может, требуется соблюдать определенные стандарты в оформлении кода?

Можно ли придумать что-либо проще и очевиднее, чем вариант от shurik-ua выше? Сомневаюсь. А именно понятность кода для коллег является одним из главных качеств программиста, которые хотят видеть работодатели.

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

Скажем, если процессор не имеет аппаратного деления или, если деление медленное - то имеет право на жизнь такой вариант:


#include <stdio.h>
void main(void)
{
int r3=1;
int r5=1;
for(int i=1; i<=100; i++)
{
if(r3==3)
{
r3=0;
printf("Fizz");
}
if(r5==5)
{
r5=0;
printf("Buzz");
}
if(r3 || r5)
{
printf("%d",i);
}
putchar('\n');
r3++;
r5++;
}
}

Но даже и здесь насчет эффективности можно поспорить, т.к. вывод на консоль почти на всех архитектурах (даже Z80) существенно медленнее, чем деление.

Shiny
13.01.2019, 06:05
шо касается деления, то:
https://i106.fastpic.ru/big/2019/0113/46/e86ffab89f39d437796d85fe3c212146.jpg

у меня получилось 64 байта (http://www.pouet.net/prod.php?which=79840)

goodboy
13.01.2019, 11:46
те-же интернеты говорят
"в голову приходит идея использования строк. Например, с помощью строк можно избавиться от одной операции сравнения.
...
А что если попробовать не приписывать к строке нужный текст, а наоборот убирать текст из строки вида «ЧислоFizzBuzz»?
алгоритм содержит всего две операции сравнения и два условных оператора. "

Shiny
13.01.2019, 18:22
Детская игра (:
https://ru.wikipedia.org/wiki/Fizz_buzz

156
15.01.2019, 08:35
Как вариант в одну строчку на ZX Besic48. На эмуляторе сработал.

Bedazzle
15.01.2019, 08:51
Чел с WOS дизассемблировал салют (https://www.worldofspectrum.org/forums/discussion/56719/partial-penetrator-disassembly-the-fireworks) из Penetrator.

JV-Soft
15.01.2019, 10:43
Чел с WOS дизассемблировал салют из Penetrator.
Не такой уж и маленький код.

Shiny
22.02.2019, 18:47
Увидел у 6502: приращение с лимитом


cp 7
adc a,0

jerri
22.02.2019, 19:59
Увидел у 6502: приращение с лимитом


cp 7
adc a,0


у них же вроде С инверсное?

zx ревю за 1997 год



;прибавляем пока не достигнет максимального значения
cp max
adc a,0

;вычитаем пока не достигнет нуля
sub 1
adc a,0

Shiny
22.02.2019, 20:24
у них же вроде С инверсное?

http://www.obelisk.me.uk/6502/reference.html#CMP

ревю за 1997 год не читал.

CodeMaster
07.03.2019, 14:22
Это не совсем программирование, скорее математика, но всё же.
Как посчитать количество состояний 9-битного регистра с 3 нулями в любых битах?

marinovsoft
07.03.2019, 14:42
Вы хотите программу написать или комбинаторику вспомнить?

Сколькими способами можно выбрать и разместить по m различным местам m из n различных предметов?
Amn = n! / (n - m)!

Или по рабоче-крестьянски: Первый нулевой бит может занять любое из девяти положений, второй любое из восьми оставшихся, третий - из семи. Amn = 9 * 8 * 7.

blackmirror
07.03.2019, 19:14
Или по рабоче-крестьянски: Первый нулевой бит может занять любое из девяти положений, второй любое из восьми оставшихся, третий - из семи. Amn = 9 * 8 * 7.
У вас так получается что из 512 возможных комбинаций 504 содержат по 3 нулевых бита, что-то в вашей формуле не так. :v2_dizzy_facepalm:

ivagor
07.03.2019, 19:27
Как посчитать количество состояний 9-битного регистра с 3 нулями в любых битах?
Ровно 3 нулевых бита или не менее 3х нулевых бит?

Bedazzle
07.03.2019, 19:31
Первый нулевой бит может занять любое из девяти положений, второй любое из восьми оставшихся, третий - из семи.

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

Доказательство "в лоб".
Посчитаем количество возможных перестановок для девяти бит. :)
Первый нулевой бит может занять любое из девяти положений, второй любое из восьми оставшихся, третий - из семи, .....
9*8*7*6*5*4*3*2*1 = 362880

Но все мы знаем, что в девять бит влазит только 256*2 = 512 возможных комбинаций вообще. :)

CodeMaster
07.03.2019, 19:59
или комбинаторику вспомнить?
Не то что бы вспомнить, у меня с этим всегда был швах.


Ровно 3 нулевых бита или не менее 3х нулевых бит?
Ровно 3, любых.


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

ivagor
07.03.2019, 20:26
Нужно посчитать число слов 9-битного двоичного кода с весом 6. Но посчитаем все
Вес - Число слов
0 - 1
1 - 9
2 - 36
3 - 84
4 - 126
5 - 126
6 - 84
7 - 36
8 - 9
9 - 1
т.е. 9-битных комбинаций ровно с тремя нулями 84.
Строка треугольника Паскаля (https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B5%D1%83%D0%B3%D0%BE%D0%BB%D1%8C%D 0%BD%D0%B8%D0%BA_%D0%9F%D0%B0%D1%81%D0%BA%D0%B0%D0 %BB%D1%8F) при n=9

krt17
07.03.2019, 20:27
Все верно это комбинаторика, простейшая задача на сочетание 3 из 9.
C(3 9)=9!/(3!(9-3)!)=84
Вроде в школе походят.

marinovsoft
07.03.2019, 21:08
У вас так получается что из 512 возможных комбинаций 504 содержат по 3 нулевых бита, что-то в вашей формуле не так. :v2_dizzy_facepalm:
Логично, меняем на такую формулу
Сmn = n! / ((n - m)! * m!)

CodeMaster
07.03.2019, 21:32
Строка треугольника Паскаля при n=9
Очень наглядно, хотя на подкорку всё-равно не ложится ;-)


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

Shiny
08.03.2019, 16:31
Не зная матана, я бы засомневался, получив такой результат

Vladson
19.03.2019, 19:23
Из FaceBook:


; 16-bit xorshift pseudorandom number generator by John Metcalf
; 20 bytes, 86 cycles (excluding ret)


Как бы оценить, насколько качественный генератор?

решил побоянить (вместо HL юзаю BC чтоб точки рисовать)


ORG #8000
START
IN A,(#FE)
AND #1F
CP #1F
RET NZ

XRND
LD BC,#0001
LD A,B
RRA
LD A,C
RRA
XOR B
LD B,A
LD A,C
RRA
LD A,B
RRA
XOR C
LD C,A
XOR B
LD B,A
LD (XRND+1),BC

LD A,#AF
CP B
CALL NC,#22E5
JR START
Выглядит кстати симпатично.


Лучше чем "стандартный" (х*5+1) у которого прямо вертикальные линии ползут по экрану

PUSH HL
LD HL,(RND+1)
ADD HL,HL
ADD HL,HL
RND LD BC,#0000
ADD HL,BC
INC HL
LD (RND+1),HL
POP HL
(HL сохраняется для красоты, в этом коде не нужно)


Однако этот и короче и тоже выглядит норм (в данном разрезе)

LFSR16 LD BC,#0001
SRL B
RR C
JR NC,_SKIP
LD A,#B4
XOR B
LD B,A
_SKIP
LD (LFSR16+1),BC

Shiny
19.03.2019, 19:40
решил побоянить (вместо HL юзаю BC чтоб точки рисовать)

я уже побоянил:
http://www.pouet.net/prod.php?which=77233

(:

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

И, кстати, процедурку можно обойти с лимитом Y=176:

http://www.pouet.net/prod.php?which=79773

Vladson
19.03.2019, 20:34
Писал на скорую руку, лень было искать ссылки, просто взял бумажную Родионова, и там глянул...

Есть кстати ещё одна процедурка из журнала какого-то, но она не имеет 65535 она странная на фибоначчи похожая, толком её не понял даже


RND LD BC,#5A05
LD A,B
LD (RND+1),A
R2 LD A,#25
LD (RND+2),A
ADD B
ADD C
RLCA
LD (R2+1),A

(точнее я понял как работает, но не понял почему оно сносно работает...)


ЗЫ, - 8b это жесть... Додуматься же...

Мой минимум увы поменьше (но за то основная идея была задумана в 1989-м, правда тогда реализовывалась на бейсике)


ORG #8000
; Если запускать с адреса кратного 256, то в С и так будет 0
; XOR A
; LD C,A


LD E,C
LD H,#18

START

LD D,#40
LD B,H
LD H,E
LD A,(HL)
RLA
LD L,A
LDIR

JR START

Bedazzle
19.03.2019, 23:45
Есть кстати ещё одна процедурка из журнала какого-то, но она не имеет 65535 она странная на фибоначчи похожая, толком её не понял даже


:eek:

Shiny
20.03.2019, 09:37
Пора расчехлить пыльную папочку. Числа Фиббоначи - мой вариант и на BrainFuck. Только у BF нолик печатается

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


LD A,(HL)
RLA
LD L,A

ld l,(hl)/rl l

Vladson
20.03.2019, 19:23
Блин и правда, забыл уже что так можно было... (Хотя уверен что кто-то уже наверняка подобное делал и я просто изобретал все эти годы велосипед)

Destr
05.06.2019, 19:27
Процедура выделения отрицательного фронта бита:


; выделение отрицательного фронта клавиши, port,bit=проверяемая клавиша, NZ=фронт был, Z=не было
MACRO FN_KEY port, bit
.FP LD A,0
LD (.KEY+1),A
LD A,port
IN A,(#FE)
CPL
LD (.FP+1),A
CPL
.KEY AND 0
BIT bit,A
ENDM


WAI FN_KEY #7F, 2: JR Z,WAI

Будет крутится до тех пор пока клавиша не сменит состоянии с нажатой на отжатую

А вот наоборот (положительный фронт) не получается.
Точней можно модернезировать, но среагирует просто на нажатие не взирая на то была-ли на предыдущем проходе отжата (а надо).
Не могу сообразить как сделать. Или вообще загнался и можно проще? Есть идеи?
P.S. И кстати просто клик (отжата-нажата-отжата) не могу сообразить...

jerri
05.06.2019, 21:22
Destr,

подумай так



;А опрошенные кнопки (8 штук) 1 нажата 0 не нажата

ld c,a
ld a,(key_holded) ;удерживаемые кнопки
xor c
and c
ld (key_presed),a ;свеженажатые кнопки
ld a,c
ld (key_holded),a
ret


второй вариант ждет нажатия двух кнопок
после чего включает/выключает музыку



ld a,(kb_buf+1)
and #08
ld h,a
ld a,(kb_buf+6)
and #10
or h
cp 0
musprs equ $-1
ld (musprs),a
jr z,musprs0
or a
jr nz,musprs0

ld a,(musoff)
cpl
ld (musoff),a
or a
jr z,musprs0
jp MUTE ;глушим музыку
musprs0
ld a,0
musoff equ $-1
or a
jp nz,ays_play
;иначе стартуем музыку

Destr
06.06.2019, 06:24
подумай так
Ну вообще смысл чтоб минимум длины и без использования регистров (ну кроме А, на крайняк A`)

Reobne
06.06.2019, 09:22
Destr, Попробуй убрать первый CPL. Это инвертер того что считалось с порта. А значит задний фронт и передний фронт поменяются местами.
Помни, что макрос будет работать несколько по разному, если использовать_макрос для одной и той-же клавиши много раз, в отличии от: запихнуть макрос для данной кнопки в подпрограмму, и вызывать её. Каждый вызов макроса создаст свои переменные, помнящие состояние клавы, и они будут помнить состояние независимо. А если будет один вызов макроса в специально сделанной для этого процедурке, то помнить предыдущее состояние она будет централизовано.
Помни, что есть разные другие способы опроса клавиатуры: Ещё более централизованные, для групп клавиш. Для всей клавиатуры в прерываниях разом.

Destr
06.06.2019, 11:12
Destr, Попробуй убрать первый CPL.../quote]
Ну вот версия 2 - как-бы оптимизированней


MACRO FN_KEY key ; выделение отрицательного фронта клавиши, port,bit=проверяемая клавиша, NZ=1 - фронт был
.prev LD A,#FF
CPL
AND low key
LD (.mask+1),A
LD A,high key
IN A,(#FE)
LD (.prev+1),A
.mask AND 0
ENDM

Крутится хорошо


WAIT FN_KEY #7F04:JR Z,WAIT

И самое главное - если при вызове УЖЕ нажата нужная клавиша - всё равно работает (в отличии от процедуры которая передний фронт ловит (да она-же, но CPL по-другому) - передний если клавиша УЖЕ зажата - сработает будто был фронт (хоть и пробовал всяко с начальными значениями)

[quote="Reobne;1015623"]Помни, что есть разные другие способы опроса клавиатур
Да это знаю, клавиши взял пока просто для удобства, а вообще нужен контроль ЛЮБОГО сигнала (бита), откуда-бы его не впихнули...

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

Reobne
06.06.2019, 12:42
вообще нужен контроль ЛЮБОГО сигнала (бита), откуда-бы его не впихнули
Если банально теоретически, то квантованный по времени сигнал, это последовательность логических значений x[i].
Вот если x[i], это принятое сейчас значение, x[i-1] - принятое предыдущее значения, то
y[i]=x[i] XOR x[i-1] ; есть ли изменение:
y_up[i]=x[i] AND NOT x[i-1]
y_down[i]=NOT x[i] AND x[i-1]

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


И самое главное - если при вызове УЖЕ нажата нужная клавиша - всё равно работает (в отличии от процедуры которая передний фронт ловит (да она-же, но CPL по-другому) - передний если клавиша УЖЕ зажата - сработает будто был фронт (хоть и пробовал всяко с начальными значениями)
Начальные значения, это константы в LD A,#FF и AND 0 ?
Другое решение:
Заключи вызов макроса как процедуру, прибавив вначале метку а в конце RET.
Перед началом цикла опроса сделай один лишний разок CALL, только как инициализацию, не глядя на Z.
А в цикле вызывай CALL и смотри флаг Z.

Destr
06.06.2019, 14:12
Заключи вызов макроса как процедуру, прибавив вначале метку а в конце RET.
Перед началом цикла опроса сделай один лишний разок CALL, только как инициализацию, не глядя на Z.
А в цикле вызывай CALL и смотри флаг Z.
Предполагается юзать именно как макрос, чтоб хранить предыдущее значение прямо в теле проги, а не делать на каждый сигнал свою ячейку отдельно где-то в памяти (ведь если сигналов будет несколько - то в теле вызываемой процедуры уже нельзя хранить предыдущее состояние)

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

Кажется домучал (были уже рабочие варианты у меня, просто эмуль подвёл - ведь тестил через ALT+F3 зажав клавишу, а эмуль не сразу опрашивает оказывается, если сделать задержку - то при зажатой кнопке изначально - передний фронт не детектится, т.е. всё как надо работает)


MACRO FN_KEY key ; отрицательный фронт, key=high порт/mask (#7f04="m"), Z=1 - фронт был
.prev LD A,#FF
CPL
AND low key
LD (.mask+1),A
LD A,high key
IN A,(#FE)
LD (.prev+1),A
.mask AND 0
ENDM

MACRO FP_KEY key ; положительный фронт, key=high порт/mask (#7f04="m"), Z=1 - фронт был
.prev LD A,#00
AND low key
LD (.mask+1),A
LD A,high key
IN A,(#FE)
LD (.prev+1),A
CPL
.mask AND 0
ENDM

Reobne, а формула клика (т.е. 0-1-0) как получается? Там уже надо видимо хранить 2 предыдущих значения, причём обновлять не каждый вызов, а ставить флаг что мол была клавиша отжатой, потом была нажатой, а теперь вот снова отжалась - тут-то и подымать флаг "клик!" ?

Reobne
09.06.2019, 04:42
Всё правильно!

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

Предположим в игре есть ГГ, который вот вот умрёт. Игрок давит на "R", но отпустить кнопку не успевает, ГГ умирает по игровой причине. Показывается анимация смерти, потом надпись: "Приготовся!". Игрок уже отпустил "R", готовится такой. А макрос твой помнит, что кнопка R, переиграть, была нажата. И как только начнётся главный игровой цикл, твой макрос увидит, что кнопку только что отпустили. И игрок потеряет вместо одной жизни сразу две жизни. Это плохо.

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

Bolt
28.06.2019, 11:14
Сравнить два значения (например, регистр A и регистр B) и если A<=B, то получить в аккумуляторе true (ненулевое значение, желательно FFh), иначе false (00h).
Без условных переходов, только арифметикой. Это для использования в компиляторе, а условные переходы вида "jr $+n" усложнят последующую оптимизацию.

Если A<B, то флаги C=1, Z=0
Если A=B, то флаги C=0, Z=1
Если A>B, то флаги C=0, Z=0

Дошёл до такого кода:


rra
ccf
sbc a,0
rla
sbc a,a

6 байт, 23 такта (без учёта самого сравнения "cp b" или "sub a,b")
Можно ли сделать короче и/или быстрее?

Destr
28.06.2019, 17:40
Можно ли сделать короче и/или быстрее?
Вроде сработало


NEG ; 8т, 2b
ADD A,B ; 4т, 1b
SBC A,A ; 4т, 1b
;=16т, 4b

СP B делать не надо, на выходе #FF или #00
(только это с беззнаковыми числами)

Reobne
28.06.2019, 19:29
если A<=B, то получить в аккумуляторе true

Destr, при нулевых A и B должно получаться #FF! А у тебя ноль выходит.

А так то, если известно что A никогда не 0, можно ещё чуть быстрее DEC A:CP B:SBC A,A

Bolt
28.06.2019, 20:51
Destr, при нулевых A и B должно получаться #FF! А у тебя ноль выходит.

А так то, если известно что A никогда не 0, можно ещё чуть быстрее DEC A:CP B:SBC A,A
Нет, оба числа могут быть любыми.

При нулевых A и B:


sub a,b ; A=00h, C=0
rra ; A=00h, C=0
ccf ; A=00h, C=1
sbc a,0 ; A=FFh
rla ; C=1
sbc a,a ; A=FFh

Вроде всё правильно. Где я ошибаюсь?

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

А, понял, не я ошибаюсь.


NEG ; A=00h
ADD A,B ; A=00h, C=0
SBC A,A ; A=00h

Но этот код натолкнул на интересную мысль... :)

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

Забыл указать ещё одно условие. Считаем что вычитание, которое для сравнения, уже произведено. Нужен только универсальный "хвост" для получения true/false.

krt17
28.06.2019, 21:26
Давно не брал я в руки шашки


cpl
scf
adc a, b
sbc a, a


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

Если A<B, то флаги C=1, Z=0, A=FF
Если A=B, то флаги C=0, Z=1, A=FF
Если A>B, то флаги C=0, Z=0, A=0

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

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

Ладно не совсем бред конечно, но мнемоники желательно писать правильно.

Bolt
28.06.2019, 21:32
Еще и условия какие-то дополнительные, тфу одним словом. Не удивительно что паскаль не работает при таком подходе.
Кодогенератор собирает программу из отдельных блоков, принцип хорошо описал Andrew771 в журнале "Downgrade". Вычитание уже произведено, нужен именно этот блок.


Ладно не совсем бред конечно, но мнемоники желательно писать правильно.

Если речь о rra/rla, то с этими мнемониками полный бардак. Ассемблер, который я использую, их понимает, бинарник собирается, работает, и это главное :)

krt17
28.06.2019, 21:49
Неа.

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

Я сагрился на sub a, r. Нормально все, это рефлекторно.

Bolt
29.06.2019, 11:05
ccf и sbc можно заменить на adc:


rra
adc a,0FFh
rla
sbc a,a

Для проверки A>B:


rra
adc a,07Fh
rla
sbc a,a

5 байт, 19 тактов.

blackmirror
06.08.2019, 22:31
Имеется многоядерная система, в которой отсутствует блокировка памяти для выполнения атомарных операций. Совсем отсутствует. Требуется сконструировать функцию AtomicInc, которую можно будет вызывать на разных ядрах и получать уникальные значения счётчика. Посылать выделенному ядру прерывания не вариант, не факт что нашей программе это разрешат, кроме этого мы не знаем на каких ядрах нас запустили, но номер своего ядра каждый поток узнать может. Изначально обнулённый общий блок памяти для синхронизации решения задачи у них тоже имеется, кеширование для него отключёно. Единственный вариант который пока удалось придумать:
0) сделать каждому ядру свой флаг, изначально сброшенный
1) установить свой флаг перед чтением счётчика
2) прочитать флаги остальных ядер и счётчик
3) если стоит только наш, записываем новый счётчик и снимаем флаг, и на этом выходим
4) если стоят флаги с большим номером, переходим к пункту 2 ожидая пока их снимут
5) если стоят флаги с меньшим номером, снимаем свой и ждём пока снимут остальные чтобы перейти к пункту 1 для новой попытки
Будет ли такой алгоритм работать или есть варианты проще и надёжнее?

Bolt
07.08.2019, 00:31
Многозадачность вытесняющая? Зашёл поток на ядре в функцию, а диспетчер прервал на полуслове и на это ядро другой поток повесил, который зашёл в функцию...
Нужно больше информации о системе.

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

Запускаем некий главный процесс.
0. Процесс в цикле ищет установленный флаг запроса.
Если нашёл:
1. Прочитать счётчик.
2. Инкремент.
3. Записать новое значение в счётчик и в элемент массива, в котором найден флаг.
4. Сбросить флаг запроса.
5. Перейти в пункт 0 и искать новый запрос.

Получение значения (работа ведётся со своим элементом массива, по номеру ядра):
1. Установить флаг запроса.
2. Дождаться сброса флага запроса.
3. Прочитать значение.

Но одно ядро занято.

blackmirror
07.08.2019, 07:38
Многозадачность вытесняющая?
На данный момент нет, считается что функция, запущенная на некотором ядре, работает пока ей это нужно. Изначально, общий блок памяти обнуляется, после чего функция должна запуститься на N ядрах, но если некоторые заняты, для них это произойдёт чуть позже. А может на каких-то ядрах будет произведён повторный запуск, или вообще все запуски произойдут на одном и том же ядре. Выделять отдельное ядро для инкремента счётчика нельзя, оно слишком производительное чтобы заниматься такой фигнёй.
У меня идея заключается в том, что если записать флаг и быстро проверить остальные, то не более одного процесса успеет увидеть всего один флаг, и в этом случае можно менять счётчик уже без дополнительных проверок.

Bolt
07.08.2019, 11:31
Может тогда типа как в сетях используется CSMA/CD?

1. Зашли в функцию, сразу поставили флаг.
2. Просмотрели флаги, если никого нет - инкремент, сброс флага, выход.
Если есть кто-то ещё:
3. Сбросить свой флаг.
4. Выждать некий случайный интервал.
5. Начать заново с пункта 1.

Если кто-то уже работает - он работает до конца, остальные будут сбрасывать-устанавливать флаги.

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

Примерно так разруливает коллизии Ethernet.

blackmirror
07.08.2019, 19:14
Bolt, там проблема в том, что при шине в 16 байт реальное обращение в память занимает 50 тактов, то есть пока мы ждём этот флаг, можно успеть прочитать 800 байт(и столько же записать, так как шины отдельные). Моя версия алгоритма именно поэтому начинается с записи, а не чтения флага, так как такой подход вроде как уменьшает время блокировки свободного ресурса, но это еще нужно проверить. А вот если ресурс часто оказывается занят, возможно имеет смысл вместо освобождения поставить флаг, что нам он тоже нужен, чтобы захвативший ресурс раздал уникальные счётчики всем кто ждёт.

Bolt
07.08.2019, 19:44
blackmirror, какая-то сложная там у вас система :)

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

Destr
01.10.2019, 15:04
Народ, есть идеи как оптимизировать такую конструкцию?


PUSH DE
PMID LD A,L:ADD A,E:LD C,A:RRA:XOR L:XOR E:RLA:RR C
LD A,H:ADD A,D:SRA A:LD B,A
JP P,BPOS
LD HL,BC
JP PMID
BPOS JP Z,BZER
LD DE,BC
JP PMID
BZER POP DE
LD HL,BC
RET

Всю голову сломал, хочется развернуть в DUP-EDUP чтоб избавится от JP (для ускорения), но условные ветвления мешают...

Bolt
01.10.2019, 16:20
Условия мешают, но ускорить можно.


PUSH DE
JP PMID
PMID_2
LD HL,BC
PMID
LD A,L:ADD A,E:LD C,A:RRA:XOR L:XOR E:RLA:RR C
LD A,H:ADD A,D:SRA A:LD B,A

JP NP,PMID_2 ; не помню как правильно not P
BPOS ; метка не используется
LD DE,BC
JP NZ,PMID
BZER ; метка не используется
POP DE
LD HL,BC
RET

blackmirror
01.10.2019, 20:00
Destr, нужно три ветки, одна вычисляет BC=func(DE,HL), вторая DE=func(BC,HL) и третья HL=func(BC,DE). Тогда LD DE(или HL),BC можно будет оставить только в конце, а внутри переходим к правильной ветке, примерно так:

PUSH DE
L1: BC=DE+HL
JM L3
JZ X1
L2: DE=BC+HL
JM L1
JZ X2
L3: HL=BC+DE
JM L2
JNZ L1
POP DE
RET
X1: LD HL,BC
POP DE
RET
X2: LD HL,DE
POP DE
RET

Destr
02.10.2019, 06:28
не помню как правильно not P
JP M,...


нужно три ветки
Вроде как ещё больше переходов стало

Спасибо, ребят, ща буду пробовать...

blackmirror
02.10.2019, 07:59
Вроде как ещё больше переходов стало
Изначально было 2 перехода в отрицательной ветви и 3 перехода в положительной, здесь 1 или 2 перехода и нет пересылки, если JP Z выполняется после фиксированного числа итераций, то его можно вообще убрать. Вообще неплохо бы пояснить что это за код, потому что сейчас это что-то типа (A+B)/2 для старшей части и (A+B)/2^(128&(A^B)) для младшей, может здесь тоже что-то можно сократить.

Reobne
02.10.2019, 08:59
Вообще неплохо бы пояснить что это за код
Именно.
И если среднее считается, то границы сойдутся скорее всего не в нуле, Z не случится, и цикл будет бесконечным.

Destr
02.10.2019, 11:41
Вообще неплохо бы пояснить что это за код
8-ми битное клиппирование по 0 для Y2
In:
DE=Y1X1 (заведомо находится в "видимой части" (D>0)
HL=Y2X2 (Y2 - заведомо находится за границей (H<0, L может быть как >0 так и <0)
Out:
DE - без изменений
HL - новые координаты (H=0, L - высчитывается этой самой попдрограммкой)

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

Собственно потому и рассчитываются немного по разному средняя точка для X ил для Y - ибо у X учитывается полярность, а для Y она уже известно (D+,H-)


И если среднее считается, то границы сойдутся скорее всего не в нуле, Z не случится, и цикл будет бесконечным.
Всё сходится, бро, не забывай что координаты каждый раз новые, отрезок делится постоянно и в зависимости от того куда упало среднее (в + или -) - меняются точки расчёта, в конце-концов средняя оказывается в нуле (по Y) что и требуется.

Bolt
02.10.2019, 13:17
Проверка на 0 понятна, а зачем проверяется чётность?

Destr
02.10.2019, 13:59
Проверка на 0 понятна, а зачем проверяется чётность?
Чётность?
Если ты про JP P, то путаешь видимо с JP PO(PE)
JP P,n - это переход если результат ПОЛОЖИТЕЛЬНЫЙ (PLUS)
Антипод - JP M,n (MINUS). Это флаг знака S (SIGNUM что-ли)
А флаг переполнения/чётности V/P, да, но в мнемониках путаница (только С и Z флаги "правильно" пишутся в мнемониках, C/NC-Z/NZ, а в остальном бардак)

Вообще косяков в мнемониках полно, тот-же ADD A,n (по идее ему быть ADD n ибо только к аккумулятору и применим, вот SUB n - "правильное")

Bolt
02.10.2019, 16:54
Отблин, как же тяжело на 10 языках сразу думать :) и становится всё сложнее. Старею, что ли...

Ещё предложение. Считать не BC=f(DE,HL), а HL=f(BC,DE), и в одной из веток "LD DE,BC" заменить на "EX DE,HL".

И ещё:


add HL,BC
sra H
rr L

не то же самое? Не совсем понял общий алгоритм, но примерно так:


PUSH DE
JP PMID
PMID_2
RR L
PMID
LD BC,HL
ADD HL,DE
SRA H
JP M,PMID_2
JR Z,BZER ; jr быстрее jp, если переход не выполняется
BPOS
RR L
LD DE,HL
ADD HL,BC
SRA H
JP M,PMID_2
JP NZ,BPOS
BZER
POP DE
RET

blackmirror
02.10.2019, 21:12
Destr, насколько длинные отрезки попадают на вход алгоритма? Если вычислять x=x1+dx или y=y1+dy, то dx или dy можно считать за 8 развернутых итераций как выражение A*B/C, где все числа беззнаковые и B<=C. Если A<=127 - в одной итерации будут 2 сложения с аккумулятором, условный переход и сдвиг для установки бита результата. Или можно использовать регистровые пары, если требуется A до 255, хотя цикл немного замедлится. Примерно по 30-35 команд в положительной и отрицательной ветке, и еще некоторое количество команд в ветке инициализации в которой B и C умножаются на 2, пока С<128, при этом такое же количество шагов будет пропущено в основных ветках. Или сотня команд слишком большая цена для оптимизации этого цикла?

Destr
03.10.2019, 06:34
щё предложение. Считать не BC=f(DE,HL), а HL=f(BC,DE), и в одной из веток "LD DE,BC" заменить на "EX DE,HL".
Про это думал, но оставил на потом, как явный вариант который будет применён когда уже остальное всё будет развёрнуто и избавлено от лишнего


Не совсем понял общий алгоритм
Алгоритм простой:
0. В DE коорд.начала отрезка YnXn, в HL коорд. конца YkXk (известно что H<0)
1. Находится средняя точка отрезка (середина) Xm=(Xn+Xk)/2: Ym=(Yn+Yk)/2
2. Если Ym равен нулю - то это конец отрезка (YkXk=YmXm), клиппирование выполнено, RET
3. Если Ym<0 то XmYm - это новые координаты конца (YkXk=YmXm)
4. Если Ym>0 то XmYm - это новые координаты начала (YnXn=YmXm)
5. Goto 1


насколько длинные отрезки попадают на вход алгоритма
-128...127
Получается максимум: DE=#7f7f, HL=#8080, это длина отрезка= SQR(255^2 + 255^2)=360


Или сотня команд слишком большая цена для оптимизации этого цикла?
Да небольшая, но пока не понял что ты предлагаешь.

blackmirror
06.10.2019, 19:53
Да небольшая, но пока не понял что ты предлагаешь.
Если есть две точки (X1,Y1) и (X2,Y2) через которые проходит некоторая прямая, то узнать значение X для заданного Y чтобы точка оказалась на прямой можно по формуле:
X=X1+(Y-Y1)/(Y2-Y1)*(X2-X1), то есть фактически задача сводится к вычислению D=A*B/C. Далее некоторые рассуждения на тему того, как эти операции можно выполнить вместе без увеличения разрядности, но пока у алгоритма есть существенные ограничения по диапазону корректно обрабатываемых величин.

В развёрнутом алгоритме деления используется остаток S, который сдвигается с добавлением по 1 биту из A, если S<0, то к нему добавляется С, иначе вычитается, после чего частное сдвигается и к нему добавляется 1 если S>=0.
Для алгоритма умножения можно сдвигать B и если в перенос попадает 1, то добавлять к произведению A (здесь требуется увеличение разрядности).
Если объединить добавление A и С(или вычитание) из этих двух алгоритмов, то получается 4(на счёт 2х я ошибся) параллельные ветки по 8 итераций:
S<0, B>=128, нужно добавлять A+C
S<0, B<128, нужно добавлять С
S>=0, B<128, нужно добавлять -С
S>=0, B>=128, нужно добавлять A-C
Одна итерация в каждой ветке выглядит так:
сдвигаем B и затягиваем в него перенос полученный после сложения в качестве бита частного
если требуется, делаем переход в другую ветку
удваиваем сумму(из-за этого шага алгоритм деления не может работать с числами более 2^7, а использование A+C в суммировании уменьшает их диапазон вдвое)
добавляем константу соответствующую данной ветке
делаем переход в другую ветку, если знак суммы поменялся

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

Destr
07.10.2019, 06:41
X=X1+(Y-Y1)/(Y2-Y1)*(X2-X1)
Все эти деления/умножения напроч убивают производительность, ну и разрядность теряем как сам пишешь

из-за этого шага алгоритм деления не может работать с числами более 2^7, а использование A+C в суммировании уменьшает их диапазон вдвое

ALKO
09.10.2019, 10:18
Есть у кого процедурка быстрого циклического познакоместного скролла по горизонтали? Достаточно лишь треть экрана скроллить.
Взял с Supercode, но там кадр рвётся и скорость недостаточно быстрая, на мой взгляд.
Кстати, картинки идут копипастом 64х64 в ряд. Может их можно по-демосценерски прокешировать "гифкой" ?
Но опять же, реализации на асме я не знаю.

Reobne
09.10.2019, 17:56
ALKO, POP-PUSH-ами можно. Тебе куда надо; направо, налево или туда-сюда?

ALKO
09.10.2019, 20:09
ALKO, POP-PUSH-ами можно. Тебе куда надо; направо, налево или туда-сюда?

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

ALKO
10.10.2019, 01:48
Было бы ещё круче - параллаксом.
Чтоб на каждый второй знакоместный тик ряда из 32ух пикселей снизу приходился один тик ряда 32ух последующих пикселей.
То есть суммарно 64 пикселя скроллируется (8 знакомест снизу) но по скоростям скролла разделены.

ALKO
01.01.2020, 21:52
Смена картинок (в цвете) по принципу растворения пикселей. Есть такое у кого-нибудь ?
Желательно сами картинки чтоб с какой-нибудь компрессией были.... ах да, и как их вообще подготовить в том же ZX-Paintbrush
В BMP2SCR есть встроенный компрессор, но он фуллскриновый, а мне для конкретной области экрана.

SfS
02.01.2020, 01:36
Есть некое подобие смены картинок путем растворения пикселов. Меняется сначала пиксельгая часть, а затем атрибуты.

https://github.com/salextpuru/sdcc-noinit/tree/master/apps/csp2018invitro

Файл logos.c и библиотеки с функциями.

Тут https://github.com/salextpuru/sdcc-noinit/blob/master/doc/sdcc-csp2018invitro.pdf описано как что работает немного.

SfS
02.01.2020, 11:42
Добрался до компа.

Вот тут https://github.com/salextpuru/sdcc-noinit/blob/master/libsrc/libspr/spr0_fade.c процедура замена изображения на экране на изображение спрайта (один шаг). Заменяются случайные пиксели.

Для эффекта "замены путём растворения пикселов" - вызываем данную процедуру несколько раз подряд с задержкой между вызовами. Я вызывал 8 раз.
Затем (чтобы установить незамененные пиксели и установить атрибуты) вызывал просто печать спрайта с атрибутами: https://github.com/salextpuru/sdcc-noinit/blob/master/libsrc/libspr/spr0_out0_s.s (там же описан формат спрайта).


Вот тут https://github.com/salextpuru/sdcc-noinit/blob/master/apps/csp2018invitro/logos.c в процедуре void logos_check() как раз замена изображения за 8 шагов.

Все привязано к SDCC. Фанатам ассемблера не читать !:)

Destr
02.01.2020, 12:10
Заменяются случайные пиксели.
Кстати, если делать по-уму - то заменятся должны не просто случайные пиксели, но ещё и так чтобы дважды не заменялись те что уже заменены.
Решается толково написаным RND. Тогда количество итераций можно выяснить исходя из знания площади картинки и количество заменяемых пикселей за раз...
Это как-бы настоящий подход, а то в большинстве процедур - костыли, прогнали несколько замен - а потом окончательная - весь кусок сразу...

SfS
02.01.2020, 13:42
Кстати, если делать по-уму


С удовольствием использую вашу процедуру rnd, сделанную "по уму".

Destr
02.01.2020, 13:56
С удовольствием использую вашу процедуру rnd, сделанную "по уму".
Это зависит от картинки. Период RND должен равнятся её площади в пикселях.
Тогда каждый вызов процедура будет обрабатывать ровно 1 пиксель. И никогда не повторится с тем пикселем который уже был обработан.
Когда вызовется на S раз - все пиксели будут обработаны.
По очереди в общем-то, но ведь RND - это перемешивание и выглядеть оно будет как случайность.
Так что тут нужно осваивать матан и методы получения псевдо-случайных значений (ещё и правильно интерпретировать ответ RND - это по-сути координаты того пикселя который обрабатываем на данной итерации, неважно гасим, зажигаем, заменяем другой картинкой)
Я лично в математике слабоват, у меня получалось только "в лоб", классической процедурой которая имеет период 65535, вот эти два байта и брал за X и Y
Интерпретируюя как коорду пикселя который нужно зажеч. Ща покажу.
https://yadi.sk/d/ufC3XZnK-pidpw
Вот, изображение солдата появляется по одному пикселу за раз (каждый HALT, на самом деле нет, но прикручивать не стал, иначе оно бы появлялось 65535 хальтов, больше 20 минут, но у тебя видимо изображение планируется попроще, вот я и обобщил в описаниии)
Как-бы он интерпретируется как картинка 256х256, но поскольку экран у нас 256 на 192 то просто не зажигаются те пиксели которые ниже...

Не знаю, понятно ли объяснил, но в общем-то думаю достаточно наглядно чтоб понять что имел в виду...

SfS
02.01.2020, 13:59
По очереди в общем-то, но ведь RND - это перемешивание и выглядеть оно будет как случайность.
Так что тут нужно осваивать матан и методы получения псевдо-случайных значений (ещё и правильно интерпретировать ответ RND - это по-сути координаты того пикселя который обрабатываем на данной итерации, неважно гасим, зажигаем, заменяем другой картинкой)
Я лично в математике слабоват, у меня получалось только "в лоб", классической процедурой которая имеет период 65535, вот эти два байта и брал за X и Y
Интерпретируюя как коорду пикселя который нужно зажеч. Ща покажу.

ИМХО, визуально, что мой "КОСТЫЛЬ", что ваше "ПО УМУ" будет практически неотличимо. А зачем тогда огород городить?:)

Destr
02.01.2020, 14:05
В общем к концу цикла (65536) все пиксели встали на места. Без дополнительных LDIR и прочего :)

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

За тем что одна процедура вывода, и не нужно ещё и доп-процедуру прикручивать.
Это грамотней.

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

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

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

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

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

Всё таки демо - это программа, а не видеоплеер...
Хотя конечно кому как :)

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

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

SfS
02.01.2020, 18:12
Все от задачи зависит.
У меня было ограничено время. Инвитро должна была появиться к сроку.

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

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

Destr
03.01.2020, 17:02
Инвитро должна была появиться к сроку
Только не говори что ты с ААА работаешь...
Я как-то сотрудничал
Было норм...
Кроме одного - он как организатор (лучше сказать инициатор) гуд
А остальное всё переделывалось с нуля...
(про клона демку погляди и отчёт)
Вроде самое характерное (ну что я знаю, остальные с кем ему приходилось морочится - даже и этого не писали, ну по-крайней мере я не видел)
Он конечно молодец, он коллекционер...
А вот чтоб всё сделать как надо - почему-то тру-программеры ему плюются и отказываются...
Я не настолько жёсток, потому и поясняю порой где что и как...
Хоть и казалось-бы токлу-то?
(а ведь есть толк, ещё какой...)

SfS
05.01.2020, 10:53
Ааа не при чем.
Я для csp делал инвитру.

Sayman
14.01.2020, 14:02
а может кто-нибудь подкинуть исходник несложного эффекта для мелкой интрушки?

Denn
24.01.2020, 12:47
Коллеги, добрый день.
Потребовалось сделать быстрое (не втупую вычитаниями, разумеется) деление на 10, много думал, пробовал разное.
Потом читал интернеты и вумные книжки (например, Генри С. Уоррен мл. "Алгоритмические трюки для программистов", 2-е издание (https://vk.com/doc10903696_329143255?hash=df6a972a776244ba38&dl=c520c465c467d57198)), пробовал всякие разложения в ряд, умножение на "0,8" и деление сдвигами на 8, "магические" множители и т.п. - всё не то, либо слишком сложно/медленно, либо недостаточная точность (с рядами).
Спустя пару-тройку дней нашёл в сети (http://z80-heaven.wikidot.com/math#toc21) следующий код:



DIV10:
; Вх: [HL]
; Вых: [HL]

XRA A
LXI B,100Ah

LOOP:
DAD H
RAL
CMP C
JC SKIP
SUB C
INR L

SKIP:
DCR B
JNZ LOOP
RET


Чёрт возьми! Он работает моментально (всего 16 оборотов предельно короткого цикла), малый объём, красив во всех смыслах... В общем, 99% людей порадовались бы, использовали и забыли.

Но я трудный) Мне надо понять КАК он работает, и как такое вообще смогли придумать люди?!
Второй день ломаю голову! Пробовал скармливать разные тестовые числа, смотреть отладчиком их преобразование на каждой итерации алгоритма - не могу ничего понять((

Насколько вижу, происходит следующее. Весь исходник побитно прокручивается влево, в результате чего последовательно выталкиваются все биты в аккумулятор. Параллельно, с другого конца той же пары HL, теми же сдвигами накапливается результат. В результирующие биты пишется "0" когда вытолкнутое содержимое в аккумуляторе меньше 10, а когда больше 10, то пишется "1" и из аккумулятора вычитается 10. И так все 16 бит.
На протяжении всего цикла в причинных регистрах творится полнейшая ахинея, и ровно после последней итерации получается точный ответ. Идеально точный!

- "Холмс, но как?!" (С)

ivagor
24.01.2020, 13:18
Просто хорошо организованное деление HL/C в столбик, математических откровений тут не видно.

Denn
24.01.2020, 13:56
Просто хорошо организованное деление HL/C в столбик, математических откровений тут не видно.

Речи про математические откровения нет, они все известны. Тут, кмк, какая-то хитрость применительно к двоичной с/с и программированию.

Связи со столбиком не вижу.

https://calc.by/images/math/img_long_division1.png

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

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

ivagor
24.01.2020, 14:28
Используется какая-то хитрость
Единственная "хитрость" - это использование одновременно старших бит HL для делимого и младших - для частного. Трюк известный, но этого не менее хороший.

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

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


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

Denn
24.01.2020, 14:34
Я так понимаю это опечатка, т.к. именно от делимого число итераций и зависит, но не зависит от делителя.

Нет, очепятки нет. Я расписал работу алгоритма выше. Ровно 16 итераций и ответ готов. А делимое может быть от 0 до 65535.
Делитель фиксированный, в исходном случае = 10. Методом интуиции и научного тыка я перезаточил данный алгоритм под деление на 100, просто изменив значение регистра [C] - работает! Но как оно работает, я до сих пор не понимаю. И из-за этого уже "не сплю" второй день :)

ivagor
24.01.2020, 14:44
Нет, очепятки нет. Я расписал работу алгоритма выше. Ровно 16 итераций и ответ готов. А делимое может быть от 0 до 65535.
Я не писал, что от числа значащих бит делимого. Повторюсь, число итераций определяется числом бит делимого - их 16. Могу уточнить - общим числом бит делимого. Если, например, делимое будет в H, то достаточно будет 8 итераций.


Методом интуиции и научного тыка я перезаточил

деление HL/C
поэтому можно "перезаточить" на любой делитель от 0 до 255 просто изменив C

Denn
24.01.2020, 15:08
Если, например, делимое будет в H, то достаточно будет 8 итераций.
...
поэтому можно "перезаточить" на любой делитель от 0 до 255 просто изменив C

Это всё я уже понял.

Но, не понял как оно работает! Как выполняется деление, на каком принципе?
Делитель из делимого не вычитается. Происходит некая обработка каждого бита по отдельности, принцип вычисления каждого бита не зависит от его "веса" в делимом... не понятно.
Если пытаться рассуждать математическими экивалентами сдвигов (умножениями на 2), то тоже не понятно... зачем 16 раз делимое умножать на два? Почему решение о вычитании делителя принимается на основании результатов накопления выталкивающихся битов?

ivagor
24.01.2020, 15:11
Делитель из делимого не вычитается.
SUB C

Denn
24.01.2020, 15:13
SUB C

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

ivagor
24.01.2020, 15:15
зачем 16 раз делимое умножать на два?
Биты из HL вдвигаются в "окошко сравнения", которое в A.

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

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


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

Denn
24.01.2020, 15:16
Если, например, делимое будет в H, то достаточно будет 8 итераций.

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

ivagor
24.01.2020, 15:18
Но для получения корректного результата прокрутить надо все 16 раз, тогда нужные биты встанут на свои места.
Нет, за 8 итераций частное будет в L. Чтобы не было сомнений, я говорю про деление H/C=L

Denn
24.01.2020, 15:20
Нет, за 8 итераций частное будет в L. Чтобы не было сомнений, я говорю про деление H/C=L

Мысль понял, но это уже как бы другой код. В исходном нужны всегда 16 итераций, и вход/выход в 8-битном варианте будут в L - я об этом.

ivagor
24.01.2020, 16:15
это уже как бы другой код
Для 8-битного варианта (делимого) всего лишь меняем LXI B,100Ah на LXI B,080Ah. H/C=L

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

Кстати о разрядности. Если фиксировать делитель =10dec, то максимальное число разрядов делимого в этой процедуре (только надо убрать XRA A) м.б. 19, а не 16 - 7FFFF (A=7;HL=FFFF).

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


Для 8-битного варианта (делимого)
При делении на 10dec этот вариант допускает (при убирании XRA A) делимое до 11 разрядов - 7F (A=7;H=F)

Denn
24.01.2020, 16:38
Так работает деление в столбик.

Каким образом можно с помощью 16 (шест-над-ца-ти) действий разделить 10 на 10 в столбик?

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

Пытаюсь зайти с т.з. математики. По сути алгоритм делает следующее: умножает делимое на 2 и делит (получается как бы автоматом) на 65536, результаты этих действий накапливаются в аккумуляторе и при превышении значения равного делителю, последний вычитается из накопителя и в этот момент "зажигается" разряд частного, который потом будет умножен на 2 оставшееся число раз... это реально придумал марсианин!

В итоге математически имеем следующее: Х/32768+Х/16384+Х/8192+...+Х/2+Х/1

Но как в эту формулу ввести условное вычитание делимого при первышении с помощью средств математики?..

ivagor
24.01.2020, 16:58
Каким образом можно с помощью 16 (шест-над-ца-ти) действий разделить 10 на 10 в столбик?

Исходные данные
Делимое =0000 0000 0000 0000 1010
Делитель=1010

1. Делимое =0000 0000 0000 0001 0100
Делитель =1010
Частное =0

2. Делимое =0000 0000 0000 0010 1000
Делитель =1010
Частное =00

3-14. ...

15.Делимое =0101 0000 0000 0000 0000
Делитель =1010
Частное =000 0000 0000 0000

16.Делимое =1010 0000 0000 0000 0000
Делитель =1010
Частное =0000 0000 0000 0001

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

Все правые нули, которые я добавлял к делимому, можно или убрать или заменить на X или какой-нибудь другой нецифровой символ

Denn
24.01.2020, 17:11
Все правые нули, которые я добавлял к делимому, можно или убрать или заменить на X или какой-нибудь другой нецифровой символ

К сожалению, данная информация мне не даёт ключ к пониманию принципа работы алгоритма.


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

ivagor, у меня только за один ход получается:

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

Denn
24.01.2020, 17:16
ivagor, я по-прежнему не вижу аналогии с алгоритмом классического деления столбиком, в котором - в первую очередь - кол-во итераций зависит от значений делимого и делителя. Добавление незначащих нулей не меняет картину.

Bolt
24.01.2020, 17:35
Denn, давай разделим 00115 на 7 в десятичной системе.

1. Сдвигаем 00115 влево на одну позицию, 0|0115?. 0 меньше 7, поэтому ?=0, итого 0|01150
2. Сдвигаем, 00|1150?. 00 меньше 7, поэтому опять 0. 00|11500.
3. 001|1500?, 1 меньше 7, 001|15000.
4. 0011|5000?, 11 больше 7, вычитаем, остаётся 4|50001.
5. 45|0001?, 45 больше 7, вычитаем 6 раз, остаётся 3|00016.

5 разрядов, 5 шагов. Остаток в аккумуляторе, частное там, где было делимое.

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

В коде то же самое, но в двоичной системе.

ivagor
24.01.2020, 17:37
алгоритмом классического деления столбиком, в котором - в первую очередь - кол-во итераций зависит от значений делимого и делителя
Потому что в школе не дают делимых со старшими незначащими нулями. Детям не ставят задачу как процедуре: "деление 4х разрядного числа на 2х разрядное". Им дают числа и школьники не задумываясь выравнивают старшие значащие цифры делимого и делителя - для процедуры это тоже итерации!

Bolt
24.01.2020, 17:38
Denn, не надо понимать это "математически". Допиши при делении в столбик к делимому незначащие нули до N разрядов, сделай N итераций, получишь N разрядов частного с незначащими нулями.

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

ivagor
24.01.2020, 17:43
не надо понимать это "математически"
Почему? Это чистая математика, только не как Denn расписал.

Bolt
24.01.2020, 18:09
не как Denn расписал.
Я это и имел в виду.

ivagor
24.01.2020, 18:27
умножает делимое на 2
Думаю это принципиальный момент. В контексте данного алгоритма DAD H и RAL это не умножение на 2/сдвиг влево AHL, это деление на 2/сдвиг вправо C относительно AHL. Все относительно, вручную мы привыкли сдвигать делитель вправо относительно делимого, а здесь двигают делимое влево относительно делителя (так делают в большинстве процедур деления для 8080, т.к. команды сдвига влево есть только для A). Но результат одинаковый. И в качестве бонуса такой сдвиг обнуляет младший бит L.

Denn
25.01.2020, 01:05
Denn, давай разделим 00115 на 7 в десятичной системе.

1. Сдвигаем 00115 влево на одну позицию, 0|0115?. 0 меньше 7, поэтому ?=0, итого 0|01150
2. Сдвигаем, 00|1150?. 00 меньше 7, поэтому опять 0. 00|11500.
3. 001|1500?, 1 меньше 7, 001|15000.
4. 0011|5000?, 11 больше 7, вычитаем, остаётся 4|50001.
5. 45|0001?, 45 больше 7, вычитаем 6 раз, остаётся 3|00016.

5 разрядов, 5 шагов. Остаток в аккумуляторе, частное там, где было делимое.

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

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



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

В коде то же самое, но в двоичной системе.

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

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


Думаю это принципиальный момент. В контексте данного алгоритма DAD H и RAL это не умножение на 2/сдвиг влево AHL, это деление на 2/сдвиг вправо C относительно AHL. Все относительно, вручную мы привыкли сдвигать делитель вправо относительно делимого, а здесь двигают делимое влево относительно делителя (так делают в большинстве процедур деления для 8080, т.к. команды сдвига влево есть только для A). Но результат одинаковый. И в качестве бонуса такой сдвиг обнуляет младший бит L.

С этим как раз у меня проблем нет. Очень часто пользуюсь сдвигами при программировании, и всегда оптимизирую - кручу в ту сторону, в какую ближе, а уж "перекинуть" байты местами для получения обратной картины не вопрос.
В данном случае мне глобально не понятен смысл всех этих действий, каким образом они ведут к результату.

Bolt
25.01.2020, 02:04
Общий алгоритм - деление в столбик.


00115 | 7
0 |----
0 | 00016
=
00
00
==
001
000
===
0011
0007
====
45
42
=====
3

Что делаем? Сносим 0, делим на 7, получаем 0 в результате, 0 в остатке. Сносим второй 0, делим на 7... Сносим 1, делим на 7... Сносим 5...

Это понятно?
Смотрим на это под другим углом.

Есть у нас три части (именно в таком порядке): "снесённая" часть (она же остаток), делимое, и частное (результат).

Не сносим, а сдвигаем (смотри на деление в столбик).
Было 00115, стало 0 и 0115, и в ответе 0.
Потом стало 00, 115, 00.
Потом 001, 15, 000.
0011, 5, 0001. (11-7*1=4)
00045, пусто, 00016. (45-7*6=3)

Это понятно?

Первая часть в аккумуляторе, а делимое и частное записаны вместе:


00115|
0115|0
115|00
15|000
5|0001
|00016


Понятно? Или расписать ещё в двоичном виде?

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


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

Denn
25.01.2020, 02:26
Действительно, нужно было посмотреть на "столбик" под другим углом (не как учили в школе, а более "компьютерно"), обобщить его до регистров фиксированной длины с незначащими нулями и "холостыми" итерациями, а также в двоичной плоскости, и тогда понимание снизошло :)

Три момента, которые видимо не давали мне ключ к пониманию:

1) Сдвиг это действительно сдвиг, а не умножение/деление на два!
2) В школьном варианте мы сдвигаем сразу всю цифру (десятичную) целиком, а тут мы это делаем по одному биту (грубо говоря, тупо ждём, когда протащится вся цифра);
3) Пожалуй, принципиальный момент, который скрывал логику: поскольку мы работаем в двоичной с/с, то на каждой итерации нам не нужно делать реальное деление цифры на делитель, как это делается в школьном столбике, а достаточно лишь понять делится оно или нет, точнее - результат ноль или больше, и так как за одну двоичную итерацию у нас не может ничего произойти с результатом больше, чем на единицу, то достаточно либо оставлять "халявный" автоматический "0" или добавлять "1".

Я бы до такого не додумался сам! Я бы стал подгонять алгоритм под известный школьный столбик, т.е. сдвигать байт сразу на тетраду и честно делить вычитаниями. Тут какой-то двоичный переворот сознания %)

Всем спасибо! Теперь можно спать спокойно :)

Bolt
25.01.2020, 02:26
Поделим в двоичном виде "0011000000111001" на "1010". (должно получиться 0000010011010010, и остаток 101).

Итерация №1
сдвигаем на 1 разряд, получаем 0 и 011000000111001?
0 меньше 1010, значит в результат задвигаем 0, получаем ???????????????0

Итерация №2
сдвигаем на 1 разряд...

... получаем 00 и 11000000111001??
00 меньше 1010, значит в результат задвигаем 0, получаем ??????????????00

Итерация №3
сдвигаем на 1 разряд, получаем 001 и 1000000111001???
001 меньше 1010, значит в результат задвигаем 0, получаем ?????????????000

Итерация №4
сдвигаем на 1 разряд, получаем 0011 и 000000111001????
0011 меньше 1010, значит в результат задвигаем 0, получаем ????????????0000

Итерация №5
сдвигаем на 1 разряд, получаем 00110 и 00000111001?????
00110 меньше 1010, значит в результат задвигаем 0, получаем ???????????00000

Итерация №6
сдвигаем на 1 разряд, получаем 001100 и 0000111001??????
001100 больше 1010, значит вычитаем и в результат задвигаем 1, получаем ??????????000001
(остаток 000010)

Итерация №7
сдвигаем на 1 разряд, получаем 0000100 и 000111001???????
0000100 меньше 1010, в результат задвигаем 0, получаем ?????????0000010

Итерация №8
сдвигаем на 1 разряд, получаем 00001000 и 00111001????????
00001000 меньше 1010, в результат задвигаем 0, получаем ????????00000100

Итерация №9
сдвигаем на 1 разряд, получаем 000010000 и 0111001?????????
000010000 больше 1010, вычитаем, в результат задвигаем 1, получаем ???????000001001
(остаток 110, нули отбросим для удобства)

Итерация №10
сдвигаем на 1 разряд, получаем 1100 и 111001??????????
1100 больше 1010, вычитаем, в результат задвигаем 1, получаем ??????0000010011
(остаток 0010)

и т.д.


Количество оставшихся разрядов в делимом уменьшается, на их место можно записать частное.


0011000000111001 (0x3039)
011000000111001 0 (0x6072)
11000000111001 00 (0xC0E4)
1000000111001 000 (0x81C8)
000000111001 0000 (0x0390)
00000111001 00000 (0x0720)
0000111001 000001 (0x0E41)
000111001 0000010 (0x1C82)
00111001 00000100 (0x3904)
0111001 000001001 (0x7209)
111001 0000010011 (0xE413)
11001 00000100110 (0xC826)
1001 000001001101 (0x904D)
001 0000010011010 (0x209A)
01 00000100110100 (0x4134)
1 000001001101001 (0x8269)
0000010011010010 (0x04D2 = 1234)

ivagor
25.01.2020, 10:13
Убрал про дальшейшее увеличение разрядности делимого больше 7FFFF. В общем случае там надо еще команды добавлять, а это уже не так интересно.

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

Сообразил компромиссный вариант, можно увеличить делимое до 3FFFFF без добавления команд если 1) убрать XRA A; 2) Заменить LXI B,100Ah на LXI B,1350h. Но если честно, то команды все же придется добавить для разделения остатка и старших бит частного, т.к. остаток будет в 5(4) старших битах A, и 3 старших бита частного будут в 3х младших битах A.

Bedazzle
25.01.2020, 12:41
Я уже как-то спрашивал. Постоянно пробегают небольшие удобные кусочки кода разного назначения.
Никто так и не взялся собирать их в одно место, не приводит в порядок?

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

Denn
25.01.2020, 12:49
ivagor, в источнике оригинала есть варианты для 24-битного и 32-битного делимого:

http://z80-heaven.wikidot.com/math#toc22

http://z80-heaven.wikidot.com/math#toc23

В последнем красивый замут с "удлинением" регистра до 32-битного с помощью переворота XCHG.

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


Никто так и не взялся собирать их в одно место, не приводит в порядок?

Дело хорошее и полезное!

Отправной точкой как раз может послужить этот ресурс - http://z80-heaven.wikidot.com/math


П.С. для Ориона я по-возможности оформляю полезные подпрограммы в виде библиотек

ivagor
25.01.2020, 13:25
z80-heaven ресурс хороший, но там бывают неточности, например (https://zx-pk.ru/threads/26834-kvadratnyj-koren-na-i8080.html?p=882574&viewfull=1#post882574). В описании E_div_10 не упомянули, что деление приближенное. Все надо проверять.

Bedazzle
25.01.2020, 14:11
z80-heaven ресурс хороший, но там бывают неточности, например (https://zx-pk.ru/threads/26834-kvadratnyj-koren-na-i8080.html?p=882574&viewfull=1#post882574). В описании E_div_10 не упомянули, что деление приближенное. Все надо проверять.

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

Shadow Maker
25.01.2020, 15:04
Это wikidot, а не сайт, она вряд ли подохнет. 15 лет уже работает. Но если боишься - сделай экспорт и заливай периодически на archive.org.

Denn
25.01.2020, 15:39
Меня печалит, что ресурсы периодически дохнут

Всё верно, лучше дублировать нужную инфу. Я обычно скачиваю к себе локально на NAS, плюс дублирую в свою группу ВК.

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


В описании E_div_10 не упомянули, что деление приближенное.

Там используется "трюк": умножаем на 26 и делим на 256, т.е. по сути умножаем на 0,1015625 - что очень хорошо приближается к 1/10. Для 8-битных чисел, под которые заточена процедура, точность получается достаточная.
Всё делается сдвигами и парой сложений. Красиво придумано!

ivagor
26.01.2020, 07:50
Для 8-битных чисел, под которые заточена процедура, точность получается достаточная.
Смотря для каких задач. Деление на 10 у меня в первую очередь ассоциируется с преобразованием bin->dec для печати, для этой цели я бы не стал использовать приближенную процедуру. Но задачи бывают разные, для интерполяции при воспроизведении звука я использовал деление через умножение, там точности достаточно.

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

Если подумать, то E_div_10 нельзя использовать для преобразования bin->dec не только из-за неточности, но и из-за того, что она не вычисляет остаток.

ivagor
26.01.2020, 11:47
Хватит исправлять других, исправлю себя. Данная процедура (https://zx-pk.ru/threads/9031-etyudy.html?p=1043288&viewfull=1#post1043288) будет правильно делить HL/C не при любых соотношениях HL и С. Но это можно легко поправить

DIV_HL_C:
; Делимое: [HL]
; Делитель: [C]
; Частное: [HL]
; Остаток: [A]
XRA A
MVI B,16
LOOP:
DAD H
RAL
JC NOSKIP
CMP C
JC SKIP
NOSKIP:
SUB C
INR L
SKIP:
DCR B
JNZ LOOP
RET

Denn
26.01.2020, 12:55
Деление на 10 у меня в первую очередь ассоциируется с преобразованием bin->dec для печати

Именно для этой задачи мне и понадобилось деление на 10 ;)

blackmirror
26.01.2020, 13:39
Именно для этой задачи мне и понадобилось деление на 10
Самая быстрая процедура перевода в десятичный вид делением вообще не пользуется - в зависимости знака текущего остатка(сначала он равен исходному числу) в HL она вычитает или добавляет:
40K, 20K, 10K, 4K, 4K, 2K, 1K, 400, 400, 200, 100, 40, 40, 20, 10,
Параллельно при неотрицательном остатке в HL к A добавляется 4, 4, 2, 1.

ivagor
26.01.2020, 15:25
Самая быстрая процедура перевода в десятичный вид делением вообще не пользуется
Круто, но у меня получилось довольно громоздко. Оптимизировать можно, но скорее всего вариант с делением все же будет компактнее. Интересно бы сравнить с double dabble.

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

Один момент не отметил - использовал флаг заема/переноса, не знака.

Denn
26.01.2020, 17:34
Самая быстрая процедура перевода в десятичный вид делением вообще не пользуется - в зависимости знака текущего остатка(сначала он равен исходному числу) в HL она вычитает или добавляет:
40K, 20K, 10K, 4K, 4K, 2K, 1K, 400, 400, 200, 100, 40, 40, 20, 10,
Параллельно при неотрицательном остатке в HL к A добавляется 4, 4, 2, 1.

Долгое время пользовался какой-то чужой процедурой, честно спёртой из кода какой-то игры (вроде РКшной?). Сейчас решил разобраться, как она устроена. Там тоже сделано вычитаниями констант: сначала вычитают 10000 пока не уйдут в минус, потом -1000, потом -100 и т.д.. В общем не сильно громоздко, но скорость очень зависит от значения исходного числа, мне показалось это "некрасивым", решил сделать по-своему.

В итоге придумалось так. Исходник в [HL]. Сначала умножаем [AHL] на 6,5536 (тобишь *65536/10000), в результате в [A] у нас оказывается первая (слева) цифра, её выводим на экран. Обнуляем аккумулятор. Далее 4 раза умножаем [AHL] на 10 (3хDAD H + 2xDAD D) и на каждом шаге выводим, а затем обнуляем значение [A].
Скорость не зависит от числа, а самый "тормозной" участок алгоритма - это деление на 10000 (два раза делим на 100 с помощью "марсианского" кода). Как-то так.

b2m
26.01.2020, 18:36
самый "тормозной" участок алгоритма - это деление на 10000
Если нужно вывести число, самый быстрый метод, на мой взгляд, перевод в BCD:

LXI H,1234
CALL TOBCD
JMP $ ; десятичное число в регистрах B,C,D = 00,12,34

TOBCD: LXI B,0
LXI D,16
L1: DAD H
MOV A,D
ADC A
DAA
MOV D,A
MOV A,C
ADC A
DAA
MOV C,A
MOV A,B
ADC A
DAA
MOV B,A
DCR E
JNZ L1
RET

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

ivagor
26.01.2020, 19:20
самый быстрый метод
По алгоритму blackmirrora быстрее, но если твою процедуру тоже развернуть, то скорее всего будет близко. Огромный плюс твоего варианта - сочетание компактности и скорости.

ivagor
27.01.2020, 11:30
b2m, ты тоже недоиспользовал возможности процедуры (https://zx-pk.ru/threads/9031-etyudy.html?p=1043534&viewfull=1#post1043534) - исходное число не ограничивается HL, можно в DHL разместить число до 9FFFF. При этом ничего не нужно добавлять и процедура даже станет короче за счет замены LXI D,16 на MVI E,16.

b2m
27.01.2020, 11:41
Ты как всегда прав :)

ivagor
27.01.2020, 18:09
Нового или остроумного ответа не смог придумать, поэтому просто приведу еще ссылку по теме (https://www.cemetech.net/forum/viewtopic.php?t=10848&start=0). Тот вариант выглядит более громоздким и медленным, и использует уникальные возможности z80, т.е. он больше для коллекции, чем для практического использования.

Denn
28.01.2020, 23:23
Надо будет на досуге сделать сравнение скоростей отработки всех этих алгоритмов. Замьютить вывод символа и прогнать в цикле от 0 до 65535 через каждый.
Только поскольку практический интерес представляет онлайн вывод значения на экран, то в варианте b2m нужно будет добавить код преобразования (отброс незначащих нулей и вывод цифр слева-направо).

ivagor
29.01.2020, 07:31
Самые быстрые - это процедура b2ma и по алгоритму blackmirrora. Вариант b2ma примерно в полтора раза медленнее, зато раз в 10 короче (но его можно развернуть, если очень нужна скорость). Надо учесть, что алгоритм blackmirrora в моей реализации, возможно его собственная быстрее и короче. Ну и я не учитывал преобразование в символы, которое будет немного быстрее после процедуры blackmirrora. Еще момент - у процедуры b2ma диапазон преобразования на десятичный разряд больше, это существенно. И процедуру b2ma гораздо проще масштабировать на любое число разрядов. Вариант blackmirrora имхо имеет смысл для процессоров без команды десятичной коррекции.

blackmirror
29.01.2020, 08:03
ivagor, вариант b2m можно переделать следующим образом: делим число на 4х разрядные цифры, для каждой цифры из таблицы или по дереву переходов вытаскиваем десятичное представление, а суммирование цифр производим уже в десятичном представлении. Кстати мой вариант тоже может работать с небольшими деревьями переходов, чтобы выдать цифру сразу а не накапливать в аккумуляторе.

ivagor
29.01.2020, 08:16
для каждой цифры из таблицы
Варианты с таблицами я не рассматривал. На msxном форуме есть вариант, я в него не вникал, т.к. теперь не вижу большого смысла в ускорении за счет размера для задачи bin->dec при наличии команды daa.

ALKO
02.02.2020, 22:18
Интересует смена одной картинки познакоместным скроллом другой из края экрана (влево/вправо).
А также смена картинок посредством по-тайлового появления квадратом от центра к краям.

Ещё не знаю какими средствами сами картинки (в цвете) запихнуть в Горбатыша, да так чтоб максимально большое количество, возможно с компрессией (и использованием 128кб банков памяти). Сами картинки не фулл-скрин. Где-то 1/3, 2/3 экрана.

Сможет кто помочь в данном вопросе?

Lethargeek
02.02.2020, 22:36
Ещё не знаю какими средствами сами картинки (в цвете) запихнуть в Горбатыша, да так чтоб максимально большое количество, возможно с компрессией (и использованием 128кб банков памяти). Сами картинки не фулл-скрин. Где-то 1/3, 2/3 экрана.

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

Destr
03.02.2020, 04:41
Интересует смена одной картинки познакоместным скроллом другой из края экрана (влево/вправо)
Если познакоместно - LDIR-LDI (если с извращениями то стек, если с серъёзными извращениями то таки-да "вы снова вышли на Дерибасовскую!")

ALKO
03.02.2020, 09:47
Если познакоместно - LDIR-LDI (если с извращениями то стек, если с серъёзными извращениями то таки-да "вы снова вышли на Дерибасовскую!")

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

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

Хм.. а если LDIRить, то эт картинки будут размером строго по ширине экрана ведь? Я предполагал размеры пикч отличные от 256 пикселей по ширине.
160х88 или около того. В зависимости от сцены.

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


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

Lethargeek Kompakt v1.1?

Я пока не за компом, нет возможности ознакомиться.
А в каком виде скармливать данные из того же ZX painbrush или bmp2scr? Кстати, в последнем тоже имеется свой компрессор, но он заточен под фулл скрин, и распаковывает сразу в 16384.

Lethargeek
03.02.2020, 13:24
Хм.. а если LDIRить, то эт картинки будут размером строго по ширине экрана ведь? Я предполагал размеры пикч отличные от 256 пикселей по ширине.
160х88 или около того. В зависимости от сцены.
ну и размножь насколько тебе надо цепочку ldi/ldd


Lethargeek Kompakt v1.1?

Я пока не за компом, нет возможности ознакомиться.
А в каком виде скармливать данные из того же ZX painbrush или bmp2scr?
он, скармливать только scr (ну, и собственные результаты для контроля на распаковку))

Destr
03.02.2020, 17:41
Может быть поможет LD HL,(адрес в скрине):PUSH HL (стек тоже в экране).
Память конечно жрётся нехило, но зато быстро и если железо путнее (и скомпилировано в быструю память) - во фрейм может и удатся...

ALKO
04.02.2020, 11:55
он, скармливать только scr (ну, и собственные результаты для контроля на распаковку))

Глянул демку. Экономия примерно в два раза получилась, видимо. Правда там несколько пикч читерские - с пустотами.
В целом скорость распаковки норм при условии что скроллить или проявляться из центра будет по мере данной распаковки.

Lethargeek
04.02.2020, 13:48
ALKO, смотря как там нужно скролить и проявлять, распиши подробней здесь или в личку

ALKO
04.02.2020, 14:28
Lethargeek, ну вот, допустим, есть картинка
160х88, например, или около того +/-. Края по бокам можно захайдить атрибутами (чёрный инк/черный пэйпер), в случае чего использовать их как буферную зону распаковки перед выполнением скролла.(хотя не, отдельно атрибуты шлёпать придётся, усложнится алгоритм)
Затем в зависимости от нажатой кнопки познакоместный скролл влево/вправо, одна картинка сменяется другой (можно и 16px, все равно не экшн, поэтому дискретность допускается). А также при нажатии условного "вперёд" из центра картинки квадратом разрастается следующая (недавно обсуждали Лоде Руннер в холиварах, вот на MSX и SG1000 карта генерится в подобном виде).
Пока контент не рисовал, поскольку не ясно точно, под какое разрешение будут работать процедуры, если таковые будут вообще.

Lethargeek
04.02.2020, 15:49
ALKO, ok, попозже объясню, что к чему

ivagor
07.02.2020, 12:36
В дополнение/окончание темы bin2bcd с использованием daa. Оказывается достаточно давно на форуме уже была ссылка (https://zx-pk.ru/threads/1061-fast-48x48-mul-div.html?p=18647&viewfull=1#post18647) на такую процедуру (там много чего).

tae1980
07.02.2020, 13:32
А можно текст по ссылки из группы ФИДО в читаемой кодировке? А то мне браузер не даёт сменить кодировку.

Bedazzle
08.02.2020, 01:39
А можно текст по ссылки из группы ФИДО в читаемой кодировке? А то мне браузер не даёт сменить кодировку.

Похоже, фиг

https://i.imgur.com/uI9nZ7Q.png

Dart Alver
08.02.2020, 10:44
А можно текст по ссылки из группы ФИДО в читаемой кодировке?

Похоже, фиг

А так ? https://groups.google.com/forum/?hl=en#!msg/fido7.zx.spectrum/ugkHleegp80/HRyzU9fkmU4J

blackmirror
08.02.2020, 12:06
В дополнение/окончание темы bin2bcd с использованием daa. Оказывается достаточно давно на форуме уже была ссылка на такую процедуру (там много чего).
Эти процедуры нельзя считать окончанием темы, поскольку на форуме были и более оптимизированные варианты. Вообще использовать 32х разрядное умножение/деление для генератора случайных чисел идея так себе. Лучше взять CRC32 и на выходе сделать XOR старшей и младшей половины, это явно будет менее 3000 тактов. А вот то, что в делении торчит add hl,bc / jc $+4 / sbc hl,bc вообще никуда не годится. Мы уже выяснили, что нужно вычитать или добавлять делитель в зависимости от знака остатка, переходя в другую ветку, если знак поменялся. Это следует из тех соображений, что после вычитания и сдвига мы должны получить 2A-2B или 2A если вычитание было ошибочным и мы делали коррекцию. При следующем вычитании мы получим 2A-2B-B или 2A-B, которое равно 2A-2B+B, то есть делать коррекцию не нужно!
Даже 8080 при всех своих ограничениях может весьма эффективно делить число любой длины на 16 разрядное, и немного менее эффективно чем zx80 одолеть и 32х разрядный делитель, правда в последнем случае ему придётся грузить делитель или минус делитель в BC частями.

ivagor
08.02.2020, 12:24
"Окончание" я только про bin2bcd. Варианты с вычитанием 4,4,2,1 немного быстрее, но заметно крупнее и хуже масштабируются. Для процедуры bin2bcd компактность в сочетании со скоростью для меня важнее максимальной скорости, но это для меня, у каждого свои приоритеты. Если есть еще варианты - интересно взглянуть.
А про остальные процедуры по ссылке я ничего не писал (про скорость и размер), кроме того, что они там есть, т.к. я их внимательно не смотрел.

blackmirror
08.02.2020, 12:57
У меня как-то была необходимость разбирать гигабайтные логи, строки там были примерно такого вида:
20/02/03 16:13:12.536 1234586903 2A8 8C 2D B3 2C 23 3E
В некоторых логах для дня или месяца могла быть и одна цифра или миллисекунды(когда их меньше 100), могли быть выведены с двумя цифрами. В десятичном счётчике число цифр тоже постоянно увеличивалось, первое 16 разрядное число могло быть как с 2, так и с 3 цифрами, ну а 16ричных байт тоже могло быть произвольное количество. Ну и количество пробелов тоже иногда плавало. В общем решением этой задачи оказалась хеш таблица размером в 65536 элементов, из строки брались символы по 4 штуки как простое 32 разрядное число, умножались на магическую константу, после чего получался индекс в таблице. По нему проверялось совпадают прочитанные цифры с тем что есть в таблице, какое они имеют значение и сколько цифр пропустить. То есть 16ричные байты читались вместе с левым и правым пробелом, а пропускались 3 символа, чтобы следующий байт прочитать точно так же, а последний из них в таблице сидел вместе с переводом строки и по нему было ясно что строка закончилась. Для счётчика тоже вытаскивалось по 4 цифры, которые добавлялись к накопленному значению умноженному на 10000. В итоге скорость разбора этих логов стала совпадать со скоростью чтения диска, даже ассемблер брать не пришлось.

ALKO
12.02.2020, 23:20
В общем, с компрессором пока отбой.
BMP2SCR неплохо трамбует, и можно задавать адрес декомпрессии.
Разве что пока с познакоместной пересылкой из буфера на экран со скроллом/проявлением из центра пока не знаю чё делать. Я в таких вещах лишь теоретик.

Bedazzle
13.02.2020, 00:21
Разве что пока с познакоместной пересылкой из буфера на экран со скроллом/проявлением из центра пока не знаю чё делать.

Вот нифига не понятно, как выглядеть должно.
Плюс непонятны ограничения по памяти/скорости.

ALKO
13.02.2020, 01:53
Вот нифига не понятно, как выглядеть должно.

Есть картинка. При нажатии влево - картинка скроллится познакоместно вправо за пределы экрана, и тут же вслед за ней появляется новая, скроллом.

Проявление из центра -> имеющаяся картинка на экране зарисовывается познакоместно следующей.


.Плюс непонятны ограничения по памяти/скорости

Это не экшн, так что скорость не критична. Но и слоупочно нежелательно, шоб не сильно выбешивало. Если 8px скролл выйдет тормозным, то можно и 16px.

По памяти пока я и сам точно не знаю границы. Арты пока что в процессе.

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

Кроме того, я хотел задействовать банки 128кб тачек.
Но это для меня темный лес.
Они еще и на 16кб разбиты, то есть инфа будет фрагментирована, если туда картинки паковать.

Bedazzle
20.02.2020, 01:32
Есть картинка. При нажатии влево - картинка скроллится познакоместно вправо за пределы экрана, и тут же вслед за ней появляется новая, скроллом.


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

Жесть вчера фигню наворотил :)
Вот поприличнее вариант:

https://www.dropbox.com/s/p6v8w3koz6n8y5k/scroller2.sna?dl=0

Bedazzle
20.02.2020, 14:04
А по-хорошему, если фуллскриновые картинки, лучше резать на 32 вертикальных блока + атрибуты и пожать zx7.
Если картинок много, то будет выигрыш по объёму.

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

Из центра так должно выезжать? Т.е. замещающая картинка от краёв к центру, или от центра к краям?

https://www.dropbox.com/s/z2w4b54z0znu7jc/center.sna?dl=0

https://pastebin.com/1wT9ceMR

ALKO
21.02.2020, 19:20
Жесть вчера фигню наворотил
Вот поприличнее вариант:

https://www.dropbox.com/s/p6v8w3koz6...ller2.sna?dl=0

Супер!
Только не обязательно фуллскрин.




Из центра так должно выезжать? Т.е. замещающая картинка от краёв к центру, или от центра к краям?

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

Bedazzle
22.02.2020, 00:33
Только не обязательно фуллскрин.


Тогда переписать надо. Сейчас приколочено на фиксированный размер.



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

Сделаю без скролла тоже.

Outcast
23.02.2020, 21:02
Быстро пробежавшись поиском по форуму и заодно решив вспомнить программирование, изваял такой этюд. (Если не подходит по теме, перенесите.)

Интерпретатор языка Brainfuck на Бейсике.




10 DIM p$(1,255)
15 DIM c(255)
20 LET p$(1)="++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.e"
30 LET j=1: LET i=1
40 IF p$(1,i)=">" THEN LET j=j+1
50 IF p$(1,i)="<" THEN LET j=j-1
60 IF p$(1,i)="+" THEN LET c(j)=c(j)+1
70 IF p$(1,i)="-" THEN LET c(j)=c(j)-1
80 IF p$(1,i)="." THEN PRINT CHR$ c(j);
90 IF p$(1,i)="," THEN INPUT x$: LET c(j)= CODE x$
100 IF p$(1,i)<>"[" THEN GO TO 110
101 IF c(j)=0 THEN IF p$(1,i)<>"]" THEN LET i=i+1: GO TO 101
102 IF p$(1,i)="]" THEN LET i=i+1: GO TO 200
110 IF p$(1,i)<>"]" THEN GO TO 200
111 IF c(j)<>0 THEN IF p$(1,i)<>"[" THEN LET i=i-1: GO TO 111
200 IF p$(1,i)<>"e" THEN LET i=i+1: GO TO 40



Можно в полной мере насладиться отсутствием проверок входящих данных, границ диапазонов, громоздкостью конструкций и прочими прелестями *****кода начинающего программиста.
Из-за отсутствия наличия поддержки вложенных циклов работают только простейшие программы.
Кроме изначальной Hello World! еще работает преобразование строчных букв в верхний регистр
",----------[----------------------.,----------]".(В конце поставить букву e как окончание кода).

zebest
03.04.2020, 21:26
Все познаеЦЦа в сравнении, не так ли?)
Про LDIR
Имеем такой код:


;-----------------------------------
push hl
ld de,16384
ld bc,6144
ldir
pop hl
;-----------------------------------

в HL - Начало буфера с от такой картинкой,
https://s.micp.ru/O3Sg3.jpg
и МЫ ее с максимально возможной скоростью (?) переносим в экран.
Я правильно понимаю, что во фрейм не уложиЦЦа ну никак??
в аттаЧе сам тест, начатЬ заново - кнопка <5>, кнопки 1-4 жать не надо :)
И да ,сам то вопрос - это максимум, что можно на стандартном Спектруме?

jerri
03.04.2020, 21:35
Про LDIR
Имеем такой код:


;-----------------------------------
push hl
ld de,16384
ld bc,6144
ldir
pop hl
;-----------------------------------

в HL - Начало буфера с от такой картинкой,
https://s.micp.ru/O3Sg3.jpg
и МЫ ее с максимально возможной скоростью (?) переносим в экран.
Я правильно понимаю, что во фрейм не уложиЦЦа ну никак??
в аттаЧе сам тест, начатЬ заново - кнопка <5>, кнопки 1-4 жать не надо :)

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

zebest
03.04.2020, 21:46
чтбы уложится надо делать по другому
ну так этот тест как раз "по-другомуу", для DMA.

https://www.youtube.com/watch?v=dfvYvuKklkY
на 10 сек включаю DMA, скорость заметно вырастает, красная полоска на бордюре - как раз процент "утилизации".
Забавная штука.
ps - эм. а малой кровью нельзя ли сделать, чтобы правая часть не портилась?))
Для теста - то - " и таааааак сойдееет..." (с), но как то неаккуратненько, доктор (с)
upd: а, нее, все, третья реинкарнация мне уже нравиЦЦа.
Заменил видео.
Синий бордюр - обычный режим, Красный бордюр - с включенным ДМА

Upd2: Ыыыыыыыыыыы..
ZEsarUX_win-8.2 ( и ранее) - оказуеЦЦа поддерживает DMA!
Кнопки 1 и 4 - работают более правильно, хоть и не идеально, а 2 и 3 - чет тормозят.
Но это уже Аве Цезаря надо спрашивать.
Так что можете заценить работу ДМА в эмуле.
И да, в Следующем есть то жи ДМА, но то жи свой собственный, "непохожий на других" :)

Ped7g
04.04.2020, 18:42
...

I did answer to your private message here, but now I did notice the zx-pk.ru site writes something about your inbox being full, so I'm not sure if the answer was delivered, let me know... (I hope it was, because I don't have copy of it, and it was quite long answer ... :D ).

Systems using original Zilog DMA chip (or similar interface, like zxnDMA) are a bit more difficult to set up than `ldir`, especially the first-time init, but they can be configured to do 2+2 T-state transfers, so 4T per byte beats easily even ZX pop+push trick for memory transfer (or unrolled `ldi` block) for any transfer longer than 20-30 bytes. (and once you know the state of DMA chip, you can shorten the init sequence a lot, for second+ transfer)

(too lazy to provide example, but my DMA tests for Zilog DMA and zxnDMA are public: https://github.com/MrKWatkins/ZXSpectrumNextTests
(look for Tests/Misc/ for two Zilog DMA tests, and Tests/Base/DMA/ for zxnDMA (ZX Next) test).

zebest
07.04.2020, 22:19
Systems using original Zilog DMA chip (or similar interface, like zxnDMA) are a bit more difficult to set up than `ldir`, especially the first-time init, but they can be configured to do 2+2 T-state transfers, so 4T per byte beats easily even ZX pop+push trick for memory transfer (or unrolled `ldi` block) for any transfer longer than 20-30 bytes. (and once you know the state of DMA chip, you can shorten the init sequence a lot, for second+ transfer)

Спасибо, твои рассказы про различные DMA (железные - Z8410, Z84C10, и не очень - zxnDMA) - мне очень понравились. Для общего развития . У меня же еще одна реинкарнацийя, отличная от всех вышепоименованных :-)

Соль в том, что к той реинкарнации, с которой имейю дело я - совершенно нет никакой документации. Ноль, нет , даже так - 0/0.:v2_dizzy_botan:
За три года автор так и не удосужился хоть что-то описать, есть две с половиной программы, хорошо что в исходниках :) Так же написанные три года назад. Все. Любитесь как хотите. Желающих похоже не нашлось. на тот же Следующий вон тоже пара-тройка программ есть, но там видимо хоть ман-ы есть.
Вобщем у меня как всегда, что бы не делал - получается фигня на бордюре :))
https://s.micp.ru/Pkdv2.jpg

С бордюром при ДМА все гораздо веселее. Напоминаю, в стандартном Спеки условная минимальнайя "точка" 12 тактов, или 24 pix, в лучшем случае, как делаю я, или 16 тактов (32 pix), как делал Великий VNN.
Тут интереснее, вывод в порт ровно 4 такта, итого 8 pix, что в 3 раза интереснее. Результат - выше.
Это в режиме zx48, в режиме Пятногона потом поэксперементирую :)
Файл не прилагаю, ибо в том эмуле от Тцезаря если mem=>mem хоть как то работает, то mem=> I/O не работает почти никак, отлаживать невозможно подделки).

https://www.youtube.com/watch?v=Ga8jhR1siZc&feature=youtu.be

ALKO
13.04.2020, 10:31
А я всё сижу в печали, так как обделён программиздскими навыками.

Всё думу думаю, как бы совокупить компрессор и плавные переходы (скролл из-за краёв экрана).

Конечно можно забить на всё, сделать банальное слайдшоу, как это было в Myst. Но это некрасивое уродство. Спек должен превосходить Макинтоша/ДОСа.

Bedazzle
13.04.2020, 11:20
Всё думу думаю, как бы совокупить компрессор и плавные переходы (скролл из-за краёв экрана).


А что декомпрессировать нужно?

ALKO
13.04.2020, 12:06
.А что декомпрессировать нужно?

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

Lethargeek
13.04.2020, 19:13
ALKO, чем тебя не устраивает распаковка в буфер и потом переброс из буфера на экран?
можешь даже в буфер распаковать и держать там сразу всю панораму, разбивая как удобнее для тебя

ALKO
13.04.2020, 20:00
ALKO, чем тебя не устраивает распаковка в буфер и потом переброс из буфера на экран?
можешь даже в буфер распаковать и держать там сразу всю панораму, разбивая как удобнее для тебя

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

Evgeny Muchkin
13.04.2020, 20:45
ALKO, это уже дизайнерские измышления :)

Destr
13.04.2020, 21:51
Вот мысля пришла, как-бы переделать dehrust чтоб он распаковывал не всё сразу, а поэтапно.
Вызвали call dehrust - он распаковал часть (ну допустим там 5 нулей подряд) и ret
Потом ещё раз - он следущий кусок.
И так до победного...
Давно уже помышляю поковырять, но уж больно там мудрено...

shurik-ua
27.04.2020, 22:07
задача:
есть координаты X, Y в диапазоне от 0 до 0xffff,
какая формула нужна чтобы найти длину между двумя произвольными точками с такими координатами ?
можно на паскале, С, не обязательно асм

NEO SPECTRUMAN
27.04.2020, 22:41
длина вектора же :v2_dizzy_facepalm:
sqr(x^2 + y^2)

чтоб получить вектор x,y из координат x1,x2,y1,y2
вычти из большего x меньший x
и из большего y меньший y

shurik-ua
27.04.2020, 22:42
забыл добавить - всё это нужно для целых чисел
существует ли такая формула без извлечения корня ?

NEO SPECTRUMAN
27.04.2020, 22:49
забыл добавить - всё это нужно для целых чисел
существует ли такая формула без извлечения корня ?
врятли
уточняй для каких задач это нужно
и с какой точностью

shurik-ua
27.04.2020, 22:54
это для радара для одной древней игры, точность ну +-2 или даже +-5 хватит
можно в принципе и с флоатами сделать - но конвертить придётся туда обратно - попробую погуглить на тему sqrt в целых числах.

Titus
27.04.2020, 23:05
sqrt в целых числах.
Корень в целых числах, тем более приближенный, считается элементарно.
Например, побитно.

shurik-ua
27.04.2020, 23:11
я примерно так и полагал - найти номер самого старшего бита, а затем взять нижнюю половину бит как результат -

NEO SPECTRUMAN
27.04.2020, 23:12
тоже самое только с логарифмами :)
возможно с ходу ошибки
щас проверю



logx = log(x)
logy = log(y)

a = (logx + logx)
b = (logy + logy)

c = (((a-b)+1)+b)

l = длина вектора

l = 10 ^ (((c))/2)
или
l = 10 ^ (((c))-(log(2)))
или
l = 10 ^ (((c))-0.3010)

или :)

l = 10 ^ ((((((logx + logx)-(logy + logy))+1)+(logy + logy)))-0.3010)
может можно сократить


с ходу не осилил :)
вот рабочее


после того как нашли вектор x y
x=3
y=4

sqr(3^2 + 4^2) = 5


logx = log(x)
logy = log(y)

logx = log(3)=0.4771
logy = log(4)=0.6020

a = (logx + logx)
b = (logy + logy)
a = (0.4771 + 0.4771) = 0.9542
b = (0.6020 + 0.6020) = 1.204

c = ((log(10 ^ (a-b)) + 1)+b)
c = ((log(10 ^ (0.9542-1.204)) + 1)+1.204) = 1.3979



l = длина вектора

l = 10 ^ (c/2)
l = 10 ^ (1.3979/2) = 4.9997 Ok

оно же
l = 10 ^ (((log(10 ^ ((logx + logx)-(logy + logy))) + 1)+(logy + logy))/2)

знать бы как инкриментить в логарифмах
можно было бы упростить

shurik-ua
27.04.2020, 23:44
у нас же логарифм с основанием 2 - ну и целые числа должны быть.

NEO SPECTRUMAN
27.04.2020, 23:46
ну и целые числа должны быть.
целые числа легким движением руки превращаются в числа с фиксированной запятой...


у нас же логарифм с основанием 2
да хоть натуральный
роли не играет

shurik-ua
27.04.2020, 23:55
целые числа легким движением руки превращаются в числа с фиксированной запятой...

но конвертить придётся туда обратно
этого как раз и хочется избежать

NEO SPECTRUMAN
28.04.2020, 00:04
а зачем туда обратно?

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


для одной древней игры,
а на сколько древняя игра?\на чем?
2 128К таблицы не катит? (^2 и корень)
для нормального вычисления sqr(x^2+y^2)?

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

или это на спектрумах?
хотя так же можно и на спектрумах

shurik-ua
28.04.2020, 00:13
это на ПЦ - онлайн игра начала нулевых Dark age of Camelot
да таблицами пожалуй будет самое то )

NEO SPECTRUMAN
28.04.2020, 01:05
тут немного прикинул
не самое то
чтоб уместить результат таблицы 2-й степени его нужно будет поделить на 65535
https://jpegshare.net/images/4a/e8/4ae8b41d35c7b5d6ff77f6cc4123c74c.png
в итоге длин меньше 300 не будет находиться вообще

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

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

по моей извращенной формуле

l = 10 ^ (((log(10 ^ ((logx + logx)-(logy + logy))) + 1)+(logy + logy))/2)
на оборот будет высокая точность на маленьких дистанциях
ну и так же понадобятся 2 128К таблицы (logx и a^x)
+куча сложений и вычитаний

shurik-ua
28.04.2020, 01:06
там нужно меньше - максимальная длина при которой сервер шлёт пакет о другом игроке где-то примерно 6000

NEO SPECTRUMAN
28.04.2020, 02:32
кстате на предыдущей картинке ошибка
для диагонали ФФФФхФФФФ цифры наверно еще в 2 раза хуже
я не учел что значения сумируются
и именно сумма не должна превышать FFFF
а не отдельное значение


там нужно меньше - максимальная длина при которой сервер шлёт пакет о другом игроке где-то примерно 6000
так делитель 1099 (забыл поменять надпись 550 которая в расчетах не участвует)
https://jpegshare.net/images/96/dc/96dc4da15ab924bb4ff6ba65f85b287f.png
длину меньше 40 не определить

так что логарифмы наше все :)

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

А угол известен по которому нужно определить длину?

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


существует ли такая формула без извлечения корня ?
можно другими способами

можно считать тангенс угла y/x
и сумму x+y по модулю
а потом по таблице по тангенсу угла находить множитель или делитель для (x+y)
который скорректирует значение

зеленные значения правильный результат
https://jpegshare.net/images/d5/d5/d5d5f2a84b8134e459f262786319e73c.png

итого деление, сложение, 128К таблица и умножение (если есть 16b*16b=32b)

я как то так делал коррекцию для вульфа (как именно уже не помню)
тк у меня длина по диагонали была с искажениеми
и ее нужно было дополнительно корректировать

так же вот нашел еще (если что гипотенуза это длина вектора %) )
https://profmeter.com.ua/communication/learning/course/course7/lesson1083/?LESSON_PATH=456.486.544.1083
можно идти по длинному пути
находить тангенс(деление)
находить угол (брать арктангенс(таблица))
брать синус(таблица)
и делить y на этот синус :)

еще может как то можно через теорему синусов

shurik-ua
28.04.2020, 02:59
можно идти по длинному пути
находить тангенс(деление)
находить угол (брать арктангенс(таблица))
брать синус(таблица)
и делить y на этот синус
ужос )

IgorR76
28.04.2020, 03:07
задача:
есть координаты X, Y в диапазоне от 0 до 0xffff,
какая формула нужна чтобы найти длину между двумя произвольными точками с такими координатами ?
можно на паскале, С, не обязательно асм
Формула—теорема Пифагора. Надеюсь, помните. Для извлечения корня с произвольной точностью есть алгоритм:

NEO SPECTRUMAN
28.04.2020, 03:17
надо будет проверить



кстате вот наглядная картинка по теореме синусов
но вычисление тоже наверно будет по длинному пути
даже не буду выводить
https://planetcalc.ru/users/2/1282213319.jpg
https://planetcalc.ru/cgi-bin/mimetex.cgi?%5Cfrac%7Ba%7D%7Bsin%20%5Calpha%7D%3D% 5Cfrac%7Bb%7D%7Bsin%20%5Cbeta%7D%3D%5Cfrac%7Bc%7D% 7Bsin%20%5Cgamma%7D

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


Формула—теорема Пифагора. Надеюсь, помните. Для извлечения корня с произвольной точностью есть алгоритм:
присмотрелся
НЕ КАТИТ
получается много делений на каждый шаг

сходу решил что все время деление на 0,5
так бы это было быстро

shurik-ua
28.04.2020, 03:20
Для извлечения корня с произвольной точностью есть алгоритм:

то что надо - и точность можно устанавливать )


получается много делений на каждый шаг

деление не проблема.

NEO SPECTRUMAN
28.04.2020, 03:47
ида оно работает
https://jpegshare.net/images/50/19/5019f811e8c7b2efb899b4f29d6ff7c2.png
но шагов нужно много

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


то что надо - и точность можно устанавливать )
и 8 делений нужно :)

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

чем больше значение на входе
тем больше шагов нужно
https://jpegshare.net/images/3f/45/3f457ab2a230c462ff0e9c0c0534d3af.png
для получения нужного +-
хотя в процентном соотношении наверно все нормально
нет не нормально смотрим на 8 шаг
значение в 30 раз больше чем надо

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

а вот имитация целочисленных расчетов
на вид не плохо
я думал будет намного хуже
https://jpegshare.net/images/78/75/7875f22217fb6c4d0c376f084bcd0375.png

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

интересно 10 делений и 2 умножения
быстрей чем 1 деление 1 умножение и 1 промах кеша :)

Reobne
28.04.2020, 04:11
shurik-ua, Иногда извлекать корень вообще не нужно. Например, когда расстояние сравнивается с некоторой константой. Просто сравниваем квадрат расстояния с квадратом этой константы.

shurik-ua
28.04.2020, 04:57
Просто сравниваем квадрат расстояния с квадратом этой константы.
вот жеж - о настолько элементарном я даже и не подумал ) - задача стоит ровно такая - нужно определять для каждого игрока поблизости попадает ли он в радиус действия скила или нет.

спасибо всем откликнувшимся - задача для меня решена )

Sayman
28.04.2020, 06:49
а чем не нравятся такие варианты?:


Первый способ - расстояние от Px, Py до
конечной точки Ex, Ey = sqrt ( (Px-Ex)^2 +
+ (Py-Ey)^2 ). Этот способ неудобен тем,
что много медленных операций - два умноже-
ния и взятие квадратного корня.
Второй способ - расстояние = abs (Px -
Ex)/cos(a) = abs (Py - Ey)/sin(a), где a =
угол луча. Этот способ удобнее тем,что та-
бличку косинуса и синуса можно посчитать
заранее,а из медленных операций - одно де-
ление.

плюс квадраты можно через логорифмы высчитывать (+табличка). вообще не вижу глобального замысла считать всё честно. таблички (ТАБЛИЧКИИИ).

NEO SPECTRUMAN
28.04.2020, 15:23
а чем не нравятся такие варианты?:
тем что оба способа уже обсудили :v2_dizzy_facepalm:

Reobne
29.04.2020, 04:36
спасибо всем откликнувшимся - задача для меня решена )
:)
Ещё, на всякий случай, озвучу такую мысль:
Можно попробовать оптимизировать. Перед тем как вычислять сумму квадратов разностей, то есть попадание в окружность, можно сразу отсеять то, что не попадает в описанный квадрат. Как бы:
DX:=abs(x1-x2);
IF DX>R THEN EXIT;
DY:=abs(y1-y2);
IF DY>R THEN EXIT;
IF SQR(DX)+SQR(DY)>R2 THEN EXIT;

shurik-ua
29.04.2020, 05:29
да про это я подумал



function in_range(x1,y1,x2,y2,range: dword):boolean;
var
dx,dy: dword;
begin
result:=false;
if x1>x2 then dx:=x1-x2
else dx:=x2-x1;
if dx > range then exit;
if y1>y2 then dy:=y1-y2
else dy:=y2-y1;
if dy > range then exit;
if (range*range) > dx*dx + dy*dy then result:=true;
end;

LW
29.04.2020, 09:33
забыл добавить - всё это нужно для целых чисел
существует ли такая формула без извлечения корня ?

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

гипотенуза = maxКатет + 0.41 * minКатет (насколько помню, погрешность около 5%)

либо другой вариант, точнее, но и затратнее по тактам

гипотенуза = maxКатет + 0.428 * minКатет * minКатет / maxКатет (погрешность около 1%)

ALKO
01.05.2020, 12:05
Хотел спросить по табличкам SIN-COS вращения относительно игрока.


https://youtu.be/fagmxBesv5w

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

blackmirror
01.05.2020, 12:53
Окружности скорее всего рисуются вообще без всяких таблиц. А если синусов и косинусов считать нужно много, значит в табличках должны быть указатели на функции которые будут выполнять умножение радиуса на константу соответствующую синусу заданного угла. Это как таблица из 256 функций выполняющих умножения на всевозможные значения байта, только ячейки вне заполнены так, чтобы умножение происходило на значения синуса.

ALKO
01.05.2020, 14:05
Окружности скорее всего рисуются вообще без всяких таблиц.

Я имею ввиду окружности позиционирования объектов относительно игрока.

LW
02.05.2020, 22:32
А собственно зачем их хранить?
В игровом пространстве объекты перемещаются согласно своему алгоритму, игрок перемещается так вообще непредсказуемо.
Всё это рассчитывается из координат объекта и игрока.

ALKO
05.06.2020, 09:15
Решился наконец-то на покорение 128к формата.
По крайней мере теневой экран удалось заюзать.
Но в итоге доступной памяти стало на 16кб меньше, ибо переключаемую банку только для экрана и использую каждый кадр. Поэтому пришлось и стэк переместить, и своих данных туда уже не затолкать (разве что дублировать на обе банки)
И вот назрел вопрос, как затолкать графику в виде DEFB массивов хотя бы в остальные банки?
Org ведь не может превышать 65535
Да и как её потом оттуда извлекать?

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


А собственно зачем их хранить?
В игровом пространстве объекты перемещаются согласно своему алгоритму, игрок перемещается так вообще непредсказуемо.
Всё это рассчитывается из координат объекта и игрока.

В игровом пространстве многое предсказуемо, даже псевдо-рандом.

Зачем их хранить? Во благо скорости, разумеется.


перемещаются согласно своему алгоритму
И это отрицает тот факт, что многие алгоритмы (особенно на спеке) опираются на табличные значения?
Даже прыжки марио, и те прекалькулированы.

Destr
05.06.2020, 13:17
И вот назрел вопрос, как затолкать графику в виде DEFB массивов хотя бы в остальные банки?
Org ведь не может превышать 65535
Обычно компилятор понимает такое:


Page n ; n=номер нужной страницы
org #c000 ; начало страничной области
incbin "graphic.scr" ; ну или твои DEFB


Потом или вернуть страницу (и ORG) куда надо или просто ставить эту конструкцию в конце листинга кода...

ALKO
05.06.2020, 14:09
Чем больше представляю себе грядущий гемор, тем больше хочется вернуться в блаженные 48к.
Тут же в распоряжении лишь одно активное окно, которое и в роли фрейм-буфера, и в роли хранилища данных... Ух. Сложновато.
Наверное погорячился я с тем, что сунулся в эти дебри.

NEO SPECTRUMAN
06.06.2020, 18:54
А собственно зачем их хранить?

в принципе их вполне момжно и хранить

нужно всего 8 штук (каких то 2К)
sin*1
sin*2
sin*4
sin*8
sin*16
sin*32
sin*64
sin*128

далее просто складывая 8 комбинаций
можно будет получить 256 вариантов синуса помноженного на 0...255 с достаточной точностью

sin*1 можно вообще упустить
изза малой значимосте...

Rubts0FF
08.06.2020, 11:15
Я иногда забываю и заглядываю в этот раздел, и раз уж сегодня снова забыл и заглянул, хочу задать пару вопросов которые давно, очень давно, хотел задать.
Какое отношение вот все то что на последних страницах .., десятках страниц, имеет к "ЭТЮДАМ" и к ZX Spectrum программированию вообще. Да, подобные обсуждения нужны и важны, но все же не здесь. Здесь хотелось бы видеть готовые "этюды".
Вопрос риторический.

NEO SPECTRUMAN
08.06.2020, 11:20
who cares?

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

и чем те не этюды?
кто то ставит задачу
а другие пытаются найти для оно решение

Shadow Maker
08.06.2020, 12:31
Я иногда забываю и заглядываю в этот раздел, и раз уж сегодня снова забыл и заглянул, хочу задать пару вопросов которые давно, очень давно, хотел задать.
Какое отношение вот все то что на последних страницах .., десятках страниц, имеет к "ЭТЮДАМ" и к ZX Spectrum программированию вообще. Да, подобные обсуждения нужны и важны, но все же не здесь. Здесь хотелось бы видеть готовые "этюды".
Вопрос риторический.
Да не то чтобы риторический. Я просто сначала думал разделить, потом подумалось, что если одни готовые Этюды хранить - люди не будут вступать в дискуссию (будут пользоваться просто как справочником) и в итоге тема заглохнет - новых задач нет, никто ничего не спрашивает и не предлагает. Так и оставил как есть.

shurik-ua
08.06.2020, 12:37
я рассматриваю Этюды как виртуозное владение языком программирования (не важно каким)
главное чтоб было кратко и практично

Rubts0FF
10.06.2020, 18:05
Да не то чтобы риторический. Я просто сначала думал разделить, потом подумалось, что если одни готовые Этюды хранить - люди не будут вступать в дискуссию (будут пользоваться просто как справочником) и в итоге тема заглохнет - новых задач нет, никто ничего не спрашивает и не предлагает. Так и оставил как есть.

Так то оно так, только тема "Этюды" не заглохла, а её забили .. . Обычно для однотипных задач используются одни и те же подпрограммы, процедуры. Как то понадобился .., не помню если честно, то ли очистка экрана через PUSH, то ли пиксельная прокрутка экрана, захотелось глянуть на готовые решения, заглянул. А здесь черт ногу .., и что в общем плохого в справочнике? Как по мне это и должен быть справочник, точнее библиотека мелких и не только подпрограмм. Обсуждения - можно и нужно, но сейчас это больше напоминает философские споры, к программированию на ZX Spectrum имеют очень далекое отношение.

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


и чем те не этюды?
Этюды - это готовые решения, без задач. А здесь флудилка.

NEO SPECTRUMAN
10.06.2020, 18:27
Этюды - это готовые решения, без задач. А здесь флудилка.
этюд это УПРАЖНЕНИЕ на развитие техники
или нечто, что используется в качестве него

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

не вижу проблем

Shadow Maker
10.06.2020, 19:31
Так то оно так, только тема "Этюды" не заглохла, а её забили .. . Обычно для однотипных задач используются одни и те же подпрограммы, процедуры. Как то понадобился .., не помню если честно, то ли очистка экрана через PUSH, то ли пиксельная прокрутка экрана, захотелось глянуть на готовые решения, заглянул. А здесь черт ногу .., и что в общем плохого в справочнике? Как по мне это и должен быть справочник, точнее библиотека мелких и не только подпрограмм. Обсуждения - можно и нужно, но сейчас это больше напоминает философские споры, к программированию на ZX Spectrum имеют очень далекое отношение.
Это форум же, здесь разговаривают... Тебе видимо сюда http://zxdn.narod.ru/

Rubts0FF
11.06.2020, 10:38
Вопрос риторический.
!

Andrew771
12.06.2020, 11:37
Тебе видимо сюда http://zxdn.narod.ru/
жалко, что не обновляется давно. А так сайт супер, я многое оттуда брал.