1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
|
;****************************************************************************
;*======= 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 <mov word ptr [first_shift],0ebd1h> ;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 <mov word ptr [jmp_or_not],07ebh> ;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
|