TalismanChet
@TalismanChet
Лицо зла

Как исправить движение мыши?

Я пишу свою ОС на ассемблере (под все платформы, сейчас - х86-16), и работал над мышкой. я использовал решение этого вопроса из стека, но курсор просто бешено носится по экрану с такой скоростью, что отследить его во время движения невозможно. Предоставить весь код проблематично, но при необходимости, возможно (займет прилично времени).

АПД:

я смог скачать исходник. Не бейте палкой, я всё в одном файле кодил.

Сам исходник
format binary

	include "lib/kernel.inc"

	org 0x7C00

	xor ax, ax
	mov ds, ax
	mov ss, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	mov sp, 0xFFFE

	jmp 0:@f

@@:

	clc
	mov ah, 0x02
	mov al, 8
	mov bx, 0x1000
	mov cx, 0x0002
	int 0x13
	mov ax, 0x0013
	int 0x10
	jnc 0x1000

	cli
	hlt

draw_pixel_13:
	; cx, dx, al = x, y, c
	push es VIDEOSEG
	pop es
	mov bx, dx
	push cx
	mov cx, 319
.cycle:
	add bx, dx
	loop .cycle
	pop cx
	add bx, cx
	mov byte [es:bx], al
	pop es
	ret

draw_rect_13:
	push ds bx di
	imul bx, 320
	add bx, ax
	mov ax, VIDEOSEG
	mov ds, ax
.__:
	push si
	jmp ._
._:
	dec si
	mov [bx+si], cl
	jnz ._
	pop si
	add bx, 320
	dec di
	jnz .__
	pop di bx ds
	ret

times 510-$+$$\
	db 0x00
	dw 0xAA55

;;===    KERNEL   ===;;

	org 0x1000

kernel.routine.startup:
	call kernel.routine.mouse.init
	call kernel.routine.mouse.enable
	;invc!set 0x08, kernel.routine.timer
	;invc!set 0x21, kernel.routine.osapi

	call kernel.routine.video
	jmp kernel.routine.idle

kernel.routine.video:
	cli
	video!fill 0x4E
	video!window 30, 40, 100, 60, 0x1A, 0xFF, 13 , 0x1F
	video!cursor
	sti
	ret

kernel.routine.idle:

	cmp byte [kernel.system.render], 0
	je kernel.routine.idle.pass_render
	call kernel.routine.video
	mov byte [kernel.system.render], 0
kernel.routine.idle.pass_render:

	jmp kernel.routine.idle

kernel.routine.mouse.init:
	push es bx
	int 0x11
	test ax, 4
	jz kernel.routine.mouse.init.error
	mov ax, 0xC203
	mov bh, MOUSE_RESOLUTION
	int 0x15
	jc kernel.routine.mouse.init.error

	push cs
	pop es

	mov bx, kernel.routine.mouse.dummy
	mov ax, 0xC207
	int 0x15
	jc kernel.routine.mouse.init.error

	clc
	jmp kernel.routine.mouse.init.finish
kernel.routine.mouse.init.error:
	stc
kernel.routine.mouse.init.finish:
	pop bx es
	ret

kernel.routine.mouse.enable:
	push es bx
	call kernel.routine.mouse.disable

	push cs
	pop es
	mov bx, kernel.routine.mouse.callback
	mov ax, 0xC207
	int 0x15

	mov ax, 0xC200
	mov bh, 1
	int 0x15

	pop bx es
	ret

kernel.routine.mouse.disable:
	push es bx

	mov ax, 0xC200
	xor bx, bx
	int 0x15

	pop bx es
	ret

kernel.routine.mouse.callback:
	push bp
	mov bp, sp
	push ds ax bx cx dx cs
	pop ds

	mov al, [bp+12]
	mov bl, al
	mov cl, 3
	shl al, cl

	sbb dh, dh
	cbw
	mov dl, [bp+8]
	mov al, [bp+10]

	neg dx
	mov cx, [kernel.shared.cursor.ypos]
	add dx, cx
	mov cx, [kernel.shared.cursor.xpos]
	add ax, cx

	mov byte [kernel.shared.cursor.stat], bl
	mov word [kernel.shared.cursor.xpos], ax
	mov word [kernel.shared.cursor.ypos], dx
	not byte [kernel.system.render]

	pop dx cx bx ax ds bp

kernel.routine.mouse.dummy:
	retf

kernel.shared.osmeta.name db "HexOS", 0x00
kernel.shared.cursor.stat db 0
kernel.shared.cursor.xpos dw 300
kernel.shared.cursor.ypos dw 300

kernel.system.render db 0

times 4096-$+$$\
	db 0x00


Заголовок к исходнику
VIDEOSEG = 0xA000

MOUSE_RESOLUTION = 127

