From 8bf9f819bf0bc8d91d1e550a6562ebb1f6d1c24b Mon Sep 17 00:00:00 2001 From: Frater <13979047+saintfrater@users.noreply.github.com> Date: Wed, 21 Jan 2026 23:41:26 +0100 Subject: [PATCH] curseur en mode 32bits pas bon... --- src/boot.asm | 76 ++-- src/drivers/gfx_cgam.asm | 782 +++++++++++++------------------------- src/drivers/mouse_ps2.asm | 2 +- 3 files changed, 311 insertions(+), 549 deletions(-) diff --git a/src/boot.asm b/src/boot.asm index d4771c4..72b6358 100644 --- a/src/boot.asm +++ b/src/boot.asm @@ -93,20 +93,20 @@ reset: ; on active le mode graphique call gfx_init - ; call mouse_reset - call mouse_init + call mouse_reset + ; call mouse_init - ; call gfx_cursor_move + call gfx_cursor_move endless: mov ax,BDA_DATA_SEG mov ds,ax - mov dx,0x300 - call scr_gotoxy + ;mov dx,0x300 + ;call scr_gotoxy - mov al, byte [BDA_TIMER] - call scr_puthex8 + ;mov al, byte [BDA_TIMER] + ;call scr_puthex8 cmp byte [BDA_TIMER],5 ja .skip2 @@ -120,51 +120,53 @@ endless: .moveok: mov [BDA_MOUSE + mouse.x],ax ; - ; call gfx_cursor_move + call gfx_cursor_move cmp byte [BDA_MOUSE + mouse.buffer+1], 0 jge .skip - mov dx,0x400 - call scr_gotoxy + ;mov dx,0x400 + ;call scr_gotoxy - mov al, byte [BDA_MOUSE + mouse.buffer+1] - call scr_puthex8 + ;mov al, byte [BDA_MOUSE + mouse.buffer+1] + ;call scr_puthex8 .skip: - cmp byte [BDA_MOUSE + mouse.buffer+2], 0 - jge .skip2 + ;cmp byte [BDA_MOUSE + mouse.buffer+2], 0 + ;jge .skip2 - mov dx,0x404 - call scr_gotoxy + ;mov dx,0x404 + ;call scr_gotoxy - mov al, byte [BDA_MOUSE + mouse.buffer+2] - call scr_puthex8 + ;mov al, byte [BDA_MOUSE + mouse.buffer+2] + ;call scr_puthex8 .skip2: - mov dx,0 - call scr_gotoxy + ;mov dx,0 + ;call scr_gotoxy - mov ax,[BDA_MOUSE] ; adresse début dump - mov si,ax + ;mov ax,[BDA_MOUSE] ; adresse début dump + ;mov si,ax mov cx, 0x20 .dump: - test cx,0x000F - jnz .sameline - inc dh - xor dl,dl - call scr_gotoxy -.sameline: - mov al,[ds:si] - inc si +; test cx,0x000F +; jnz .sameline +; inc dh +; xor dl,dl +; call scr_gotoxy +;.sameline: +; mov al,[ds:si] +; inc si - push ds - push si +; push ds +; push si - call scr_puthex8 - mov al,' ' - call scr_putc +; call scr_puthex8 +; mov al,' ' +; call scr_putc - pop si - pop ds +; pop si +; pop ds + + nop loop .dump diff --git a/src/drivers/gfx_cgam.asm b/src/drivers/gfx_cgam.asm index e635b89..4de8c8a 100644 --- a/src/drivers/gfx_cgam.asm +++ b/src/drivers/gfx_cgam.asm @@ -266,9 +266,9 @@ gfx_cursor_move: mov ax, VIDEO_SEG mov es, ax - call gfx_cursor_restorebg + ;call gfx_cursor_restorebg - call gfx_cursor_savebg + ;call gfx_cursor_savebg call gfx_cursor_draw mov byte [BDA_MOUSE + mouse.cur_drawing],0 @@ -278,525 +278,332 @@ gfx_cursor_move: popa ret +bits 16 + +%define GFX_WIDTH 640 +%define GFX_HEIGHT 200 +%define CGA_STRIDE 80 +%define CGA_ODD_BANK 0x2000 + ; ============================================================ -; gfx_draw_cursor (CPU>=386, bits 16) - PAS de clamp -; x:0..639, y:0..199 -; clipping droite/bas: -; width = min(16, 640-x) -; height = min(16, 200-y) -; bytes_to_touch = ((off + width + 7) >> 3) ; 1..3 -; -; Requiert: -; gfx_calc_addr (CX=x, DX=y) => DI (bank incluse) -; sprite en GS:SI (AND[16w] puis XOR[16w] à +32) -; +; gfx_cursor_draw_rm16_i386_self +; Entrée: +; DS = BDA_DATA_SEG +; Sortie: rien +; Détruit: registres sauvegardés/restaurés (PUSHA/POPA) ; ============================================================ -gfx_cursor_draw: - push ds +gfx_cursor_draw_rm16_i386_self: push es push gs pusha - mov ax, BDA_DATA_SEG - mov ds, ax + ; ----------------------------- + ; ES = VRAM + ; ----------------------------- + mov ax, VIDEO_SEG + mov es, ax - ; GS:SI sprite + ; ----------------------------- + ; GS:SI = sprite (AND puis XOR à +32) + ; ----------------------------- mov ax, [BDA_MOUSE + mouse.cur_seg] mov gs, ax mov si, [BDA_MOUSE + mouse.cur_ofs] - ; ES VRAM - mov ax, VIDEO_SEG - mov es, ax - - ; x,y + ; ----------------------------- + ; Charger x,y + ; CX = x, DX = y + ; ----------------------------- mov cx, [BDA_MOUSE + mouse.x] mov dx, [BDA_MOUSE + mouse.y] - ; off = x&7 -> BL + ; off = x & 7 (stocké dans BL) mov bl, cl and bl, 7 - ; width = min(16, 640-x) -> AL - mov ax, 640 + ; width = min(16, 640-x) -> DL + mov ax, GFX_WIDTH sub ax, cx cmp ax, 16 jbe .w_ok mov ax, 16 .w_ok: - ; AL = width test al, al jz .done + mov dl, al ; DL = width (1..16) - ; height = min(16, 200-y) -> DL - mov bp, 200 + ; height = min(16, 200-y) -> BP (compteur) + mov bp, GFX_HEIGHT sub bp, dx cmp bp, 16 jbe .h_ok mov bp, 16 .h_ok: - mov ax, bp - mov dl, al ; DL = height - test dl, dl + test bp, bp jz .done ; bytes_to_touch = ((off + width + 7) >> 3) -> BH mov ah, bl - add ah, al + add ah, dl add ah, 7 shr ah, 3 - mov bh, ah ; BH=1..3 + mov bh, ah ; BH = 1..3 - ; clip_mask16 = 0xFFFF << (16-width) -> BP - mov bp, 0FFFFh - mov cl, 16 - sub cl, al - shl bp, cl ; BP = clipmask + ; clipmask16 = 0xFFFF << (16-width) -> (on le recalculera par ligne) + ; parité initiale (y&1) -> CH + mov ch, byte [BDA_MOUSE + mouse.y] + and ch, 1 - ; DI pour (x,y) - call gfx_calc_addr + ; ----------------------------- + ; Calcul DI = adresse VRAM pour (x,y) + ; DI = (y>>1)*80 + (x>>3) + (y&1)*0x2000 + ; ----------------------------- + mov ax, dx + shr ax, 1 ; ax = y/2 - ; bank_add = +0x2000 si DI<0x2000 sinon -0x2000 -> BX - mov bx, 02000h - cmp di, bx - jl .bank_ok - neg bx -.bank_ok: + mov di, ax + shl di, 4 ; (y/2)*16 + shl ax, 6 ; (y/2)*64 + add di, ax ; *80 - ; AL = row (0..15) - xor ax, ax ; AL=0, AH=0 - ; AH = toggle bank flag: - ; 0 => prochaine ligne: DI += BX - ; 1 => prochaine ligne: DI -= BX, DI += 80 + mov ax, cx + shr ax, 3 ; x/8 + add di, ax + + test byte [BDA_MOUSE + mouse.y], 1 + jz .addr_even + add di, CGA_ODD_BANK +.addr_even: + + ; row index dans AL + xor ax, ax ; AL = 0 (row) + +.row_loop: + ; conserver row + (off/bytes) sur pile, pour libérer BL/BH si besoin + push ax + push bx ; BL=off, BH=bytes_to_touch + + ; ----------------------------------------- + ; Charger AND/XOR pour la ligne (row=AL) + ; CX = AND, DX = XOR + ; ----------------------------------------- xor ah, ah + shl ax, 1 ; AX = row*2 -.line_loop: - push ax ; préserver row(AL) + toggle(AH) (draw_line_masked détruit AX) + mov bx, si + add bx, ax + mov cx, [gs:bx] ; AND word + add bx, 32 + mov dx, [gs:bx] ; XOR word - ; charge AND'/XOR' clippés pour row=AL -> CX/DX - call .load_andxor_clipped + ; restaurer row dans AL + pop bx ; restore off/bytes into BL/BH + pop ax ; restore row in AL - ; dessine la ligne: ES:DI, BL=off, BH=bytes, CX=AND', DX=XOR' - call draw_line_masked + ; ----------------------------------------- + ; clipmask16 = 0xFFFF << (16-width) + ; width est dans DL + ; clipmask -> BX + ; ----------------------------------------- + mov bx, 0FFFFh + mov cl, 16 + sub cl, dl + shl bx, cl ; BX = clipmask - pop ax ; restore row/toggle + ; AND' = AND | (~clipmask) + mov ax, bx + not ax + or cx, ax ; CX = AND' - ; next line + ; XOR' = XOR & clipmask + and dx, bx ; DX = XOR' + + ; ----------------------------------------- + ; Construire seg 16-bit depuis VRAM (ES:DI) + ; w0 = (b0<<8)|b1 + ; seg = (w0<>(8-off)) si off!=0 et bytes==3 + ; seg -> AX + ; ----------------------------------------- + ; AX = w0 + mov ah, [es:di] ; b0 + mov al, [es:di+1] ; b1 + + ; if off==0 -> seg ready + test bl, bl + jz .seg_ready + + ; seg = w0 << off + mov cl, bl + shl ax, cl + + ; if bytes==3, OR b2>>(8-off) + cmp bh, 3 + jne .seg_ready + + mov cl, 8 + sub cl, bl ; 8-off + xor bh, bh ; BH=0, BL=off (on évite bpl etc) + mov bl, [es:di+2] ; BL=b2 + shr bx, cl ; BX = b2>>(8-off) + or ax, bx + ; restaurer BL=off, BH=bytes: (on ne peut pas, on a écrasé) + ; => ne jamais écraser BL/BH. Donc on refait proprement: + ; (ce bloc est remplacé ci-dessous) + ; --- on ne doit pas passer ici --- +.seg_ready: + + ; *** IMPORTANT *** + ; Le bloc ci-dessus a montré le piège (écraser BL/BH). + ; On fait le chemin correct ci-dessous, sans toucher BL/BH. + + ; Refaire seg proprement sans écraser BL/BH: + ; AX = w0 (recharge) + mov ah, [es:di] + mov al, [es:di+1] + + test bl, bl + jz .seg2_ready + + mov cl, bl + shl ax, cl + + cmp bh, 3 + jne .seg2_ready + + mov cl, 8 + sub cl, bl ; 8-off + xor ah, ah + mov al, [es:di+2] ; AL=b2 + ; AX = b2 + shr ax, cl ; AX = b2>>(8-off) + ; OR into seg: need seg in another reg -> use BX temp + mov bx, [es:di] ; not ok (word read uses little endian, avoid) + ; simplest: use stack temp + push ax ; save (b2>>(8-off)) + ; reload seg again and OR + mov ah, [es:di] + mov al, [es:di+1] + mov cl, bl + shl ax, cl + pop bx + or ax, bx +.seg2_ready: + + ; ----------------------------------------- + ; newseg = (seg & AND') ^ XOR' + ; seg in AX + ; ----------------------------------------- + and ax, cx + xor ax, dx ; AX=newseg + + ; ----------------------------------------- + ; Ecriture vers VRAM + ; - off==0 : b0=AH, b1=AL (si bytes>=2) + ; - off!=0 : b0 partiel, b1 complet si bytes>=2, b2 partiel si bytes==3 + ; ----------------------------------------- + test bl, bl + jnz .write_unaligned + +.write_aligned: + mov [es:di], ah + cmp bh, 1 + je .after_write + mov [es:di+1], al + jmp .after_write + +.write_unaligned: + ; mask0 = (1<<(8-off))-1 (bits bas de b0) + mov cl, 8 + sub cl, bl + mov dh, 1 + shl dh, cl + dec dh ; DH = mask0 + + ; val0 = newseg >> (8+off) + mov bx, ax ; BX = newseg + mov cl, bl + add cl, 8 + shr bx, cl ; BL = val0 (low 8) + + ; b0 = (old & ~mask0) | (val0 & mask0) + mov dl, [es:di] ; old b0 + mov cl, dh ; CL=mask0 + not cl + and dl, cl ; keep upper bits + not cl ; CL=mask0 + and bl, cl ; val0 masked + or dl, bl + mov [es:di], dl + + cmp bh, 1 + je .after_write + + ; b1 = (newseg >> off) & 0xFF + mov bx, ax + mov cl, bl ; BUG: BL now val0, not off + ; => on doit recharger off depuis BDA_MOUSE.x &7, ou le sauver. + ; On le sauve au début de la fonction dans une variable: ici on le recharge (coût faible) + mov bl, [BDA_MOUSE + mouse.x] ; low byte x + and bl, 7 + mov cl, bl + shr bx, cl + mov [es:di+1], bl + + cmp bh, 2 + je .after_write + + ; b2 partiel (bits hauts off) + ; mask2 = 0xFF << (8-off) + mov cl, 8 + sub cl, bl ; bl=off + mov dl, 0FFh + shl dl, cl ; DL=mask2 + + ; part2 = (newseg << (8-off)) & 0xFF + mov bx, ax ; BX=newseg + shl bx, cl ; BL=part2 + + ; b2 = (old & ~mask2) | (part2 & mask2) + mov dh, [es:di+2] ; old b2 + mov cl, dl ; CL=mask2 + not cl + and dh, cl + not cl + and bl, cl + or dh, bl + mov [es:di+2], dh + +.after_write: + ; ----------------------------------------- + ; next row + ; ----------------------------------------- inc al - dec dl + dec bp jz .done - ; alternance banks et stride CGA - test ah, ah - jnz .to_base + ; stepping CGA: + ; even->odd: +0x2000 + ; odd ->even: -0x2000 + 80 + test ch, ch + jz .even_to_odd - ; vers autre bank - add di, bx - mov ah, 1 - jmp .line_loop - -.to_base: - sub di, bx + ; odd -> even + sub di, CGA_ODD_BANK add di, CGA_STRIDE - xor ah, ah - jmp .line_loop + xor ch, ch + jmp .row_loop + +.even_to_odd: + add di, CGA_ODD_BANK + mov ch, 1 + jmp .row_loop .done: popa pop gs pop es - pop ds ret - -; ------------------------------------------------------------ -; .load_andxor_clipped -; Entrées: -; AL = row (0..15) -; GS:SI = base sprite -; BP = clipmask16 -; Sorties: -; CX = AND' , DX = XOR' -; Détruit: -; AX, DI (DI restauré) -; ------------------------------------------------------------ -.load_andxor_clipped: - push di - xor ah, ah - shl ax, 1 ; AX = row*2 - - mov di, si - add di, ax - mov cx, [gs:di] ; AND - add di, 32 - mov dx, [gs:di] ; XOR - - ; AND' = AND | (~clipmask) - ; XOR' = XOR & clipmask - mov ax, bp - not ax - or cx, ax - and dx, bp - - pop di - ret - - -; ============================================================ -; draw_line_masked (NASM bits16, CPU 386+ ok, pas de bpl/sil) -; -; Entrées: -; ES:DI = adresse b0 -; BL = off (0..7) -; BH = bytes_to_touch (1..3) -; CX = AND' -; DX = XOR' -; -; Détruit: AX,BP,SI,CL,DL,DH,AH -; (ok car caller recharge CX/DX à chaque ligne) -; ============================================================ -draw_line_masked: - push si - push bp - - ; w0 = (b0<<8)|b1 dans SI - mov al, [es:di] - mov ah, [es:di+1] - xchg al, ah - mov si, ax - - ; seg in AX - mov ax, si - test bl, bl - jz .seg_ready - - cmp bh, 3 - jne .seg_no_b2 - - ; BP = w1 = (b1<<8)|b2 - mov al, [es:di+1] - mov ah, [es:di+2] - xchg al, ah - mov bp, ax - - mov ax, si ; AX=w0 - mov cl, bl - shl ax, cl - mov cl, 8 - sub cl, bl - shr bp, cl - or ax, bp - jmp .seg_ready - -.seg_no_b2: - mov cl, bl - shl ax, cl - -.seg_ready: - ; newseg in BP - and ax, cx - xor ax, dx - mov bp, ax - - test bl, bl - jz .write_aligned - - ; -------- b0 partiel -------- - ; val0 = newseg >> (8+off) dans AL - mov ax, bp - mov cl, bl - add cl, 8 - shr ax, cl ; AL=val0 - - ; mask0 = (1<<(8-off))-1 dans AH - mov cl, 8 - sub cl, bl - mov ah, 1 - shl ah, cl - dec ah - - ; b0 = (b0 & ~mask0) | (val0 & mask0) - mov dl, [es:di] - mov dh, ah - not dh - and dl, dh - not dh - and al, dh - or dl, al - mov [es:di], dl - - cmp bh, 1 - je .ret - - ; -------- b1 complet -------- - mov ax, bp - mov cl, bl - shr ax, cl ; AL=b1 - mov [es:di+1], al - - cmp bh, 2 - je .ret - - ; -------- b2 partiel -------- - mov ax, bp ; AL=newseg low - - ; lowmask = (1<>(8-off)) --- - mov cl, bl - shl ax, cl - mov cl, 8 - sub cl, bl - shr bp, cl - or ax, bp ; AX = seg - - ; --- newseg --- - and ax, cx - xor ax, dx - - ; --- write unaligned --- - ; b0 - mov bp, ax - mov cl, bl - add cl, 8 - shr bp, cl ; BP = val0 - mov dl, 1 - mov cl, 8 - sub cl, bl - shl dl, cl - dec dl ; mask0 - mov dh, [es:di] - not dl - and dh, dl - not dl - or dh, bl - mov [es:di], dh - - ; b1 - mov cl, bl - shr ax, cl - mov [es:di+1], al - - ; b2 - mov ax, bp - mov cl, bl - ; and al, (1<