Assembly 装配中的图形光标

Assembly 装配中的图形光标,assembly,mouse,dosbox,Assembly,Mouse,Dosbox,我正在试着为DOSBox在汇编中制作一个类似绘画的小程序。虽然我不确定DOSBox模拟的是什么CPU类型,但从我发现的情况来看,它可能是386 我做了研究,找到了如何使用鼠标中断,33h。我还设法使用屏幕遮罩和光标遮罩来定义自己的光标。但是,我希望能够在用户稍后切换到(例如)颜色采样器工具时在程序中更改光标。当我尝试这样做时,光标变成了一个黑色正方形。这是因为我不知道执行这种更改所需的确切步骤 我应该隐藏光标,然后重置它,然后更改光标掩码,然后再次显示它吗?我是否更改了遮罩,然后才重置?我根本不

我正在试着为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)
  • 对于视频模式,“最大宽度”和“最大高度”设置为“最大”
所以stdBrush+graphicsMode+restoreScreen+resetMouse+showCursor很可能是个问题

还有什么是
graphicsMode
?如果它正在设置gfx模式,它很可能也会破坏光标图形

因此,如果您想调用所有这些,我将首先尝试以下命令:

  • 图形模式
  • 重置鼠标
  • 还原屏幕
  • stdBrush
  • 显示光标
或者尝试最小化设置/重置之类的操作,如果您一直处于相同的图形模式,“还原屏幕”无法全部重画?对于鼠标,我看到每次重置它的好处更少(尽管在gfx模式改变后可能是安全的)


Dosbox模仿您所做的

cputype=auto | 386 | 386 | 486 | U slow |奔腾| U slow| 386_预取


关于如何更改光标gfx。。您不需要调用任何隐藏/重置/显示/等。只需使用新的gfx数据再次调用set“INT 33,9”。它将立即替换它(它只是在gfx驱动程序中设置两个地址,让它知道应该在哪里获取掩码+墨水数据,而gfx驱动程序正在使用每个显示帧…IIRC该帧是如何工作的)


我肯定记得,当我在13h DOS模式下制作“精灵编辑器”时,我选择了自己的光标绘制例程,这样我就可以使用256色精灵(它们的最终版本在编辑器中绘制)。但我记不起任何技术细节,它是~25y回来的。:)

无需隐藏/显示光标即可更改其形状

如果您看到一个黑框,请再次选中

  • ES
    。如果您正在构建COM,它应该等于
    CS
    ;如果正在生成EXE,则如果光标位于数据段中,则应等于
    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