' IdCodeMaxQrFontDemo -- Crystal Reports Custom Function (Basic Syntax)
'
' DEMO VERSION -- prepends "DEMO-" to the payload before encoding, so the
' resulting QR always differs from the real customer data. See
' IdCodeMaxQrFont.txt for the full (unprefixed) version.
'
' Generates a real QR Code (ISO/IEC 18004), Byte mode, ECC level Quartile,
' automatic version selection (1-40), FIXED mask pattern 0 -- entirely
' inside Crystal Reports, independent of the database. Returns a
' multi-line grid of "#" (dark module) / "." (light module) characters,
' one line per QR row, for the "IdCodeMax QR" block font.
'
' IMPORTANT -- packed arrays: Crystal Reports formula arrays are capped
' at 1000 elements ("An array dimension must be an integer between 1
' and 1000", confirmed empirically). A version-40 QR needs up to 31329
' grid cells and ~3706 codeword bytes, so every array here packs several
' logical values into each physical element (32 booleans/element for the
' module grid, 4 bytes/element for codeword arrays) and unpacks them with
' arithmetic (Truncate/Mod), the same technique used for XOR emulation.
' Verified in Python at the maximum version/payload size before writing
' this file -- see crystal-reports/qr_python_reference/crystal_sim_qr_packed.py.
'
' The light module is ".", deliberately NOT a space: Crystal Reports (like
' many text renderers) special-cases U+0020 as a non-printing character
' instead of drawing its glyph.
'
' Fixed mask pattern 0 (not the usual "try all 8, pick lowest penalty"):
' any of the 8 masks yields a fully standard-compliant QR; evaluating all
' 8 penalty scores over the whole grid would be expensive per report row
' in a language with no native bitwise ops. Verified scannable with mask 0.
'
' Algorithm: IdCodeMax own from-scratch QR encoder (cross-checked
' against Project Nayuki QR-Code-generator, MIT licensed, for the
' standard numeric tables).
'
' Self-contained -- no dependency on any other Custom Function. Bit-XOR
' emulation is inlined directly (confirmed empirically: a Custom Function
' calling another Custom Function from inside its own body causes a
' runtime "Not implemented" error in Crystal Reports, even though each
' function works fine called directly from a report formula).
'
' Usage in a formula: IdCodeMaxQrFontDemo({YourTable.YourField})

