;**************************************************************************** ;*======= Copyright (C) 1985,86 Martin Schoenbeck, Spenge ==================* ;* * ;* Graphikroutinen fuer IBM - PC * ;* * ;* * ;**************************************************************************** gr_base dw 03d0h ;default grahpic adress gr_pointer equ 4 ;pointer register of 6845 gr_data equ 5 ;data register of 6845 gr_msr equ 8 ;mode select register gr_csr equ 9 ;color select register gr_status equ 10 ;status register gr_xmsr equ 10 ;extended mode select register gr_cfgswitch equ 15 ;hercules config switch switch_mode: cmp dh,1 jz gm_switch ;tecmar graphics master cmp dh,2 ;hercules jz herc_switch push dx push ax mov dx,[gr_base] add dx,gr_xmsr ;tecmar auf normal mode setzen mov al,0 out (dx),al jmp short $+2 ;io pause machen add dx,gr_cfgswitch-gr_xmsr ;hercules configswitch out (dx),al pop ax pop dx mov byte ptr [plot_mode],0 ;kein mode, den wir direkt auswerten mov al,dl mov ah,0 int 10h ;auf gewuenschten mode schalten mov cx,0 jnc mode_ok unallowed_mode: mov cx,-1 mode_ok: ret herc_switch: mov word ptr [gr_base],03b0h cmp dl,1 ;mode 0 ist erlaubt jnc unallowed_mode add dl,6 ;da steht der erste herculesmode jmp short all_allowed gm_switch: ;tecmar graphics master cmp dl,6 ;werte 0 bis 5 erlaubt jnc unallowed_mode push dx mov dx,[gr_base] add dx,gr_status ;statusregister holen in al,dx pop dx test al,80h ;schalter auf monochrom jnz all_allowed ;nein, alle modi erlaubt cmp dh,2 ;nur 0 und 1 jnc unallowed_mode all_allowed: mov byte ptr [plot_mode],1 ;merken, dass in erweitertem mode mov dh,0 mov ax,offset mod_tb_length ;laenge einer tabelle mul dx ;auf passende tabelle zeigen mov bx,ax add bx,offset mod_tables ;auf erstes byte der tabelle ; mov ah,13 ;vierzehn register muessen ausgegeben werden mov dx,[gr_base] add dx,gr_msr ;da ist mode select register unserer graphik mov al,0 ;disable screen output out (dx),al jmp short $+2 add dx,gr_cfgswitch-gr_msr ;hercules einschalten (wenn da) mov al,3 out (dx),al sub dx,gr_cfgswitch-gr_pointer set_6845: mov al,ah out (dx),al ;in dieses register wollen wir schreiben inc dx ;und hier muss der wert hin mov al,byte ptr [bx] inc bx ;auf naechstes feld out (dx),al dec dx ;wieder auf zeiger_register dec ah jns set_6845 ;bis nummer negativ ; cld mov cx,08000h ;fill 64k mov ax,0a000h mov es,ax xor ax,ax ;fill with 0 xor di,di ;start at 0 in area rep stosw mov cx,08000h mov ax,0b000h ;next 64k mov es,ax xor ax,ax ;fill with 0 xor di,di ;start at 0 in area rep stosw ; mov al,byte ptr[bx] ;csr wert holen inc bx add dx,gr_csr-gr_pointer out (dx),al ; inc dx ;to xmsr mov al,byte ptr [bx] inc bx out (dx),al ; sub dx,gr_xmsr-gr_msr ;to msr mov al,byte ptr [bx] inc bx out (dx),al ; mov ax,word ptr [bx] ;laenge einer graphik zeile inc bx inc bx mov word ptr [gr_linelength],ax ; mov al,byte ptr [bx] ;maske, um ein pixel zu behalten push ds pop es mov cx,16 mov di,offset color_tab rep stosb ;farbtabelle auf 3 initalisieren mov ah,0 inc bx mov word ptr [gr_pixel_mask],ax xor al,0ffh ;maske erzeugen, die ein pixel loescht mov byte ptr [gr_pixel_inv_mask],al ; mov word ptr [first_shift],9090h ;ersten shift wegnoppen test byte ptr [bx],1 ;vier segmente ? ifnz ;shift wieder eintragen inc bx ; mov al,byte ptr [bx] ;mask fuer pixel_pro_byte holen inc bx mov byte ptr [gr_pixel_per_byte_mask],al mov word ptr [shift_count_shift],0c902h ;volles shift annehmen mov word ptr [shift_count_shift+2],0c902h ;add cl,cl mov ah,1 ;anzahl shifts, um byteoffset zu kriegen shr al,1 ;bei mehr als zwei pixel ein shift weniger jz shifts_nopped inc ah mov word ptr [shift_count_shift],09090h ;nops shr al,1 ;bei acht pixel gar kein shift jz shifts_nopped inc ah mov word ptr [shift_count_shift+2],09090h ;nops shifts_nopped: mov byte ptr [gr_byte_calc_shift],ah ; mov si,bx mov di,offset gr_segtable mov cx,4 rep movsw ;segmentwerte uebertragen add bx,8 mov cx,0 ret pen: mov word ptr [maske],dx mov byte ptr [linetype],bl ret new_pen1: mov cx,bx ;bx merken mov bx,offset color_tab call set4 mov cx,dx call set4 ret new_pen2: mov cx,bx ;bx merken mov bx,offset color_tab+8 ;zweite haelfte der tabelle call set4 mov cx,dx call set4 ret set4: call set2 mov cl,ch set2: mov al,cl and al,15 ;nur untersten 4 bits behalten mov byte ptr [bx],al inc bx mov al,cl mov cl,4 shr al,cl ;obersten 4 bits mov byte ptr [bx],al inc bx ret mask_mode: mov word ptr [jmp_or_not],9090h ;set mask mode mov cx,word ptr [mask_count] ;alten mask_count zurueckliefern mov word ptr [mask_count],bx cmp dx,0 ;wirklich mask_mode gewuenscht ifz ;nein, sprung wieder einbauen ret move: mov word ptr [altx],dx ;neuen x wert mov word ptr [alty],bx ;und y wert setzen ret draw: mov byte ptr [stepx],46h ;inc si mov byte ptr [stepy],47h ;inc di mov cx,dx ;in welche richtung wie weit gehen sub cx,word ptr [altx] jns positiv_x neg cx ;negative richtung, positiv machen und mov byte ptr [stepx],4eh ;dec si zum ausgleich positiv_x: mov dx,bx ;y wert holen sub dx,word ptr [alty] ;wie weit und welche richtung jns positiv_y neg dx ;negative richtung, positiv rechnen und mov byte ptr [stepy],4fh ;dec di zur korrektur positiv_y: cmp dx,cx ;hauptrichtung entlang des groesseren ;offsets jc direction_ok ;hauptrichtung war entlang si mov bx,word ptr [stepy] ;richtungen tauschen xchg bh,bl mov word ptr [stepy],bx xchg cx,dx ;und richtungslaengen tauschen ;hauptrichtung ist jetzt entlang di direction_ok: ;der wert fuer die hauptrichtung ist ;in cx, fuer die nebenrichtung in dx ;der fehlerwert der nebenrichtung in ;1/abs(hauptrichtung) - einheiten ist in bx mov bx,0 ;fehlerwert ist im moment 0 mov word ptr [delta_x],cx ;wert fuer hauptrichtung merken mov si,word ptr [altx] ;alte werte holen mov di,word ptr [alty] paint: jcxz paint_done ;fertig, letzten punkt noch malen sub bx,dx ;ist gerader fehler schon negativ jns stepx ;nur hauptrichtung nehmen mov ax,bx ;geraden fehler nach ax add ax,ax ; add ax,word ptr [delta_x] ; jns stepx ;nur hauptrichtung add bx,word ptr [delta_x] stepy: inc di stepx: inc si ; errechneten punkt setzen call punkt loop paint paint_done: call punkt ;letzten punkt setzen mov word ptr [alty],di mov word ptr [altx],si ret punkt: test byte ptr [plot_mode],0ffh jnz new_punkt push cx push dx mov dx,di mov cx,si ror word ptr maske,1 linetype equ $+1 mov ax,0c01h ;write dot and al,byte ptr [maske] ;linie einbauen int 10h pop dx pop cx ret new_punkt: push ax push bx push cx push dx push es mov bx,di and bx,3 add bx,bx ; *2 mov es,[bx+gr_segtable] ;in diesem segment liegt unser punkt gr_linelength equ $+1 mov ax,720/4 ;bytes pro zeile horizontal mov bx,di ;y wert wieder holen first_shift: ;dieser shift faellt bei zwei segmenten aus shr bx,1 shr bx,1 ;di / 4 mul bx ;mal anzahl bytes pro graphikzeile mov bx,si ;byte in zeile ausrechnen gr_byte_calc_shift equ $+1 mov cl,2 ;so oft si shiften, fuer byte in zeile shr bx,cl add bx,ax ;dies byte enthaelt unseren punkt mov cx,si ;untersten bits geben shiftfaktor an inc cx ;einmal mehr shiften (oder gar nicht) gr_pixel_per_byte_mask equ $+2 and cl,3 ;vier pixel pro byte (15 fuer zwei pixel etc shift_count_shift: add cl,cl ;shiftfaktor verdoppeln add cl,cl ;oder vervierfachen mov al,byte ptr es:[bx] ;byte holen rol al,cl ;pixel nach 0 holen mov bp,ax ;evtl. wird pixelwert als index benutzt gr_pixel_mask equ $+2 and bp,3 ;die pixel bits behalten jmp_or_not: jmp short punkt_no_mask mask_count equ $+1 ;zaehler fuer maske mov bp,0 and bp,15 ;maskenzaehler MOD 16 nehmen punkt_no_mask: gr_pixel_inv_mask equ $+1 and al,0fch ;rest behalten or al,byte ptr ds:[bp+color_tab] ;pixel setzen ror al,cl ;zurueckdrehen mov byte ptr es:[bx],al ;wieder eintragen inc word ptr ds:[mask_count] pop es pop dx pop cx pop bx pop ax ret even maske dw 0ffffh altx dw 0 alty dw 0 delta_x dw 0 ;gr_pixel_mask dw 3 ;maske, welche bits zum pixel gehoeren ;mask_count dw 0 ;zaehler fuer maskiertes schreiben gr_segtable dw 0a000h ;tabelle der graphik segmente dw 0a800h dw 0b000h dw 0b800h ;gr_linelength dw 720/4 ;laenge einer graphikzeile ;mask_mod db 0 ;nicht 0, wenn mit maske color_tab db 16 DUP (3) ;farbtabelle plot_mode db 0 ;gr_pixel_inv_mask db 0fch ;invertiert, nur byte mod_tables equ $ ;mode 0 ; 6845 regs 13 - 0,csr,xmsr,msr db 0,0,0,32,3,2,88,86,1,91,14,90,90,109, 0, 191, 11 dw 720/4 ;laenge einer graphikzeile db 3 ;maske, um ein pixel zu behalten db 1 ;1 = 4 segmente, 0 = 2 segmente db 3 ;maske, um si MOD pixel_pro_byte zu machen dw 0a000h,0a800h,0b000h,0b800h ;die vier segmente mod_tb_length equ $-mod_tables ;mode 1 ; 6845 regs 13 - 0,csr,xmsr,msr db 0,0,0,32,3,3,88,86,1,91,14,90,90,109, 0, 191, 11 dw 720/4 ;laenge einer graphikzeile db 3 ;maske, um ein pixel zu behalten db 1 ;1 = 4 segmente, 0 = 2 segmente db 3 ;maske, um si MOD pixel_pro_byte zu machen dw 0a000h,0a800h,0b000h,0b800h ;die vier segmente ;mode 2 ; 6845 regs 13 - 0,csr,xmsr,msr db 0,0,0,32,1,2,112,100,6,127,15,184,160,227, 0, 31, 24 dw 640/2 ;laenge einer graphikzeile db 15 ;maske, um ein pixel zu behalten db 0 ;1 = 4 segmente, 0 = 2 segmente db 1 ;maske, um si MOD pixel_pro_byte zu machen dw 0a000h,0a800h,0a000h,0a800h ;die vier segmente ;mode 3 ; 6845 regs 13 - 0,csr,xmsr,msr db 0,0,0,32,3,3,56,50,1,64,15,184,160,227, 0, 31, 24 dw 640/2 ;laenge einer graphikzeile db 15 ;maske, um ein pixel zu behalten db 1 ;1 = 4 segmente, 0 = 2 segmente db 1 ;maske, um si MOD pixel_pro_byte zu machen dw 0a000h,0a800h,0b000h,0b800h ;die vier segmente ;mode 4 ; 6845 regs 13 - 0,csr,xmsr,msr db 0,0,0,32,1,2,112,100,7,127,15,98,90,128, 0, 63, 11 dw 720/4 ;laenge einer graphikzeile db 3 ;maske, um ein pixel zu behalten db 0 ;1 = 4 segmente, 0 = 2 segmente db 3 ;maske, um si MOD pixel_pro_byte zu machen dw 0a000h,0a800h,0a000h,0a800h ;die vier segmente ;mode 5 ; 6845 regs 13 - 0,csr,xmsr,msr db 0,0,0,32,3,3,56,50,3,64,15,98,90,128, 0, 63, 11 dw 720/4 ;laenge einer graphikzeile db 3 ;maske, um ein pixel zu behalten db 1 ;1 = 4 segmente, 0 = 2 segmente db 3 ;maske, um si MOD pixel_pro_byte zu machen dw 0a000h,0a800h,0b000h,0b800h ;die vier segmente ;mode 6 (hercules) ; 6845 regs 13 - 0,csr,xmsr,msr db 0,0,0,0,3,2,87,87,2,91,7,46,45,53, 0, 0, 10 dw 720/8 ;laenge einer graphikzeile db 1 ;maske, um ein pixel zu behalten db 1 ;1 = 4 segmente, 0 = 2 segmente db 7 ;maske, um si MOD pixel_pro_byte zu machen dw 0b000h,0b200h,0b400h,0b600h ;die vier segmente