thedeemon: (office)
[personal profile] thedeemon
На днях доделывал новый кодек, в одном месте занятная загогулина получилась.
Нужно, чтобы незарегистрированная версия при кодировании через N кадров или M секунд после начала работы (что произойдет раньше) рисовала на видео похабную надпись большими красивыми буквами, тем самым побуждая к регистрации. Рисовать надпись обычными средствами GDI плохо - векторным шрифтом это делать медленно, да и нужного шрифта у пользователя может не быть. Быстрый вариант - накладывать картинку с прозрачностью. Но ее слишком легко заменить на полностью прозрачную, сам так делал с одним скринсейвером. :) К тому же, хочется какой-то защиты от взлома - чтобы так просто надпись было не убрать.
Воспользовался привычным решением, которое успешно применял в предыдущих продуктах - функциональность, которую хочется защитить от взлома, пишется на моем DSEL, который компилится в байткод простенькой регистровой виртуальной машины. Получилось следующее. Нарисовал нужную картинку нужным шрифтом в графическом редакторе, превратил в монохромную, сохранил. Дальше моя программка на Окамле прочитала картинку и прошлась по ней чем-то вроде RLE, превратив в такой примерно текст:
[[
  [119,5]
],
[
  [117,3], [3,4]
],
[
  [67,1], [56,4], [69,1], [9,19], [3,19], [4,5], [7,5], [5,5], [17,5]
],
[
  [11,2], [6,2], [9,2], [6,2], [8,2], [6,2], [7,4], [5,3], [3,3], [17,5], [2,6], [15,5]
],
[
  [11,2], [5,3], [8,3], [5,3], [8,3], [5,3], [6,5], [4,3]
],
...
]
Каждая строка картинки кодируется последовательностью пар чисел - число прозрачных точек, число непрозрачных. Записаны данные намеренно в синтаксисе Руби. А дальше происходит вот что.
Код, который будет выполняться в ВМ, у меня пишется на С-образном язычке, являющимся DSEL Руби. Т.е. синтаксически это код на Руби, который в результате выполнения порождает скомпилированный код ВМ. А раз это код на Руби, то у меня есть полная свобода действий во время компиляции - Руби выступает в качестве мета-языка. И вот, во время такой компиляции я читаю из файла описание картинки в виде того массива и прохожусь по нему, на каждой итерации цикла порождая кусочек кода для ВМ:
____________________________________________________
def drawwm(x, y, pSrc, stride, lines, bpp)
  sy = _int(y/2 - 30)
sx = _int(x/2 - 128)
pPic = _pbyte
j = _int
for ny in 0...lines.length if lines[ny].length > 0 pPic.point(pSrc + (sy+ny)*stride + sx*bpp) for pair in lines[ny] pPic.add(bpp * pair[0])
_for(j <= 0, j < bpp * pair[1], j.inc) {
pPic <= 81
pPic.inc
}
end end end end lines = open('lines.rb') {|f| eval(f.read) } _if(draw > 0) {
_if(bytespp.eq(2)) {
drawwm(x, y, pSrc, stride, lines, 2)
}.else {
drawwm(x, y, pSrc, stride, lines, 3)
}
}
____________________________________________________

Здесь синим обозначены конструкции, которые генерят код для ВМ, это как бы run-time, а черным - то, что происходит в compile-time, в частности, выражения типа bpp * pair[0] превращаются в сгенеренном коде в константы. Compile-time функция drawwm вызывается дважды - с разными значениями числа байт на пиксел, что приводит к генерации двух рисующих кусков кода, отличающихся лишь конкретными значениями констант. Т.е. налицо partial evaluation. В итоге, для каждой пары чисел из того массива, например [4,5], генерится такой вот код (bpp=3):

ADD|RV, 23, 12,  # перепрыгиваем через 4 точки
MOV|RV, 24, 0,   # обнуляем счетчик цикла
LE|RV, 24, 15,   # цикл на 5 точек - 15 байт
JZ, 13,
MOVB|PV, 23, 81, # пишем в картинку 
ADD|RV, 23, 1,   # увеличиваем указатель на место рисования и счетчик цикла
ADD|RV, 24, 1,
JMP, -14,        # конец цикла

И, как ни удивительно, все это даже работает, и надпись рисуется как надо в разных цветовых режимах.
This account has disabled anonymous posting.
If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting

Profile

thedeemon: (Default)
Dmitry Popov

May 2025

S M T W T F S
    123
45678910
11 121314151617
18192021222324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 16th, 2025 04:15 pm
Powered by Dreamwidth Studios