2153 lines
56 KiB
PHP
2153 lines
56 KiB
PHP
iglobal
|
|
places db 6,0,0,0,0,0,0
|
|
|
|
dark dd 0
|
|
lite dd 0ffffffH
|
|
unus dd 02H
|
|
ddat dd 01H
|
|
ldat dd 0fffffeH
|
|
resr dd 0fffffdH
|
|
endg
|
|
|
|
|
|
uglobal
|
|
version DD 1 DUP (?)
|
|
mode DD 1 DUP (?)
|
|
maxcodewords DD 1 DUP (?)
|
|
eclevel DD 1 DUP (?)
|
|
maskpattern DD 1 DUP (?)
|
|
size DD 1 DUP (?)
|
|
size2 DD 1 DUP (?)
|
|
genpoly DB 32 DUP (?)
|
|
versionstring DD 18 DUP (?)
|
|
formatstring DD 16 DUP (?)
|
|
message DB 154 DUP (?)
|
|
datcodewords DB 0e84H DUP (?)
|
|
ileaveddata DB 0e84H DUP (?)
|
|
matrix DD 31330 DUP (?)
|
|
endg
|
|
|
|
|
|
;system function 78: prepare QR code
|
|
;input: eax = 78
|
|
; ebx = pointer to payload data
|
|
; ecx = length of payload data
|
|
; edx = pointer to buffer at least (31330 * 3) bytes long
|
|
; to hold the QR code as a 24-bit RGB bitmap
|
|
;output: if QR code generation failed:
|
|
; eax = -1
|
|
; otherwise:
|
|
; eax = number of pixels per side of QR code
|
|
; bitmap is copied to buffer starting at [edx]
|
|
|
|
syscall_qrcode:
|
|
stdcall is_region_userspace, edx, 31330 * 3
|
|
jnz .error
|
|
push edx
|
|
|
|
push -1
|
|
push -1
|
|
push ecx
|
|
push ebx
|
|
call makeQR
|
|
cmp eax, -1
|
|
je .error
|
|
push eax
|
|
call reducematrix
|
|
mov eax, [esp]
|
|
imul eax, eax
|
|
imul eax, eax, 3
|
|
mov ecx, eax
|
|
mov esi, matrix
|
|
mov edi, [esp + 4]
|
|
rep movsb
|
|
pop eax
|
|
pop edx
|
|
mov [esp + SYSCALL_STACK.eax], eax
|
|
ret
|
|
|
|
.error:
|
|
mov [esp + SYSCALL_STACK.eax], -1
|
|
ret
|
|
|
|
DARK equ 0
|
|
CMSK equ 0FFFF00H
|
|
|
|
makeQR:
|
|
;input: 4 dwords in the stack
|
|
; top argument is pointer to input data
|
|
; 2nd argument is length of input data, as number of bytes
|
|
; 3rd argument indicates extended channel interpretation mode
|
|
; -1 - no ECI
|
|
; 22 - windows-1251
|
|
; 26 - utf8
|
|
; (see list of ECI indicators at the bottom of this file)
|
|
; note: there is no ECI indicator for code page 866
|
|
; 4th argument is not used currently
|
|
; planned to use it to indicate if negative
|
|
; (white on black) QR code is desired
|
|
;output: if QR code could not be made, eax = -1
|
|
; otherwise, eax = size of QR code, as number of pixels per side
|
|
; matrix variable contains QR code as RGBA bitmap
|
|
|
|
;---------local variable declarations----------
|
|
_ecwords EQU [ebp]
|
|
_bytechars1 EQU [ebp + 4]
|
|
_alphachars2 EQU [ebp + 8]
|
|
_numchars3 EQU [ebp + 12]
|
|
_leadalpha21 EQU [ebp + 16]
|
|
_totalblocks EQU [ebp + 20]
|
|
_g1b EQU [ebp + 24] ;number of group 1 blocks
|
|
_g1dc EQU [ebp + 28] ;data codewords per block
|
|
_g2b EQU [ebp + 32] ;number of group 2 blocks
|
|
_g2dc EQU [ebp + 36] ;data codewords per block
|
|
_wordssofar EQU [ebp + 40]
|
|
_requiredbitslength EQU [ebp + 44]
|
|
_charcountlength EQU [ebp + 48]
|
|
_thisblockwords10 EQU [ebp + 52]
|
|
_thisblock12 EQU [ebp + 56] ;block counter
|
|
_unusedbits EQU [ebp + 60]
|
|
_ord20 EQU [ebp + 64] ;polynomial division cycle counter
|
|
;caller's ebp here 68
|
|
;return address here 72
|
|
_theinput EQU [ebp + 76] ;address of input data
|
|
_theinputlength EQU [ebp + 80]
|
|
_theecimode EQU [ebp + 84]
|
|
_makenegative EQU [ebp + 88] ;not used
|
|
;---------end of local variable declarations----------
|
|
EBPNUMBER EQU 68
|
|
push ebp
|
|
lea ebp, dword [esp - EBPNUMBER]
|
|
sub esp, EBPNUMBER - 4
|
|
push esi
|
|
and dword _requiredbitslength, 0
|
|
;return -1 if input length is more than absolute maximum
|
|
or eax, - 1
|
|
cmp dword _theinputlength, 7089
|
|
ja makeQR_end
|
|
;------------------
|
|
;figure out if input is numeric, alphanumeric, or
|
|
;binary, and set [mode] variable accordingly
|
|
and dword [mode], 0
|
|
mov ebx, dword _theinputlength
|
|
dec ebx
|
|
cld
|
|
mov esi, dword _theinput
|
|
findmodeloop:
|
|
lodsb
|
|
push eax
|
|
call alphaindex
|
|
cmp eax, 9
|
|
jle @f
|
|
mov dword [mode], 1
|
|
cmp eax, 46
|
|
jl @f
|
|
mov dword [mode], 2
|
|
jmp findmodeloopend
|
|
@@:
|
|
dec ebx
|
|
jns findmodeloop
|
|
findmodeloopend:
|
|
;------------------
|
|
;backslashes (\) need escaping in QR code,
|
|
;so they count double towards input length
|
|
cmp dword _theecimode, -1
|
|
je countslashloopend
|
|
mov ebx, dword _theinputlength
|
|
cld
|
|
mov esi, dword _theinput
|
|
countslashloop:
|
|
lodsb
|
|
cmp al, 92
|
|
jne @f
|
|
inc dword _theinputlength
|
|
@@:
|
|
dec ebx
|
|
jns countslashloop
|
|
countslashloopend:
|
|
;------------------
|
|
;return -1 if mode is 1 or 2 and input
|
|
;length is more than respective maxima
|
|
or eax, -1
|
|
cmp dword [mode], 1
|
|
jne @f
|
|
cmp dword _theinputlength, 4296
|
|
ja makeQR_end
|
|
@@:
|
|
cmp dword [mode], 2
|
|
jne @f
|
|
cmp dword _theinputlength, 2953
|
|
ja makeQR_end
|
|
@@:
|
|
;------------------
|
|
and dword _unusedbits, 0
|
|
and dword _charcountlength, 0
|
|
mov dword [version], 1
|
|
findversionloop:
|
|
mov dword [eclevel], 3
|
|
findeclevelloop:
|
|
mov eax, dword [version]
|
|
;same as eax = 21 + (version - 1) * 4
|
|
lea eax, dword [eax * 4 + 17]
|
|
mov dword [size], eax
|
|
imul eax, eax
|
|
mov dword [size2], eax
|
|
;fill matrix with unused pixels
|
|
mov ecx, eax ; 31330
|
|
mov eax, dword [unus]
|
|
mov edi, matrix
|
|
cld
|
|
rep stosd
|
|
;--------------
|
|
call reserveareas
|
|
call drawversion
|
|
call drawfinders
|
|
call drawtiming
|
|
call drawalign
|
|
call drawdarkmodule
|
|
;--------------
|
|
;count unused pixels in matrix; these are
|
|
;the pixels which will carry input and EC data
|
|
xor ecx, ecx
|
|
mov eax, dword [size2]
|
|
countunusedloop:
|
|
mov ebx, dword [matrix + eax * 4]
|
|
cmp ebx, dword [unus]
|
|
jne @f
|
|
inc ecx
|
|
@@:
|
|
dec eax
|
|
jns countunusedloop
|
|
mov dword _unusedbits, ecx
|
|
;-------------
|
|
;mov ecx, dword _unusedbits
|
|
shr ecx, 3
|
|
mov dword [maxcodewords], ecx
|
|
|
|
call getcharcountlength
|
|
movzx eax, al
|
|
mov dword _charcountlength, eax
|
|
|
|
call numdatacodewords
|
|
movzx eax, ax
|
|
shl eax, 3
|
|
mov dword _requiredbitslength, eax
|
|
;-------------
|
|
;begin computing capacity of current QR code
|
|
;mov ebx, dword _requiredbitslength
|
|
|
|
mov ebx, eax
|
|
sub ebx, 4
|
|
cmp dword _theecimode, -1
|
|
je @f
|
|
sub ebx, 12
|
|
@@:
|
|
sub ebx, dword _charcountlength
|
|
;mov dword _avail ableb its5, ebx
|
|
push ebx
|
|
|
|
mov eax, ebx
|
|
add eax, ebx
|
|
add eax, ebx
|
|
cdq
|
|
mov ecx, 10
|
|
idiv ecx
|
|
;calculated maximum number of characters this
|
|
;QR code can contain, if it is numeric
|
|
mov dword _numchars3, eax
|
|
|
|
mov eax, [esp]
|
|
add eax, eax
|
|
cdq
|
|
mov ecx, 11
|
|
idiv ecx
|
|
;calculated maximum number of characters this
|
|
;QR code can contain, if it is alphanumeric
|
|
mov dword _alphachars2, eax
|
|
|
|
pop eax
|
|
sar eax, 3
|
|
;calculated maximum number of bytes this
|
|
;QR code can contain, if it is binary
|
|
mov dword _bytechars1, eax
|
|
|
|
;it is possible to pre compute and look up the
|
|
;three previous results, which only depend on
|
|
;version and error correction level, however I
|
|
;prefer to calculate them explicitly
|
|
|
|
|
|
;break out of the loop if current version and
|
|
;EC level are sufficient to contain the input
|
|
cmp dword [mode], 0
|
|
jne @f
|
|
mov eax, dword _numchars3
|
|
cmp eax, dword _theinputlength
|
|
jge Loopfinished
|
|
@@:
|
|
cmp dword [mode], 1
|
|
jne @f
|
|
mov eax, dword _alphachars2
|
|
cmp eax, dword _theinputlength
|
|
jge Loopfinished
|
|
@@:
|
|
cmp dword [mode], 2
|
|
jne @f
|
|
mov eax, dword _bytechars1
|
|
cmp eax, dword _theinputlength
|
|
jge Loopfinished
|
|
@@:
|
|
dec dword [eclevel]
|
|
cmp dword [eclevel], 0
|
|
jnl findeclevelloop
|
|
inc dword [version]
|
|
cmp dword [version], 40
|
|
jng findversionloop
|
|
Loopfinished:
|
|
;--------------
|
|
;return -1 if version is greater than 40, which is
|
|
;the maximum for QR codes
|
|
;this should never happen, because of the prior checks
|
|
;regarding input length
|
|
or eax, - 1
|
|
cmp dword [version], 40
|
|
ja makeQR_end
|
|
;--------------
|
|
;reset data structures in case
|
|
;they have been used previously
|
|
cld
|
|
mov ecx, 5 ; 929
|
|
xor eax, eax
|
|
mov edi, datcodewords
|
|
rep stosd
|
|
mov ecx, 5 ; 929
|
|
mov edi, ileaveddata
|
|
rep stosd
|
|
;---------------
|
|
;add ECI mode indicator if necessary
|
|
;see page 24 of ISO/IEC 18004:2015
|
|
cmp dword _theecimode, 999999
|
|
jng @f
|
|
mov dword _theecimode, -1
|
|
@@:
|
|
cmp dword _theecimode, -1
|
|
je eciskip
|
|
push dword 4
|
|
push dword 7
|
|
push datcodewords
|
|
call appendtobitset
|
|
mov eax, dword _theecimode
|
|
cmp eax, 127
|
|
jg @f
|
|
push 8
|
|
and eax, 127
|
|
jmp addeci
|
|
@@:
|
|
cmp eax, 16383
|
|
jg @f
|
|
push 16
|
|
and eax, 16383
|
|
or eax, 32768
|
|
jmp addeci
|
|
@@:
|
|
push 24
|
|
and eax, 2097151
|
|
or eax, 12582912
|
|
addeci:
|
|
push eax
|
|
push datcodewords
|
|
call appendtobitset
|
|
eciskip:
|
|
;-----------------
|
|
;add mode indicator
|
|
mov eax, dword [mode]
|
|
movzx eax, byte [modeindicators + eax]
|
|
push 4
|
|
push eax
|
|
push datcodewords
|
|
call appendtobitset
|
|
;add length-of-input marker
|
|
push dword _charcountlength
|
|
push dword _theinputlength
|
|
push datcodewords
|
|
call appendtobitset
|
|
;-------------------
|
|
;prepare registers for data acquisition
|
|
cld
|
|
mov esi, dword _theinput
|
|
mov edi, esi
|
|
add edi, dword _theinputlength
|
|
;-------------------
|
|
;mode 0: acquire numeric data
|
|
cmp dword [mode], 0
|
|
jne mode0loopend
|
|
;cld
|
|
;mov esi, dword _theinput
|
|
;mov edi, esi
|
|
;add edi, dword _theinputlength
|
|
mode0loop:
|
|
mov ebx, edi
|
|
sub ebx, esi
|
|
lodsb
|
|
sub al, 48
|
|
cmp ebx, 1
|
|
jne @f
|
|
push 4
|
|
jmp mode0next
|
|
@@:
|
|
cmp ebx, 2
|
|
jne @f
|
|
imul eax, eax, 10
|
|
mov ebx, eax
|
|
lodsb
|
|
sub al, 48
|
|
add eax, ebx
|
|
push 7
|
|
jmp mode0next
|
|
@@:
|
|
cmp ebx, 3
|
|
jl mode0next
|
|
imul eax, eax, 100
|
|
mov ebx, eax
|
|
lodsb
|
|
sub al, 48
|
|
imul eax, eax, 10
|
|
add ebx,eax
|
|
lodsb
|
|
sub al, 48
|
|
add eax, ebx
|
|
push 10
|
|
mode0next:
|
|
push eax
|
|
push datcodewords
|
|
call appendtobitset
|
|
cmp esi, edi
|
|
jnge mode0loop
|
|
mode0loopend:
|
|
;-------------------
|
|
;mode 1: acquire alphanumeric data
|
|
cmp dword [mode], 1
|
|
jne skipmode1
|
|
;cld
|
|
;mov esi, dword _theinput
|
|
;mov edi, esi
|
|
;add edi, dword _theinputlength
|
|
mode1loop:
|
|
mov ebx, edi
|
|
sub ebx, esi
|
|
lodsb
|
|
push eax
|
|
call alphaindex
|
|
cmp ebx, 2
|
|
jnae @f
|
|
imul eax, 45
|
|
mov edx, eax
|
|
lodsb
|
|
push eax
|
|
call alphaindex
|
|
add eax, edx
|
|
push dword 11
|
|
jmp mode1next
|
|
@@:
|
|
push dword 6
|
|
mode1next:
|
|
push eax
|
|
push dword datcodewords
|
|
call appendtobitset
|
|
cmp esi, edi
|
|
jb mode1loop
|
|
skipmode1:
|
|
;-------------------
|
|
;mode 2: acquire binary data
|
|
cmp dword [mode], 2
|
|
jne skipmode2
|
|
;cld
|
|
;mov esi, dword _theinput
|
|
;mov edi, esi
|
|
;add edi, dword _theinputlength
|
|
mode2loop:
|
|
lodsb
|
|
push dword 8
|
|
push eax
|
|
push datcodewords
|
|
;if ECI mode is not default and input contains a
|
|
;backslash, escape it in the QR code by doubling it up
|
|
cmp dword _theecimode, -1
|
|
je @f
|
|
cmp eax, 92
|
|
jne @f
|
|
push dword 8
|
|
push eax
|
|
push dword datcodewords
|
|
call appendtobitset
|
|
@@:
|
|
call appendtobitset
|
|
cmp esi, edi
|
|
jb mode2loop
|
|
skipmode2:
|
|
;----------------
|
|
;if number of payload bits so far is less than capacity,
|
|
;!!! append four 0s to terminate !!! (emphasis intentional)
|
|
;or append 0s up to full capacity, whichever happens first
|
|
mov eax, dword _requiredbitslength
|
|
sub eax, dword [datcodewords + 4]
|
|
cmp eax, 4
|
|
jle @f
|
|
mov al, 4
|
|
@@:
|
|
push eax
|
|
push 0
|
|
push datcodewords
|
|
call appendtobitset
|
|
;if number of payload bits so far is not multiple of 8,
|
|
;append 0s until it is
|
|
mov al, 8
|
|
sub al, byte [datcodewords + 8]
|
|
and eax, 7
|
|
jz @f
|
|
push eax
|
|
push 0
|
|
push datcodewords
|
|
call appendtobitset
|
|
@@:
|
|
;-------------
|
|
;add repeating padding {236, 17} if necessary to fill capacity
|
|
mov esi, 236
|
|
mov edi, 17
|
|
push ebp
|
|
mov ebp, dword _requiredbitslength
|
|
sar ebp, 3
|
|
sub ebp, dword [datcodewords]
|
|
paddingloop:
|
|
cmp ebp, 0
|
|
jng paddingloopend
|
|
push 8
|
|
push esi
|
|
push datcodewords
|
|
call appendtobitset
|
|
xchg esi, edi
|
|
dec ebp
|
|
jmp paddingloop
|
|
paddingloopend:
|
|
pop ebp
|
|
;---------------------
|
|
;prepare some local variables
|
|
call numblocksingroup2; movzx eax, al
|
|
mov dword _g2b, eax
|
|
call numblocksingroup1; movzx eax, al
|
|
mov dword _g1b, eax
|
|
mov eax, dword _g1b
|
|
add eax, dword _g2b
|
|
mov dword _totalblocks, eax
|
|
call group1datacodewords; movzx eax, al
|
|
mov dword _g1dc, eax
|
|
call group2datacodewords; movzx eax, al
|
|
mov dword _g2dc, eax
|
|
call eccodewordsperblock
|
|
mov dword _ecwords, eax
|
|
and dword _wordssofar, 0
|
|
|
|
push dword _ecwords
|
|
call makeECgenerator
|
|
and dword _thisblock12, 0
|
|
processblockloop:
|
|
mov ebx, dword _g1dc
|
|
mov eax, dword _thisblock12
|
|
cmp eax, dword _g1b
|
|
jl @f
|
|
mov ebx, dword _g2dc
|
|
@@:
|
|
;determined how many codewords this block must contain
|
|
mov dword _thisblockwords10, ebx
|
|
|
|
;clear the array that is used to
|
|
;calculate error correction codewords
|
|
cld
|
|
mov ecx, 76 ; 154
|
|
xor eax, eax
|
|
mov edi, message
|
|
rep stosw
|
|
|
|
;copy this block's data to the array in reverse order
|
|
;with leading 0s required for next computation
|
|
mov edi, message
|
|
add edi, dword _ecwords
|
|
mov ecx, dword _thisblockwords10
|
|
mov esi, datcodewords + 9
|
|
add esi, dword _wordssofar
|
|
;also increase the counter of codewords processed so far
|
|
add dword _wordssofar, ecx
|
|
dec ecx
|
|
add esi, ecx
|
|
@@:
|
|
movsb
|
|
dec esi
|
|
dec esi
|
|
dec ecx
|
|
jns @b
|
|
|
|
;----------------
|
|
mov eax, dword _thisblockwords10
|
|
mov ecx, dword _ecwords
|
|
lea eax, dword [ecx + eax - 1]
|
|
mov dword _ord20, eax
|
|
errorcorrectionloop:
|
|
mov eax, dword _ord20
|
|
movzx eax, byte [message + eax]
|
|
test eax, eax
|
|
;if lead exponent is 0, skip this polynomial division cycle
|
|
jz errorcorrectionnext
|
|
|
|
;calculate lead value for this polynomial division cycle
|
|
mov eax, dword _ord20
|
|
movzx eax, byte [message + eax]
|
|
mov al, byte [mod285antilogs + eax]
|
|
mov byte _leadalpha21, al
|
|
|
|
;perform one cycle of dividing this block's codewords by the
|
|
;EC generator polynomial, using Galois Field 256 arithmetic
|
|
mov ecx, dword _ord20
|
|
mov edi, dword _ecwords
|
|
sub ecx, edi
|
|
polydivisionloop:
|
|
movzx eax, byte [genpoly + edi]
|
|
movzx edx, byte _leadalpha21
|
|
add eax, edx
|
|
cdq
|
|
mov esi, 255
|
|
idiv esi
|
|
movzx eax, byte [mod285logs + edx]
|
|
mov edx, edi
|
|
movzx ebx, byte [message + edx + ecx]
|
|
xor ebx, eax
|
|
mov byte [message + edi + ecx], bl
|
|
dec edi
|
|
jns polydivisionloop
|
|
;------------------
|
|
errorcorrectionnext:
|
|
dec dword _ord20
|
|
mov eax, dword _ord20
|
|
cmp eax, dword _ecwords
|
|
jnl errorcorrectionloop
|
|
|
|
;store error correction data
|
|
mov edi, dword _ecwords
|
|
mov esi, dword message
|
|
dec edi
|
|
add esi, edi
|
|
std
|
|
@@:
|
|
lodsb
|
|
push 8
|
|
push eax
|
|
push datcodewords
|
|
call appendtobitset
|
|
dec edi
|
|
jns @b
|
|
cld
|
|
;------------
|
|
inc dword _thisblock12
|
|
mov eax, dword _thisblock12
|
|
cmp eax, dword _totalblocks
|
|
jnge processblockloop
|
|
;------------
|
|
;interleave data
|
|
xor esi, esi
|
|
ileavegroup1loop:
|
|
xor edi, edi
|
|
ileavegroup1_innerloop:
|
|
mov ecx, edi
|
|
sub ecx, dword _g1b
|
|
cmp edi, dword _g1b
|
|
jnle @f
|
|
xor ecx, ecx
|
|
@@:
|
|
mov eax, edi
|
|
imul eax, dword _g1dc
|
|
add eax, esi
|
|
movzx eax, byte [datcodewords + eax + ecx + 9]
|
|
push 8
|
|
push eax
|
|
push ileaveddata
|
|
call appendtobitset
|
|
inc edi
|
|
cmp edi, dword _totalblocks
|
|
jnge ileavegroup1_innerloop
|
|
|
|
inc esi
|
|
cmp esi, dword _g1dc
|
|
jnge ileavegroup1loop
|
|
|
|
|
|
cmp dword _g2dc, 0
|
|
jle skipgroup2
|
|
|
|
;interleave data from group 2
|
|
mov esi, 1
|
|
group2loop:
|
|
mov ecx, esi
|
|
mov eax, dword _g1dc
|
|
imul eax, dword _g1b
|
|
imul ecx, dword _g2dc
|
|
movzx eax, byte [datcodewords + eax + ecx + 8]
|
|
push 8
|
|
push eax
|
|
push ileaveddata
|
|
call appendtobitset
|
|
inc esi
|
|
cmp esi, dword _g2b
|
|
jng group2loop
|
|
skipgroup2:
|
|
|
|
;interleave error correction data
|
|
mov eax, dword _g1b
|
|
mov ecx, dword _g2b
|
|
imul eax, dword _g1dc
|
|
imul ecx, dword _g2dc
|
|
add eax, ecx
|
|
push eax; startecwords
|
|
call eccodewordsperblock
|
|
push eax; bk
|
|
push 0; n
|
|
push 0; i
|
|
ix EQU dword [esp]
|
|
jx EQU dword [esp + 4]
|
|
bk EQU [esp + 8]
|
|
startecwords EQU [esp + 12]
|
|
ileaveloop2:
|
|
mov ix, 0
|
|
ileaveloop1:
|
|
xor edx,edx
|
|
mov eax, ix
|
|
imul dword bk
|
|
add eax, startecwords
|
|
mov ecx, jx
|
|
movzx eax, byte [datcodewords + 9 + eax + ecx]
|
|
push 8
|
|
push eax
|
|
push ileaveddata
|
|
call appendtobitset
|
|
inc ix
|
|
mov eax, ix
|
|
cmp eax, dword _totalblocks
|
|
jnge ileaveloop1
|
|
inc jx
|
|
mov eax, jx
|
|
cmp eax, bk
|
|
jnge ileaveloop2
|
|
sub esp, 16 ; discard last 4 local variables
|
|
;------------------
|
|
;if there are any unused pixels left over,
|
|
;fill the corresponding data with 0s
|
|
mov eax, dword _unusedbits
|
|
sub eax, dword [ileaveddata + 4]
|
|
cmp eax, 0
|
|
jle @f
|
|
push dword eax
|
|
push dword 0
|
|
push ileaveddata
|
|
call appendtobitset
|
|
@@:
|
|
;-----------------
|
|
;draw interleaved data,
|
|
;find which mask pattern minimizes penalty score,
|
|
;apply mask,
|
|
;return size of QR code
|
|
call drawdata
|
|
call minimalpenaltymask
|
|
mov dword [maskpattern], eax
|
|
push dword eax
|
|
call mask
|
|
mov eax, dword [size]
|
|
makeQR_end:
|
|
pop esi
|
|
add ebp, EBPNUMBER
|
|
leave
|
|
ret 16
|
|
|
|
|
|
drawdata:
|
|
;input: nothing
|
|
;output: matrix is modified
|
|
col EQU edx
|
|
row EQU ebx
|
|
ix EQU ecx
|
|
godown EQU edi
|
|
oddcol EQU ebp
|
|
push ebp
|
|
xor godown, godown
|
|
xor ix, ix
|
|
mov col, dword [size]
|
|
dec col
|
|
mov row, col
|
|
drawdataloop:
|
|
|
|
mov eax, row
|
|
mul byte [size]
|
|
add eax, col
|
|
mov esi, dword [matrix + eax * 4]
|
|
cmp esi, dword [unus]
|
|
jne skipdraw
|
|
push ebx
|
|
push ecx
|
|
push eax
|
|
mov eax, ix
|
|
call getdrawbit
|
|
pop ecx
|
|
mov dword [matrix + ecx * 4], eax
|
|
pop ecx
|
|
pop ebx
|
|
inc ix
|
|
skipdraw:
|
|
mov oddcol,col
|
|
and oddcol,1
|
|
cmp col, 6
|
|
jge @f
|
|
xor oddcol, 1
|
|
@@:
|
|
cmp oddcol, 1
|
|
je isoddcol
|
|
dec col
|
|
jmp testrow0
|
|
isoddcol:
|
|
inc col
|
|
and godown, 1
|
|
jz @f
|
|
inc row
|
|
jmp testrow0
|
|
@@:
|
|
dec row
|
|
testrow0:
|
|
cmp row, 0
|
|
jge testrowsize
|
|
or godown, 1
|
|
xor row, row
|
|
cmp col, 8
|
|
jne @f
|
|
dec col
|
|
@@:
|
|
dec col
|
|
dec col
|
|
testrowsize:
|
|
cmp row, dword [size]
|
|
jnae drawdataloopend
|
|
xor godown, godown
|
|
mov row, dword [size]
|
|
dec row
|
|
dec col
|
|
dec col
|
|
cmp col, 5
|
|
jne @f
|
|
dec col
|
|
@@:
|
|
cmp col, 6
|
|
jne drawdataloopend
|
|
dec col
|
|
dec col
|
|
drawdataloopend:
|
|
cmp ix, dword [datcodewords + 4]
|
|
jnae drawdataloop
|
|
pop ebp
|
|
ret
|
|
|
|
|
|
|
|
|
|
mask:
|
|
;input: eax = mask type
|
|
;output: matrix is modified
|
|
pop ecx
|
|
pop eax
|
|
push ecx
|
|
;remove the above to change calling convention
|
|
col EQU ecx
|
|
row EQU edx
|
|
push eax
|
|
push 0
|
|
push eax
|
|
call drawformat
|
|
xor col, col
|
|
maskloopcol:
|
|
xor row, row
|
|
masklooprow:
|
|
mov eax, row
|
|
mul cl
|
|
push eax ;save result: row * column
|
|
push edx
|
|
cdq
|
|
mov ebx, 3
|
|
idiv ebx
|
|
mov eax, edx
|
|
pop edx
|
|
push eax; save result: (row * column) mod 3
|
|
mov eax, dword [esp + 12]
|
|
cmp al, 7
|
|
jg @f
|
|
jmp dword [maskbjumps + eax * 4]
|
|
@@:
|
|
pop ebx
|
|
jmp endmasks
|
|
bmask0:
|
|
mov ebx, row
|
|
add ebx, col
|
|
and bl, 1
|
|
xor ebx, 1
|
|
jmp bmaskdone
|
|
bmask1:
|
|
mov ebx, row
|
|
and bl, 1
|
|
xor ebx, 1
|
|
jmp bmaskdone
|
|
bmask2:
|
|
mov eax, col
|
|
mov bl, 3
|
|
div bl
|
|
xor ebx, ebx
|
|
cmp ah, 0
|
|
setz bl
|
|
jmp bmaskdone
|
|
bmask3:
|
|
mov eax, col
|
|
add eax, row
|
|
mov bl, 3
|
|
div bl
|
|
xor ebx, ebx
|
|
cmp ah, 0
|
|
setz bl
|
|
jmp bmaskdone
|
|
bmask4:
|
|
mov eax, col
|
|
mov ebx, 3
|
|
div bl
|
|
mov ebx, row
|
|
shr ebx, 1
|
|
add bl, al
|
|
and bl, 1
|
|
xor ebx, 1
|
|
jmp bmaskdone
|
|
bmask5:
|
|
mov eax, dword [esp]
|
|
mov ebx, dword [esp+4]
|
|
and ebx, 1
|
|
add ebx, eax
|
|
setz bl
|
|
jmp bmaskdone
|
|
bmask6:
|
|
mov eax, dword [esp]
|
|
mov ebx, dword [esp+4]
|
|
and ebx, 1
|
|
add ebx, eax
|
|
and ebx, 1
|
|
setz bl
|
|
jmp bmaskdone
|
|
bmask7:
|
|
mov eax, dword [esp]
|
|
mov ebx, row
|
|
add ebx, col
|
|
and ebx, 1
|
|
add ebx, eax
|
|
and ebx, 1
|
|
setz bl
|
|
bmaskdone:
|
|
pop eax ;discard result
|
|
pop eax ;discard result
|
|
mov dword [esp], ebx
|
|
mov eax, row
|
|
imul byte [size]
|
|
add eax, col
|
|
mov ebx, eax
|
|
mov eax, dword [matrix + ebx * 4]
|
|
cmp eax, dword [unus]
|
|
jne @f
|
|
mov eax, dword [ldat]
|
|
@@:
|
|
and dword [esp], 1
|
|
jz endflip
|
|
cmp eax, dword [ddat]
|
|
jne @f
|
|
mov eax, dword [ldat]
|
|
jmp endflip
|
|
@@:
|
|
cmp eax, dword [ldat]
|
|
jne endflip
|
|
mov eax, dword [ddat]
|
|
endflip:
|
|
mov dword [matrix + ebx * 4], eax
|
|
inc row
|
|
cmp row, dword [size]
|
|
jnge masklooprow
|
|
inc col
|
|
cmp col, dword [size]
|
|
jnge maskloopcol
|
|
endmasks:
|
|
pop eax
|
|
pop eax
|
|
ret
|
|
maskbjumps:
|
|
dd bmask0
|
|
dd bmask1
|
|
dd bmask2
|
|
dd bmask3
|
|
dd bmask4
|
|
dd bmask5
|
|
dd bmask6
|
|
dd bmask7
|
|
|
|
|
|
getratiopenalty:
|
|
;input: nothing
|
|
;output: eax = penalty score from B/W ratio of QR code
|
|
darks EQU ebx
|
|
xor darks, darks
|
|
mov ecx, dword [size2]
|
|
countdarksloop:
|
|
mov eax, dword [matrix + ix * 4]
|
|
and eax, CMSK
|
|
jnz @f
|
|
inc darks
|
|
@@:
|
|
dec ecx
|
|
jns countdarksloop
|
|
|
|
imul eax, darks, 100
|
|
mov ecx, DWORD [size2]
|
|
cdq
|
|
idiv ecx
|
|
sub eax, 50
|
|
jns @f
|
|
neg eax
|
|
@@:
|
|
xor ecx, ecx
|
|
cmp eax, 5
|
|
jle @f
|
|
ratioloop:
|
|
inc ecx
|
|
sub eax, 5
|
|
cmp eax, 5
|
|
jg ratioloop
|
|
@@:
|
|
imul eax, ecx, 10
|
|
ret
|
|
|
|
|
|
gettotalpenalty:
|
|
;input: nothing
|
|
;output: eax = total penalty score of QR code
|
|
call getblockpenalty
|
|
push eax
|
|
call getstraightpenalty
|
|
push eax
|
|
call getsequencepenalty
|
|
push eax
|
|
call getratiopenalty
|
|
pop ebx
|
|
add eax, ebx
|
|
pop ebx
|
|
add eax, ebx
|
|
pop ebx
|
|
add eax, ebx
|
|
ret
|
|
|
|
|
|
|
|
getsequencepenalty:
|
|
;input: nothing
|
|
;output: eax = penalty score for rule 3 of current QR code
|
|
ix EQU ebx
|
|
penalty EQU esi
|
|
col EQU dword [esp]
|
|
row EQU dword [esp + 4]
|
|
xor penalty, penalty
|
|
push 0
|
|
push 0
|
|
seqloopA:
|
|
mov col, 10
|
|
seqloopB:
|
|
xor edi, edi
|
|
xor ix, ix
|
|
seqloopC:
|
|
mov eax, col
|
|
sub eax, ix
|
|
mov ecx, row
|
|
imul ecx, dword [size]
|
|
add eax, ecx
|
|
mov eax, dword [matrix + eax * 4]
|
|
and eax, CMSK
|
|
cmp eax, dword [sequence + ix * 4]
|
|
jne @f
|
|
inc edi
|
|
@@:
|
|
cmp eax, dword [sequence + ix * 4 + 16]
|
|
jne @f
|
|
add edi, 16
|
|
@@:
|
|
mov eax, col
|
|
sub eax, ix
|
|
imul eax, dword [size]
|
|
add eax, row
|
|
mov eax, dword [matrix + eax * 4]
|
|
and eax, CMSK
|
|
cmp eax, dword [sequence + ix * 4]
|
|
jne @f
|
|
add edi, 256
|
|
@@:
|
|
cmp eax, dword [sequence + ix * 4 + 16]
|
|
jne @f
|
|
add edi, 4096
|
|
@@:
|
|
inc ix
|
|
cmp ix, 10
|
|
jng seqloopC
|
|
push ecx
|
|
xor ecx, ecx
|
|
incpenaltyloop:
|
|
mov eax, edi
|
|
shr eax, cl
|
|
and eax, 15
|
|
cmp eax, 11
|
|
jl @f
|
|
inc penalty
|
|
@@:
|
|
add cl, 4
|
|
cmp cl, 12
|
|
jle incpenaltyloop
|
|
pop ecx
|
|
inc col
|
|
mov eax, col
|
|
cmp eax, dword [size]
|
|
jnge seqloopB
|
|
inc row
|
|
mov eax, row
|
|
cmp eax, dword [size]
|
|
jnge seqloopA
|
|
pop eax
|
|
pop eax
|
|
imul eax, penalty, 40
|
|
ret
|
|
|
|
|
|
|
|
minimalpenaltymask:
|
|
;input: nothing
|
|
;output: al = number of mask pattern that minimizes
|
|
; penalty score for current QR code
|
|
mov ecx,0
|
|
sub esp, 8
|
|
mpmloop:
|
|
push ecx
|
|
mov eax, ecx
|
|
push eax
|
|
call mask
|
|
call gettotalpenalty
|
|
pop ecx
|
|
cmp ecx, 0
|
|
jne @f
|
|
mov dword [esp], ecx
|
|
mov dword [esp + 4], eax
|
|
@@:
|
|
mov edx, dword [esp + 4]
|
|
cmp eax, edx
|
|
jge @f
|
|
mov dword [esp + 4], eax
|
|
mov dword [esp], ecx
|
|
@@:
|
|
push ecx
|
|
mov eax, ecx
|
|
push eax
|
|
call mask
|
|
pop ecx
|
|
inc ecx
|
|
cmp ecx, 8
|
|
jl mpmloop
|
|
pop eax
|
|
pop edx
|
|
ret
|
|
|
|
|
|
reserveareas:
|
|
;input: nothing
|
|
;output: some parts of matrix are marked as reserved
|
|
; so the data drawing algorithm will skip them
|
|
push dword [resr]
|
|
push 9
|
|
push 0
|
|
push 0
|
|
call fillbox
|
|
push dword [resr]
|
|
push 8
|
|
mov eax, dword [size]
|
|
sub eax, 8
|
|
push eax
|
|
push 1
|
|
call fillbox
|
|
push dword [resr]
|
|
push 8
|
|
push 1
|
|
mov eax, dword [size]
|
|
sub eax, 8
|
|
push eax
|
|
call fillbox
|
|
cmp dword [version], 7
|
|
jl @f
|
|
push dword [resr]
|
|
push 3
|
|
mov eax, dword [size]
|
|
sub eax, 11
|
|
push eax
|
|
push 0
|
|
call fillbox
|
|
push dword [resr]
|
|
push 3
|
|
mov eax, dword [size]
|
|
sub eax, 11
|
|
push eax
|
|
push 3
|
|
call fillbox
|
|
push dword [resr]
|
|
push 3
|
|
push 0
|
|
mov eax, dword [size]
|
|
sub eax, 11
|
|
push eax
|
|
call fillbox
|
|
push dword [resr]
|
|
push 3
|
|
push 3
|
|
mov eax, dword [size]
|
|
sub eax, 11
|
|
push eax
|
|
call fillbox
|
|
@@:
|
|
ret
|
|
|
|
|
|
drawformat:
|
|
;input: eax = type of mask
|
|
;output: formatstring array is modified
|
|
; format info is drawn in matrix
|
|
;uses eax ebx ecx edx esi
|
|
pop ecx
|
|
pop eax
|
|
push ecx
|
|
ix EQU ecx
|
|
xor ix, ix
|
|
mov ebx, dword [eclevel]
|
|
shl ebx, 3
|
|
add eax, ebx
|
|
dfloop1:
|
|
mov ebx, 1
|
|
shl ebx, cl
|
|
movzx edx, word [formatstrings + eax * 2]
|
|
mov esi, dword [dark]
|
|
and ebx, edx
|
|
jnz @f
|
|
mov esi, dword [lite]
|
|
@@:
|
|
mov ebx, 14
|
|
sub ebx, ix
|
|
mov dword [formatstring + ebx * 4], esi
|
|
inc ix
|
|
cmp ix, 14
|
|
jle dfloop1
|
|
|
|
row EQU edx
|
|
xor ix, ix
|
|
mov row, dword [size]
|
|
dfloop2:
|
|
dec row
|
|
mov eax, row
|
|
imul byte [size]
|
|
mov ebx, dword [formatstring + ix * 4]
|
|
inc ix
|
|
mov dword [matrix + 32 + eax * 4], ebx
|
|
cmp row, 7
|
|
jne @f
|
|
dec row
|
|
@@:
|
|
mov ebx, dword [size]
|
|
sub ebx, 7
|
|
cmp row, ebx
|
|
jne @f
|
|
mov row, 9
|
|
@@:
|
|
cmp row, 0
|
|
jge dfloop2
|
|
|
|
col EQU edx
|
|
xor ix, ix
|
|
xor col, col
|
|
mov eax, dword [size]
|
|
shl eax, 5
|
|
dfloop3:
|
|
mov ebx, dword [formatstring + ix * 4]
|
|
inc ix
|
|
mov dword [matrix + eax + col * 4], ebx
|
|
cmp col, 5
|
|
jne @f
|
|
inc col
|
|
@@:
|
|
cmp col, 7
|
|
jne @f
|
|
mov col, dword [size]
|
|
sub col, 9
|
|
@@:
|
|
inc col
|
|
cmp col, dword [size]
|
|
jnge dfloop3
|
|
ret
|
|
|
|
|
|
drawtiming:
|
|
;input: nothing
|
|
;output: timing pattern is drawn in matrix
|
|
mov eax, 8
|
|
mov ebx, dword [size]
|
|
mov esi, ebx
|
|
sub ebx, eax
|
|
dtloop:
|
|
mov ecx, dword [dark]
|
|
test eax, 1
|
|
jz @f
|
|
mov ecx, dword [lite]
|
|
@@:
|
|
mov edx, 6
|
|
imul edx, esi
|
|
add edx, eax
|
|
mov [matrix + edx * 4], ecx
|
|
mov edx, eax
|
|
imul edx, esi
|
|
add edx, 6
|
|
mov [matrix + edx * 4], ecx
|
|
inc eax
|
|
cmp eax, ebx
|
|
jl dtloop
|
|
ret
|
|
|
|
|
|
fillbox:
|
|
;input: 4 dwords in the stack: startx, starty, boxsize, content
|
|
;output: a filled box is drawn in matrix
|
|
pop esi; return address
|
|
pop edi
|
|
pop eax
|
|
pop ecx
|
|
pop edx
|
|
push esi; save return address
|
|
push ebp; save previous base pointer
|
|
mov ebp, edi
|
|
shl ebp, 2
|
|
mov esi, eax
|
|
add edi, ecx
|
|
shl edi, 2
|
|
add esi, ecx
|
|
movzx ecx, byte [size]
|
|
mul cl
|
|
imul esi, ecx
|
|
fbloop:
|
|
mov ebx, ebp
|
|
@@:
|
|
mov [matrix + ebx + eax * 4], edx
|
|
add ebx, 4
|
|
cmp edi, ebx
|
|
jg @b
|
|
add eax, ecx
|
|
cmp esi, eax
|
|
jg fbloop
|
|
pop ebp; restore previous base pointer
|
|
ret
|
|
|
|
|
|
numblocksingroup2:
|
|
;input: nothing
|
|
;output: eax = number of blocks in group 2 of QR code
|
|
mov edx, 2
|
|
jmp lbt
|
|
group1datacodewords:
|
|
;input: nothing
|
|
;output: eax = number of data codewords in group 1 of QR code
|
|
mov edx, 1
|
|
jmp lbt
|
|
numblocksingroup1:
|
|
;input: nothing
|
|
;output: eax = number of blocks in group 1 of QR code
|
|
mov edx, 0
|
|
lbt:
|
|
mov eax, dword [version]
|
|
dec eax
|
|
imul eax, eax, 12
|
|
imul ecx, dword [eclevel], 3
|
|
add eax, edx
|
|
movzx eax, byte [bigtable + ecx + eax]
|
|
ret
|
|
|
|
|
|
group2datacodewords:
|
|
;input: nothing
|
|
;output: eax = number of data codewords in group 2 of QR code
|
|
call numblocksingroup2
|
|
test eax, eax
|
|
jz @f
|
|
call group1datacodewords
|
|
inc eax
|
|
@@:
|
|
ret
|
|
|
|
|
|
eccodewordsperblock:
|
|
;input: nothing
|
|
;output: eax = number of EC codewords per block
|
|
call numdatacodewords
|
|
mov esi, DWORD [maxcodewords]
|
|
sub esi, eax
|
|
call numblocksingroup1
|
|
mov edi, eax
|
|
call numblocksingroup2
|
|
add edi, eax
|
|
mov eax, esi
|
|
cdq
|
|
idiv edi
|
|
ret
|
|
|
|
|
|
numdatacodewords:
|
|
;input: nothing
|
|
;output: eax = number of data codewords in QR code
|
|
call group1datacodewords
|
|
mov esi, eax
|
|
call numblocksingroup1
|
|
imul esi, eax
|
|
call group2datacodewords
|
|
mov edi, eax
|
|
call numblocksingroup2
|
|
imul edi, eax
|
|
add esi, edi
|
|
mov eax, esi
|
|
ret
|
|
|
|
alphaindex:
|
|
;input: al
|
|
;output: eax = index of input in alphamode table, or 46 if not found
|
|
pop ecx
|
|
pop eax
|
|
push ecx
|
|
xor ecx, ecx
|
|
@@:
|
|
cmp [alphamode + ecx], al
|
|
je @f
|
|
inc cl
|
|
cmp cl, 46
|
|
jl @b
|
|
@@:
|
|
mov eax, ecx
|
|
ret
|
|
|
|
|
|
mem7 db 7
|
|
|
|
drawalign:
|
|
;input: nothing
|
|
;output: alignment patterns (small squares) are drawn in matrix
|
|
mov eax, dword [version]
|
|
cmp al, 1
|
|
jle drawalign_end
|
|
push eax
|
|
shl al, 2
|
|
add al, 10
|
|
mov byte [places + 1], al
|
|
pop eax
|
|
mov ebx, eax
|
|
idiv byte [mem7]
|
|
and eax, 255
|
|
cmp al, 0
|
|
je startloop
|
|
cmp al, 1
|
|
jg case2
|
|
inc bl
|
|
jmp @f
|
|
case2:
|
|
cmp al, 2
|
|
jg case3
|
|
sub bl, 4
|
|
jmp @f
|
|
case3:
|
|
cmp al, 3
|
|
jg case4
|
|
sub bl, 10
|
|
@@:
|
|
shl bl, 1
|
|
jmp da_endcases
|
|
case4:
|
|
cmp al, 4
|
|
jg case5
|
|
sub bl, 28
|
|
jmp @f
|
|
case5:
|
|
sub bl, 34
|
|
@@:
|
|
mov bl, byte [diffs + ebx]
|
|
da_endcases:
|
|
mov ecx, 1
|
|
@@:
|
|
mov dl, byte [places + ecx]
|
|
sub dl, bl
|
|
mov byte [places + 1 + ecx], dl
|
|
inc ecx
|
|
cmp ecx, eax
|
|
jle @b
|
|
startloop:
|
|
xor ecx, ecx
|
|
da_loop1:
|
|
xor edx, edx
|
|
da_loop2:
|
|
cmp cl, 0
|
|
jne @f
|
|
cmp dl, 1
|
|
jle da_continue
|
|
@@:
|
|
cmp cl, 1
|
|
jne @f
|
|
cmp dl, 0
|
|
je da_continue
|
|
@@:
|
|
push edx
|
|
push ecx
|
|
push dword [dark]
|
|
push 1
|
|
movzx edx, byte [places + edx]
|
|
push edx
|
|
movzx ecx, byte [places + ecx]
|
|
push ecx
|
|
dec edx
|
|
dec ecx
|
|
push dword [lite]
|
|
push 3
|
|
push edx
|
|
push ecx
|
|
dec ecx
|
|
dec edx
|
|
push dword [dark]
|
|
push 5
|
|
push edx
|
|
push ecx
|
|
call fillbox
|
|
call fillbox
|
|
call fillbox
|
|
pop ecx
|
|
pop edx
|
|
da_continue:
|
|
inc dl
|
|
cmp dl, 7
|
|
jge @f
|
|
cmp byte [places + edx], 0
|
|
je @f
|
|
jmp da_loop2
|
|
@@:
|
|
inc cl
|
|
cmp cl, 7
|
|
jge @f
|
|
cmp byte [places + ecx], 0
|
|
je @f
|
|
jmp da_loop1
|
|
@@:
|
|
drawalign_end:
|
|
ret
|
|
|
|
drawdarkmodule:
|
|
;input: nothing
|
|
;output: fixed dark module is drawn in matrix
|
|
push dword [dark]
|
|
push dword 1
|
|
mov eax, dword [size]
|
|
sub eax, 8
|
|
push eax
|
|
push dword 8
|
|
call fillbox
|
|
ret
|
|
|
|
getcharcountlength:
|
|
;input: nothing
|
|
;output: eax = length of character count marker, in bits
|
|
mov eax, [mode]
|
|
xor ebx, ebx
|
|
cmp [version], 9
|
|
setg bl
|
|
cmp [version], 26
|
|
setg cl
|
|
add bl, cl
|
|
shl bl, 2
|
|
add ebx, charcountlengths
|
|
xlatb
|
|
ret
|
|
|
|
|
|
appendtobitset:
|
|
;input: ebx = pointer to bitset
|
|
; eax = data to add
|
|
; ecx = number of low-order bits from eax to add
|
|
;output: bitset is modified
|
|
pop ecx
|
|
pop ebx
|
|
pop eax
|
|
xchg ecx, dword [esp]
|
|
;remove the above to change calling convention
|
|
mbs EQU ebx
|
|
numbits EQu ecx
|
|
push ebp
|
|
dec numbits
|
|
appendloop:
|
|
mov edx, eax
|
|
shr edx, cl
|
|
push numbits
|
|
mov ecx, 7
|
|
sub cl, byte [mbs + 8]
|
|
mov ebp, 1
|
|
shl ebp, cl
|
|
mov ecx, dword [mbs]
|
|
add ecx, 9
|
|
xchg ebp, ecx
|
|
and edx, 1
|
|
jz @f
|
|
or byte [mbs + ebp], cl
|
|
jmp appenddone
|
|
@@:
|
|
not ecx
|
|
and byte [mbs + ebp], cl
|
|
appenddone:
|
|
pop numbits
|
|
inc dword [mbs + 4]
|
|
inc byte [mbs + 8]
|
|
and byte [mbs + 8], 7
|
|
jnz @f
|
|
inc dword [mbs]
|
|
@@:
|
|
dec numbits
|
|
cmp numbits, 0
|
|
jge appendloop
|
|
pop ebp
|
|
ret
|
|
|
|
|
|
drawfinders:
|
|
;input: nothing
|
|
;output: finder patterns (large squares) are drawn in matrix
|
|
push dword [lite]
|
|
push 8
|
|
push 0
|
|
push 0
|
|
call fillbox
|
|
push dword [dark]
|
|
push 7
|
|
push 0
|
|
push 0
|
|
call fillbox
|
|
push dword [lite]
|
|
push 5
|
|
push 1
|
|
push 1
|
|
call fillbox
|
|
push dword [dark]
|
|
push 3
|
|
push 2
|
|
push 2
|
|
call fillbox
|
|
push dword [lite]
|
|
push 8
|
|
mov eax, dword [size]
|
|
sub eax, 8
|
|
push eax
|
|
push 0
|
|
call fillbox
|
|
push dword [dark]
|
|
push 7
|
|
mov eax, dword [size]
|
|
sub eax, 7
|
|
push eax
|
|
push 0
|
|
call fillbox
|
|
push dword [lite]
|
|
push 5
|
|
mov eax, dword [size]
|
|
sub eax, 6
|
|
push eax
|
|
push 1
|
|
call fillbox
|
|
push dword [dark]
|
|
push 3
|
|
mov eax, dword [size]
|
|
sub eax, 5
|
|
push eax
|
|
push 2
|
|
call fillbox
|
|
push dword [lite]
|
|
push 8
|
|
push 0
|
|
mov eax, dword [size]
|
|
sub eax, 8
|
|
push eax
|
|
call fillbox
|
|
push dword [dark]
|
|
push 7
|
|
push 0
|
|
mov eax, dword [size]
|
|
sub eax, 7
|
|
push eax
|
|
call fillbox
|
|
push dword [lite]
|
|
push 5
|
|
push 1
|
|
mov eax, dword [size]
|
|
sub eax, 6
|
|
push eax
|
|
call fillbox
|
|
push dword [dark]
|
|
push 3
|
|
push 2
|
|
mov eax, dword [size]
|
|
sub eax, 5
|
|
push eax
|
|
call fillbox
|
|
ret
|
|
|
|
|
|
getdrawbit:
|
|
;input: eax = index of desired bit from ileaveddata
|
|
;output: eax = [ddat] if bit is 1, [ldat] otherwise
|
|
;pop ebx
|
|
;pop eax
|
|
;pop eax
|
|
;push ebx
|
|
;remove the above to change calling convention
|
|
mov ebx, eax
|
|
shr eax, 3
|
|
and ebx, 7
|
|
mov ecx, 7
|
|
sub ecx, ebx
|
|
mov bl, byte [ileaveddata + 9 + eax]
|
|
shr bx, cl
|
|
mov eax, dword [ddat]
|
|
and ebx, 1
|
|
jnz @f
|
|
mov eax, dword [ldat]
|
|
@@:
|
|
ret
|
|
|
|
drawversion:
|
|
;input: nothing
|
|
;output: version info is drawn in matrix
|
|
mov ebx, dword [version]
|
|
cmp bx, 7
|
|
jnge drawversion_end
|
|
sub bx, 7
|
|
mov ebx, dword [versionstrings + ebx * 4]
|
|
xor ecx, ecx
|
|
drawverloop:
|
|
mov eax, 1
|
|
shl ax, cl
|
|
and ax, bx
|
|
mov eax, dword [dark]
|
|
jnz @f
|
|
mov eax, dword [lite]
|
|
@@:
|
|
mov dword [versionstring + ecx * 4], eax
|
|
inc ecx
|
|
cmp ecx, 17
|
|
jng drawverloop
|
|
xor ecx, ecx
|
|
xor ebx, ebx ;col
|
|
mov edx, dword [size]
|
|
sub dl, 8
|
|
push edx
|
|
putversion1:
|
|
mov edx, dword [size]
|
|
sub edx, 11 ;row
|
|
putversion2:
|
|
mov eax, edx
|
|
mul byte [size]
|
|
add eax, ebx
|
|
push ebx
|
|
mov ebx, dword [versionstring + ecx * 4]
|
|
mov dword [matrix + eax * 4], ebx
|
|
pop ebx
|
|
push edx
|
|
mov eax, ebx
|
|
mul byte [size]
|
|
add eax, edx
|
|
mov edx, dword [versionstring + ecx * 4]
|
|
mov dword [matrix + eax * 4], edx
|
|
inc cx
|
|
pop edx
|
|
inc edx
|
|
cmp edx, dword [esp]
|
|
jl putversion2
|
|
inc bx
|
|
cmp bx, 6
|
|
jl putversion1
|
|
pop edx
|
|
drawversion_end:
|
|
ret
|
|
|
|
makeECgenerator:
|
|
;input: eax = desired order of EC generator polynomial
|
|
;output: genpoly array is modified
|
|
pop ecx
|
|
pop eax
|
|
push ecx
|
|
;remove the above to change calling convention
|
|
mov [genpoly], 0
|
|
push eax
|
|
cld
|
|
mov ecx, 31
|
|
mov edi, genpoly
|
|
xor eax, eax
|
|
rep stosb
|
|
mov ecx, 2
|
|
ecgenloop:
|
|
push ecx
|
|
mov eax, ecx
|
|
dec eax
|
|
push eax
|
|
std
|
|
mov esi, genpoly - 1
|
|
add esi, ecx
|
|
mov edi, esi
|
|
inc edi
|
|
rep movsb
|
|
mov al, [genpoly]
|
|
add eax, [esp]
|
|
cmp eax, 255
|
|
jnge @f
|
|
sub eax, 255
|
|
cmp eax, 255
|
|
jnge @f
|
|
sub eax, 255
|
|
@@:
|
|
mov [genpoly], al
|
|
inc cl
|
|
xorloop:
|
|
mov ebx, genpoly
|
|
mov eax, ecx
|
|
xlatb
|
|
mov dh, al
|
|
mov al, cl
|
|
inc eax
|
|
xlatb
|
|
add eax, [esp]
|
|
cmp eax, 255
|
|
jnge @f
|
|
sub eax, 255
|
|
cmp eax, 255
|
|
jnge @f
|
|
sub eax, 255
|
|
@@:
|
|
mov ebx, mod285logs
|
|
xlatb
|
|
mov dl, al
|
|
mov al, dh
|
|
xlatb
|
|
xor al, dl
|
|
mov ebx, mod285antilogs
|
|
xlatb
|
|
mov byte [genpoly + ecx], al
|
|
inc cl
|
|
cmp ecx, dword [esp + 4]
|
|
jl xorloop
|
|
pop ecx
|
|
pop ecx
|
|
inc cl
|
|
cmp cl, byte [esp]
|
|
jle ecgenloop
|
|
pop eax
|
|
end2:
|
|
cld
|
|
ret
|
|
|
|
getblockpenalty:
|
|
;input: nothing
|
|
;output: eax = penalty score from squares
|
|
mov esi, 0
|
|
mov ebx, [size]
|
|
dec bl
|
|
dec bl
|
|
sqloop2:
|
|
mov ecx, [size]
|
|
dec cl
|
|
dec cl
|
|
sqloop:
|
|
mov eax, ecx
|
|
imul byte [size]
|
|
add eax, ebx
|
|
mov edx, [matrix + eax * 4]
|
|
and edx, CMSK
|
|
mov edi, edx
|
|
mov edx, [matrix + 4 + eax * 4]
|
|
and edx, CMSK
|
|
cmp edx, edi
|
|
jne @f
|
|
add eax, [size]
|
|
mov edx, [matrix + eax * 4]
|
|
and edx, CMSK
|
|
cmp edx, edi
|
|
jne @f
|
|
mov edx, [matrix + 4 + eax * 4]
|
|
and edx, CMSK
|
|
cmp edx, edi
|
|
jne @f
|
|
add esi, 3
|
|
@@:
|
|
dec ecx
|
|
cmp ecx, 0
|
|
jge sqloop
|
|
dec ebx
|
|
cmp ebx, 0
|
|
jge sqloop2
|
|
mov eax, esi
|
|
ret
|
|
|
|
getstraightpenalty:
|
|
;input: nothing
|
|
;output: eax = penalty score of qr code for
|
|
; straight runs of identical pixels
|
|
mov esi, 0 ; penalty
|
|
mov edi, 3 ; flags 1=new row, 2= new column
|
|
mov ecx, dword [size]
|
|
sub ecx, 5
|
|
gsploop2:
|
|
mov ebx, dword [size]
|
|
sub ebx, 5
|
|
gsploop1:
|
|
mov eax, ecx
|
|
imul byte [size]
|
|
add eax, ebx
|
|
push ecx
|
|
mov edx, dword [matrix + eax * 4]
|
|
and edx, CMSK
|
|
mov ecx, dword [matrix + 4 + eax * 4]
|
|
and ecx, CMSK
|
|
cmp edx, ecx
|
|
jne nostraightrow
|
|
mov ecx, dword [matrix + 8 + eax * 4]
|
|
and ecx, CMSK
|
|
cmp edx, ecx
|
|
jne nostraightrow
|
|
mov ecx, dword [matrix + 12 + eax * 4]
|
|
and ecx, CMSK
|
|
cmp edx, ecx
|
|
jne nostraightrow
|
|
mov ecx, dword [matrix + 16 + eax * 4]
|
|
and ecx, CMSK
|
|
cmp edx, ecx
|
|
jne nostraightrow
|
|
inc esi
|
|
test edi, 1
|
|
jz @f
|
|
inc esi
|
|
inc esi
|
|
@@:
|
|
and edi, 2
|
|
jmp @f
|
|
nostraightrow:
|
|
or edi, 1
|
|
@@:
|
|
pop ecx
|
|
mov eax, ebx
|
|
imul byte [size]
|
|
add eax, ecx
|
|
push ecx
|
|
mov edx, dword [matrix + eax * 4]
|
|
and edx, CMSK
|
|
add eax, dword [size]
|
|
mov ecx, dword [matrix + eax * 4]
|
|
and ecx, CMSK
|
|
cmp edx, ecx
|
|
jne nostraightcol
|
|
add eax, dword [size]
|
|
mov ecx, dword [matrix + eax * 4]
|
|
and ecx, CMSK
|
|
cmp edx, ecx
|
|
jne nostraightcol
|
|
add eax, dword [size]
|
|
mov ecx, dword [matrix + eax * 4]
|
|
and ecx, CMSK
|
|
cmp edx, ecx
|
|
jne nostraightcol
|
|
add eax, dword [size]
|
|
mov ecx, dword [matrix + eax * 4]
|
|
and ecx, CMSK
|
|
cmp edx, ecx
|
|
jne nostraightcol
|
|
inc esi
|
|
test edi, 2
|
|
jz @f
|
|
inc esi
|
|
inc esi
|
|
@@:
|
|
and edi, 1
|
|
jmp @f
|
|
nostraightcol:
|
|
or edi, 2
|
|
@@:
|
|
pop ecx
|
|
dec ebx
|
|
cmp ebx, 0
|
|
jge gsploop1
|
|
mov edi, 3
|
|
dec ecx
|
|
cmp ecx, 0
|
|
jge gsploop2
|
|
mov eax, esi
|
|
ret
|
|
|
|
|
|
;kolibrios_drawtowindow:
|
|
;;input: nothing
|
|
; call reducematrix
|
|
; mov eax, 7
|
|
; mov ebx, matrix
|
|
; mov ecx, [size]
|
|
; shl ecx, 16
|
|
; add ecx, [size]
|
|
; mov edx, 40
|
|
; shl edx, 16
|
|
; add edx, 80
|
|
; int 0x40
|
|
; ret
|
|
|
|
|
|
reducematrix:
|
|
;input: nothing
|
|
;reduces matrix from rgba to 3-byte rgb
|
|
;for use in KolibriOS system function 7
|
|
mov ecx, [size2]
|
|
dec ecx
|
|
mov esi, matrix
|
|
mov edi, esi
|
|
redloop:
|
|
lodsd
|
|
mov bx, 0
|
|
cmp al, 5
|
|
jb @f
|
|
mov bx, 0xffff
|
|
@@:
|
|
xchg ax, bx
|
|
stosw
|
|
stosb
|
|
dec ecx
|
|
jns redloop
|
|
ret
|
|
|
|
iglobal
|
|
|
|
versionstrings dd 0x7C94, 0x85BC, 0x9A99, 0xA4D3, 0xBBF6
|
|
dd 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78, 0x1145D
|
|
dd 0x12A17, 0x13532, 0x149A6, 0x15683, 0x168C9, 0x177EC
|
|
dd 0x18EC4, 0x191E1, 0x1AFAB, 0x1B08E, 0x1CC1A, 0x1D33F
|
|
dd 0x1ED75, 0x1F250, 0x209D5, 0x216F0, 0x228BA, 0x2379F
|
|
dd 0x24B0B, 0x2542E, 0x26A64, 0x27541, 0x28C69
|
|
|
|
formatstrings dw 0x77C4, 0x72F3, 0x7DAA, 0x789D, 0x662F
|
|
dw 0x6318, 0x6C41, 0x6976, 0x5412, 0x5125, 0x5E7C
|
|
dw 0x5B4B, 0x45F9, 0x40CE, 0x4F97, 0x4AA0, 0x355F
|
|
dw 0x3068, 0x3F31, 0x3A06, 0x24B4, 0x2183, 0x2EDA
|
|
dw 0x2BED, 0x1689, 0x13BE, 0x1CE7, 0x19D0, 0x762
|
|
dw 0x255, 0xD0C, 0x83B
|
|
|
|
mod285logs db 1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232
|
|
db 205, 135, 19, 38, 76, 152, 45, 90, 180, 117, 234, 201
|
|
db 143, 3, 6, 12, 24, 48, 96, 192, 157, 39, 78, 156, 37
|
|
db 74, 148, 53, 106, 212, 181, 119, 238, 193, 159, 35
|
|
db 70, 140, 5, 10, 20, 40, 80, 160, 93, 186, 105, 210
|
|
db 185, 111, 222, 161, 95, 190, 97, 194, 153, 47, 94
|
|
db 188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231
|
|
db 211, 187, 107, 214, 177, 127, 254, 225, 223, 163, 91
|
|
db 182, 113, 226, 217, 175, 67, 134, 17, 34, 68, 136, 13
|
|
db 26, 52, 104, 208, 189, 103, 206, 129, 31, 62, 124, 248
|
|
db 237, 199, 147, 59, 118, 236, 197, 151, 51, 102, 204
|
|
db 133, 23, 46, 92, 184, 109, 218, 169, 79, 158, 33, 66
|
|
db 132, 21, 42, 84, 168, 77, 154, 41, 82, 164, 85, 170
|
|
db 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191
|
|
db 99, 198, 145, 63, 126, 252, 229, 215, 179, 123, 246
|
|
db 241, 255, 227, 219, 171, 75, 150, 49, 98, 196, 149
|
|
db 55, 110, 220, 165, 87, 174, 65, 130, 25, 50, 100, 200
|
|
db 141, 7, 14, 28, 56, 112, 224, 221, 167, 83, 166, 81
|
|
db 162, 89, 178, 121, 242, 249, 239, 195, 155, 43, 86
|
|
db 172, 69, 138, 9, 18, 36, 72, 144, 61, 122, 244, 245
|
|
db 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125
|
|
db 250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142, 1
|
|
|
|
mod285antilogs db 0, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238
|
|
db 27, 104, 199, 75, 4, 100, 224, 14, 52
|
|
db 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113, 5
|
|
db 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240
|
|
db 18, 130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201
|
|
db 154, 9, 120, 77, 228, 114, 166, 6, 191, 139, 98, 102, 221
|
|
db 48, 253, 226, 152, 37, 179, 16, 145, 34, 136, 54, 208
|
|
db 148, 206, 143, 150, 219, 189, 241, 210, 19, 92, 131, 56
|
|
db 70, 64, 30, 66, 182, 163, 195, 72, 126, 110, 107, 58, 40
|
|
db 84, 250, 133, 186, 61, 202, 94, 155, 159, 10, 21, 121
|
|
db 43, 78, 212, 229, 172, 115, 243, 167, 87, 7, 112, 192
|
|
db 247, 140, 128, 99, 13, 103, 74, 222, 237, 49, 197, 254, 24
|
|
db 227, 165, 153, 119, 38, 184, 180, 124, 17, 68, 146, 217
|
|
db 35, 32, 137, 46, 55, 63, 209, 91, 149, 188, 207, 205, 144
|
|
db 135, 151, 178, 220, 252, 190, 97, 242, 86, 211, 171, 20
|
|
db 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31, 45, 67
|
|
db 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12, 111
|
|
db 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134, 177
|
|
db 187, 204, 62, 90, 203, 89, 95, 176, 156, 169, 160, 81, 11
|
|
db 245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230
|
|
db 231, 173, 232, 116, 214, 244, 234, 168, 80, 88, 175
|
|
|
|
;bigtable (blocks by version and ec level)
|
|
;rowmajor - version
|
|
;rowminor - eclevel
|
|
;columns: number of blocks in group 1,
|
|
; number of data codewords in each of group 1's blocks,
|
|
; number of blocks in group 2,
|
|
bigtable db 1,19,0,1,16,0,1,13,0,1,9,0,1,34,0,1,28,0,1,22,0
|
|
db 1,16,0,1,55,0,1,44,0,2,17,0,2,13,0,1,80
|
|
db 0,2,32,0,2,24,0,4,9,0,1,108,0,2,43,0,2,15,2,2,11
|
|
db 2,2,68,0,4,27,0,4,19,0,4,15,0,2,78,0,4
|
|
db 31,0,2,14,4,4,13,1,2,97,0,2,38,2,4,18,2,4,14,2,2
|
|
db 116,0,3,36,2,4,16,4,4,12,4,2,68,2,4,43
|
|
db 1,6,19,2,6,15,2,4,81,0,1,50,4,4,22,4,3,12,8,2,92
|
|
db 2,6,36,2,4,20,6,7,14,4,4,107,0,8,37,1,8
|
|
db 20,4,12,11,4,3,115,1,4,40,5,11,16,5,11,12,5,5,87
|
|
db 1,5,41,5,5,24,7,11,12,7,5,98,1,7,45,3
|
|
db 15,19,2,3,15,13,1,107,5,10,46,1,1,22,15,2,14,17
|
|
db 5,120,1,9,43,4,17,22,1,2,14,19,3,113,4,3
|
|
db 44,11,17,21,4,9,13,16,3,107,5,3,41,13,15,24,5,15
|
|
db 15,10,4,116,4,17,42,0,17,22,6,19,16,6,2
|
|
db 111,7,17,46,0,7,24,16,34,13,0,4,121,5,4,47,14,11
|
|
db 24,14,16,15,14,6,117,4,6,45,14,11,24,16
|
|
db 30,16,2,8,106,4,8,47,13,7,24,22,22,15,13,10,114
|
|
db 2,19,46,4,28,22,6,33,16,4,8,122,4,22,45
|
|
db 3,8,23,26,12,15,28,3,117,10,3,45,23,4,24,31,11
|
|
db 15,31,7,116,7,21,45,7,1,23,37,19,15,26,5
|
|
db 115,10,19,47,10,15,24,25,23,15,25,13,115,3,2,46
|
|
db 29,42,24,1,23,15,28,17,115,0,10,46,23,10
|
|
db 24,35,19,15,35,17,115,1,14,46,21,29,24,19,11,15
|
|
db 46,13,115,6,14,46,23,44,24,7,59,16,1,12
|
|
db 121,7,12,47,26,39,24,14,22,15,41,6,121,14,6,47
|
|
db 34,46,24,10,2,15,64,17,122,4,29,46,14,49
|
|
db 24,10,24,15,46,4,122,18,13,46,32,48,24,14,42,15
|
|
db 32,20,117,4,40,47,7,43,24,22,10,15,67,19
|
|
db 118,6,18,47,31,34,24,34,20,15,61
|
|
|
|
charcountlengths db 10,9,8,8,12,11,16,10,14,13,16,12
|
|
|
|
modeindicators db 1,2,4,8,7
|
|
|
|
diffs db 24,24,26,26,26,28,28
|
|
|
|
alphamode db '0123456789ABCDEFGHIJKL'
|
|
db 'MNOPQRSTUVWXYZ $%*+-./:', 0
|
|
|
|
DARK equ 0
|
|
CMSK equ 0FFFF00H
|
|
|
|
;1 dark, 1 light, 3 dark, 1 light, 1 dark
|
|
;preceded or followed by 4 light
|
|
sequence dd CMSK, CMSK, CMSK, CMSK
|
|
dd DARK, CMSK, DARK, DARK, DARK, DARK
|
|
dd CMSK, DARK, CMSK, CMSK, CMSK, CMSK
|
|
|
|
endg |