Function IdCodeMaxQrFontDemo (payload As String) As String
    Dim gfExp(255) As Number
    Dim gfLog(256) As Number
    Dim eccPerBlock(40) As Number
    Dim numBlocksTable(40) As Number
    Dim modulesPacked(980) As Number
    Dim isFuncPacked(980) As Number
    Dim dataCwPacked(417) As Number
    Dim divisor(31) As Number
    Dim allCwPacked(927) As Number
    Dim blockBytesPacked(935) As Number
    Dim alignPos(8) As Number
    Dim finderX(3) As Number
    Dim finderY(3) As Number
    Dim pow2(34) As Number
    Dim pow256(4) As Number
    Dim blocksStartIdx(69) As Number
    Dim reg(31) As Number

    Dim i As Number
    Dim j As Number
    Dim k As Number
    Dim n As Number
    Dim version As Number
    Dim size As Number
    Dim capBits As Number
    Dim ccBits As Number
    Dim usedBits As Number
    Dim idx As Number
    Dim x As Number
    Dim y As Number
    Dim dx As Number
    Dim dy As Number
    Dim xx As Number
    Dim yy As Number
    Dim mm As Number
    Dim numAlign As Number
    Dim numAlignV As Number
    Dim step_ As Number
    Dim skip As Boolean
    Dim mask As Number
    Dim dataVal As Number
    Dim remVal As Number
    Dim bits As Number
    Dim bitVal As Boolean
    Dim a_ As Number
    Dim b_ As Number
    Dim byteCode As Number
    Dim termBits As Number
    Dim padBits As Number
    Dim datacapBits As Number
    Dim numDataBytes As Number
    Dim v As Number
    Dim blockEccLen As Number
    Dim numBlocks As Number
    Dim root As Number
    Dim sumLog As Number
    Dim product As Number
    Dim rawCodewords As Number
    Dim numShort As Number
    Dim shortLen As Number
    Dim blockDataLen As Number
    Dim blockDataStart As Number
    Dim factor As Number
    Dim ci As Number
    Dim writePos As Number
    Dim totalCodewordsBuilt As Number
    Dim bitIndex As Number
    Dim totalBits As Number
    Dim right_ As Number
    Dim vert As Number
    Dim jj As Number
    Dim upward As Boolean
    Dim bitPos As Number
    Dim result As String
    Dim rowText As String
    Dim curByteVal As Number
    Dim curNBits As Number
    Dim byteCount As Number
    Dim bitsWritten As Number
    Dim bitToEmit As Number
    Dim padCycle As Number
    Dim n1 As Number
    Dim pbIdx As Number
    Dim pbOff As Number
    Dim pbCur As Number
    Dim pbNew As Number
    Dim pyIdx As Number
    Dim pyOff As Number
    Dim pyCur As Number
    Dim isFuncVal As Boolean
    Dim moduleVal As Boolean
    Dim extra As Number
    Dim xorResult As Number
    Dim xorPlace As Number
    Dim xorA As Number
    Dim xorB As Number
    Dim xorI As Number
    Dim xorABit As Number
    Dim xorBBit As Number

    payload = "DEMO-" & payload

    ' ---- GF(256) log/antilog tables (primitive poly 0x11D, generator 2) ----
    gfExp(1) = 1
    gfExp(2) = 2
    gfExp(3) = 4
    gfExp(4) = 8
    gfExp(5) = 16
    gfExp(6) = 32
    gfExp(7) = 64
    gfExp(8) = 128
    gfExp(9) = 29
    gfExp(10) = 58
    gfExp(11) = 116
    gfExp(12) = 232
    gfExp(13) = 205
    gfExp(14) = 135
    gfExp(15) = 19
    gfExp(16) = 38
    gfExp(17) = 76
    gfExp(18) = 152
    gfExp(19) = 45
    gfExp(20) = 90
    gfExp(21) = 180
    gfExp(22) = 117
    gfExp(23) = 234
    gfExp(24) = 201
    gfExp(25) = 143
    gfExp(26) = 3
    gfExp(27) = 6
    gfExp(28) = 12
    gfExp(29) = 24
    gfExp(30) = 48
    gfExp(31) = 96
    gfExp(32) = 192
    gfExp(33) = 157
    gfExp(34) = 39
    gfExp(35) = 78
    gfExp(36) = 156
    gfExp(37) = 37
    gfExp(38) = 74
    gfExp(39) = 148
    gfExp(40) = 53
    gfExp(41) = 106
    gfExp(42) = 212
    gfExp(43) = 181
    gfExp(44) = 119
    gfExp(45) = 238
    gfExp(46) = 193
    gfExp(47) = 159
    gfExp(48) = 35
    gfExp(49) = 70
    gfExp(50) = 140
    gfExp(51) = 5
    gfExp(52) = 10
    gfExp(53) = 20
    gfExp(54) = 40
    gfExp(55) = 80
    gfExp(56) = 160
    gfExp(57) = 93
    gfExp(58) = 186
    gfExp(59) = 105
    gfExp(60) = 210
    gfExp(61) = 185
    gfExp(62) = 111
    gfExp(63) = 222
    gfExp(64) = 161
    gfExp(65) = 95
    gfExp(66) = 190
    gfExp(67) = 97
    gfExp(68) = 194
    gfExp(69) = 153
    gfExp(70) = 47
    gfExp(71) = 94
    gfExp(72) = 188
    gfExp(73) = 101
    gfExp(74) = 202
    gfExp(75) = 137
    gfExp(76) = 15
    gfExp(77) = 30
    gfExp(78) = 60
    gfExp(79) = 120
    gfExp(80) = 240
    gfExp(81) = 253
    gfExp(82) = 231
    gfExp(83) = 211
    gfExp(84) = 187
    gfExp(85) = 107
    gfExp(86) = 214
    gfExp(87) = 177
    gfExp(88) = 127
    gfExp(89) = 254
    gfExp(90) = 225
    gfExp(91) = 223
    gfExp(92) = 163
    gfExp(93) = 91
    gfExp(94) = 182
    gfExp(95) = 113
    gfExp(96) = 226
    gfExp(97) = 217
    gfExp(98) = 175
    gfExp(99) = 67
    gfExp(100) = 134
    gfExp(101) = 17
    gfExp(102) = 34
    gfExp(103) = 68
    gfExp(104) = 136
    gfExp(105) = 13
    gfExp(106) = 26
    gfExp(107) = 52
    gfExp(108) = 104
    gfExp(109) = 208
    gfExp(110) = 189
    gfExp(111) = 103
    gfExp(112) = 206
    gfExp(113) = 129
    gfExp(114) = 31
    gfExp(115) = 62
    gfExp(116) = 124
    gfExp(117) = 248
    gfExp(118) = 237
    gfExp(119) = 199
    gfExp(120) = 147
    gfExp(121) = 59
    gfExp(122) = 118
    gfExp(123) = 236
    gfExp(124) = 197
    gfExp(125) = 151
    gfExp(126) = 51
    gfExp(127) = 102
    gfExp(128) = 204
    gfExp(129) = 133
    gfExp(130) = 23
    gfExp(131) = 46
    gfExp(132) = 92
    gfExp(133) = 184
    gfExp(134) = 109
    gfExp(135) = 218
    gfExp(136) = 169
    gfExp(137) = 79
    gfExp(138) = 158
    gfExp(139) = 33
    gfExp(140) = 66
    gfExp(141) = 132
    gfExp(142) = 21
    gfExp(143) = 42
    gfExp(144) = 84
    gfExp(145) = 168
    gfExp(146) = 77
    gfExp(147) = 154
    gfExp(148) = 41
    gfExp(149) = 82
    gfExp(150) = 164
    gfExp(151) = 85
    gfExp(152) = 170
    gfExp(153) = 73
    gfExp(154) = 146
    gfExp(155) = 57
    gfExp(156) = 114
    gfExp(157) = 228
    gfExp(158) = 213
    gfExp(159) = 183
    gfExp(160) = 115
    gfExp(161) = 230
    gfExp(162) = 209
    gfExp(163) = 191
    gfExp(164) = 99
    gfExp(165) = 198
    gfExp(166) = 145
    gfExp(167) = 63
    gfExp(168) = 126
    gfExp(169) = 252
    gfExp(170) = 229
    gfExp(171) = 215
    gfExp(172) = 179
    gfExp(173) = 123
    gfExp(174) = 246
    gfExp(175) = 241
    gfExp(176) = 255
    gfExp(177) = 227
    gfExp(178) = 219
    gfExp(179) = 171
    gfExp(180) = 75
    gfExp(181) = 150
    gfExp(182) = 49
    gfExp(183) = 98
    gfExp(184) = 196
    gfExp(185) = 149
    gfExp(186) = 55
    gfExp(187) = 110
    gfExp(188) = 220
    gfExp(189) = 165
    gfExp(190) = 87
    gfExp(191) = 174
    gfExp(192) = 65
    gfExp(193) = 130
    gfExp(194) = 25
    gfExp(195) = 50
    gfExp(196) = 100
    gfExp(197) = 200
    gfExp(198) = 141
    gfExp(199) = 7
    gfExp(200) = 14
    gfExp(201) = 28
    gfExp(202) = 56
    gfExp(203) = 112
    gfExp(204) = 224
    gfExp(205) = 221
    gfExp(206) = 167
    gfExp(207) = 83
    gfExp(208) = 166
    gfExp(209) = 81
    gfExp(210) = 162
    gfExp(211) = 89
    gfExp(212) = 178
    gfExp(213) = 121
    gfExp(214) = 242
    gfExp(215) = 249
    gfExp(216) = 239
    gfExp(217) = 195
    gfExp(218) = 155
    gfExp(219) = 43
    gfExp(220) = 86
    gfExp(221) = 172
    gfExp(222) = 69
    gfExp(223) = 138
    gfExp(224) = 9
    gfExp(225) = 18
    gfExp(226) = 36
    gfExp(227) = 72
    gfExp(228) = 144
    gfExp(229) = 61
    gfExp(230) = 122
    gfExp(231) = 244
    gfExp(232) = 245
    gfExp(233) = 247
    gfExp(234) = 243
    gfExp(235) = 251
    gfExp(236) = 235
    gfExp(237) = 203
    gfExp(238) = 139
    gfExp(239) = 11
    gfExp(240) = 22
    gfExp(241) = 44
    gfExp(242) = 88
    gfExp(243) = 176
    gfExp(244) = 125
    gfExp(245) = 250
    gfExp(246) = 233
    gfExp(247) = 207
    gfExp(248) = 131
    gfExp(249) = 27
    gfExp(250) = 54
    gfExp(251) = 108
    gfExp(252) = 216
    gfExp(253) = 173
    gfExp(254) = 71
    gfExp(255) = 142
    gfLog(1) = 0
    gfLog(2) = 0
    gfLog(3) = 1
    gfLog(4) = 25
    gfLog(5) = 2
    gfLog(6) = 50
    gfLog(7) = 26
    gfLog(8) = 198
    gfLog(9) = 3
    gfLog(10) = 223
    gfLog(11) = 51
    gfLog(12) = 238
    gfLog(13) = 27
    gfLog(14) = 104
    gfLog(15) = 199
    gfLog(16) = 75
    gfLog(17) = 4
    gfLog(18) = 100
    gfLog(19) = 224
    gfLog(20) = 14
    gfLog(21) = 52
    gfLog(22) = 141
    gfLog(23) = 239
    gfLog(24) = 129
    gfLog(25) = 28
    gfLog(26) = 193
    gfLog(27) = 105
    gfLog(28) = 248
    gfLog(29) = 200
    gfLog(30) = 8
    gfLog(31) = 76
    gfLog(32) = 113
    gfLog(33) = 5
    gfLog(34) = 138
    gfLog(35) = 101
    gfLog(36) = 47
    gfLog(37) = 225
    gfLog(38) = 36
    gfLog(39) = 15
    gfLog(40) = 33
    gfLog(41) = 53
    gfLog(42) = 147
    gfLog(43) = 142
    gfLog(44) = 218
    gfLog(45) = 240
    gfLog(46) = 18
    gfLog(47) = 130
    gfLog(48) = 69
    gfLog(49) = 29
    gfLog(50) = 181
    gfLog(51) = 194
    gfLog(52) = 125
    gfLog(53) = 106
    gfLog(54) = 39
    gfLog(55) = 249
    gfLog(56) = 185
    gfLog(57) = 201
    gfLog(58) = 154
    gfLog(59) = 9
    gfLog(60) = 120
    gfLog(61) = 77
    gfLog(62) = 228
    gfLog(63) = 114
    gfLog(64) = 166
    gfLog(65) = 6
    gfLog(66) = 191
    gfLog(67) = 139
    gfLog(68) = 98
    gfLog(69) = 102
    gfLog(70) = 221
    gfLog(71) = 48
    gfLog(72) = 253
    gfLog(73) = 226
    gfLog(74) = 152
    gfLog(75) = 37
    gfLog(76) = 179
    gfLog(77) = 16
    gfLog(78) = 145
    gfLog(79) = 34
    gfLog(80) = 136
    gfLog(81) = 54
    gfLog(82) = 208
    gfLog(83) = 148
    gfLog(84) = 206
    gfLog(85) = 143
    gfLog(86) = 150
    gfLog(87) = 219
    gfLog(88) = 189
    gfLog(89) = 241
    gfLog(90) = 210
    gfLog(91) = 19
    gfLog(92) = 92
    gfLog(93) = 131
    gfLog(94) = 56
    gfLog(95) = 70
    gfLog(96) = 64
    gfLog(97) = 30
    gfLog(98) = 66
    gfLog(99) = 182
    gfLog(100) = 163
    gfLog(101) = 195
    gfLog(102) = 72
    gfLog(103) = 126
    gfLog(104) = 110
    gfLog(105) = 107
    gfLog(106) = 58
    gfLog(107) = 40
    gfLog(108) = 84
    gfLog(109) = 250
    gfLog(110) = 133
    gfLog(111) = 186
    gfLog(112) = 61
    gfLog(113) = 202
    gfLog(114) = 94
    gfLog(115) = 155
    gfLog(116) = 159
    gfLog(117) = 10
    gfLog(118) = 21
    gfLog(119) = 121
    gfLog(120) = 43
    gfLog(121) = 78
    gfLog(122) = 212
    gfLog(123) = 229
    gfLog(124) = 172
    gfLog(125) = 115
    gfLog(126) = 243
    gfLog(127) = 167
    gfLog(128) = 87
    gfLog(129) = 7
    gfLog(130) = 112
    gfLog(131) = 192
    gfLog(132) = 247
    gfLog(133) = 140
    gfLog(134) = 128
    gfLog(135) = 99
    gfLog(136) = 13
    gfLog(137) = 103
    gfLog(138) = 74
    gfLog(139) = 222
    gfLog(140) = 237
    gfLog(141) = 49
    gfLog(142) = 197
    gfLog(143) = 254
    gfLog(144) = 24
    gfLog(145) = 227
    gfLog(146) = 165
    gfLog(147) = 153
    gfLog(148) = 119
    gfLog(149) = 38
    gfLog(150) = 184
    gfLog(151) = 180
    gfLog(152) = 124
    gfLog(153) = 17
    gfLog(154) = 68
    gfLog(155) = 146
    gfLog(156) = 217
    gfLog(157) = 35
    gfLog(158) = 32
    gfLog(159) = 137
    gfLog(160) = 46
    gfLog(161) = 55
    gfLog(162) = 63
    gfLog(163) = 209
    gfLog(164) = 91
    gfLog(165) = 149
    gfLog(166) = 188
    gfLog(167) = 207
    gfLog(168) = 205
    gfLog(169) = 144
    gfLog(170) = 135
    gfLog(171) = 151
    gfLog(172) = 178
    gfLog(173) = 220
    gfLog(174) = 252
    gfLog(175) = 190
    gfLog(176) = 97
    gfLog(177) = 242
    gfLog(178) = 86
    gfLog(179) = 211
    gfLog(180) = 171
    gfLog(181) = 20
    gfLog(182) = 42
    gfLog(183) = 93
    gfLog(184) = 158
    gfLog(185) = 132
    gfLog(186) = 60
    gfLog(187) = 57
    gfLog(188) = 83
    gfLog(189) = 71
    gfLog(190) = 109
    gfLog(191) = 65
    gfLog(192) = 162
    gfLog(193) = 31
    gfLog(194) = 45
    gfLog(195) = 67
    gfLog(196) = 216
    gfLog(197) = 183
    gfLog(198) = 123
    gfLog(199) = 164
    gfLog(200) = 118
    gfLog(201) = 196
    gfLog(202) = 23
    gfLog(203) = 73
    gfLog(204) = 236
    gfLog(205) = 127
    gfLog(206) = 12
    gfLog(207) = 111
    gfLog(208) = 246
    gfLog(209) = 108
    gfLog(210) = 161
    gfLog(211) = 59
    gfLog(212) = 82
    gfLog(213) = 41
    gfLog(214) = 157
    gfLog(215) = 85
    gfLog(216) = 170
    gfLog(217) = 251
    gfLog(218) = 96
    gfLog(219) = 134
    gfLog(220) = 177
    gfLog(221) = 187
    gfLog(222) = 204
    gfLog(223) = 62
    gfLog(224) = 90
    gfLog(225) = 203
    gfLog(226) = 89
    gfLog(227) = 95
    gfLog(228) = 176
    gfLog(229) = 156
    gfLog(230) = 169
    gfLog(231) = 160
    gfLog(232) = 81
    gfLog(233) = 11
    gfLog(234) = 245
    gfLog(235) = 22
    gfLog(236) = 235
    gfLog(237) = 122
    gfLog(238) = 117
    gfLog(239) = 44
    gfLog(240) = 215
    gfLog(241) = 79
    gfLog(242) = 174
    gfLog(243) = 213
    gfLog(244) = 233
    gfLog(245) = 230
    gfLog(246) = 231
    gfLog(247) = 173
    gfLog(248) = 232
    gfLog(249) = 116
    gfLog(250) = 214
    gfLog(251) = 244
    gfLog(252) = 234
    gfLog(253) = 168
    gfLog(254) = 80
    gfLog(255) = 88
    gfLog(256) = 175

    ' ---- ECC codewords per block / number of EC blocks, ECC level Quartile ----
    eccPerBlock(1) = 13
    eccPerBlock(2) = 22
    eccPerBlock(3) = 18
    eccPerBlock(4) = 26
    eccPerBlock(5) = 18
    eccPerBlock(6) = 24
    eccPerBlock(7) = 18
    eccPerBlock(8) = 22
    eccPerBlock(9) = 20
    eccPerBlock(10) = 24
    eccPerBlock(11) = 28
    eccPerBlock(12) = 26
    eccPerBlock(13) = 24
    eccPerBlock(14) = 20
    eccPerBlock(15) = 30
    eccPerBlock(16) = 24
    eccPerBlock(17) = 28
    eccPerBlock(18) = 28
    eccPerBlock(19) = 26
    eccPerBlock(20) = 30
    eccPerBlock(21) = 28
    eccPerBlock(22) = 30
    eccPerBlock(23) = 30
    eccPerBlock(24) = 30
    eccPerBlock(25) = 30
    eccPerBlock(26) = 28
    eccPerBlock(27) = 30
    eccPerBlock(28) = 30
    eccPerBlock(29) = 30
    eccPerBlock(30) = 30
    eccPerBlock(31) = 30
    eccPerBlock(32) = 30
    eccPerBlock(33) = 30
    eccPerBlock(34) = 30
    eccPerBlock(35) = 30
    eccPerBlock(36) = 30
    eccPerBlock(37) = 30
    eccPerBlock(38) = 30
    eccPerBlock(39) = 30
    eccPerBlock(40) = 30
    numBlocksTable(1) = 1
    numBlocksTable(2) = 1
    numBlocksTable(3) = 2
    numBlocksTable(4) = 2
    numBlocksTable(5) = 4
    numBlocksTable(6) = 4
    numBlocksTable(7) = 6
    numBlocksTable(8) = 6
    numBlocksTable(9) = 8
    numBlocksTable(10) = 8
    numBlocksTable(11) = 8
    numBlocksTable(12) = 10
    numBlocksTable(13) = 12
    numBlocksTable(14) = 16
    numBlocksTable(15) = 12
    numBlocksTable(16) = 17
    numBlocksTable(17) = 16
    numBlocksTable(18) = 18
    numBlocksTable(19) = 21
    numBlocksTable(20) = 20
    numBlocksTable(21) = 23
    numBlocksTable(22) = 23
    numBlocksTable(23) = 25
    numBlocksTable(24) = 27
    numBlocksTable(25) = 29
    numBlocksTable(26) = 34
    numBlocksTable(27) = 34
    numBlocksTable(28) = 35
    numBlocksTable(29) = 38
    numBlocksTable(30) = 40
    numBlocksTable(31) = 43
    numBlocksTable(32) = 45
    numBlocksTable(33) = 48
    numBlocksTable(34) = 51
    numBlocksTable(35) = 53
    numBlocksTable(36) = 56
    numBlocksTable(37) = 59
    numBlocksTable(38) = 62
    numBlocksTable(39) = 65
    numBlocksTable(40) = 68

    ' ---- powers of two (pow2(i+1) = 2^i), avoids relying on a Crystal exponent operator ----
    pow2(1) = 1
    pow2(2) = 2
    pow2(3) = 4
    pow2(4) = 8
    pow2(5) = 16
    pow2(6) = 32
    pow2(7) = 64
    pow2(8) = 128
    pow2(9) = 256
    pow2(10) = 512
    pow2(11) = 1024
    pow2(12) = 2048
    pow2(13) = 4096
    pow2(14) = 8192
    pow2(15) = 16384
    pow2(16) = 32768
    pow2(17) = 65536
    pow2(18) = 131072
    pow2(19) = 262144
    pow2(20) = 524288
    pow2(21) = 1048576
    pow2(22) = 2097152
    pow2(23) = 4194304
    pow2(24) = 8388608
    pow2(25) = 16777216
    pow2(26) = 33554432
    pow2(27) = 67108864
    pow2(28) = 134217728
    pow2(29) = 268435456
    pow2(30) = 536870912
    pow2(31) = 1073741824
    pow2(32) = 2147483648
    pow2(33) = 4294967296
    pow2(34) = 8589934592

    ' ---- powers of 256 (pow256(i+1) = 256^i), for byte-packed array access ----
    pow256(1) = 1
    pow256(2) = 256
    pow256(3) = 65536
    pow256(4) = 16777216

    ' ---- clear packed arrays (defensive -- Custom Functions may be called once per report row) ----
    For i = 1 To 980
        modulesPacked(i) = 0
        isFuncPacked(i) = 0
    Next
    For i = 1 To 417
        dataCwPacked(i) = 0
    Next
    For i = 1 To 935
        blockBytesPacked(i) = 0
    Next
    For i = 1 To 927
        allCwPacked(i) = 0
    Next

    ' ---- 1) choose smallest version (1-40) that fits the payload, Byte mode ----
    n = Len(payload)
    version = 0
    For v = 1 To 40
        numAlignV = Truncate(v / 7) + 2
        capBits = (16 * v + 128) * v + 64
        If v >= 2 Then
            capBits = capBits - ((25 * numAlignV - 10) * numAlignV - 55)
            If v >= 7 Then
                capBits = capBits - 36
            End If
        End If
        capBits = (Truncate(capBits / 8) - eccPerBlock(v) * numBlocksTable(v)) * 8
        If v <= 9 Then
            ccBits = 8
        Else
            ccBits = 16
        End If
        usedBits = 4 + ccBits + 8 * n
        If usedBits <= capBits Then
            version = v
            Exit For
        End If
    Next
    If version = 0 Then
        IdCodeMaxQrFontDemo = ""
        Exit Function
    End If

    size = version * 4 + 17

    ' ---- timing patterns ----
    For i = 0 To size - 1
        moduleVal = (i Mod 2 = 0)
    pbIdx = Truncate(((i * size + 6 + 1) - 1) / 32) + 1
    pbOff = ((i * size + 6 + 1) - 1) Mod 32
    pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
    If (moduleVal) Then
        pbNew = 1
    Else
        pbNew = 0
    End If
    If pbCur <> pbNew Then
        modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
    End If
    pbIdx = Truncate(((i * size + 6 + 1) - 1) / 32) + 1
    pbOff = ((i * size + 6 + 1) - 1) Mod 32
    pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
    If (True) Then
        pbNew = 1
    Else
        pbNew = 0
    End If
    If pbCur <> pbNew Then
        isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
    End If
    pbIdx = Truncate(((6 * size + i + 1) - 1) / 32) + 1
    pbOff = ((6 * size + i + 1) - 1) Mod 32
    pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
    If (moduleVal) Then
        pbNew = 1
    Else
        pbNew = 0
    End If
    If pbCur <> pbNew Then
        modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
    End If
    pbIdx = Truncate(((6 * size + i + 1) - 1) / 32) + 1
    pbOff = ((6 * size + i + 1) - 1) Mod 32
    pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
    If (True) Then
        pbNew = 1
    Else
        pbNew = 0
    End If
    If pbCur <> pbNew Then
        isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
    End If
    Next

    ' ---- 3 finder patterns (top-left, top-right, bottom-left) ----
    finderX(1) = 3 : finderY(1) = 3
    finderX(2) = size - 4 : finderY(2) = 3
    finderX(3) = 3 : finderY(3) = size - 4
    For k = 1 To 3
        For dy = -4 To 4
            For dx = -4 To 4
                xx = finderX(k) + dx
                yy = finderY(k) + dy
                If xx >= 0 And xx < size And yy >= 0 And yy < size Then
                    mm = Abs(dx)
                    If Abs(dy) > mm Then mm = Abs(dy)
                    moduleVal = (mm <> 2 And mm <> 4)
    pbIdx = Truncate(((yy * size + xx + 1) - 1) / 32) + 1
    pbOff = ((yy * size + xx + 1) - 1) Mod 32
    pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
    If (moduleVal) Then
        pbNew = 1
    Else
        pbNew = 0
    End If
    If pbCur <> pbNew Then
        modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
    End If
    pbIdx = Truncate(((yy * size + xx + 1) - 1) / 32) + 1
    pbOff = ((yy * size + xx + 1) - 1) Mod 32
    pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
    If (True) Then
        pbNew = 1
    Else
        pbNew = 0
    End If
    If pbCur <> pbNew Then
        isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
    End If
                End If
            Next
        Next
    Next

    ' ---- alignment pattern positions (get_alignment_pattern_positions) ----
    numAlign = 0
    If version <> 1 Then
        numAlign = Truncate(version / 7) + 2
        step_ = Truncate((version * 8 + numAlign * 3 + 5) / (numAlign * 4 - 4)) * 2
        For i = 0 To numAlign - 2
            alignPos(numAlign - i) = size - 7 - i * step_
        Next
        alignPos(1) = 6
    End If

    ' ---- draw alignment patterns (skip the 3 finder corners) ----
    If numAlign > 0 Then
        For i = 1 To numAlign
            For j = 1 To numAlign
                skip = (i = 1 And j = 1) Or (i = 1 And j = numAlign) Or (i = numAlign And j = 1)
                If Not skip Then
                    For dy = -2 To 2
                        For dx = -2 To 2
                            mm = Abs(dx)
                            If Abs(dy) > mm Then mm = Abs(dy)
                            moduleVal = (mm <> 1)
                            pbIdx = Truncate((((alignPos(j) + dy) * size + (alignPos(i) + dx) + 1) - 1) / 32) + 1
                            pbOff = (((alignPos(j) + dy) * size + (alignPos(i) + dx) + 1) - 1) Mod 32
                            pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
                            If (moduleVal) Then
                                pbNew = 1
                            Else
                                pbNew = 0
                            End If
                            If pbCur <> pbNew Then
                                modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
                            End If
                            pbIdx = Truncate((((alignPos(j) + dy) * size + (alignPos(i) + dx) + 1) - 1) / 32) + 1
                            pbOff = (((alignPos(j) + dy) * size + (alignPos(i) + dx) + 1) - 1) Mod 32
                            pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
                            If (True) Then
                                pbNew = 1
                            Else
                                pbNew = 0
                            End If
                            If pbCur <> pbNew Then
                                isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
                            End If
                        Next
                    Next
                End If
            Next
        Next
    End If

    ' ---- draw_format_bits(0) -- mask is always 0 (FIXED_MASK) ----
    dataVal = 3 * 8 + 0
    remVal = dataVal
    For i = 1 To 10
        a_ = remVal * 2
        b_ = Truncate(remVal / 512) * 1335
        xorResult = 0
        xorPlace = 1
        xorA = a_
        xorB = b_
        For xorI = 1 To 16
            xorABit = xorA Mod 2
            xorBBit = xorB Mod 2
            If xorABit <> xorBBit Then
                xorResult = xorResult + xorPlace
            End If
            xorA = Truncate(xorA / 2)
            xorB = Truncate(xorB / 2)
            xorPlace = xorPlace * 2
        Next
        remVal = xorResult
    Next
    bits = dataVal * 1024 + remVal
    xorResult = 0
    xorPlace = 1
    xorA = bits
    xorB = 21522
    For xorI = 1 To 16
        xorABit = xorA Mod 2
        xorBBit = xorB Mod 2
        If xorABit <> xorBBit Then
            xorResult = xorResult + xorPlace
        End If
        xorA = Truncate(xorA / 2)
        xorB = Truncate(xorB / 2)
        xorPlace = xorPlace * 2
    Next
    bits = xorResult

    For i = 0 To 5
        bitVal = (Truncate(bits / pow2(i + 1)) Mod 2 = 1)
        pbIdx = Truncate((((i) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((i) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((i) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((i) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
    Next
        bitVal = (Truncate(bits / pow2(6 + 1)) Mod 2 = 1)
        pbIdx = Truncate((((7) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((7) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((7) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((7) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        bitVal = (Truncate(bits / pow2(7 + 1)) Mod 2 = 1)
        pbIdx = Truncate((((8) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((8) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        bitVal = (Truncate(bits / pow2(8 + 1)) Mod 2 = 1)
        pbIdx = Truncate((((8) * size + (7) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (7) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((8) * size + (7) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (7) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
    For i = 9 To 14
        bitVal = (Truncate(bits / pow2(i + 1)) Mod 2 = 1)
        pbIdx = Truncate((((8) * size + (14 - i) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (14 - i) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((8) * size + (14 - i) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (14 - i) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
    Next

    For i = 0 To 7
        bitVal = (Truncate(bits / pow2(i + 1)) Mod 2 = 1)
        pbIdx = Truncate((((8) * size + (size - 1 - i) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (size - 1 - i) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((8) * size + (size - 1 - i) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (size - 1 - i) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
    Next
    For i = 8 To 14
        bitVal = (Truncate(bits / pow2(i + 1)) Mod 2 = 1)
        pbIdx = Truncate((((size - 15 + i) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((size - 15 + i) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((size - 15 + i) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((size - 15 + i) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
    Next
    bitVal = True
    pbIdx = Truncate((((size - 8) * size + 8 + 1) - 1) / 32) + 1
    pbOff = (((size - 8) * size + 8 + 1) - 1) Mod 32
    pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
    If (True) Then
        pbNew = 1
    Else
        pbNew = 0
    End If
    If pbCur <> pbNew Then
        modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
    End If
    pbIdx = Truncate((((size - 8) * size + 8 + 1) - 1) / 32) + 1
    pbOff = (((size - 8) * size + 8 + 1) - 1) Mod 32
    pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
    If (True) Then
        pbNew = 1
    Else
        pbNew = 0
    End If
    If pbCur <> pbNew Then
        isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
    End If

    ' ---- draw_version() -- only for version >= 7 ----
    If version >= 7 Then
        remVal = version
        For i = 1 To 12
            a_ = remVal * 2
            b_ = Truncate(remVal / 2048) * 7973
            xorResult = 0
            xorPlace = 1
            xorA = a_
            xorB = b_
            For xorI = 1 To 16
                xorABit = xorA Mod 2
                xorBBit = xorB Mod 2
                If xorABit <> xorBBit Then
                    xorResult = xorResult + xorPlace
                End If
                xorA = Truncate(xorA / 2)
                xorB = Truncate(xorB / 2)
                xorPlace = xorPlace * 2
            Next
            remVal = xorResult
        Next
        bits = version * 4096 + remVal
        For i = 0 To 17
            bitVal = (Truncate(bits / pow2(i + 1)) Mod 2 = 1)
            pbIdx = Truncate((((Truncate(i / 3)) * size + (size - 11 + i Mod 3) + 1) - 1) / 32) + 1
            pbOff = (((Truncate(i / 3)) * size + (size - 11 + i Mod 3) + 1) - 1) Mod 32
            pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
            If (bitVal) Then
                pbNew = 1
            Else
                pbNew = 0
            End If
            If pbCur <> pbNew Then
                modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
            End If
            pbIdx = Truncate((((Truncate(i / 3)) * size + (size - 11 + i Mod 3) + 1) - 1) / 32) + 1
            pbOff = (((Truncate(i / 3)) * size + (size - 11 + i Mod 3) + 1) - 1) Mod 32
            pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
            If (True) Then
                pbNew = 1
            Else
                pbNew = 0
            End If
            If pbCur <> pbNew Then
                isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
            End If
            pbIdx = Truncate((((size - 11 + i Mod 3) * size + (Truncate(i / 3)) + 1) - 1) / 32) + 1
            pbOff = (((size - 11 + i Mod 3) * size + (Truncate(i / 3)) + 1) - 1) Mod 32
            pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
            If (bitVal) Then
                pbNew = 1
            Else
                pbNew = 0
            End If
            If pbCur <> pbNew Then
                modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
            End If
            pbIdx = Truncate((((size - 11 + i Mod 3) * size + (Truncate(i / 3)) + 1) - 1) / 32) + 1
            pbOff = (((size - 11 + i Mod 3) * size + (Truncate(i / 3)) + 1) - 1) Mod 32
            pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
            If (True) Then
                pbNew = 1
            Else
                pbNew = 0
            End If
            If pbCur <> pbNew Then
                isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
            End If
        Next
    End If

    ' ---- Data codewords: mode indicator(4) + char count(8 or 16) + payload bytes(8 each) + terminator + pad ----
    ' Streams bits directly into byte-packed dataCwPacked -- no separate bit array (would exceed 1000 elements).
    ' NOTE: each payload character is taken as ONE byte via Asc() (Latin-1/Windows-1252
    ' style, code points 0-255) -- NOT full UTF-8 multi-byte encoding. Correct and
    ' verified for ASCII payloads (invoice numbers, CUFE, URLs).
    If version <= 9 Then
        ccBits = 8
    Else
        ccBits = 16
    End If
    datacapBits = capBits
    curByteVal = 0
    curNBits = 0
    byteCount = 0
    bitsWritten = 0
    For bitPos = (4) - 1 To 0 Step -1
        bitToEmit = Truncate((4) / pow2(bitPos + 1)) Mod 2
        curByteVal = curByteVal * 2 + bitToEmit
        curNBits = curNBits + 1
        bitsWritten = bitsWritten + 1
        If curNBits = 8 Then
            byteCount = byteCount + 1
            pyIdx = Truncate(((byteCount) - 1) / 4) + 1
            pyOff = ((byteCount) - 1) Mod 4
            pyCur = Truncate(dataCwPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            If pyCur <> (curByteVal) Then
                dataCwPacked(pyIdx) = dataCwPacked(pyIdx) + ((curByteVal) - pyCur) * pow256(pyOff + 1)
            End If
            curByteVal = 0
            curNBits = 0
        End If
    Next
    For bitPos = (ccBits) - 1 To 0 Step -1
        bitToEmit = Truncate((n) / pow2(bitPos + 1)) Mod 2
        curByteVal = curByteVal * 2 + bitToEmit
        curNBits = curNBits + 1
        bitsWritten = bitsWritten + 1
        If curNBits = 8 Then
            byteCount = byteCount + 1
            pyIdx = Truncate(((byteCount) - 1) / 4) + 1
            pyOff = ((byteCount) - 1) Mod 4
            pyCur = Truncate(dataCwPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            If pyCur <> (curByteVal) Then
                dataCwPacked(pyIdx) = dataCwPacked(pyIdx) + ((curByteVal) - pyCur) * pow256(pyOff + 1)
            End If
            curByteVal = 0
            curNBits = 0
        End If
    Next
    For k = 1 To n
        byteCode = Asc(Mid(payload, k, 1))
    For bitPos = (8) - 1 To 0 Step -1
        bitToEmit = Truncate((byteCode) / pow2(bitPos + 1)) Mod 2
        curByteVal = curByteVal * 2 + bitToEmit
        curNBits = curNBits + 1
        bitsWritten = bitsWritten + 1
        If curNBits = 8 Then
            byteCount = byteCount + 1
            pyIdx = Truncate(((byteCount) - 1) / 4) + 1
            pyOff = ((byteCount) - 1) Mod 4
            pyCur = Truncate(dataCwPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            If pyCur <> (curByteVal) Then
                dataCwPacked(pyIdx) = dataCwPacked(pyIdx) + ((curByteVal) - pyCur) * pow256(pyOff + 1)
            End If
            curByteVal = 0
            curNBits = 0
        End If
    Next
    Next

    termBits = 4
    If datacapBits - bitsWritten < termBits Then termBits = datacapBits - bitsWritten
    For bitPos = (termBits) - 1 To 0 Step -1
        bitToEmit = Truncate((0) / pow2(bitPos + 1)) Mod 2
        curByteVal = curByteVal * 2 + bitToEmit
        curNBits = curNBits + 1
        bitsWritten = bitsWritten + 1
        If curNBits = 8 Then
            byteCount = byteCount + 1
            pyIdx = Truncate(((byteCount) - 1) / 4) + 1
            pyOff = ((byteCount) - 1) Mod 4
            pyCur = Truncate(dataCwPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            If pyCur <> (curByteVal) Then
                dataCwPacked(pyIdx) = dataCwPacked(pyIdx) + ((curByteVal) - pyCur) * pow256(pyOff + 1)
            End If
            curByteVal = 0
            curNBits = 0
        End If
    Next
    padBits = (8 - (bitsWritten Mod 8)) Mod 8
    For bitPos = (padBits) - 1 To 0 Step -1
        bitToEmit = Truncate((0) / pow2(bitPos + 1)) Mod 2
        curByteVal = curByteVal * 2 + bitToEmit
        curNBits = curNBits + 1
        bitsWritten = bitsWritten + 1
        If curNBits = 8 Then
            byteCount = byteCount + 1
            pyIdx = Truncate(((byteCount) - 1) / 4) + 1
            pyOff = ((byteCount) - 1) Mod 4
            pyCur = Truncate(dataCwPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            If pyCur <> (curByteVal) Then
                dataCwPacked(pyIdx) = dataCwPacked(pyIdx) + ((curByteVal) - pyCur) * pow256(pyOff + 1)
            End If
            curByteVal = 0
            curNBits = 0
        End If
    Next

    padCycle = 0
    Do While bitsWritten < datacapBits
        If padCycle Mod 2 = 0 Then
            byteCode = 236
        Else
            byteCode = 17
        End If
    For bitPos = (8) - 1 To 0 Step -1
        bitToEmit = Truncate((byteCode) / pow2(bitPos + 1)) Mod 2
        curByteVal = curByteVal * 2 + bitToEmit
        curNBits = curNBits + 1
        bitsWritten = bitsWritten + 1
        If curNBits = 8 Then
            byteCount = byteCount + 1
            pyIdx = Truncate(((byteCount) - 1) / 4) + 1
            pyOff = ((byteCount) - 1) Mod 4
            pyCur = Truncate(dataCwPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            If pyCur <> (curByteVal) Then
                dataCwPacked(pyIdx) = dataCwPacked(pyIdx) + ((curByteVal) - pyCur) * pow256(pyOff + 1)
            End If
            curByteVal = 0
            curNBits = 0
        End If
    Next
        padCycle = padCycle + 1
    Loop

    numDataBytes = byteCount

    ' ---- Reed-Solomon generator polynomial (divisor) for this QR version block ECC length ----
    blockEccLen = eccPerBlock(version)
    numBlocks = numBlocksTable(version)
    For j = 1 To blockEccLen - 1
        divisor(j) = 0
    Next
    divisor(blockEccLen) = 1
    root = 1
    For i = 1 To blockEccLen
        For j = 1 To blockEccLen
        If (divisor(j)) = 0 Or (root) = 0 Then
            product = 0
        Else
            sumLog = gfLog((divisor(j)) + 1) + gfLog((root) + 1)
            If sumLog >= 255 Then sumLog = sumLog - 255
            product = gfExp(sumLog + 1)
        End If
            divisor(j) = product
            If j + 1 <= blockEccLen Then
                xorResult = 0
                xorPlace = 1
                xorA = divisor(j)
                xorB = divisor(j + 1)
                For xorI = 1 To 8
                    xorABit = xorA Mod 2
                    xorBBit = xorB Mod 2
                    If xorABit <> xorBBit Then
                        xorResult = xorResult + xorPlace
                    End If
                    xorA = Truncate(xorA / 2)
                    xorB = Truncate(xorB / 2)
                    xorPlace = xorPlace * 2
                Next
                divisor(j) = xorResult
            End If
        Next
        If (root) = 0 Or (2) = 0 Then
            product = 0
        Else
            sumLog = gfLog((root) + 1) + gfLog((2) + 1)
            If sumLog >= 255 Then sumLog = sumLog - 255
            product = gfExp(sumLog + 1)
        End If
        root = product
    Next

    ' ---- split data codewords into blocks, compute + append ECC per block ----
    rawCodewords = (16 * version + 128) * version + 64
    If version >= 2 Then
        rawCodewords = rawCodewords - ((25 * (Truncate(version / 7) + 2) - 10) * (Truncate(version / 7) + 2) - 55)
        If version >= 7 Then
            rawCodewords = rawCodewords - 36
        End If
    End If
    rawCodewords = Truncate(rawCodewords / 8)
    numShort = numBlocks - (rawCodewords Mod numBlocks)
    shortLen = Truncate(rawCodewords / numBlocks)

    blockDataStart = 1
    writePos = 0
    For i = 1 To numBlocks
        If i <= numShort Then
            extra = 0
        Else
            extra = 1
        End If
        blockDataLen = shortLen - blockEccLen + extra

        For j = 1 To blockEccLen
            reg(j) = 0
        Next
        For k = 1 To blockDataLen
            pyIdx = Truncate(((blockDataStart + k - 1) - 1) / 4) + 1
            pyOff = ((blockDataStart + k - 1) - 1) Mod 4
            byteCode = Truncate(dataCwPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            xorResult = 0
            xorPlace = 1
            xorA = byteCode
            xorB = reg(1)
            For xorI = 1 To 8
                xorABit = xorA Mod 2
                xorBBit = xorB Mod 2
                If xorABit <> xorBBit Then
                    xorResult = xorResult + xorPlace
                End If
                xorA = Truncate(xorA / 2)
                xorB = Truncate(xorB / 2)
                xorPlace = xorPlace * 2
            Next
            factor = xorResult
            For j = 1 To blockEccLen - 1
                reg(j) = reg(j + 1)
            Next
            reg(blockEccLen) = 0
            For ci = 1 To blockEccLen
                If (divisor(ci)) = 0 Or (factor) = 0 Then
                    product = 0
                Else
                    sumLog = gfLog((divisor(ci)) + 1) + gfLog((factor) + 1)
                    If sumLog >= 255 Then sumLog = sumLog - 255
                    product = gfExp(sumLog + 1)
                End If
                xorResult = 0
                xorPlace = 1
                xorA = reg(ci)
                xorB = product
                For xorI = 1 To 8
                    xorABit = xorA Mod 2
                    xorBBit = xorB Mod 2
                    If xorABit <> xorBBit Then
                        xorResult = xorResult + xorPlace
                    End If
                    xorA = Truncate(xorA / 2)
                    xorB = Truncate(xorB / 2)
                    xorPlace = xorPlace * 2
                Next
                reg(ci) = xorResult
            Next
        Next

        blocksStartIdx(i) = writePos + 1
        For k = 1 To blockDataLen
            writePos = writePos + 1
            pyIdx = Truncate(((blockDataStart + k - 1) - 1) / 4) + 1
            pyOff = ((blockDataStart + k - 1) - 1) Mod 4
            byteCode = Truncate(dataCwPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            pyIdx = Truncate(((writePos) - 1) / 4) + 1
            pyOff = ((writePos) - 1) Mod 4
            pyCur = Truncate(blockBytesPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            If pyCur <> (byteCode) Then
                blockBytesPacked(pyIdx) = blockBytesPacked(pyIdx) + ((byteCode) - pyCur) * pow256(pyOff + 1)
            End If
        Next
        If i <= numShort Then
            writePos = writePos + 1
            pyIdx = Truncate(((writePos) - 1) / 4) + 1
            pyOff = ((writePos) - 1) Mod 4
            pyCur = Truncate(blockBytesPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            If pyCur <> (0) Then
                blockBytesPacked(pyIdx) = blockBytesPacked(pyIdx) + ((0) - pyCur) * pow256(pyOff + 1)
            End If
        End If
        For j = 1 To blockEccLen
            writePos = writePos + 1
            pyIdx = Truncate(((writePos) - 1) / 4) + 1
            pyOff = ((writePos) - 1) Mod 4
            pyCur = Truncate(blockBytesPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
            If pyCur <> (reg(j)) Then
                blockBytesPacked(pyIdx) = blockBytesPacked(pyIdx) + ((reg(j)) - pyCur) * pow256(pyOff + 1)
            End If
        Next
        blockDataStart = blockDataStart + blockDataLen
    Next

    ' ---- interleave: for each position within a block, emit that byte from every block ----
    ' (skip the short-block virtual pad-byte position -- it was never real data)
    totalCodewordsBuilt = 0
    For i = 1 To shortLen + 1
        For j = 1 To numBlocks
            skip = (i = shortLen - blockEccLen + 1) And (j <= numShort)
            If Not skip Then
                totalCodewordsBuilt = totalCodewordsBuilt + 1
                pyIdx = Truncate(((blocksStartIdx(j) + i - 1) - 1) / 4) + 1
                pyOff = ((blocksStartIdx(j) + i - 1) - 1) Mod 4
                byteCode = Truncate(blockBytesPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
                pyIdx = Truncate(((totalCodewordsBuilt) - 1) / 4) + 1
                pyOff = ((totalCodewordsBuilt) - 1) Mod 4
                pyCur = Truncate(allCwPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
                If pyCur <> (byteCode) Then
                    allCwPacked(pyIdx) = allCwPacked(pyIdx) + ((byteCode) - pyCur) * pow256(pyOff + 1)
                End If
            End If
        Next
    Next

    ' ---- zigzag codeword placement ----
    bitIndex = 0
    totalBits = totalCodewordsBuilt * 8
    right_ = size - 1
    Do While right_ > 0
        If right_ <= 6 Then
            right_ = right_ - 1
        End If
        For vert = 0 To size - 1
            For jj = 0 To 1
                x = right_ - jj
                upward = (Truncate((right_ + 1) / 2) Mod 2 = 0)
                If upward Then
                    y = size - 1 - vert
                Else
                    y = vert
                End If
                idx = y * size + x + 1
                pbIdx = Truncate(((idx) - 1) / 32) + 1
                pbOff = ((idx) - 1) Mod 32
                isFuncVal = (Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2 = 1)
                If Not isFuncVal And bitIndex < totalBits Then
                    pyIdx = Truncate(((Truncate(bitIndex / 8) + 1) - 1) / 4) + 1
                    pyOff = ((Truncate(bitIndex / 8) + 1) - 1) Mod 4
                    byteCode = Truncate(allCwPacked(pyIdx) / pow256(pyOff + 1)) Mod 256
                    bitPos = bitIndex Mod 8
                    bitVal = (Truncate(byteCode / pow2(8 - bitPos)) Mod 2 = 1)
                    pbIdx = Truncate(((idx) - 1) / 32) + 1
                    pbOff = ((idx) - 1) Mod 32
                    pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
                    If (bitVal) Then
                        pbNew = 1
                    Else
                        pbNew = 0
                    End If
                    If pbCur <> pbNew Then
                        modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
                    End If
                    bitIndex = bitIndex + 1
                End If
            Next
        Next
        right_ = right_ - 2
    Loop

    ' ---- fixed mask 0 -- flip non-function modules where (x+y) is even ----
    For y = 0 To size - 1
        For x = 0 To size - 1
            idx = y * size + x + 1
            pbIdx = Truncate(((idx) - 1) / 32) + 1
            pbOff = ((idx) - 1) Mod 32
            isFuncVal = (Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2 = 1)
            If Not isFuncVal And (x + y) Mod 2 = 0 Then
                pbIdx = Truncate(((idx) - 1) / 32) + 1
                pbOff = ((idx) - 1) Mod 32
                moduleVal = (Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2 = 1)
                pbIdx = Truncate(((idx) - 1) / 32) + 1
                pbOff = ((idx) - 1) Mod 32
                pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
                If (Not moduleVal) Then
                    pbNew = 1
                Else
                    pbNew = 0
                End If
                If pbCur <> pbNew Then
                    modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
                End If
            End If
        Next
    Next

    ' ---- draw_format_bits(0) -- mask is always 0 (FIXED_MASK) ----
    dataVal = 3 * 8 + 0
    remVal = dataVal
    For i = 1 To 10
        a_ = remVal * 2
        b_ = Truncate(remVal / 512) * 1335
        xorResult = 0
        xorPlace = 1
        xorA = a_
        xorB = b_
        For xorI = 1 To 16
            xorABit = xorA Mod 2
            xorBBit = xorB Mod 2
            If xorABit <> xorBBit Then
                xorResult = xorResult + xorPlace
            End If
            xorA = Truncate(xorA / 2)
            xorB = Truncate(xorB / 2)
            xorPlace = xorPlace * 2
        Next
        remVal = xorResult
    Next
    bits = dataVal * 1024 + remVal
    xorResult = 0
    xorPlace = 1
    xorA = bits
    xorB = 21522
    For xorI = 1 To 16
        xorABit = xorA Mod 2
        xorBBit = xorB Mod 2
        If xorABit <> xorBBit Then
            xorResult = xorResult + xorPlace
        End If
        xorA = Truncate(xorA / 2)
        xorB = Truncate(xorB / 2)
        xorPlace = xorPlace * 2
    Next
    bits = xorResult

    For i = 0 To 5
        bitVal = (Truncate(bits / pow2(i + 1)) Mod 2 = 1)
        pbIdx = Truncate((((i) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((i) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((i) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((i) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
    Next
        bitVal = (Truncate(bits / pow2(6 + 1)) Mod 2 = 1)
        pbIdx = Truncate((((7) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((7) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((7) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((7) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        bitVal = (Truncate(bits / pow2(7 + 1)) Mod 2 = 1)
        pbIdx = Truncate((((8) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((8) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        bitVal = (Truncate(bits / pow2(8 + 1)) Mod 2 = 1)
        pbIdx = Truncate((((8) * size + (7) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (7) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((8) * size + (7) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (7) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
    For i = 9 To 14
        bitVal = (Truncate(bits / pow2(i + 1)) Mod 2 = 1)
        pbIdx = Truncate((((8) * size + (14 - i) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (14 - i) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((8) * size + (14 - i) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (14 - i) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
    Next

    For i = 0 To 7
        bitVal = (Truncate(bits / pow2(i + 1)) Mod 2 = 1)
        pbIdx = Truncate((((8) * size + (size - 1 - i) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (size - 1 - i) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((8) * size + (size - 1 - i) + 1) - 1) / 32) + 1
        pbOff = (((8) * size + (size - 1 - i) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
    Next
    For i = 8 To 14
        bitVal = (Truncate(bits / pow2(i + 1)) Mod 2 = 1)
        pbIdx = Truncate((((size - 15 + i) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((size - 15 + i) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (bitVal) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
        pbIdx = Truncate((((size - 15 + i) * size + (8) + 1) - 1) / 32) + 1
        pbOff = (((size - 15 + i) * size + (8) + 1) - 1) Mod 32
        pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
        If (True) Then
            pbNew = 1
        Else
            pbNew = 0
        End If
        If pbCur <> pbNew Then
            isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
        End If
    Next
    bitVal = True
    pbIdx = Truncate((((size - 8) * size + 8 + 1) - 1) / 32) + 1
    pbOff = (((size - 8) * size + 8 + 1) - 1) Mod 32
    pbCur = Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
    If (True) Then
        pbNew = 1
    Else
        pbNew = 0
    End If
    If pbCur <> pbNew Then
        modulesPacked(pbIdx) = modulesPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
    End If
    pbIdx = Truncate((((size - 8) * size + 8 + 1) - 1) / 32) + 1
    pbOff = (((size - 8) * size + 8 + 1) - 1) Mod 32
    pbCur = Truncate(isFuncPacked(pbIdx) / pow2(pbOff + 1)) Mod 2
    If (True) Then
        pbNew = 1
    Else
        pbNew = 0
    End If
    If pbCur <> pbNew Then
        isFuncPacked(pbIdx) = isFuncPacked(pbIdx) + (pbNew - pbCur) * pow2(pbOff + 1)
    End If

    ' ---- build the multi-line "#"/"." grid text (NOT space -- see header comment) ----
    result = ""
    For y = 0 To size - 1
        rowText = ""
        For x = 0 To size - 1
            idx = y * size + x + 1
            pbIdx = Truncate(((idx) - 1) / 32) + 1
            pbOff = ((idx) - 1) Mod 32
            moduleVal = (Truncate(modulesPacked(pbIdx) / pow2(pbOff + 1)) Mod 2 = 1)
            If moduleVal Then
                rowText = rowText & "#"
            Else
                rowText = rowText & "."
            End If
        Next
        If y > 0 Then
            result = result & Chr(13) & Chr(10)
        End If
        result = result & rowText
    Next
    IdCodeMaxQrFontDemo = result
End Function