macro invc!set\
		vector*,\
		offset* {
	cli
	push ds bx word 0
	pop ds
	mov word bx, vector
	shl word bx, 2
	add word bx, 0
	mov word [bx], offset
	mov word [bx+2], 0
	pop bx ds
	sti
}

macro video!set_at x, y, c {
	push cx dx ax bx
	mov cx, x
	mov dx, y
	mov al, c
	call draw_pixel_13
	pop bx ax dx cx
}

macro video!rect x, y, w, h, c {
	push di si cx bx ax
	mov cl, c
	mov ax, x
	mov bx, y
	mov si, w
	mov di, h
	call draw_rect_13
	pop ax bx cx si di
}

macro video!fill c {
	video!rect 0, 0, 320, 200, c
}

macro video!smrect x, y, w, h, c {
	video!rect x, y, w, 1, c
	video!rect x, y, 1, h, c
	video!rect x, y+h, w+1, 1, c
	video!rect x+w, y, 1, h+1, c
}

macro video!srect x, y, w, h, c {
	push ax bx
	video!rect x, y, w, 1, c
	video!rect x, y, 1, h, c
	mov ax, h
	add ax, y
	inc ax
	video!rect x, ax, w, 1, c
	mov bx, w
	add bx, x
	inc bx
	video!rect bx, y, 1, h, c
	pop bx ax
}

macro video!window x, y, w, h, bg, cnt, hdh, hbg {
	video!rect x, y, w, h, bg
	video!rect x, y, w, hdh-1, hbg
	video!smrect x, y, w, h, cnt
	video!smrect x, y, w, hdh-1, cnt
	video!rect x+w-hdh, y+1, hdh, hdh-2, 0x04

	video!set_at x+w-hdh/2-1-0, y+hdh/2-0, cnt
	video!set_at x+w-hdh/2-1-1, y+hdh/2-1, cnt
	video!set_at x+w-hdh/2-1-2, y+hdh/2-2, cnt
	video!set_at x+w-hdh/2-1-1, y+hdh/2+1, cnt
	video!set_at x+w-hdh/2-1-2, y+hdh/2+2, cnt
	video!set_at x+w-hdh/2-1+1, y+hdh/2-1, cnt
	video!set_at x+w-hdh/2-1+2, y+hdh/2-2, cnt
	video!set_at x+w-hdh/2-1+1, y+hdh/2+1, cnt
	video!set_at x+w-hdh/2-1+2, y+hdh/2+2, cnt
}

macro memory!copy srcseg, srcofs, dstseg, dstofs, bufsiz {
	push cx di es si ds bufsiz dstofs dstseg srcofs srcseg
	pop ds si es di cx
	rep movsb
	pop ds si es di cx
}

macro video!flip {
	memory!copy 0xAFA0, 0x0000, 0xA000, 0x0000, 0xFA00
}

macro video!cursor {
	push ax bx

	mov ax, word [kernel.shared.cursor.xpos]
	mov bx, word [kernel.shared.cursor.ypos]

	video!set_at ax, bx, 0xFF

	inc bx
	video!set_at ax, bx, 0xFF

	inc ax
	video!set_at ax, bx, 0xFF

	inc bx
	dec ax
	video!set_at ax, bx, 0xFF

	inc ax
	video!set_at ax, bx, 0xFF

	inc ax
	video!set_at ax, bx, 0xFF

	dec ax
	inc bx
	video!set_at ax, bx, 0xFF

	dec ax
	video!set_at ax, bx, 0xFF

	inc bx
	add ax, 2
	video!set_at ax, bx, 0xFF

	pop bx ax
}


Батник для сборки и отладки:
fasm os.asm
qemu-system-i386 os.bin
  • Вопрос задан
  • 264 просмотра
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
mov al, [bp+12]
  mov bl, al
  mov cl, 3
  shl al, cl

  sbb dh, dh
  cbw
  mov dl, [bp+8]
  mov al, [bp+10]

Этот кусок кода из обработчика перемещений мыши должен делать знаковое расширение 9-битных координат, но я вижу, что в существующем коде в обработчик перемещений всегда приходят нули в координатах x и y, а из-за этого знакового расширения отрицательные dx и dy всегда становятся равными -256. Если добавить вызов функции initialize (0xc205) прерывания 0x15 в mouse.init с 3-байтными пакетами:
kernel.routine.mouse.init:
  push es bx
  int 0x11
  test ax, 4
  jz kernel.routine.mouse.init.error
  mov ax, 0xC205
  mov bh, 3
  int 0x15
  jc kernel.routine.mouse.init.error
  mov ax, 0xC203
  mov bh, MOUSE_RESOLUTION
  int 0x15
  jc kernel.routine.mouse.init.error

то у меня всё начинает работать как ожидалось.
Кстати в ответе на SO по твоей ссылке вызов этой функции есть, непонятно зачем ты его выкинул.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы