Сообщение Re[4]: Золотое время АйТи от 29.12.2016 13:22
Изменено 29.12.2016 21:34 IID
Здравствуйте, vfedosov, Вы писали:
IID>>Z80 + 41кб памяти + 7кб экран (совершенно маразматической структуры с т.з. программиста) == Wolfenstein с играбельным FPS
V>Структура экрана была не так плоха: при такой структуре для того, чтобы перейти к следующей строке, с сохранением координаты x надо было прибавить к адресу 256 (в большинстве случаев) = инкремент старшего байта адреса, что для 8ми битового проца куда быстрее, чем добавлять 32 (размер строки).
Это, строго говоря, неправда. Т.к. переходить так можно только если младшие 3 бита координаты Y находятся в диапазое [000...110], в случае [111] необходима специальная обработка.
вот как выглядит переход на следующую Y координату в псевдокоде:
На ассемблере:
Скорость выполнения 25/50/65 тактов плюс всегда портится аккумулятор.
V>Это неплохо ускоряло работу со спрайтами, вывод символов.
Это ускоряло ТОЛЬКО вывод символов и ТОЛЬКО в Y позициях кратных 8.
Для спрайтов все делали табличку экранных адресов. И получали адрес нужной Y координаты лукапом в этой табличке. Переход вверх-вниз инкремент-декремент индекса. Табличка типичная для 16 битных адресоов в 8 битках: первые 256 байт это младшие байты, следующие 256 это старшие байты. Лукап змейкой, чтобы сэкономить на паре инкремента-декремента старшего байта. Итого стабильные 7 + 4 + 7 = 18 тактов на получение экранного адреса. Как вариант можно было ставить на табличку стек, и получать адрес за 10 тактов, но так не поступали, потому что выгоднее было стеком забирать данные спрайтов, ведь их больше.
V>Вроде бы и алгоритмы отрисовки линий тоже можно было сделать быстрее, правда тут не уверен.
Нет.
IID>>Z80 + 41кб памяти + 7кб экран (совершенно маразматической структуры с т.з. программиста) == Wolfenstein с играбельным FPS
V>Структура экрана была не так плоха: при такой структуре для того, чтобы перейти к следующей строке, с сохранением координаты x надо было прибавить к адресу 256 (в большинстве случаев) = инкремент старшего байта адреса, что для 8ми битового проца куда быстрее, чем добавлять 32 (размер строки).
Это, строго говоря, неправда. Т.к. переходить так можно только если младшие 3 бита координаты Y находятся в диапазое [000...110], в случае [111] необходима специальная обработка.
вот как выглядит переход на следующую Y координату в псевдокоде:
word IncY(word addr)
{
if (((addr >> 8) & 0x03) < 7)
return addr + 0x100;
if (((addr + 0x20) & 0xFF) < 0x20)
return addr + 0x100;
return addr + 0x20 - 0x700;
} На ассемблере:
; assume screen addr in DE register pair
PROC IncY
inc d
ld a, d
and 7
ret nz ; в реальном коде процедура инланится и тут не возврат а переход jp nz
ld a, e
add a, 0x20
ld e, a
ret c ; в реальном коде процедура инлайнится и тут не возврат а переход jp c
ld a, d
sub 8
ld d, a
ret ; в реальном коде процедура инлайнится и тут внешний кодСкорость выполнения 25/50/65 тактов плюс всегда портится аккумулятор.
V>Это неплохо ускоряло работу со спрайтами, вывод символов.
Это ускоряло ТОЛЬКО вывод символов и ТОЛЬКО в Y позициях кратных 8.
Для спрайтов все делали табличку экранных адресов. И получали адрес нужной Y координаты лукапом в этой табличке. Переход вверх-вниз инкремент-декремент индекса. Табличка типичная для 16 битных адресоов в 8 битках: первые 256 байт это младшие байты, следующие 256 это старшие байты. Лукап змейкой, чтобы сэкономить на паре инкремента-декремента старшего байта. Итого стабильные 7 + 4 + 7 = 18 тактов на получение экранного адреса. Как вариант можно было ставить на табличку стек, и получать адрес за 10 тактов, но так не поступали, потому что выгоднее было стеком забирать данные спрайтов, ведь их больше.
V>Вроде бы и алгоритмы отрисовки линий тоже можно было сделать быстрее, правда тут не уверен.
Нет.
Re[4]: Золотое время АйТи
Здравствуйте, vfedosov, Вы писали:
IID>>Z80 + 41кб памяти + 7кб экран (совершенно маразматической структуры с т.з. программиста) == Wolfenstein с играбельным FPS
V>Структура экрана была не так плоха: при такой структуре для того, чтобы перейти к следующей строке, с сохранением координаты x надо было прибавить к адресу 256 (в большинстве случаев) = инкремент старшего байта адреса,
Это, строго говоря, неправда. Т.к. переходить так можно только если младшие 3 бита координаты Y находятся в диапазое [000...110], в случае [111] необходима специальная обработка.
V>что для 8ми битового проца куда быстрее, чем добавлять 32 (размер строки).
Это тоже неправда. Z-80 умеет в 16 битное сложение и у него достаточно регистровых пар чтобы сделать красивый иннер-луп вида
Добавить 32 к адресу это одно сложение регистровых пар == 11 тактов. Как видно ниже, это быстрее любых других вариантов. И не требует доп. памяти на таблицы.
Учитывая что типичное значение N это 2-3, а количество инкрементов Y порядка 24-32 то экономия получается существенной.
вот как выглядит переход на следующую Y координату в псевдокоде:
На ассемблере:
Скорость выполнения 25/50/65 тактов плюс всегда портится аккумулятор.
V>Это неплохо ускоряло работу со спрайтами, вывод символов.
Это ускоряло ТОЛЬКО вывод символов и ТОЛЬКО в Y позициях кратных 8.
Для спрайтов все делали табличку экранных адресов. И получали адрес нужной Y координаты лукапом в этой табличке. Переход вверх-вниз инкремент-декремент индекса. Табличка типичная для 16 битных адресоов в 8 битках: первые 256 байт это младшие байты, следующие 256 это старшие байты. Лукап змейкой, чтобы сэкономить на паре инкремента-декремента старшего байта. Итого стабильные 7 + 4 + 7 = 18 тактов на получение экранного адреса. Как вариант можно было ставить на табличку стек, и получать адрес за 10 тактов, но так не поступали, потому что выгоднее было стеком забирать данные спрайтов, ведь их больше.
V>Вроде бы и алгоритмы отрисовки линий тоже можно было сделать быстрее, правда тут не уверен.
Нет.
IID>>Z80 + 41кб памяти + 7кб экран (совершенно маразматической структуры с т.з. программиста) == Wolfenstein с играбельным FPS
V>Структура экрана была не так плоха: при такой структуре для того, чтобы перейти к следующей строке, с сохранением координаты x надо было прибавить к адресу 256 (в большинстве случаев) = инкремент старшего байта адреса,
Это, строго говоря, неправда. Т.к. переходить так можно только если младшие 3 бита координаты Y находятся в диапазое [000...110], в случае [111] необходима специальная обработка.
V>что для 8ми битового проца куда быстрее, чем добавлять 32 (размер строки).
Это тоже неправда. Z-80 умеет в 16 битное сложение и у него достаточно регистровых пар чтобы сделать красивый иннер-луп вида
rept N
pop de : ld a, (hl): and e : or d : ld (hl), a : inc l
endr
pop de : ld a, (hl): and e : or d : ld (hl), a
add hl, bc
rept N
pop de : ld a, (hl): and e : or d : ld (hl), a : dec l
endr
pop de : ld a, (hl): and e : or d : ld (hl), a
add hl, bcДобавить 32 к адресу это одно сложение регистровых пар == 11 тактов. Как видно ниже, это быстрее любых других вариантов. И не требует доп. памяти на таблицы.
Учитывая что типичное значение N это 2-3, а количество инкрементов Y порядка 24-32 то экономия получается существенной.
вот как выглядит переход на следующую Y координату в псевдокоде:
word IncY(word addr)
{
if (((addr >> 8) & 0x03) < 7)
return addr + 0x100;
if (((addr + 0x20) & 0xFF) < 0x20)
return addr + 0x100;
return addr + 0x20 - 0x700;
} На ассемблере:
; assume screen addr in DE register pair
PROC IncY
inc d
ld a, d
and 7
ret nz ; в реальном коде процедура инланится и тут не возврат а переход jp nz
ld a, e
add a, 0x20
ld e, a
ret c ; в реальном коде процедура инлайнится и тут не возврат а переход jp c
ld a, d
sub 8
ld d, a
ret ; в реальном коде процедура инлайнится и тут внешний кодСкорость выполнения 25/50/65 тактов плюс всегда портится аккумулятор.
V>Это неплохо ускоряло работу со спрайтами, вывод символов.
Это ускоряло ТОЛЬКО вывод символов и ТОЛЬКО в Y позициях кратных 8.
Для спрайтов все делали табличку экранных адресов. И получали адрес нужной Y координаты лукапом в этой табличке. Переход вверх-вниз инкремент-декремент индекса. Табличка типичная для 16 битных адресоов в 8 битках: первые 256 байт это младшие байты, следующие 256 это старшие байты. Лукап змейкой, чтобы сэкономить на паре инкремента-декремента старшего байта. Итого стабильные 7 + 4 + 7 = 18 тактов на получение экранного адреса. Как вариант можно было ставить на табличку стек, и получать адрес за 10 тактов, но так не поступали, потому что выгоднее было стеком забирать данные спрайтов, ведь их больше.
V>Вроде бы и алгоритмы отрисовки линий тоже можно было сделать быстрее, правда тут не уверен.
Нет.