Assembly 装配中的图形光标
我正在试着为DOSBox在汇编中制作一个类似绘画的小程序。虽然我不确定DOSBox模拟的是什么CPU类型,但从我发现的情况来看,它可能是386 我做了研究,找到了如何使用鼠标中断,33h。我还设法使用屏幕遮罩和光标遮罩来定义自己的光标。但是,我希望能够在用户稍后切换到(例如)颜色采样器工具时在程序中更改光标。当我尝试这样做时,光标变成了一个黑色正方形。这是因为我不知道执行这种更改所需的确切步骤 我应该隐藏光标,然后重置它,然后更改光标掩码,然后再次显示它吗?我是否更改了遮罩,然后才重置?我根本不需要重置鼠标吗?这是我所有与鼠标相关的代码 顺便说一下,我知道我可以通过将一堆程序转换成宏来优化很多,将来我可能会在解决了错误后这样做Assembly 装配中的图形光标,assembly,mouse,dosbox,Assembly,Mouse,Dosbox,我正在试着为DOSBox在汇编中制作一个类似绘画的小程序。虽然我不确定DOSBox模拟的是什么CPU类型,但从我发现的情况来看,它可能是386 我做了研究,找到了如何使用鼠标中断,33h。我还设法使用屏幕遮罩和光标遮罩来定义自己的光标。但是,我希望能够在用户稍后切换到(例如)颜色采样器工具时在程序中更改光标。当我尝试这样做时,光标变成了一个黑色正方形。这是因为我不知道执行这种更改所需的确切步骤 我应该隐藏光标,然后重置它,然后更改光标掩码,然后再次显示它吗?我是否更改了遮罩,然后才重置?我根本不
stdBrush PROC
push bx cx ax dx
mov bx, stdBrushHotSpots
mov cx, stdBrushHotSpots + 2
mov ax, 9
mov dx, offset stdBrushMask
int 33h
pop dx ax cx bx
ret
stdBrush ENDP
pickerTool PROC
push bx cx ax dx
mov bx, pickerToolHotSpots
mov cx, pickerToolHotSpots + 2
mov ax, 9
mov dx, offset pickerToolMask
int 33h
pop dx ax cx bx
ret
pickerTool ENDP
mouseReset PROC
push ax
mov ax, 0
int 33h
pop ax
ret
mouseReset ENDP
showCursor PROC
push ax
mov ax, 1
int 33h
pop ax
ret
showCursor ENDP
hideCursor PROC
push ax
mov ax, 2
int 33h
pop ax
ret
hideCursor ENDP
getCursorStat PROC
push ax
mov ax, 3
int 33h
pop ax
ret
getCursorStat ENDP
initCursor PROC
mov ax, dseg
mov es, ax
call mouseReset
call stdBrush
call showCursor
mov ax, DISPLAY_SEG
mov es, ax
ret
initCursor ENDP
这些都是小程序,可以作为使用int 33h不同功能的快捷方式。例外情况是initCursor,它结合了这些快捷键来在程序开始时初始化光标,以及stdBrush和pickerTool,它们都将图形光标设置为特定的光标(您可以猜到,stdBrush是标准笔刷光标,pickerTool为颜色采样器工具设置光标)
下面是我的两个光标的掩码
stdBrushMask dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 0000000100000000b
dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 1111111011111111b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
dw 1111111011111111b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
dw 0000000100000000b
stdBrushHotSpots dw 7
dw 7
pickerToolMask dw 1111100001000001b
dw 1111100000000000b
dw 1111100000000000b
dw 1111100000000000b
dw 1111100000000000b
dw 1111000000000000b
dw 1110000000000000b
dw 1100000000000000b
dw 1000000000000000b
dw 1000000000000000b
dw 1000000000000000b
dw 1000000000011111b
dw 0000000000111111b
dw 0000000001111111b
dw 0000000011111111b
dw 0000111111111111b
dw 0000000000000000b
dw 0000001100011100b
dw 0000001111111110b
dw 0000000111111110b
dw 0000000111111110b
dw 0000001111111100b
dw 0000011111111100b
dw 0000111111111100b
dw 0001111111111110b
dw 0011111111100110b
dw 0001111111000000b
dw 0001111110000000b
dw 0011111100000000b
dw 0111001000000000b
dw 0110000000000000b
dw 0000000000000000b
pickerToolHotSpots dw 1
dw 14
将代码复制到stackoverflow会导致一些缩进不一致,我懒得逐行修改它们
以下是程序中给我带来麻烦的部分:
paletteModeToggle PROC
push ax
call hideCursor
mov pos_backup, cx
mov pos_backup+2, dx
mov al, colorpicker_flag
not al
mov colorpicker_flag, al
test al, al
jz palette_mode_off
palette_mode_on:
call pickerTool
call backupScreen
call graphicsMode
call paletteDraw
call mouseReset
call showCursor
pop ax
jmp input_loop
palette_mode_off:
call stdBrush
call graphicsMode
call restoreScreen
call mouseReset
call showCursor
pop ax
jmp input_loop
paletteModeToggle ENDP
它显示一个调色板,应该将光标更改为颜色采样器工具光标。相反,光标变为黑色正方形,即使在调色板模式关闭时也保持这种状态。我怀疑在更改光标时没有采取正确的步骤。当光标尚未显示时,它在程序开始时工作正常
在这个过程中,我隐藏光标,然后更改光标掩码,然后将鼠标重置为默认驱动程序值(甚至不确定这是否必要),然后使其再次可见。我做错了吗
顺便说一句,如果你还没有注意到,我正在使用TASM
如果您需要查看我的代码的任何其他部分,请让我知道。根据以下内容:
ax=0:将鼠标重置为默认驱动程序值:
- 鼠标位于屏幕中心
- 鼠标光标被重置并隐藏
- 未启用任何中断(掩码=0)
- 双速阈值设置为每秒64米
- 水平米奇像素比(8比8)
- 垂直米奇像素比(16比8)
- 对于视频模式,“最大宽度”和“最大高度”设置为“最大”
graphicsMode
?如果它正在设置gfx模式,它很可能也会破坏光标图形
因此,如果您想调用所有这些,我将首先尝试以下命令:
- 图形模式
- 重置鼠标
- 还原屏幕
- stdBrush
- 显示光标
Dosbox模仿您所做的 cputype=auto | 386 | 386 | 486 | U slow |奔腾| U slow| 386_预取
关于如何更改光标gfx。。您不需要调用任何隐藏/重置/显示/等。只需使用新的gfx数据再次调用set“INT 33,9”。它将立即替换它(它只是在gfx驱动程序中设置两个地址,让它知道应该在哪里获取掩码+墨水数据,而gfx驱动程序正在使用每个显示帧…IIRC该帧是如何工作的)
我肯定记得,当我在13h DOS模式下制作“精灵编辑器”时,我选择了自己的光标绘制例程,这样我就可以使用256色精灵(它们的最终版本在编辑器中绘制)。但我记不起任何技术细节,它是~25y回来的。:) 无需隐藏/显示光标即可更改其形状 如果您看到一个黑框,请再次选中
- 该
段。如果您正在构建COM,它应该等于ES
;如果正在生成EXE,则如果光标位于数据段中,则应等于CS
;如果光标位于代码段中,则应等于DS
李>CS
- 光标的位图。使用在每种颜色上都可见且易于生成的完全反转正方形
(dw 32 DUP(0ffffh)
)进行测试乘以32 dw 0ffffh
调试其他人的代码对于这个站点来说是无趣的,我将提供一个MCWE(最小完整工作示例),介绍如何更改光标形状 按任意键更改光标。 再次按退出
.286
.MODEL TINY
_CODE SEGMENT PARA PUBLIC 'CODE' USE16
ASSUME CS:_CODE, DS:_CODE
ORG 100h
__START__:
call initGraphics ;Get into graphic mode and show cursor
push 08h
push 08h
push OFFSET barCursor
call setCursor
xor ah, ah
int 16h
push 08h
push 08h
push OFFSET checkerCursor
call setCursor
xor ah, ah
int 16h
call finalizeGraphics
mov ax, 4c00h
int 21h
;
; PROCEDURES
;
;Set graphic mode, reset mouse and show cursor
initGraphics:
push es
mov ax, 13h
int 10h
push 0a000h
pop es
xor di, di
mov ax, 0909h
mov cx, 320*200/2
rep stosw
xor ax, ax
int 33h
mov ax, 01h
int 33h
pop es
ret
;Hide cursor and set text mode
finalizeGraphics:
mov ax, 02h
int 33h
mov ax, 03h
int 10h
ret
;Set cursor
;Hotspot X
;Hotspot Y
;Ptr to cursor bitmaps
setCursor:
push bp
mov bp, sp
pusha
push es
mov ax, 09h
mov bx, WORD PTR [bp+08h]
mov cx, WORD PTR [bp+06h]
mov dx, WORD PTR [bp+04h]
push ds ;Setting ES = DS is not necessary in COM
pop es ;files unless somebody changed ES
int 33h
pop es
popa
pop bp
ret 06h
;
; CURSORS
;
barCursor dw 16 DUP(0fe7fh)
dw 16 DUP(0180h)
checkerCursor dd 8 DUP(5555aaaah)
dd 8 DUP(0aaaa5555h)
_CODE ENDS
END __START__
对于其他阅读器,光标位图的格式为1: 16x16像素表示光标下的每个像素都映射到该矩阵中的一位。
光标大小为16x16,因此每个字(16位)定义一行。
行中最左边的像素映射到单词的LSb 例如,单词4807h(0100 1000 0000 0111)的第一、第二、第三、第十二和第十五个像素为1 AND掩码用于清除光标下的像素,1表示不影响像素,0表示将其设置为黑色 XOR掩码用于反转光标下的像素,1表示反转像素值(在模式13h中,仅为较低的半字节),0表示不受影响 这来自
OFFSET SIZE DESCRIPTION
00h 32 16x16 pixel AND mask
20h 32 16x16 pixel XOR mask