СПРАЙТ КСОРАМИ
дальше нужно раскрыть цикл for (y = 0; y != vsizey; y++), что даст 8 блоков по 16 вызовов конкретного сдвига линии (call draw_sprite16_line<сдвиг>).
как считать адрес на экране по Y (накидал что смог придумать):
0) всегда считать заново
1) пересчитывать инкрементально (в смысле не с нуля)
2) заранее определить специфику адреса и чётко располагать нужные операции
3) определить таблицу адресов каждого Y на экране: 192*2 = 384.
x) может что-то смеженное, где как-то замостить вызовы в цикле, может до кратности 8 линий, потом считать адрес заново...
2) кажется совсем нереальном, потому что специфика экрана слишком сложная
0) на вскидку, если требуется случайный адрес получить, даже быстрее его посчитать. но последовательно, исходя из того что у меня получилось, лучше таблица.
1) если бы было последовательное заполнение по знакоместам, там что-то можно было бы придумать. x + 32 давал бы переполнение через 7 в старшем байте... ([b]вот тут я похоже и погнал, не знаю что меня дёрнуло[/b])
3) беру
раскрыл я одну функцию и понял, что это уже никуда не годится. нет смысла
вызывать отрисовку линий не в цикле, ведь (в моей реализации, конечно).
средняя сложность отрисовка линии спрайта 16x16 в t-states
l = (70+149+185+201+217+201+185+149) / 8
общий размер отрисовки линий спрайта 16x16
b = 11+28+38+42+46+42+38+28
вызов отрисовки линии в цикле по Y:
142 + 10 + (91+l) * 16 = 4322 t-states (в среднем на спрайт)
(20 + 1 + 19) * 8 + b = 593 bytes (всего)
раскрытие по Y с вызовом отрисовки линии:
135 + (77+l)*16-6 = 4075
(18 + 15*16 - 1) * 8 + b = 2329
тело отрисовки линии в цикле по Y:
142 + 10 + (91-17-10+l) * 16 = 3890
(20 + 1 + 19-3) * 8 + b - 1*8 = 561
раскрытие по Y с встраиванием тела отрисовки линии
...
ну тут понятно, что даже второй вариант уже избыточен. в третьем убирается вызов (call/ret), со встраиванием тела отрисовки линии, и накладные на loop уже компенсируются.
(для наглядности вариант "вызов отрисовки линии в цикле по Y"):
.globl _draw_sprite16_lines0
_draw_sprite16_lines0:
exx
pop hl
pop de
pop bc
push bc ; pspr
push de ; x, y
push hl ; addr
push bc
ld b,#0x00
ld c,e
ld hl,#_gl_scryaddr
add hl,bc
add hl,bc
exx
pop bc
ld d,#0x10
;; hl` = pscryaddr
;; bc` = tmp
;; de` = x, y
;; hl = *pscryaddr + x
;; bc = pspr
;; de = counter, tmp
l_16_0: ;; l_16_1 ...
exx
ld a,d
or a,(hl)
inc hl
ex af,af
ld a,(hl)
inc hl
exx
ld h,a
ex af,af
ld l,a
call _draw_sprite16_line0 ;; _draw_sprite16_line1 ...
inc bc
dec d
jp nz,l_16_0 ;; jp nz,l_16_1 ...
ret
void draw_sprite2(int vpos_x, int vpos_y, int vsizex, int vsizey) {
if (vsizex != 16 && vsizey != 16) {
draw_sprite(vpos_x, vpos_y, vsizex, vsizey);
}
switch (vpos_x & 7) {
case 0: draw_sprite16_lines0(vpos_x>>3<<8 | vpos_y, SPRITE(0, 0)); break;
case 1: draw_sprite16_lines1(vpos_x>>3<<8 | vpos_y, SPRITE(0, 0)); break;
case 2: draw_sprite16_lines2(vpos_x>>3<<8 | vpos_y, SPRITE(0, 0)); break;
case 3: draw_sprite16_lines3(vpos_x>>3<<8 | vpos_y, SPRITE(0, 0)); break;
case 4: draw_sprite16_lines4(vpos_x>>3<<8 | vpos_y, SPRITE(0, 0)); break;
case 5: draw_sprite16_lines5(vpos_x>>3<<8 | vpos_y, SPRITE(0, 0)); break;
case 6: draw_sprite16_lines6(vpos_x>>3<<8 | vpos_y, SPRITE(0, 0)); break;
case 7: draw_sprite16_lines7(vpos_x>>3<<8 | vpos_y, SPRITE(0, 0)); break;
}
return;
}
сравнение c лобовой реализацией (прерываний на спрайт - отрисовка и очистка):
26/176 = 0.1477~
377/176 = 2.142~
1-4075/70908/(26/176) = 0.61~ процент времени в вышестоящем коде.
https://disk.yandex.com/d/3PmmuihT1kJRkg
(тапка теста + частичный код (без библиотеки и сборщика))