Просмотр полной версии : Табличка всех вариантов пикселей и аттрибутов
Пытаюсь составить табличку всех вариантов пикселей и аттрибутов.
Получается же 65536 комбинаций? По 4 байта на пиксель. Итого 256 кб табличка.
Но что то не ладится.
For pixels.a = 0 To 255
For attr.a = 0 To 255
Paper = (attr >> 3) & $0F
ink = (attr & 7) | ((attr & 64) >> 3)
bit = 128
For z = 0 To 7
If pixels & bit
color.l = color( ink )
Else
color = color( paper )
EndIf
color.l = $FF000000 | Red(color) << 16 | Green(color) << 8 | Blue(color)
PokeL(attributes_table + (((pixels << 8) | attr )<<2), color )
bit >> 1
Next z
Next attr
Next pixels
color(0) = 0 | 0 << 8 | 0 << 16
color(1) = 0 | 0 << 8 | 180 << 16
color(2) = 180 | 0 << 8 | 0 << 16
color(3) = 180 | 0 << 8 | 180 << 16
color(4) = 0 | 178 << 8 | 0 << 16
color(5) = 0 | 178 << 8 | 180 << 16
color(6) = 180 | 178 << 8 | 0 << 16
color(7) = 180 | 178 << 8 | 180 << 16
color(8) = 0 | 0 << 8 | 0 << 16
color(9) = 0 | 0 << 8 | 252 << 16
color(10) = 252 | 0 << 8 | 0 << 16
color(11) = 252 | 0 << 8 | 252 << 16
color(12) = 0 | 254 << 8 | 0 << 16
color(13) = 0 | 254 << 8 | 252 << 16
color(14) = 252 | 254 << 8 | 0 << 16
color(15) = 252 | 254 << 8 | 252 << 16
Для начала не могу уловить есть ли разница в какой байт класть пикселы, а в какой атрибуты.
Боюсь, что плохо сформулировано, что ты хочешь, зачем и почему.
А так же, что у тебя не так получается относительно того, чего бы ты хотел)
Интересный вриант - http://www.yoyogames.com/blog/89
память спектрума грузится в текстуру и из нее уже рисуется на экран.
Но пока хотелось бы вариант попроще.
- - - Добавлено - - -
Еще немного ускорил:
For adr.l = 0 To 6143*4 Step 4
chr_pixels.l = PeekA(*mem + PeekL(pixels_adress_table + adr) )
chr_attr.l = PeekA(*mem + PeekL(attributes_adress_table + adr) )
CopyMemory( attributes_table + ((((chr_pixels&128) << 8) | (chr_attr))<<2), texture, 4 ):texture + 4
CopyMemory( attributes_table + ((((chr_pixels&64 ) << 8) | (chr_attr))<<2), texture, 4 ):texture + 4
CopyMemory( attributes_table + ((((chr_pixels&32 ) << 8) | (chr_attr))<<2), texture, 4 ):texture + 4
CopyMemory( attributes_table + ((((chr_pixels&16 ) << 8) | (chr_attr))<<2), texture, 4 ):texture + 4
CopyMemory( attributes_table + ((((chr_pixels&8 ) << 8) | (chr_attr))<<2), texture, 4 ):texture + 4
CopyMemory( attributes_table + ((((chr_pixels&4 ) << 8) | (chr_attr))<<2), texture, 4 ):texture + 4
CopyMemory( attributes_table + ((((chr_pixels&2 ) << 8) | (chr_attr))<<2), texture, 4 ):texture + 4
CopyMemory( attributes_table + ((((chr_pixels&1 ) << 8) | (chr_attr))<<2), texture, 4 ):texture + 4
Next adr
Получается же 65536 комбинаций? По 4 байта на пиксель. Итого 256 кб табличка.
65536 комбинаций. По 8 пикселей в комбинации. По 4 байта на пиксель. Итого 2Мб табличка.
blackmirror
02.10.2016, 18:48
Зачем только сразу делать по 32 бита на точку? Чем плохо 16 цветов с палитрой? Можно сразу вычислять по 8 точек пользуясь 1(только для pixels) или 3(еще для paper и delta) таблицами на 256 элементов и это будет быстрее чем копировать по 32 байта. В таблице mask каждый бит индекса просто дублируется по 4 раза, то есть если на входе 011000100b, в ячейке должна лежать маска 0FF000F00h.
uint32 Paper = ((attr >> 3) & $0F )*$11111111
uint32 delta = ((attr&7) ^ (attr >> 3) & $0F )*$11111111
result=paper^(delta&mask[pixels])
Зачем только сразу делать по 32 бита на точку?
Потому что такой формат текстуры выбран в OpenGL. (по привычке)
Сейчас погуглил, для спектрума можно наверное и GL_R3_G3_B2 обойтись.
Можно сразу вычислять по 8 точек пользуясь 1(только для pixels) или 3(еще для paper и delta) таблицами на 256 элементов и это будет быстрее чем копировать по 32 байта. В таблице mask каждый бит индекса просто дублируется по 4 раза, то есть если на входе 011000100b, в ячейке должна лежать маска 0FF000F00h.
Ничего не понял )
blackmirror
02.10.2016, 21:52
newart, чтобы выполнить преобразование нужно из атрибутов вычислить какого цвета должен быть paper, вычислить какого цвета ink, сделать xor между paper и ink чтобы получить delta. Далее все 8 точек красим в цвет paper (delta тоже копируется в 8 точек, или можно и то и другое сразу вытащить из таблицы), из таблицы на 256 элементов вытаскиваем маску для точек которые нужно перекрасить в цвет ink, делаем побитовое and с delta и затем хоr c paper, в итоге точки которые должны быть цвета ink будут перекрашены. Если использовать GL_R3_G3_B2, значит в каждом элементе таблицы будет по 8 байт, причём в таблице масок байты будут только 00 и FF, а для других таблиц байты в пределах 1 элемента будут одинаковые.
У меня получается 128 (вариантов атрибутов) * 256 значений (байт сразу) * 2 байта на пиксель (16 битный цвет) = 65536 байт.
FLASH я делаю отдельно, инвертирую байт пикселей.
На соседнем форуме один фанат ретрокомпо накатал версию под SSE2. Получилось весьма шустро. Дает на 5-10 fps больше чем мой вариан
Вдруг кому пригодится:
; ZXScreen module by Wilbert
; *SCR has to be 6912 bytes of ZX Spectrum screen
; *Target has to be a buffer for 32 bit color data
; When FlashState is set to 1, pen and ink will be
; switched for blocks that have the flash bit set.
DeclareModule ZXScreen
Declare RenderSCR(*SCR, *Target, FlashState = 0)
EndDeclareModule
Module ZXScreen
#FlipY = #True
#SwapRB = #True
EnableExplicit
DisableDebugger ; disabling debugger is required !!
EnableASM
;- Data section
DataSection
ColorLUT:
Data.l $ff000000,$ffc03020,$ff1040c0,$ffc040c0,$ff10b040, $ffb0c050,$ff10c0e0,$ffc0c0c0
Data.l $ff000000,$ffff4030,$ff3040ff,$fff070ff,$ff10e050, $ffffe050,$ff50e8ff,$ffffffff
EndDataSection
;- Structures
Structure RenderLUT
bit_expand.l[256 * 8] ; offset 0
color.l[256 * 2] ; offset 8192
offset.u[768] ; offset 10240
EndStructure
;- Global variables
Global *Mem, *RenderLUT.RenderLUT
;- Init lookup table
Procedure SwapRB(color.l)
!mov eax, [p.v_color]
!bswap eax
!ror eax, 8
ProcedureReturn
EndProcedure
Procedure InitTable()
Protected.i bit, col, i, ink, paper, row
If Not *RenderLUT
*Mem = AllocateMemory(SizeOf(RenderLUT) + 32)
*RenderLUT.RenderLUT = (*Mem + 31) & -32
For i = 0 To 255
If i & $80
ink = (i >> 3 & 15) : paper = (i >> 3 & 8) | (i & 7) ; flash
Else
paper = (i >> 3 & 15) : ink = (i >> 3 & 8) | (i & 7) ; normal
EndIf
CompilerIf #SwapRB
*RenderLUT\color[i << 1 ] = SwapRB(PeekL(?ColorLUT + paper << 2))
*RenderLUT\color[i << 1 + 1] = SwapRB(PeekL(?ColorLUT + ink << 2))
CompilerElse
*RenderLUT\color[i << 1 ] = PeekL(?ColorLUT + paper << 2) ; paper
*RenderLUT\color[i << 1 + 1] = PeekL(?ColorLUT + ink << 2) ; ink
CompilerEndIf
Next
For row = 0 To 7
For col = 0 To 31
*RenderLUT\offset[row << 5 | col] = row << 5 | col
*RenderLUT\offset[row << 5 | col | 256] = row << 5 | col | 2048
*RenderLUT\offset[row << 5 | col | 512] = row << 5 | col | 4096
Next
Next
For i = 0 To 255
For bit = 0 To 7
If i & ($80 >> bit)
*RenderLUT\bit_expand[i << 3 | bit] = -1
EndIf
Next
Next
EndIf
EndProcedure
InitTable()
;- Main code
CompilerIf #PB_Compiler_Processor = #PB_Processor_x86
Macro rax : eax : EndMacro
Macro rbx : ebx : EndMacro
Macro rcx : ecx : EndMacro
Macro rdx : edx : EndMacro
Macro rsi : esi : EndMacro
Macro rdi : edi : EndMacro
Macro rsp : esp : EndMacro
CompilerEndIf
Macro M_8x1(line)
!movzx eax, byte [rsi + rbx + line*256] ; get bits
!shl eax, 5
!movdqa xmm0, [rdx + rax] ; expand every bit to 32 bits
!movdqa xmm1, [rdx+16 + rax] ; expand every bit to 32 bits
!pand xmm0, xmm3
!pand xmm1, xmm3
!pxor xmm0, xmm2
!pxor xmm1, xmm2
CompilerIf #FlipY
!movdqu [rdi + (7-line)*1024], xmm0
!movdqu [rdi+16 + (7-line)*1024], xmm1
CompilerElse
!movdqu [rdi + line*1024], xmm0
!movdqu [rdi+16 + line*1024], xmm1
CompilerEndIf
EndMacro
Procedure RenderSCR(*SCR, *Target, FlashState = 0)
FlashState = (FlashState << 7) ! $7f
; backup registers without push
; so references to local variables stay valid
mov [rsp - 8], rbx
mov [rsp - 16], rsi
mov [rsp - 24], rdi
; load registers
mov rdx, *RenderLUT
mov rsi, *SCR
mov rdi, *Target
CompilerIf #FlipY
add rdi, 188416
CompilerEndIf
; block loop
!xor ecx, ecx ; ecx = counter (0 - 767)
!.block_loop:
movzx eax, byte [rsi+6144 + rcx] ; get attributes of block
!and eax, [p.v_FlashState]
movq xmm0, [rdx+8192 + rax*8]
!pshufd xmm2, xmm0, 00000000b ; paper
!pshufd xmm3, xmm0, 01010101b ; ink
!pxor xmm3, xmm2
movzx ebx, word [rdx+10240 + rcx*2] ; get block offset
M_8x1(0) ; block line 0
M_8x1(1) ; block line 1
M_8x1(2) ; block line 2
M_8x1(3) ; block line 3
M_8x1(4) ; block line 4
M_8x1(5) ; block line 5
M_8x1(6) ; block line 6
M_8x1(7) ; block line 7
add rdi, 32
!inc ecx
!test ecx, 31 ; new row check
!jnz .block_loop
CompilerIf #FlipY
sub rdi, 9216
CompilerElse
add rdi, 7168
CompilerEndIf
!cmp ecx, 768
!jne .block_loop
; restore registers
mov rdi, [rsp - 24]
mov rsi, [rsp - 16]
mov rbx, [rsp - 8]
EndProcedure
EndModule
blackmirror
03.10.2016, 21:48
На соседнем форуме один фанат ретрокомпо накатал версию под SSE2. Получилось весьма шустро. Дает на 5-10 fps больше чем мой вариан
Только у него 2Мб таблиц нету, ему хватает таблиц по 256 элементов - отдельно для точек и отдельно для атрибутов.
Только у него 2Мб таблиц нету, ему хватает таблиц по 256 элементов - отдельно для точек и отдельно для атрибутов.
Ну да.
Но и его вариант наверное можно ускорить, сравнивая два кадра и пропуская байты, которые не изменились.
Довольно редко в картинке меняются все 6912 байт. Правда вариант не очень удобный из-за лишнего буффера.
Powered by vBulletin® Version 4.2.5 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot