forked from gnuplot/gnuplot-old
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pcgraph.asm
221 lines (188 loc) · 3.83 KB
/
pcgraph.asm
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
TITLE PC graphics module
; uses LINEPROC.MAC
; Michael Gordon - 8-Dec-86
;
; Certain routines were taken from the Hercules BIOS of Dave Tutelman - 8/86
; Others came from pcgraph.asm included in GNUPLOT by Colin Kelley
;
; modified slightly by Colin Kelley - 22-Dec-86
; added header.mac, parameterized declarations
; added dgroup: in HVmodem to reach HCh_Parms and HGr_Parms - 30-Jan-87
;
; modified and added to for use in plot(3) routines back end.
; Gil Webster.
;
; Assemble with masm ver. 4.
include header.mac
if1
include lineproc.mac
endif
GPg1_Base equ 0B800h ; Graphics page 1 base address
extrn _inter:far
_text segment
public _PC_line, _PC_color, _PC_mask, _PC_curloc, _PC_puts, _Vmode
public _erase, _save_stack, _ss_interrupt
pcpixel proc near
ror word ptr linemask,1
jc cont
ret
cont:
push ax
push bx
push cx
push dx
push bp
mov cx,ax ; x
mov dx,bx ; y
mov ah,0ch ; ah = write pixel
mov al,byte ptr color
mov bh, 0 ; page 0
int 10h
pop bp
pop dx
pop cx
pop bx
pop ax
ret
pcpixel endp
lineproc _PC_line, pcpixel
;
; erase - clear page 1 of the screen buffer to zero (effectively, blank
; the screen)
;
beginproc _erase
push es
push ax
push cx
push di
mov ax, GPg1_Base
mov es, ax
xor di, di
mov cx, 4000h
xor ax, ax
cld
rep stosw ; zero out screen page
pop di
pop cx
pop ax
pop es
ret
_erase endp
beginproc _PC_color
push bp
mov bp,sp
mov al,[bp+X] ; color
mov byte ptr color,al
pop bp
ret
_PC_color endp
beginproc _PC_mask
push bp
mov bp,sp
mov ax,[bp+X] ; mask
mov word ptr linemask,ax
pop bp
ret
_PC_mask endp
beginproc _Vmode
push bp
mov bp,sp
push si
push di
mov ax,[bp+X]
int 10h
pop di
pop si
pop bp
ret
_Vmode endp
beginproc _PC_curloc
push bp
mov bp,sp
mov dh, byte ptr [bp+X] ; row number
mov dl, byte ptr [bp+X+2] ; col number
mov bh, 0
mov ah, 2
int 10h
pop bp
ret
_PC_curloc endp
;
; thanks to watale!broehl for finding a bug here--I wasn't pushing BP
; and reloading AH before INT 10H, which is necessary on genuine IBM
; boards...
;
beginproc _PC_puts
push bp
mov bp,sp
push si
mov bl,byte ptr color
mov si,[bp+X] ; offset
ifdef LARGE_DATA
mov es,[bp+X+2] ; segment if large or compact data model
endif
puts2:
ifdef LARGE_DATA
mov al,es:[si]
else
mov al,[si]
endif
or al,al
jz puts3
mov ah,0eh ; write TTY char
int 10h
inc si
jmp short puts2
puts3: pop si
pop bp
ret
_PC_puts endp
; int kbhit();
; for those without MSC 4.0
; Use BIOS interrupt 16h to determine if a key is waiting in the buffer.
; Return nonzero if so.
;
beginproc _kbhit
mov ah, 1 ; function code 1 is keyboard test
int 16h ; keyboard functions
jnz kbfin ; Exit if char available
xor ax, ax ; No char: return zero.
kbfin: ret
_kbhit endp
; _save_stack and _ss_interrupt are needed due to a bug in the MSC 4.0
; code when run under MS-DOS 3.x. Starting with 3.0, MS-DOS automatically
; switches to an internal stack during system calls. This leaves SS:SP
; pointing at MS-DOS's stack when the ^C interrupt (INT 23H) is triggered.
; MSC should restore its own stack before calling the user signal() routine,
; but it doesn't.
;
; Presumably this code will be unnecessary in later releases of the compiler.
;
; _save_stack saves the current SS:SP to be loaded later by _ss_interrupt.
;
beginproc _save_stack
mov ax,ss
mov cs:save_ss,ax
mov ax,sp
mov cs:save_sp,ax
ret
_save_stack endp
; _ss_interrupt is called on ^C (INT 23H). It restores SS:SP as saved in
; _save_stack and then jumps to the C routine interrupt().
;
beginproc _ss_interrupt
cli ; no interrupts while the stack is changed!
mov ax,-1 ; self-modifying code again
save_ss equ this word - 2
mov ss,ax
mov sp,-1 ; here too
save_sp equ this word - 2
sti
jmp far ptr _inter; now it's safe to call the real routine
_ss_interrupt endp
_text ends
const segment
linemask dw -1
color db 1
const ends
end