13-часовой режим VGA в реальном режиме 16b (BIOS / DOS) имеет видеопамять, расположенную по адресу A000:0000
, не стесняйтесь читать / писать по своему усмотрению.
Также вам нужен более сложный алгоритм длявыигрыш, потому что просто отслеживание количества «A» не скажет вам, сколько пользователь пролил «B» на другие области (то есть, пользователь, просто заполнивший весь экран B, выиграет, потому что A = 0).
Пример манипуляции с видео-плунжером в 13-часовом режиме VGA (синтаксис TASM):
;filename: so_13h.asm
.model small
.code
start:
mov ax,13h ; ah = 0 set mode, al = 13h 320x200 256col mode
int 10h ; set gfx mode
push 0A000h
pop es ; es = A000 (video ram segment)
; fill video ram with some pattern
xor di,di
mov bp,200
lines_loop:
mov dx,64
mov ax,1010h
shade_loop:
stosw ; write 5 pixels
stosw
stosb
; modify colours to create sort of "dither" pattern
xchg al,ah
inc ah
dec dx
jnz shade_loop ; write 320 pixels with different shades
; write 200 lines
dec bp
jnz lines_loop
; read pixel back example
mov di,(13*320 + 56) ; read pixel from [x, y] = [56, 13]
mov al,es:[di]
; here AL = 16h (colour of pixel at [56, 13] position)
; wait for any key
xor ax,ax
int 16h
; restore text mode
mov ax,3 ; ah = 0, al = 3 (text mode 80x25)
int 10h
; terminate code
mov ah,4Ch
int 21h
end start
Для сборки + запуска под dosbox я использовал:
tasm so_13h.asm
tlink /x so_13h.obj
so_13h.exe
edit: есть также BIOSсервис для int 10h
«Чтение пикселя графики в координатах» :
ввод:
AH = 0D
BH = page number, see VIDEO PAGES
CX = column number (zero based)
DX = row number (zero based)
при возврате:
AL = color of pixel read
Но, как правило, службы BIOS работают очень медленно из-за снижения производительности самого вызова int
, плюс BIOS должен снова вычислить смещение каждого пикселя с нуля, в то время как, например, ваше "отслеживание оценки" может использовать некоторые "ожидаемые"экран "буфер" для сравнения пикселей последовательно повторное использование выключенныхи т. д. из предыдущего, чтобы перейти к следующему, избегая излишних вычислений.
Поэтому вы должны попытаться создать нечто похожее на способ заполнения экрана в примере, обрабатывая пиксели в «пакетном режиме».
Даже чтение, оптимизированное для слова (два пикселя) по сравнению с байтом (один пиксель), помогло на реальном HW в эпоху 386 года, но это, вероятно, слишком усложняет вашу задачу, JFYI, что даже такие тонкие детали имели значение тогда.
edit2: об алгоритме подсчета очков:
Зависит от того, как именно вы хотите забить, но вы можете сделать это:
- имеют оригинальное "A"буфер в памяти
- рассчитать количество «A» на экране = toPaint
- позволить пользователю рисовать с «B»
- вычислить количество «A» на экране = notPaint
- вычислить «B» из экрана над «0» в буфере = overPaintL1
- повторно запустить внутри внутреннего буфера [0,0] .. [maxX-2,, maxY-2] и изменитькаждый пиксель в «А», если есть «А» на правой или нижней стороне текущего рixel = это сделает форму "A" более толстой (возможно, будет выполнена дважды в два раза, чтобы перекрыть + -2 или + -3 пикселя)
- вычислить "B" над 0 в буфере = overPaintL2
- сделать "A" еще раз толще
- вычислить "B" над 0 в буфере = overPaintL3
Теперь итоговый результат может быть примерно таким:
счет = w0* (toPaint - notPaint) + w1 * overPaintL1 + w2 * overPaintL2 + w3 * overPaintL3
, где w0..w3 - «веса» бонуса / малуса, w0 должен быть самым сильным, так как это количество пикселей-безупречно пользователь рисовал (например, 50 ... также каждый пропущенный пиксель равен -50), w1 должен быть очень маленьким мальчиком, например -1 (это только 1 пиксель), w2 может быть что-то вроде -5 (2 пикселя)off), w3 может быть что-то вроде -10 (пиксели полностью не соответствуют форме).
Так что, если пользователь имеет форму ~ 200 пикселей (квадрат 50x50 пикселей), и он переопределяет 184 пикселя: notPaint = 16и в основном поражает почти везде + -1 пиксель (создавая квадрат шириной 2 пикселя): overPaintL1 = 200 и сомВременами он уходит немного дальше: overPaintL2 = 15, overPaintL3 = 35
Затем оценка = 50 * (200-16) + -1 * 200 + -5 * 15 + -10 * 35 = 8575 (идеально)в этом примере оценка составляет 50 * 200 = 10000).
Может быть, вам нужно будет перенастроить веса и сгущения, но я думаю, что этот подход может сработать в конце.
edit: еще одно замечание о сгущении ... вы должны сгущать во всех направлениях одинаково, чтобы сделать перерасход "B" дорогостоящим в каждом направлении в равной степени, поэтому моя первоначальная проверка справа / снизу не действительна, но выполняется в 4-х направленияхпроверка в одном буфере тоже невозможна.Так что либо вам нужно будет ввести второй внутренний буфер, сгущаясь от одного к другому, либо выполнить двухпроходное сгущение, сначала идущее вперед и расширяющееся вправо + внизу, второе идущее назад и расширяющееся влево + вверх, либо вы можете рисовать форму с помощью "A "во внутренний буфер в позициях [-N .. + N, -N .. + N], чтобы охватить + -N пикселей вокруг оригинального дизайна.
Вероятно, проще всего кодировать обнаружение двух "буферов" в любой сетке 3x3 в исходном буфере для текущей позиции назначения.
Мое первоначальное описание сгущало форму A только в направлении слева + сверху, поэтомуоверрейд внизу / справа будет более наказуемым, чем оверрейд слева / вверху.
Хмм ... в конце концов, это оказалось более хитрым, чем ожидалось, убедитесь, что вы кодируете его небольшими частями,и отлаживать каждый по отдельности и правильно, включая угловые случаи и экстремальные входные данные.