summaryrefslogtreecommitdiff
path: root/system/shard-x86-at/7/src/PCPLOT.ASM
blob: a922bd7f1d82544e8b944baddd6c91140e6ca06d (plain)
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