├── ADSR.ASM ├── ADSR2.ASM ├── BANKSW1.ASM ├── BANKSW2.ASM ├── BGILINE.C ├── CIRCLE1.ASM ├── CIRCLE2.ASM ├── CIRCLE3.ASM ├── CIRCLE4.ASM ├── CIRCLE5.ASM ├── CLINE.C ├── CORDIC1.ASM ├── DECAY.ASM ├── DECIMAL.ASM ├── DOSMEM.ASM ├── ELLIPSE1.ASM ├── ELLIPSE2.ASM ├── ELLIPSE3.ASM ├── ELLIPSE4.ASM ├── ELLIPSE5.ASM ├── ELLIPSE6.ASM ├── Ellipse.jl ├── Ellipse2.jl ├── Ellipse3.jl ├── Ellipse4.jl ├── HELLO.ASM ├── HIRES.ASM ├── HIRES2.ASM ├── HIRES2.EXE ├── JITTER1.ASM ├── JITTER2.ASM ├── JITTER3C.ASM ├── JITTER3a.ASM ├── JITTER3b.ASM ├── KEYPRESS.ASM ├── LINE.ASM ├── LINE2.ASM ├── LINEAR.ASM ├── LINEAR2.ASM ├── LINEAR3.ASM ├── LINEAR3a.ASM ├── LINEAR4.ASM ├── LINEAR5.ASM ├── LINEAR7.ASM ├── LINEAR8.ASM ├── LINEAR9.ASM ├── LINEARA.ASM ├── MANDEL.ASM ├── MANDEL2.ASM ├── MCGA.ASM ├── MCGA1.ASM ├── MYLINE.ASM ├── POINT1.ASM ├── POINT2.ASM ├── REFRESH.ASM ├── SLOWREFR.ASM ├── TANDYDIT.ASM ├── TANDYDOT.ASM ├── TANDYLIN.ASM ├── TANDYSND.ASM ├── TETRA3D.COM ├── TIMELINE.BAS ├── TIMELINE.C ├── TIMER.ASM ├── TNDYLIN2.ASM ├── TNDYLIN2.EXE ├── TNDYLINR.ASM ├── WILTON.C ├── line3.asm └── line4.asm /BGILINE.C: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | int main(int ac, char ** av) 7 | { 8 | int i, gd = CGA, gm = CGAC0; 9 | int x0, y0, x1, y1; 10 | struct time time1; 11 | double t; 12 | 13 | if (ac != 5) 14 | { 15 | printf("Usage:\n"); 16 | printf(" bgiline x0 y0 x1 y1\n"); 17 | abort(); 18 | } 19 | 20 | x0 = atoi(av[1]); 21 | y0 = atoi(av[2]); 22 | x1 = atoi(av[3]); 23 | y1 = atoi(av[4]); 24 | 25 | time1.ti_hour = 0; 26 | time1.ti_min = 0; 27 | time1.ti_sec = 0; 28 | time1.ti_hund = 0; 29 | 30 | initgraph(&gd, &gm, ""); 31 | cleardevice(); 32 | 33 | settime(&time1); 34 | 35 | for (i = 0; i < 10000; i++) 36 | line(x0, y0, x1, y1); 37 | 38 | gettime(&time1); 39 | 40 | t = 60.0*time1.ti_min; 41 | t += time1.ti_sec; 42 | t += (time1.ti_hund/100.0); 43 | t *= 18.206; 44 | 45 | printf("%f\n", t); 46 | 47 | getch(); 48 | closegraph(); 49 | 50 | return 0; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /CIRCLE1.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _cga_circle PROC 7 | ARG x0:WORD, y0:WORD, r:WORD, colour:BYTE 8 | 9 | ; ax = accum, dx = dx, bp = dy, si = D 10 | ; di = offset, bl = mask, bh = colour 11 | 12 | push bp 13 | mov bp, sp 14 | push si 15 | push di 16 | 17 | ; set up CGA segment 18 | mov ax, 0b800h 19 | mov es, ax 20 | 21 | ; get r 22 | mov dx, r 23 | mov di, dx 24 | 25 | ; compute (x0 + r) mod 4 and (x0 + r) / 4 26 | add di, x0 27 | mov cx, di 28 | and cl, 3 29 | shr di, 1 30 | shr di, 1 31 | 32 | ; compute colour and mask 33 | mov bh, colour 34 | mov bl, 03fh 35 | shl cl, 1 36 | ror bl, cl 37 | inc cl 38 | inc cl 39 | ror bh, cl 40 | 41 | ; compute y offset 42 | mov ax, y0 43 | 44 | ; offset += 8192 if y0 odd 45 | shr ax, 1 46 | sbb si, si 47 | and si, 8192 48 | add di, si 49 | 50 | ; add 80*(y0/2) to offset 51 | shl ax, 1 52 | shl ax, 1 53 | shl ax, 1 54 | shl ax, 1 55 | add di, ax 56 | shl ax, 1 57 | shl ax, 1 58 | add di, ax 59 | 60 | ; compute initial D and dx 61 | mov si, dx 62 | neg si 63 | shl dx, 1 64 | 65 | ; compute dy 66 | xor bp, bp 67 | 68 | circle_loop: 69 | mov al, es:[di] ; get pixel 70 | and al, bl ; and with mask 71 | or al, bh ; or with colour 72 | stosb ; write pixel 73 | 74 | add si, bp ; D += dy + 1 75 | inc si 76 | 77 | jl circle_skipy ; if D >= 0 78 | 79 | rol bh, 1 ; dec x 80 | rol bh, 1 81 | rol bl, 1 82 | rol bl, 1 83 | cmc 84 | sbb di, 0 85 | 86 | dec dx ; dx -= 2 87 | dec dx 88 | 89 | sub si, dx ; D -= dx 90 | 91 | circle_skipy: 92 | sub di, 8113 ; increment y 93 | sbb ax, ax 94 | and ax, 16304 95 | add di, ax 96 | 97 | inc bp ; dy += 2 98 | inc bp 99 | 100 | cmp dx, bp 101 | jge circle_loop 102 | 103 | pop di 104 | pop si 105 | pop bp 106 | ret 107 | _cga_circle ENDP 108 | 109 | start: 110 | ; set video mode = 4 (CGA 320x200x4) 111 | xor ah, ah 112 | mov al, 4 113 | int 10h 114 | 115 | mov al, 2 ; colour = 2 116 | push ax 117 | xor ah, ah 118 | mov al, 50 ; r = 50 119 | push ax 120 | mov al, 100 ; y0 = 100 121 | push ax 122 | mov al, 100 ; x0 = 100 123 | push ax 124 | call _cga_circle 125 | add sp, 8 126 | 127 | ; wait for keypress 128 | xor ah, ah 129 | int 16h 130 | 131 | ; restore video mode 132 | xor ah, ah 133 | mov al, 3 134 | int 10h 135 | 136 | mov ah, 4ch ; terminate program 137 | int 21h 138 | END start 139 | -------------------------------------------------------------------------------- /CIRCLE2.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _cga_circle PROC 7 | ARG x0:WORD, y0:WORD, r:WORD, colour:BYTE 8 | 9 | ; ax = accum, si = dx, bp = dy, cx = D, bx = offset diff 10 | ; di = offset, dl = mask, dh = colour 11 | 12 | push bp 13 | mov bp, sp 14 | push si 15 | push di 16 | 17 | ; set up CGA segment 18 | mov ax, 0b800h 19 | mov es, ax 20 | 21 | ; compute y offset 22 | mov ax, y0 23 | 24 | ; offset += 4*8192 if y0 odd 25 | xor di, di 26 | shr ax, 1 27 | rcr di, 1 28 | 29 | ; get r 30 | mov si, r 31 | add di, si 32 | 33 | ; compute (x0 + r) mod 4 and 4*(x0 + r) / 4 34 | add di, x0 35 | mov cx, di 36 | and cl, 3 37 | 38 | ; compute colour and mask 39 | mov dh, colour 40 | mov dl, 03fh 41 | shl cl, 1 42 | ror dl, cl 43 | inc cl 44 | inc cl 45 | ror dh, cl 46 | 47 | ; add 4*80*(y0/2) to offset and divide by 4 48 | xchg ah, al 49 | add di, ax 50 | shr ax, 1 51 | shr ax, 1 52 | add di, ax 53 | shr di, 1 54 | shr di, 1 55 | 56 | ; compute initial D and dx 57 | mov cx, 1 58 | sub cx, si 59 | shl si, 1 60 | 61 | ; compute dy 62 | xor bp, bp 63 | 64 | xor bx, bx ; offset diff = 0 65 | 66 | circle_loop: 67 | mov al, es:[di+bx] ; get pixel 68 | and al, dl ; and with mask 69 | or al, dh ; or with colour 70 | mov es:[di+bx], al ; write pixel 71 | 72 | mov al, es:[di] ; get pixel 73 | and al, dl ; and with mask 74 | or al, dh ; or with colour 75 | stosb ; write pixel 76 | 77 | cmp cx, 0 ; if D >= 0 78 | jl circle_skipy 79 | 80 | rol dh, 1 ; dec x 81 | rol dh, 1 82 | rol dl, 1 83 | rol dl, 1 84 | cmc 85 | sbb di, 0 86 | 87 | dec si ; dx -= 2 88 | dec si 89 | 90 | sub cx, si ; D -= dx 91 | 92 | circle_skipy: 93 | sub di, 8113 ; increment y 94 | sbb ax, ax 95 | and ax, 16304 96 | add di, ax 97 | 98 | sub bx, 80 ; decrease offset diff 99 | 100 | inc bp ; dy += 2 101 | inc bp 102 | 103 | add cx, bp ; D += dy + 1 104 | inc cx 105 | 106 | cmp si, bp 107 | jge circle_loop 108 | 109 | pop di 110 | pop si 111 | pop bp 112 | ret 113 | _cga_circle ENDP 114 | 115 | start: 116 | ; set video mode = 4 (CGA 320x200x4) 117 | xor ah, ah 118 | mov al, 4 119 | int 10h 120 | 121 | mov al, 2 ; colour = 2 122 | push ax 123 | xor ah, ah 124 | mov al, 50 ; r = 50 125 | push ax 126 | mov al, 100 ; y0 = 100 127 | push ax 128 | mov al, 100 ; x0 = 100 129 | push ax 130 | call _cga_circle 131 | add sp, 8 132 | 133 | ; wait for keypress 134 | xor ah, ah 135 | int 16h 136 | 137 | ; restore video mode 138 | xor ah, ah 139 | mov al, 3 140 | int 10h 141 | 142 | mov ah, 4ch ; terminate program 143 | int 21h 144 | END start 145 | -------------------------------------------------------------------------------- /CIRCLE3.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _cga_circle PROC 7 | ARG x0:WORD, y0:WORD, r:WORD, colour:BYTE 8 | 9 | ; ax = accum, si = dx, bp = dy, cx = D, bx = offset diff 10 | ; di = offset, dl = mask, dh = colour 11 | 12 | push bp 13 | mov bp, sp 14 | push si 15 | push di 16 | 17 | ; set up CGA segment 18 | mov ax, 0b800h 19 | mov es, ax 20 | 21 | push bp 22 | 23 | ; right arc of circle 24 | 25 | ; compute y offset 26 | mov ax, y0 27 | 28 | ; offset += 4*8192 if y0 odd 29 | xor di, di 30 | shr ax, 1 31 | rcr di, 1 32 | 33 | ; get r 34 | mov si, r 35 | mov di, x0 36 | 37 | ; compute (x0 + r) mod 4 and 4*(x0 + r) / 4 38 | add di, si 39 | mov cx, di 40 | and cl, 3 41 | 42 | ; compute colour and mask 43 | mov dh, colour 44 | mov dl, 03fh 45 | shl cl, 1 46 | ror dl, cl 47 | inc cl 48 | inc cl 49 | ror dh, cl 50 | 51 | ; add 4*80*(y0/2) to offset 52 | xchg ah, al 53 | add di, ax 54 | shr ax, 1 55 | shr ax, 1 56 | add di, ax 57 | shr di, 1 58 | shr di, 1 59 | 60 | ; compute initial D and dx 61 | mov cx, 1 62 | sub cx, si 63 | shl si, 1 64 | 65 | ; compute dy 66 | xor bp, bp 67 | 68 | xor bx, bx ; offset diff = 0 69 | 70 | circle_loop1: 71 | mov al, es:[di+bx] ; get pixel 72 | and al, dl ; and with mask 73 | or al, dh ; or with colour 74 | mov es:[di+bx], al ; write pixel 75 | 76 | mov al, es:[di] ; get pixel 77 | and al, dl ; and with mask 78 | or al, dh ; or with colour 79 | stosb ; write pixel 80 | 81 | cmp cx, 0 ; if D >= 0 82 | jl circle_skipy1 83 | 84 | rol dh, 1 ; dec x 85 | rol dh, 1 86 | rol dl, 1 87 | rol dl, 1 88 | cmc 89 | sbb di, 0 90 | 91 | dec si ; dx -= 2 92 | dec si 93 | 94 | sub cx, si ; D -= dx 95 | 96 | circle_skipy1: 97 | sub di, 8113 ; increment y 98 | sbb ax, ax 99 | and ax, 16304 100 | add di, ax 101 | 102 | sub bx, 80 ; increase offset diff 103 | 104 | inc bp ; dy += 2 105 | inc bp 106 | 107 | add cx, bp ; D += dy + 1 108 | inc cx 109 | 110 | cmp si, bp 111 | jge circle_loop1 112 | 113 | pop bp 114 | 115 | ; left arc of circle 116 | 117 | ; compute y offset 118 | mov ax, y0 119 | 120 | ; offset += 4*8192 if y0 odd 121 | xor di, di 122 | shr ax, 1 123 | rcr di, 1 124 | 125 | ; get r 126 | mov si, r 127 | 128 | ; compute (x0 - r) mod 4 and 4*(x0 - r) / 4 129 | mov di, x0 130 | sub di, si 131 | mov cx, di 132 | and cl, 3 133 | 134 | ; compute colour and mask 135 | mov dh, colour 136 | mov dl, 03fh 137 | shl cl, 1 138 | ror dl, cl 139 | inc cl 140 | inc cl 141 | ror dh, cl 142 | 143 | ; add 4*80*(y0/2) to offset 144 | xchg ah, al 145 | add di, ax 146 | shr ax, 1 147 | shr ax, 1 148 | add di, ax 149 | shr di, 1 150 | shr di, 1 151 | 152 | ; compute initial D and dx 153 | mov cx, 1 154 | sub cx, si 155 | shl si, 1 156 | 157 | ; compute dy 158 | xor bp, bp 159 | 160 | xor bx, bx ; offset diff = 0 161 | 162 | circle_loop2: 163 | mov al, es:[di+bx] ; get pixel 164 | and al, dl ; and with mask 165 | or al, dh ; or with colour 166 | mov es:[di+bx], al ; write pixel 167 | 168 | mov al, es:[di] ; get pixel 169 | and al, dl ; and with mask 170 | or al, dh ; or with colour 171 | stosb ; write pixel 172 | 173 | cmp cx, 0 ; if D >= 0 174 | jl circle_skipy2 175 | 176 | ror dh, 1 ; inc x 177 | ror dh, 1 178 | ror dl, 1 179 | ror dl, 1 180 | cmc 181 | adc di, 0 182 | 183 | dec si ; dx -= 2 184 | dec si 185 | 186 | sub cx, si ; D -= dx 187 | 188 | circle_skipy2: 189 | sub di, 8113 ; increment y 190 | sbb ax, ax 191 | and ax, 16304 192 | add di, ax 193 | 194 | sub bx, 80 ; increase offset diff 195 | 196 | inc bp ; dy += 2 197 | inc bp 198 | 199 | add cx, bp ; D += dy + 1 200 | inc cx 201 | 202 | cmp si, bp 203 | jge circle_loop2 204 | 205 | pop di 206 | pop si 207 | pop bp 208 | ret 209 | _cga_circle ENDP 210 | 211 | start: 212 | ; set video mode = 4 (CGA 320x200x4) 213 | xor ah, ah 214 | mov al, 4 215 | int 10h 216 | 217 | mov al, 2 ; colour = 2 218 | push ax 219 | xor ah, ah 220 | mov al, 50 ; r = 50 221 | push ax 222 | mov al, 100 ; y0 = 100 223 | push ax 224 | mov al, 100 ; x0 = 100 225 | push ax 226 | call _cga_circle 227 | add sp, 8 228 | 229 | ; wait for keypress 230 | xor ah, ah 231 | int 16h 232 | 233 | ; restore video mode 234 | xor ah, ah 235 | mov al, 3 236 | int 10h 237 | 238 | mov ah, 4ch ; terminate program 239 | int 21h 240 | END start 241 | -------------------------------------------------------------------------------- /CIRCLE4.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _cga_circle PROC 7 | ARG x0:WORD, y0:WORD, r:WORD, colour:BYTE 8 | 9 | ; ax = accum, si = dx, bp = dy, cx = D, bx = offset diff 10 | ; di = offset, dl = mask, dh = colour 11 | 12 | push bp 13 | mov bp, sp 14 | push si 15 | push di 16 | 17 | ; set up CGA segment 18 | mov ax, 0b800h 19 | mov es, ax 20 | 21 | push bp 22 | 23 | ; right arc of circle 24 | 25 | ; compute y offset 26 | mov ax, y0 27 | 28 | ; offset += 4*8192 if y0 odd 29 | xor di, di 30 | shr ax, 1 31 | rcr di, 1 32 | 33 | ; get r 34 | mov si, r 35 | mov di, x0 36 | 37 | ; compute (x0 + r) mod 4 and 4*(x0 + r) / 4 38 | add di, si 39 | mov cx, di 40 | and cl, 3 41 | 42 | ; compute colour and mask 43 | mov dh, colour 44 | mov dl, 03fh 45 | shl cl, 1 46 | ror dl, cl 47 | inc cl 48 | inc cl 49 | ror dh, cl 50 | 51 | ; add 4*80*(y0/2) to offset 52 | xchg ah, al 53 | add di, ax 54 | shr ax, 1 55 | shr ax, 1 56 | add di, ax 57 | shr di, 1 58 | shr di, 1 59 | 60 | ; compute initial D and dx 61 | mov cx, 1 62 | sub cx, si 63 | shl si, 1 64 | 65 | ; compute dy 66 | xor bp, bp 67 | 68 | xor bx, bx ; offset diff = 0 69 | 70 | circle_loop1: 71 | mov al, es:[di+bx] ; get pixel 72 | and al, dl ; and with mask 73 | or al, dh ; or with colour 74 | mov es:[di+bx], al ; write pixel 75 | 76 | mov al, es:[di] ; get pixel 77 | and al, dl ; and with mask 78 | or al, dh ; or with colour 79 | stosb ; write pixel 80 | 81 | cmp cx, 0 ; if D >= 0 82 | jl circle_skipy1 83 | 84 | rol dh, 1 ; dec x 85 | rol dh, 1 86 | rol dl, 1 87 | rol dl, 1 88 | cmc 89 | sbb di, 0 90 | 91 | dec si ; dx -= 2 92 | dec si 93 | 94 | sub cx, si ; D -= dx 95 | 96 | circle_skipy1: 97 | sub di, 8113 ; increment y 98 | sbb ax, ax 99 | and ax, 16304 100 | add di, ax 101 | 102 | sub bx, 80 ; increase offset diff 103 | 104 | inc bp ; dy += 2 105 | inc bp 106 | 107 | add cx, bp ; D += dy + 1 108 | inc cx 109 | 110 | cmp si, bp 111 | jge circle_loop1 112 | 113 | pop bp 114 | push bp 115 | 116 | ; left arc of circle 117 | 118 | ; compute y offset 119 | mov ax, y0 120 | 121 | ; offset += 4*8192 if y0 odd 122 | xor di, di 123 | shr ax, 1 124 | rcr di, 1 125 | 126 | ; get r 127 | mov si, r 128 | mov di, x0 129 | 130 | ; compute (x0 - r) mod 4 and 4*(x0 - r) / 4 131 | sub di, si 132 | mov cx, di 133 | and cl, 3 134 | 135 | ; compute colour and mask 136 | mov dh, colour 137 | mov dl, 03fh 138 | shl cl, 1 139 | ror dl, cl 140 | inc cl 141 | inc cl 142 | ror dh, cl 143 | 144 | ; add 4*80*(y0/2) to offset 145 | xchg ah, al 146 | add di, ax 147 | shr ax, 1 148 | shr ax, 1 149 | add di, ax 150 | shr di, 1 151 | shr di, 1 152 | 153 | ; compute initial D and dx 154 | mov cx, 1 155 | sub cx, si 156 | shl si, 1 157 | 158 | ; compute dy 159 | xor bp, bp 160 | 161 | xor bx, bx ; offset diff = 0 162 | 163 | circle_loop2: 164 | mov al, es:[di+bx] ; get pixel 165 | and al, dl ; and with mask 166 | or al, dh ; or with colour 167 | mov es:[di+bx], al ; write pixel 168 | 169 | mov al, es:[di] ; get pixel 170 | and al, dl ; and with mask 171 | or al, dh ; or with colour 172 | stosb ; write pixel 173 | 174 | cmp cx, 0 ; if D >= 0 175 | jl circle_skipy2 176 | 177 | ror dh, 1 ; inc x 178 | ror dh, 1 179 | ror dl, 1 180 | ror dl, 1 181 | cmc 182 | adc di, 0 183 | 184 | dec si ; dx -= 2 185 | dec si 186 | 187 | sub cx, si ; D -= dx 188 | 189 | circle_skipy2: 190 | sub di, 8113 ; increment y 191 | sbb ax, ax 192 | and ax, 16304 193 | add di, ax 194 | 195 | sub bx, 80 ; increase offset diff 196 | 197 | inc bp ; dy += 2 198 | inc bp 199 | 200 | add cx, bp ; D += dy + 1 201 | inc cx 202 | 203 | cmp si, bp 204 | jge circle_loop2 205 | 206 | ; left top and bottom arcs of circle 207 | 208 | pop bp 209 | push bp 210 | 211 | ; get r 212 | mov si, r 213 | 214 | ; compute y offset 215 | mov ax, y0 216 | sub ax, si 217 | 218 | ; offset += 4*8192 if y0 odd 219 | xor di, di 220 | shr ax, 1 221 | rcr di, 1 222 | 223 | ; compute x0 mod 4 and 4*x0 / 4 224 | mov cx, x0 225 | add di, cx 226 | and cl, 3 227 | 228 | ; compute colour and mask 229 | mov dh, colour 230 | mov dl, 03fh 231 | shl cl, 1 232 | ror dl, cl 233 | inc cl 234 | inc cl 235 | ror dh, cl 236 | 237 | ; add 4*80*((y0 - r)/2) to offset 238 | xchg ah, al 239 | add di, ax 240 | shr ax, 1 241 | shr ax, 1 242 | add di, ax 243 | shr di, 1 244 | shr di, 1 245 | 246 | ; save offset, colour and mask bytes 247 | push di 248 | push dx 249 | 250 | ; compute initial D 251 | mov cx, 1 252 | sub cx, si 253 | 254 | ; compute offset diff = 80*r 255 | mov bx, si 256 | shl bx, 1 257 | shl bx, 1 258 | shl bx, 1 259 | shl bx, 1 260 | mov ax, bx 261 | shl bx, 1 262 | shl bx, 1 263 | add bx, ax 264 | 265 | ; compute dy 266 | xor bp, bp 267 | 268 | ; compute dx 269 | shl si, 1 270 | 271 | std 272 | 273 | circle_loop3: 274 | mov al, es:[di+bx] ; get pixel 275 | and al, dl ; and with mask 276 | or al, dh ; or with colour 277 | mov es:[di+bx], al ; write pixel 278 | 279 | mov al, es:[di] ; get pixel 280 | and al, dl ; and with mask 281 | or al, dh ; or with colour 282 | stosb ; write pixel 283 | 284 | cmp cx, 0 ; if D >= 0 285 | jl circle_skipy3 286 | 287 | sub di, 8112 ; increment y 288 | sbb ax, ax 289 | and ax, 16304 290 | add di, ax 291 | 292 | sub bx, 80 ; decrease offset diff 293 | 294 | dec si ; dx -= 2 295 | dec si 296 | 297 | sub cx, si ; D -= dx 298 | 299 | circle_skipy3: 300 | rol dh, 1 ; dec x 301 | rol dh, 1 302 | rol dl, 1 303 | rol dl, 1 304 | adc di, 0 305 | 306 | inc bp ; dy += 2 307 | inc bp 308 | 309 | add cx, bp ; D += dy + 1 310 | inc cx 311 | 312 | cmp si, bp 313 | jge circle_loop3 314 | 315 | cld 316 | 317 | ; restore offset, colour and mask bytes 318 | pop dx 319 | pop di 320 | 321 | pop bp 322 | 323 | ; get r 324 | mov si, r 325 | 326 | ; compute initial D 327 | mov cx, 1 328 | sub cx, si 329 | 330 | ; compute offset diff = 80*r 331 | mov bx, si 332 | shl bx, 1 333 | shl bx, 1 334 | shl bx, 1 335 | shl bx, 1 336 | mov ax, bx 337 | shl bx, 1 338 | shl bx, 1 339 | add bx, ax 340 | 341 | ; compute dy 342 | xor bp, bp 343 | 344 | ; compute dx 345 | shl si, 1 346 | 347 | circle_loop4: 348 | mov al, es:[di+bx] ; get pixel 349 | and al, dl ; and with mask 350 | or al, dh ; or with colour 351 | mov es:[di+bx], al ; write pixel 352 | 353 | mov al, es:[di] ; get pixel 354 | and al, dl ; and with mask 355 | or al, dh ; or with colour 356 | stosb ; write pixel 357 | 358 | cmp cx, 0 ; if D >= 0 359 | jl circle_skipy4 360 | 361 | sub di, 8112 ; increment y 362 | sbb ax, ax 363 | and ax, 16304 364 | add di, ax 365 | 366 | sub bx, 80 ; decrease offset diff 367 | 368 | dec si ; dx -= 2 369 | dec si 370 | 371 | sub cx, si ; D -= dx 372 | 373 | circle_skipy4: 374 | ror dh, 1 ; inc x 375 | ror dh, 1 376 | ror dl, 1 377 | ror dl, 1 378 | sbb di, 0 379 | 380 | inc bp ; dy += 2 381 | inc bp 382 | 383 | add cx, bp ; D += dy + 1 384 | inc cx 385 | 386 | cmp si, bp 387 | jge circle_loop4 388 | 389 | pop di 390 | pop si 391 | pop bp 392 | ret 393 | _cga_circle ENDP 394 | 395 | start: 396 | ; set video mode = 4 (CGA 320x200x4) 397 | xor ah, ah 398 | mov al, 4 399 | int 10h 400 | 401 | mov al, 2 ; colour = 2 402 | push ax 403 | xor ah, ah 404 | mov al, 50 ; r = 50 405 | push ax 406 | mov al, 100 ; y0 = 100 407 | push ax 408 | mov al, 100 ; x0 = 100 409 | push ax 410 | call _cga_circle 411 | add sp, 8 412 | 413 | ; wait for keypress 414 | xor ah, ah 415 | int 16h 416 | 417 | ; restore video mode 418 | xor ah, ah 419 | mov al, 3 420 | int 10h 421 | 422 | mov ah, 4ch ; terminate program 423 | int 21h 424 | END start 425 | -------------------------------------------------------------------------------- /CLINE.C: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "graphics.h" 5 | 6 | int main(int ac, char ** av) 7 | { 8 | int i; 9 | int x0, y0, x1, y1; 10 | struct time time1; 11 | double t; 12 | unsigned char far * video = MK_FP(0xb800, 0x0); 13 | 14 | if (ac != 5) 15 | { 16 | printf("Usage:\n"); 17 | printf(" cline x0 y0 x1 y1\n"); 18 | abort(); 19 | } 20 | 21 | x0 = atoi(av[1]); 22 | y0 = atoi(av[2]); 23 | x1 = atoi(av[3]); 24 | y1 = atoi(av[4]); 25 | 26 | time1.ti_hour = 0; 27 | time1.ti_min = 0; 28 | time1.ti_sec = 0; 29 | time1.ti_hund = 0; 30 | 31 | set_video_mode(4); 32 | 33 | settime(&time1); 34 | 35 | for (i = 0; i < 10000; i++) 36 | cga_draw_line(video, x0, y0, x1, y1, 3); 37 | 38 | gettime(&time1); 39 | 40 | t = 60.0*time1.ti_min; 41 | t += time1.ti_sec; 42 | t += (time1.ti_hund/100.0); 43 | t *= 18.206; 44 | 45 | printf("%f\n", t); 46 | 47 | getch(); 48 | 49 | set_video_mode(3); 50 | 51 | return 0; 52 | } 53 | 54 | -------------------------------------------------------------------------------- /DECAY.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL tiny 3 | .STACK 100h 4 | 5 | ; Code is VERY rough. Assumes: 6 | ; 7 | ; * Bank 0 and 1 are 64kb 8 | ; * Refresh is at most 256 cycle 9 | ; * 4.77 MHz CPU 10 | ; 11 | ; Timing is VERY rough. Location in code is marked if you want to 12 | ; run the code on a different speed CPU. 13 | ; 14 | ; If you run this on an IBM XT with 256kbit chips in banks 0 and 1 15 | ; you need to alter the address of bank 1 from 1000h to 4000h 16 | ; The three locations in the code are marked 17 | ; 18 | ; If your chips are 512 cycle refresh, you need to access 512 rows 19 | ; not 256, to do manual refresh. Location is marked in code if you 20 | ; want to change this 21 | ; 22 | ; Look for <-- in code for locations to modify 23 | 24 | ITERS_BASE EQU 6600 ; number of milliseconds between each test (approx) 25 | ITERS EQU 11 ; number of data points to collect (1-1024) 26 | 27 | .DATA 28 | 29 | buffer DB 256 DUP (0ffh) 30 | errors DB 1024 DUP (0) 31 | 32 | .CODE 33 | 34 | _print_hex PROC 35 | ; expects 16 bit value to print in dx 36 | push ax 37 | push bx 38 | push cx 39 | 40 | mov cx, 4 41 | print_loop: 42 | rol dx, 1 43 | rol dx, 1 44 | rol dx, 1 45 | rol dx, 1 46 | mov al, dl 47 | and al, 0fh 48 | cmp al, 9 49 | ja letter 50 | add al, 30h 51 | jmp print 52 | letter: 53 | add al, 37h 54 | print: 55 | mov ah, 0eh 56 | mov bx, 1 57 | int 10h 58 | loop print_loop 59 | 60 | mov ah, 0eh 61 | mov al, 32 62 | mov bx, 1 63 | int 10h 64 | 65 | pop cx 66 | pop bx 67 | pop ax 68 | ret 69 | _print_hex ENDP 70 | 71 | start: 72 | mov ax, @data 73 | mov ds, ax 74 | mov es, ax 75 | mov si, offset buffer 76 | mov di, offset buffer 77 | mov bx, offset errors 78 | xor bp, bp 79 | xor dx, dx 80 | 81 | in al, 0a0h ; disable NMI 82 | and al, 07fh 83 | out 0a0h, al 84 | 85 | ; turn off DRAM refresh 86 | mov al, 072h ; PIT channel 1, lo/hi byte, mode 1, binary 87 | out 43h, al 88 | mov al, 1 ; low byte = 1 89 | out 41h, al ; channel 1 data port 90 | xor al, al ; high byte = 0 91 | out 41h, al 92 | 93 | mov ax, ds 94 | add ax, 1000h ; <-- address of bank to test 95 | mov ds, ax 96 | mov es, ax 97 | 98 | mov cx, 256 99 | mov al, 0ffh 100 | rep stosb 101 | 102 | mov di, offset buffer 103 | 104 | iter_loop1: 105 | mov cx, 256 106 | xor ax, ax 107 | check_loop: 108 | lodsb 109 | cmp al, 0ffh 110 | je no_error 111 | inc ah 112 | no_error: 113 | loop check_loop 114 | 115 | mov cx, 256 116 | mov al, 0ffh 117 | ; rep stosb 118 | 119 | mov cx, ds 120 | sub cx, 1000h ; <-- address of bank to test 121 | mov ds, cx 122 | mov es, cx 123 | 124 | mov [bx], ah 125 | inc bx 126 | inc bp 127 | cmp bp, ITERS 128 | jne not_done 129 | jmp done 130 | not_done: 131 | 132 | mov dx, bp 133 | add dx, ITERS_BASE 134 | mov si, offset buffer 135 | 136 | mov di, offset buffer 137 | 138 | iter_loop2: 139 | rept 256 ; <-- change to 512 for 512 cycle refresh 140 | nop 141 | endm 142 | 143 | rept 16 ; 1ms delay 144 | mov cl, 56 ; <-- adjust to change timing to be 1 ms per iteration 145 | shl ax, cl 146 | endm 147 | 148 | dec dx 149 | jz done_iter2 150 | jmp iter_loop2 151 | done_iter2: 152 | 153 | mov ax, ds 154 | add ax, 1000h ; <-- address of bank to test 155 | mov ds, ax 156 | mov es, ax 157 | 158 | jmp iter_loop1 159 | 160 | done: 161 | 162 | ; turn on DRAM refresh 163 | mov al, 074h ; PIT channel 1, lo/hi byte, mode 2, binary 164 | out 43h, al 165 | mov al, 18 ; low byte = 18 166 | out 41h, al ; channel 1 data port 167 | xor al, al ; high byte = 0 168 | out 41h, al 169 | 170 | mov bx, 1000h ; blank memory, starting at second bank of 64kb 171 | mov es, bx 172 | xor di, di 173 | xor ax, ax 174 | mov dx, 9 175 | 176 | clear_mem_loop: 177 | mov cx, 8000h 178 | rep stosw 179 | add bx, 1000h 180 | mov es, bx 181 | dec dx 182 | jnz clear_mem_loop 183 | 184 | mov cx, ITERS 185 | mov bx, offset errors 186 | 187 | error_print_loop: 188 | xor dx, dx 189 | mov dl, [bx] 190 | inc bx 191 | 192 | push bx 193 | 194 | call _print_hex 195 | pop bx 196 | 197 | loop error_print_loop 198 | 199 | xor ah, ah ; wait for keypress 200 | int 16h 201 | 202 | ; in al, 0a0h ; enable NMI 203 | ; or al, 080h 204 | ; out 0a0h, al 205 | 206 | mov ah, 04ch ; exit to DOS 207 | int 21h 208 | 209 | END start -------------------------------------------------------------------------------- /DECIMAL.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | 4 | .STACK 100h 5 | .DATA 6 | 7 | .CODE 8 | 9 | DECIMAL_TOP MACRO 10 | ; assumes binary number n in range [0, 65535] is in ax 11 | ; returns first two decimal digits (from the left) in 12 | ; unpacked BCD in ah, al and remainder in dx 13 | 14 | push bx 15 | 16 | xor dx, dx ; n = al*1000 + dx 17 | mov bx, 1000 18 | 19 | div bx 20 | 21 | aam 22 | pop bx 23 | ENDM 24 | 25 | DECIMAL_BOTTOM MACRO 26 | ; assumes binary number n in range [0, 999] is in ax 27 | ; returns three decimal digits (from the left) in 28 | ; unpacked BCD in ah, al, dl 29 | 30 | mov dl, 10 31 | div dl 32 | 33 | mov dl, ah ; n = ah*100 + al*10 + dl 34 | aam 35 | ENDM 36 | 37 | print_decimal PROC 38 | ; assumes value to print is in AX 39 | push ax 40 | push bx 41 | push dx 42 | 43 | DECIMAL_TOP ; get top two digits 44 | 45 | mov bx, dx ; save remainder 46 | 47 | xchg ah, al 48 | mov dx, ax 49 | add dx, 3030h ; convert to ASCII 50 | 51 | mov ah, 02h ; print character 52 | int 21h 53 | 54 | mov dl, dh ; print character 55 | int 21h 56 | 57 | mov ax, bx 58 | 59 | DECIMAL_BOTTOM ; get bottom 3 characters 60 | 61 | mov bx, dx ; save dx 62 | 63 | xchg ah, al 64 | mov dx, ax 65 | 66 | add dx, 3030h ; convert to ASCII 67 | 68 | mov ah, 02h ; print character 69 | int 21h 70 | 71 | mov dl, dh ; print character 72 | int 21h 73 | 74 | mov dx, bx 75 | 76 | add dl, 30h ; convert to ASCII 77 | 78 | int 21h ; print character 79 | 80 | pop dx 81 | pop bx 82 | pop ax 83 | ret 84 | print_decimal ENDP 85 | 86 | start: 87 | xor ax, ax 88 | 89 | integer_loop: 90 | call print_decimal 91 | 92 | mov bx, ax 93 | 94 | mov ah, 02h 95 | 96 | mov dl, 13 ; print CR LF 97 | int 21h 98 | 99 | mov dl, 10 100 | int 21h 101 | 102 | mov ax, bx 103 | 104 | inc ax 105 | jnz integer_loop 106 | 107 | ; wait for keypress 108 | mov ah, 0 109 | int 16h 110 | 111 | ; exit to DOS 112 | mov ah, 4ch 113 | int 21h 114 | 115 | END start 116 | -------------------------------------------------------------------------------- /DOSMEM.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL tiny 3 | .STACK 100h 4 | .CODE 5 | 6 | _print_hex PROC 7 | ; expects 16 bit value to print in dx 8 | push ax 9 | push bx 10 | push cx 11 | 12 | mov cx, 4 13 | print_loop: 14 | rol dx, 1 15 | rol dx, 1 16 | rol dx, 1 17 | rol dx, 1 18 | mov al, dl 19 | and al, 0fh 20 | cmp al, 9 21 | ja letter 22 | add al, 30h 23 | jmp print 24 | letter: 25 | add al, 37h 26 | print: 27 | mov ah, 0eh 28 | mov bx, 1 29 | int 10h 30 | loop print_loop 31 | 32 | mov ah, 0eh 33 | mov al, 13 34 | mov bx, 1 35 | int 10h 36 | 37 | pop cx 38 | pop bx 39 | pop ax 40 | ret 41 | _print_hex ENDP 42 | 43 | start: 44 | mov dx, cs ; get current code segment address 45 | 46 | call _print_hex ; print segment address to screen in hex 47 | 48 | xor ah, ah ; wait for keypress 49 | int 16h 50 | 51 | mov ah, 04ch ; exit to DOS 52 | int 21h 53 | 54 | END start -------------------------------------------------------------------------------- /ELLIPSE1.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _cga_ellipse PROC 7 | ARG x0:WORD, y0:WORD, r:WORD, s:WORD, colour:BYTE 8 | 9 | ; ax = accum, dh:si = D, dl:bx = dx, cl:bp = dy 10 | ; di = offset, ch = mask 11 | 12 | push bp 13 | mov bp, sp 14 | push si 15 | push di 16 | 17 | ; set up CGA segment 18 | mov ax, 0b800h 19 | mov es, ax 20 | 21 | mov al, colour 22 | mov ah, al 23 | shl al, 1 24 | shl al, 1 25 | add al, ah 26 | shl al, 1 27 | shl al, 1 28 | add al, ah 29 | shl al, 1 30 | shl al, 1 31 | add al, ah 32 | 33 | mov BYTE PTR cs:[ellipse_colour1+1], al 34 | 35 | ; compute x0 + r 36 | mov di, x0 37 | mov bx, r ; save r 38 | add di, bx 39 | 40 | ; compute x0 + r mod 4 and x0 + r 41 | mov cx, di 42 | and cl, 3 43 | 44 | ; compute mask 45 | mov ch, 03h 46 | shl cl, 1 47 | inc cl 48 | inc cl 49 | ror ch, cl 50 | 51 | ; compute y0 offset 52 | mov ax, y0 53 | 54 | ; offset += 4*8192 if y0 odd 55 | shr ax, 1 56 | jnc scanline_even 57 | add di, 32768 58 | scanline_even: 59 | 60 | ; add 4*80*(y0/2) to offset 61 | xchg ah, al 62 | add di, ax 63 | shr ax, 1 64 | shr ax, 1 65 | add di, ax 66 | 67 | ; divide offset by 4 68 | shr di, 1 69 | shr di, 1 70 | 71 | mov ax, s ; compute c = s*s 72 | mul al 73 | mov WORD PTR cs:[const_c1+2], ax 74 | mov WORD PTR cs:[const_c2+2], ax 75 | mov bp, ax 76 | 77 | mov ax, bx ; compute a = r*r 78 | mul al 79 | shl ax, 1 80 | mov WORD PTR cs:[const_2a1+2], ax 81 | shr ax, 1 82 | 83 | xor dx, dx 84 | xchg ax, bp ; compute dx = 2*s*s*r 85 | mul bx 86 | shl ax, 1 87 | rcl dx, 1 88 | mov bx, ax 89 | 90 | xor cl, cl 91 | xor si, si 92 | xor dh, dh 93 | 94 | ellipse_loop1: 95 | 96 | ellipse_colour1: 97 | mov ah, 012h 98 | and ah, ch ; and with mask 99 | 100 | mov al, ch ; get inverse mask 101 | not al 102 | and al, es:[di] ; get pixel 103 | 104 | or al, ah ; or with colour 105 | stosb ; write pixel 106 | 107 | add si, bp ; D += dy 108 | adc dh, cl 109 | 110 | const_2a1: 111 | add bp, 01234h ; dy += 2a 112 | adc cl, 0 113 | 114 | sub di, 8113 ; y += 1, adjust for stosb 115 | jnc ellipse_odd1 116 | add di, 16304 117 | ellipse_odd1: 118 | 119 | shr dl, 1 ; dx >> 1 120 | rcr bx, 1 121 | 122 | cmp dh, dl ; if D >= dx >> 1 123 | jl ellipse_skip_x1 124 | jne ellipse_inc_x1 125 | cmp si, bx 126 | jb ellipse_skip_x1 127 | ellipse_inc_x1: 128 | 129 | shl bx, 1 130 | rcl dl, 1 131 | 132 | const_c1: 133 | sub bx, 01234 ; dx -= c 134 | sbb dl, 0 135 | 136 | sub si, bx ; D -= dx 137 | sbb dh, dl 138 | 139 | const_c2: 140 | sub bx, 01234 ; dx -= c 141 | sbb dl, 0 142 | 143 | rol ch, 1 ; x -= 1 144 | rol ch, 1 145 | sbb di, 0 146 | 147 | cmp dl, cl 148 | jg ellipse_loop1 149 | jne ellipse_done1 150 | cmp bx, bp 151 | ja ellipse_loop1 152 | jmp ellipse_done1 153 | 154 | ellipse_skip_x1: 155 | shl bx, 1 156 | rcl dl, 1 157 | 158 | cmp dl, cl 159 | jg ellipse_loop1 160 | jne ellipse_done1 161 | cmp bx, bp 162 | ja ellipse_loop1 163 | 164 | ellipse_done1: 165 | 166 | pop di 167 | pop si 168 | pop bp 169 | ret 170 | _cga_ellipse ENDP 171 | 172 | start: 173 | ; set video mode = 4 (CGA 320x200x4) 174 | mov ax, 4 175 | int 10h 176 | 177 | mov ax, 2 ; colour = 2 178 | push ax 179 | mov al, 30 ; s = 30 180 | push ax 181 | mov al, 100 ; r = 100 182 | push ax 183 | push ax ; y0 = 100 184 | mov al, 160 185 | push ax ; x0 = 160 186 | call _cga_ellipse 187 | add sp, 10 188 | 189 | ; wait for keypress 190 | xor ah, ah 191 | int 16h 192 | 193 | ; restore video mode 194 | xor ah, ah 195 | mov al, 3 196 | int 10h 197 | 198 | mov ah, 4ch ; terminate program 199 | int 21h 200 | END start 201 | -------------------------------------------------------------------------------- /ELLIPSE2.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _cga_ellipse PROC 7 | ARG x0:WORD, y0:WORD, r:WORD, s:WORD, colour:BYTE 8 | 9 | ; ax = accum, dh:si = D, dl:bx = dx, cl:bp = dy 10 | ; di = offset, ch = mask 11 | 12 | push bp 13 | mov bp, sp 14 | push si 15 | push di 16 | 17 | ; set up CGA segment 18 | mov ax, 0b800h 19 | mov es, ax 20 | 21 | mov al, colour 22 | mov ah, al 23 | shl al, 1 24 | shl al, 1 25 | add al, ah 26 | shl al, 1 27 | shl al, 1 28 | add al, ah 29 | shl al, 1 30 | shl al, 1 31 | add al, ah 32 | 33 | mov BYTE PTR cs:[ellipse_colour1+1], al 34 | mov BYTE PTR cs:[ellipse_colour2+1], al 35 | 36 | ; compute x0 + r 37 | mov di, x0 38 | mov bx, r ; save r 39 | add di, bx 40 | 41 | ; compute x0 + r mod 4 and x0 + r 42 | mov cx, di 43 | and cl, 3 44 | 45 | ; compute mask 46 | mov ch, 03h 47 | shl cl, 1 48 | inc cl 49 | inc cl 50 | ror ch, cl 51 | 52 | ; compute y0 offset 53 | mov ax, y0 54 | 55 | ; offset += 4*8192 if y0 odd 56 | shr ax, 1 57 | jnc scanline_even 58 | add di, 32768 59 | scanline_even: 60 | 61 | ; add 4*80*(y0/2) to offset 62 | xchg ah, al 63 | add di, ax 64 | shr ax, 1 65 | shr ax, 1 66 | add di, ax 67 | 68 | ; divide offset by 4 69 | shr di, 1 70 | shr di, 1 71 | 72 | mov ax, s ; compute c = s*s 73 | mul al 74 | mov WORD PTR cs:[const_c1+2], ax 75 | mov WORD PTR cs:[const_c2+2], ax 76 | mov WORD PTR cs:[const_c3+2], ax 77 | mov WORD PTR cs:[const_c4+2], ax 78 | mov bp, ax 79 | 80 | mov ax, bx ; compute a = r*r 81 | mul al 82 | shl ax, 1 83 | mov WORD PTR cs:[const_2a1+2], ax 84 | mov WORD PTR cs:[const_2a2+2], ax 85 | mov WORD PTR cs:[const_2a3+2], ax 86 | shr ax, 1 87 | 88 | xor dx, dx 89 | xchg ax, bp ; compute dx = 2*s*s*r 90 | mul bx 91 | shl ax, 1 92 | rcl dx, 1 93 | mov bx, ax 94 | 95 | xor cl, cl 96 | xor si, si 97 | xor dh, dh 98 | 99 | ellipse_loop1: 100 | 101 | ellipse_colour1: 102 | mov ah, 012h 103 | and ah, ch ; and with mask 104 | 105 | mov al, ch ; get inverse mask 106 | not al 107 | and al, es:[di] ; get pixel 108 | 109 | or al, ah ; or with colour 110 | stosb ; write pixel 111 | 112 | add si, bp ; D += dy 113 | adc dh, cl 114 | 115 | const_2a1: 116 | add bp, 01234h ; dy += 2a 117 | adc cl, 0 118 | 119 | sub di, 8113 ; y += 1, adjust for stosb 120 | jnc ellipse_odd1 121 | add di, 16304 122 | ellipse_odd1: 123 | 124 | shr dl, 1 ; dx >> 1 125 | rcr bx, 1 126 | 127 | cmp dh, dl ; if D >= dx >> 1 128 | jl ellipse_skip_x1 129 | jne ellipse_inc_x1 130 | cmp si, bx 131 | jb ellipse_skip_x1 132 | ellipse_inc_x1: 133 | 134 | shl bx, 1 135 | rcl dl, 1 136 | 137 | const_c1: 138 | sub bx, 01234 ; dx -= c 139 | sbb dl, 0 140 | 141 | sub si, bx ; D -= dx 142 | sbb dh, dl 143 | 144 | const_c2: 145 | sub bx, 01234 ; dx -= c 146 | sbb dl, 0 147 | 148 | rol ch, 1 ; x -= 1 149 | rol ch, 1 150 | sbb di, 0 151 | 152 | cmp dl, cl 153 | jg ellipse_loop1 154 | jne ellipse_done1 155 | cmp bx, bp 156 | ja ellipse_loop1 157 | jmp ellipse_done1 158 | 159 | ellipse_skip_x1: 160 | shl bx, 1 161 | rcl dl, 1 162 | 163 | cmp dl, cl 164 | jg ellipse_loop1 165 | jne ellipse_done1 166 | cmp bx, bp 167 | ja ellipse_loop1 168 | 169 | ellipse_done1: 170 | 171 | shr cl, 1 ; dy >> 1 172 | rcr bp, 1 173 | lahf 174 | 175 | cmp dh, cl ; if D > dy >> 1 176 | jl ellipse_skip_diag1 177 | jne ellipse_diag1 178 | cmp si, bp 179 | jbe ellipse_skip_diag1 180 | 181 | ellipse_diag1: 182 | sahf 183 | rcl bp, 1 184 | rcl cl, 1 185 | 186 | const_2a2: 187 | sub bp, 01234 ; dy -= 2a 188 | sbb cl, 0 189 | 190 | sub si, bp ; D -= dy 191 | sbb dh, cl 192 | 193 | sub di, 8192 ; y -= 1 194 | jnc ellipse_odd2 195 | add di, 16304 196 | ellipse_odd2: 197 | 198 | jmp ellipse_done_diag1 199 | 200 | ellipse_skip_diag1: 201 | sahf 202 | rcl bp, 1 203 | rcl cl, 1 204 | 205 | ellipse_done_diag1: 206 | 207 | neg si ; D = -D 208 | not dh 209 | adc dh, 0 210 | 211 | ellipse_loop2: 212 | 213 | ellipse_colour2: 214 | mov ah, 012h 215 | and ah, ch ; and with mask 216 | 217 | mov al, ch ; get inverse mask 218 | not al 219 | and al, es:[di] ; get pixel 220 | 221 | or al, ah ; or with colour 222 | stosb ; write pixel 223 | 224 | const_c3: 225 | sub bx, 01234 ; dx -= c 226 | sbb dl, 0 227 | 228 | add si, bx ; D += dx 229 | adc dh, dl 230 | 231 | const_c4: 232 | sub bx, 01234 ; dx -= c 233 | sbb dl, 0 234 | 235 | rol ch, 1 ; x -= 1 236 | rol ch, 1 237 | sbb di, 1 238 | 239 | shr cl, 1 ; dy >> 1 240 | rcr bp, 1 241 | lahf 242 | 243 | cmp dh, cl ; if D > dy >> 1 244 | jl ellipse_skip_y1 245 | jne ellipse_inc_y1 246 | cmp si, bp 247 | jbe ellipse_skip_y1 248 | ellipse_inc_y1: 249 | 250 | sahf 251 | rcl bp, 1 252 | rcl cl, 1 253 | 254 | sub si, bp ; D -= dy 255 | sbb dh, cl 256 | 257 | const_2a3: 258 | add bp, 01234h ; dy += 2a 259 | adc cl, 0 260 | 261 | sub di, 8112 ; y += 1 262 | jnc ellipse_odd3 263 | add di, 16304 264 | ellipse_odd3: 265 | 266 | cmp dl, 0 267 | jge ellipse_loop2 268 | jmp ellipse_done2 269 | 270 | ellipse_skip_y1: 271 | sahf 272 | rcl bp, 1 273 | rcl cl, 1 274 | 275 | cmp dl, 0 276 | jge ellipse_loop2 277 | 278 | ellipse_done2: 279 | 280 | pop di 281 | pop si 282 | pop bp 283 | ret 284 | _cga_ellipse ENDP 285 | 286 | start: 287 | ; set video mode = 4 (CGA 320x200x4) 288 | mov ax, 4 289 | int 10h 290 | 291 | mov ax, 2 ; colour = 2 292 | push ax 293 | mov al, 30 ; s = 30 294 | push ax 295 | mov al, 100 ; r = 100 296 | push ax 297 | push ax ; y0 = 100 298 | mov al, 160 299 | push ax ; x0 = 160 300 | call _cga_ellipse 301 | add sp, 10 302 | 303 | ; wait for keypress 304 | xor ah, ah 305 | int 16h 306 | 307 | ; restore video mode 308 | xor ah, ah 309 | mov al, 3 310 | int 10h 311 | 312 | mov ah, 4ch ; terminate program 313 | int 21h 314 | END start 315 | -------------------------------------------------------------------------------- /ELLIPSE3.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .DATA 5 | 6 | ellipse_diff DW 0 7 | 8 | .CODE 9 | 10 | _cga_ellipse PROC 11 | ARG x0:WORD, y0:WORD, r:WORD, s:WORD, colour:BYTE 12 | 13 | ; ax = accum, dh:si = D, dl:bx = dx, cl:bp = dy 14 | ; di = offset, ch = mask 15 | 16 | push bp 17 | mov bp, sp 18 | push si 19 | push di 20 | 21 | ; set up CGA segment 22 | mov ax, 0b800h 23 | mov es, ax 24 | 25 | mov WORD PTR [ellipse_diff], 0 26 | 27 | mov al, colour 28 | mov ah, al 29 | shl al, 1 30 | shl al, 1 31 | add al, ah 32 | shl al, 1 33 | shl al, 1 34 | add al, ah 35 | shl al, 1 36 | shl al, 1 37 | add al, ah 38 | 39 | mov BYTE PTR cs:[ellipse_colour1+1], al 40 | mov BYTE PTR cs:[ellipse_colour2+1], al 41 | 42 | ; compute x0 + r 43 | mov di, x0 44 | mov bx, r ; save r 45 | add di, bx 46 | 47 | ; compute x0 + r mod 4 and x0 + r 48 | mov cx, di 49 | and cl, 3 50 | 51 | ; compute mask 52 | mov ch, 03h 53 | shl cl, 1 54 | inc cl 55 | inc cl 56 | ror ch, cl 57 | 58 | ; compute y0 offset 59 | mov ax, y0 60 | 61 | ; offset += 4*8192 if y0 odd 62 | shr ax, 1 63 | jnc scanline_even 64 | add di, 32768 65 | scanline_even: 66 | 67 | ; add 4*80*(y0/2) to offset 68 | xchg ah, al 69 | add di, ax 70 | shr ax, 1 71 | shr ax, 1 72 | add di, ax 73 | 74 | ; divide offset by 4 75 | shr di, 1 76 | shr di, 1 77 | 78 | mov ax, s ; compute c = s*s 79 | mul al 80 | mov WORD PTR cs:[const_c1+2], ax 81 | mov WORD PTR cs:[const_c2+2], ax 82 | mov WORD PTR cs:[const_c3+2], ax 83 | mov WORD PTR cs:[const_c4+2], ax 84 | mov bp, ax 85 | 86 | mov ax, bx ; compute a = r*r 87 | mul al 88 | shl ax, 1 89 | mov WORD PTR cs:[const_2a1+2], ax 90 | mov WORD PTR cs:[const_2a2+2], ax 91 | mov WORD PTR cs:[const_2a3+2], ax 92 | shr ax, 1 93 | 94 | xor dx, dx 95 | xchg ax, bp ; compute dx = 2*s*s*r 96 | mul bx 97 | shl ax, 1 98 | rcl dx, 1 99 | mov bx, ax 100 | 101 | xor cl, cl 102 | xor si, si 103 | xor dh, dh 104 | 105 | ellipse_loop1: 106 | 107 | ellipse_colour1: 108 | mov ah, 012h 109 | and ah, ch ; and with mask 110 | 111 | mov al, ch ; get inverse mask 112 | not al 113 | and al, es:[di] ; get pixel 114 | 115 | or al, ah ; or with colour 116 | stosb ; write pixel 117 | dec di 118 | 119 | sub di, [ellipse_diff] 120 | 121 | mov al, ch ; get inverse mask 122 | not al 123 | and al, es:[di] ; get pixel 124 | 125 | or al, ah ; or with colour 126 | stosb ; write pixel 127 | 128 | add si, bp ; D += dy 129 | adc dh, cl 130 | 131 | const_2a1: 132 | add bp, 01234h ; dy += 2a 133 | adc cl, 0 134 | 135 | sub di, 8113 ; y += 1, adjust for stosb 136 | jnc ellipse_odd1 137 | add di, 16304 138 | ellipse_odd1: 139 | 140 | mov ax, [ellipse_diff] 141 | add di, ax 142 | add ax, 80 143 | mov [ellipse_diff], ax 144 | 145 | shr dl, 1 ; dx >> 1 146 | rcr bx, 1 147 | 148 | cmp dh, dl ; if D >= dx >> 1 149 | jl ellipse_skip_x1 150 | jne ellipse_inc_x1 151 | cmp si, bx 152 | jb ellipse_skip_x1 153 | ellipse_inc_x1: 154 | 155 | shl bx, 1 156 | rcl dl, 1 157 | 158 | const_c1: 159 | sub bx, 01234 ; dx -= c 160 | sbb dl, 0 161 | 162 | sub si, bx ; D -= dx 163 | sbb dh, dl 164 | 165 | const_c2: 166 | sub bx, 01234 ; dx -= c 167 | sbb dl, 0 168 | 169 | rol ch, 1 ; x -= 1 170 | rol ch, 1 171 | sbb di, 0 172 | 173 | jmp ellipse_skip_recover 174 | 175 | ellipse_skip_x1: 176 | shl bx, 1 177 | rcl dl, 1 178 | 179 | ellipse_skip_recover: 180 | cmp dl, cl 181 | jg ellipse_loop1 182 | jne ellipse_done1 183 | cmp bx, bp 184 | ja ellipse_loop1 185 | 186 | ellipse_done1: 187 | 188 | shr cl, 1 ; dy >> 1 189 | rcr bp, 1 190 | lahf 191 | 192 | cmp dh, cl ; if D > dy >> 1 193 | jl ellipse_skip_diag1 194 | jne ellipse_diag1 195 | cmp si, bp 196 | jbe ellipse_skip_diag1 197 | 198 | ellipse_diag1: 199 | sahf 200 | rcl bp, 1 201 | rcl cl, 1 202 | 203 | sub WORD PTR [ellipse_diff], 80 204 | 205 | const_2a2: 206 | sub bp, 01234 ; dy -= 2a 207 | sbb cl, 0 208 | 209 | sub si, bp ; D -= dy 210 | sbb dh, cl 211 | 212 | sub di, 8192 ; y -= 1 213 | jnc ellipse_odd2 214 | add di, 16304 215 | ellipse_odd2: 216 | 217 | jmp ellipse_done_diag1 218 | 219 | ellipse_skip_diag1: 220 | sahf 221 | rcl bp, 1 222 | rcl cl, 1 223 | 224 | ellipse_done_diag1: 225 | 226 | neg si ; D = -D 227 | not dh 228 | adc dh, 0 229 | 230 | ellipse_loop2: 231 | 232 | ellipse_colour2: 233 | mov ah, 012h 234 | and ah, ch ; and with mask 235 | 236 | mov al, ch ; get inverse mask 237 | not al 238 | and al, es:[di] ; get pixel 239 | 240 | or al, ah ; or with colour 241 | stosb ; write pixel 242 | dec di 243 | 244 | sub di, [ellipse_diff] 245 | 246 | mov al, ch ; get inverse mask 247 | not al 248 | and al, es:[di] ; get pixel 249 | 250 | or al, ah ; or with colour 251 | stosb ; write pixel 252 | 253 | const_c3: 254 | sub bx, 01234 ; dx -= c 255 | sbb dl, 0 256 | 257 | add si, bx ; D += dx 258 | adc dh, dl 259 | 260 | const_c4: 261 | sub bx, 01234 ; dx -= c 262 | sbb dl, 0 263 | 264 | rol ch, 1 ; x -= 1 265 | rol ch, 1 266 | sbb di, 1 267 | 268 | shr cl, 1 ; dy >> 1 269 | rcr bp, 1 270 | lahf 271 | 272 | mov ax, [ellipse_diff] 273 | add di, ax 274 | 275 | cmp dh, cl ; if D > dy >> 1 276 | jl ellipse_skip_y1 277 | jne ellipse_inc_y1 278 | cmp si, bp 279 | jbe ellipse_skip_y1 280 | ellipse_inc_y1: 281 | 282 | sahf 283 | rcl bp, 1 284 | rcl cl, 1 285 | 286 | sub si, bp ; D -= dy 287 | sbb dh, cl 288 | 289 | const_2a3: 290 | add bp, 01234h ; dy += 2a 291 | adc cl, 0 292 | 293 | sub di, 8112 ; y += 1 294 | jnc ellipse_odd3 295 | add di, 16304 296 | ellipse_odd3: 297 | 298 | add ax, 80 299 | mov [ellipse_diff], ax 300 | 301 | cmp dl, 0 302 | jge ellipse_loop2 303 | jmp ellipse_done2 304 | 305 | ellipse_skip_y1: 306 | sahf 307 | rcl bp, 1 308 | rcl cl, 1 309 | 310 | mov [ellipse_diff], ax 311 | 312 | cmp dl, 0 313 | jge ellipse_loop2 314 | 315 | ellipse_done2: 316 | 317 | pop di 318 | pop si 319 | pop bp 320 | ret 321 | _cga_ellipse ENDP 322 | 323 | start: 324 | ; set video mode = 4 (CGA 320x200x4) 325 | mov ax, 4 326 | int 10h 327 | 328 | mov ax, 2 ; colour = 2 329 | push ax 330 | mov al, 30 ; s = 30 331 | push ax 332 | mov al, 100 ; r = 100 333 | push ax 334 | push ax ; y0 = 100 335 | mov al, 160 336 | push ax ; x0 = 160 337 | call _cga_ellipse 338 | add sp, 10 339 | 340 | ; wait for keypress 341 | xor ah, ah 342 | int 16h 343 | 344 | ; restore video mode 345 | xor ah, ah 346 | mov al, 3 347 | int 10h 348 | 349 | mov ah, 4ch ; terminate program 350 | int 21h 351 | END start 352 | -------------------------------------------------------------------------------- /Ellipse.jl: -------------------------------------------------------------------------------- 1 | using SimpleDirectMediaLayer 2 | using SimpleDirectMediaLayer.LibSDL2 3 | 4 | @assert SDL_Init(SDL_INIT_EVERYTHING) == 0 "error initializing SDL: $(unsafe_string(SDL_GetError()))" 5 | 6 | win = SDL_CreateWindow("Ellipse", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 800, SDL_WINDOW_SHOWN) 7 | SDL_SetWindowResizable(win, SDL_TRUE) 8 | 9 | renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC) 10 | 11 | function drawPixel(renderer, x, y) 12 | LibSDL2.boxRGBA(renderer, 4*x, 4*y, 4*x+4, 4*y+4, 255, 255, 255, 255) 13 | end 14 | 15 | try 16 | x = 160 17 | y = 100 18 | close = false 19 | while !close 20 | event_ref = Ref{SDL_Event}() 21 | while Bool(SDL_PollEvent(event_ref)) 22 | evt = event_ref[] 23 | evt_ty = evt.type 24 | if evt_ty == SDL_QUIT 25 | close = true 26 | break 27 | elseif evt_ty == SDL_KEYDOWN 28 | scan_code = evt.key.keysym.scancode 29 | if scan_code == SDL_SCANCODE_W || scan_code == SDL_SCANCODE_UP 30 | y -= 1 31 | break 32 | elseif scan_code == SDL_SCANCODE_A || scan_code == SDL_SCANCODE_LEFT 33 | x -= 1 34 | break 35 | elseif scan_code == SDL_SCANCODE_S || scan_code == SDL_SCANCODE_DOWN 36 | y += 1 37 | break 38 | elseif scan_code == SDL_SCANCODE_D || scan_code == SDL_SCANCODE_RIGHT 39 | x += 1 40 | break 41 | elseif scan_code == SDL_SCANCODE_ESCAPE 42 | close = true 43 | break 44 | else 45 | break 46 | end 47 | end 48 | end 49 | 50 | x >= 320 && (x = 319;) 51 | x < 0 && (x = 0;) 52 | y >= 200 && (y = 199;) 53 | y < 0 && (y = 0;) 54 | 55 | drawPixel(renderer, x, y) 56 | 57 | SDL_RenderPresent(renderer) 58 | 59 | SDL_Delay(1000 ÷ 60) 60 | end 61 | finally 62 | SDL_DestroyRenderer(renderer) 63 | SDL_DestroyWindow(win) 64 | SDL_Quit() 65 | end -------------------------------------------------------------------------------- /Ellipse2.jl: -------------------------------------------------------------------------------- 1 | using SimpleDirectMediaLayer 2 | using SimpleDirectMediaLayer.LibSDL2 3 | 4 | @assert SDL_Init(SDL_INIT_EVERYTHING) == 0 "error initializing SDL: $(unsafe_string(SDL_GetError()))" 5 | 6 | win = SDL_CreateWindow("Ellipse", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 800, SDL_WINDOW_SHOWN) 7 | SDL_SetWindowResizable(win, SDL_TRUE) 8 | 9 | renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC) 10 | 11 | function drawFilledRect(renderer, x, y, w, h, r, g, b, a) 12 | LibSDL2.filledTrigonRGBA(renderer, x, y, x + w, y, x + w, y + h, r, g, b, a) 13 | LibSDL2.filledTrigonRGBA(renderer, x, y, x + w, y + h, x, y + h, r, g, b, a) 14 | end 15 | 16 | function drawPixel(renderer, x, y) 17 | drawFilledRect(renderer, 4*x, 4*y, 4, 4, 255, 255, 255, 255) 18 | end 19 | 20 | function clear(renderer) 21 | drawFilledRect(renderer, 0, 0, 1279, 799, 0, 0, 0, 255) 22 | end 23 | 24 | function drawEllipse(renderer, r, s, θ::Float64) 25 | rSq = r*r 26 | sSq = s*s 27 | c = sqrt(Float64(rSq - sSq)) 28 | Xf = c*cos(θ) 29 | Yf = c*sin(θ) 30 | XfSq = Xf*Xf 31 | YfSq = Yf*Yf 32 | 33 | A = rSq - XfSq 34 | B = -2Xf*Yf 35 | C = rSq - YfSq 36 | F = rSq*(YfSq - A) 37 | 38 | @assert(A > 0) 39 | 40 | sum = A + abs(B) + C 41 | sq = (2.0^15 - 4)/sum # so that rounded sum < 2^15 42 | 43 | fq = -(2.0^31 - 2)/F # so that rounded F < 2^31 44 | 45 | mq = min(sq, fq) 46 | 47 | A = Int32(round(A*mq)) 48 | B = Int32(round(B*mq)) 49 | C = Int32(round(C*mq)) 50 | F = Int32(round(F*mq)) 51 | 52 | testA = UInt16(A) 53 | testB = Int16(B) 54 | testC = UInt16(C) 55 | 56 | Δ = B^2 - 4A*C 57 | 58 | k2 = -B/(2A) 59 | yN = sqrt(Float64(4F*A)/Δ) 60 | xN = k2*yN 61 | 62 | k1 = B/(2C) 63 | xE = sqrt(Float64(4F*C)/Δ) 64 | yE = k1*xN 65 | 66 | xNE = sqrt(Float64(F*(2C-B)^2)/((A+C-B)*Δ)) 67 | yNE = (2A-B)*xNE/(2C-B) 68 | if xNE < yNE*k2 69 | yNE = -yNE 70 | end 71 | 72 | xNW = -sqrt(Float64(F*(2C+B)^2)/((A+B+C)*Δ)) 73 | yNW = -(2A+B)*xNW/(2C+B) 74 | if xNW > yNW*k1 75 | xNW = -xNW 76 | end 77 | 78 | xH = Int16(round(xN)) 79 | yH = Int16(round(yN)) 80 | 81 | xV = Int16(round(xE)) 82 | yV = Int16(round(yE)) 83 | 84 | xR = Int16(round(xNE)) 85 | yR = Int16(round(yNE)) 86 | 87 | xL = Int16(round(xNW)) 88 | yL = Int16(round(yNW)) 89 | 90 | drawPixel(renderer, xH + 160, yH + 100) 91 | drawPixel(renderer, -xH + 160, -yH + 100) 92 | 93 | drawPixel(renderer, xV + 160, yV + 100) 94 | drawPixel(renderer, -xV + 160, -yV + 100) 95 | 96 | drawPixel(renderer, xL + 160, yL + 100) 97 | drawPixel(renderer, -xL + 160, -yL + 100) 98 | 99 | drawPixel(renderer, xR + 160, yR + 100) 100 | drawPixel(renderer, -xR + 160, -yR + 100) 101 | end 102 | 103 | try 104 | r = 1 105 | s = 1 106 | θ = 0.0 107 | close = false 108 | while !close 109 | event_ref = Ref{SDL_Event}() 110 | while Bool(SDL_PollEvent(event_ref)) 111 | evt = event_ref[] 112 | evt_ty = evt.type 113 | if evt_ty == SDL_QUIT 114 | close = true 115 | break 116 | elseif evt_ty == SDL_KEYDOWN 117 | scan_code = evt.key.keysym.scancode 118 | if scan_code == scan_code == SDL_SCANCODE_RIGHT 119 | r += 1 120 | break 121 | elseif scan_code == scan_code == SDL_SCANCODE_LEFT 122 | if r > s 123 | r -= 1 124 | end 125 | break 126 | elseif scan_code == scan_code == SDL_SCANCODE_UP 127 | if s < r 128 | s += 1 129 | end 130 | break 131 | elseif scan_code == scan_code == SDL_SCANCODE_DOWN 132 | if s > 0 133 | s -= 1 134 | end 135 | break 136 | elseif scan_code == SDL_SCANCODE_EQUALS 137 | θ += 2*π/512 138 | break 139 | elseif scan_code == SDL_SCANCODE_MINUS 140 | θ -= 2*π/512 141 | break 142 | elseif scan_code == SDL_SCANCODE_ESCAPE 143 | close = true 144 | break 145 | else 146 | break 147 | end 148 | end 149 | end 150 | 151 | clear(renderer) 152 | 153 | drawEllipse(renderer, r, s, θ) 154 | 155 | SDL_RenderPresent(renderer) 156 | 157 | SDL_Delay(1000 ÷ 60) 158 | end 159 | finally 160 | SDL_DestroyRenderer(renderer) 161 | SDL_DestroyWindow(win) 162 | SDL_Quit() 163 | end -------------------------------------------------------------------------------- /Ellipse3.jl: -------------------------------------------------------------------------------- 1 | using SimpleDirectMediaLayer 2 | using SimpleDirectMediaLayer.LibSDL2 3 | 4 | # Initialize SDL and SDL_TTF 5 | @assert SDL_Init(SDL_INIT_EVERYTHING) == 0 "Error initializing SDL: $(unsafe_string(SDL_GetError()))" 6 | @assert SimpleDirectMediaLayer.TTF_Init() == 0 "Error initializing SDL_TTF: $(unsafe_string(SDL_GetError()))" 7 | 8 | # Create a window and renderer 9 | win = SDL_CreateWindow("Ellipse", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 800, SDL_WINDOW_SHOWN) 10 | SDL_SetWindowResizable(win, SDL_TRUE) 11 | renderer = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC) 12 | 13 | # Load a font (ensure you have a valid .ttf font file) 14 | font_path = "times.ttf" 15 | font = SimpleDirectMediaLayer.TTF_OpenFont("times.ttf", 48) 16 | if font == C_NULL 17 | println(unsafe_string(SimpleDirectMediaLayer.SDL_GetError())) 18 | exit(1) 19 | end 20 | 21 | function render_text(renderer, font, text, x, y) 22 | color = SDL_Color(255, 255, 255, 255) # White color 23 | surface = SimpleDirectMediaLayer.TTF_RenderText_Solid(font, text, color) 24 | if surface == C_NULL 25 | println(unsafe_string(SimpleDirectMediaLayer.SDL_GetError())) 26 | return 27 | end 28 | texture = SDL_CreateTextureFromSurface(renderer, surface) 29 | SDL_FreeSurface(surface) 30 | 31 | # Use Ref to pass w and h as mutable references 32 | w = Ref{Int32}(0) 33 | h = Ref{Int32}(0) 34 | 35 | # Query the texture for its width and height 36 | SDL_QueryTexture(texture, C_NULL, C_NULL, w, h) 37 | 38 | rect = SDL_Rect(x, y, w[], h[]) 39 | SDL_RenderCopy(renderer, texture, C_NULL, Ref(rect)) 40 | SDL_DestroyTexture(texture) 41 | end 42 | 43 | # Function to draw a filled rectangle (helper for drawing pixels) 44 | function drawFilledRect(renderer, x, y, w, h, r, g, b, a) 45 | LibSDL2.filledTrigonRGBA(renderer, x, y, x + w, y, x + w, y + h, r, g, b, a) 46 | LibSDL2.filledTrigonRGBA(renderer, x, y, x + w, y + h, x, y + h, r, g, b, a) 47 | end 48 | 49 | # Function to draw individual pixel 50 | function drawPixel(renderer, x, y) 51 | drawFilledRect(renderer, 4*x-2, 4*y-2, 4, 4, 255, 255, 255, 255) 52 | end 53 | 54 | # Function to clear the screen 55 | function clear(renderer) 56 | drawFilledRect(renderer, 0, 0, 1279, 799, 0, 0, 0, 255) 57 | end 58 | 59 | # Function to create and draw a rotated red ellipse in the offscreen buffer 60 | function draw_rotated_red_ellipse(renderer, w, h, θ) 61 | # Create an off-screen texture 62 | offscreen_texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, 1280, 800) 63 | @assert offscreen_texture != C_NULL "Error creating offscreen texture" 64 | 65 | # Set the texture as the render target 66 | SDL_SetRenderTarget(renderer, offscreen_texture) 67 | 68 | # Clear the off-screen texture 69 | SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0) # Transparent background 70 | SDL_RenderClear(renderer) 71 | 72 | # Draw a red ellipse centered on the screen 73 | cx, cy = 640, 400 # Center of the screen 74 | rw, rh = 4*w, 4*h # Width and height of the ellipse 75 | LibSDL2.ellipseRGBA(renderer, cx, cy, rw, rh, 255, 0, 0, 255) # Draw the red ellipse 76 | 77 | # Reset the render target to the screen 78 | SDL_SetRenderTarget(renderer, C_NULL) 79 | 80 | # Prepare rotation of the offscreen texture 81 | center = SDL_Point(640, 400) # Rotate around the center of the screen 82 | src_rect = SDL_Rect(0, 0, 1280, 800) 83 | dest_rect = SDL_Rect(0, 0, 1280, 800) 84 | 85 | # Rotate the offscreen texture by θ 86 | SDL_RenderCopyEx(renderer, offscreen_texture, Ref(src_rect), Ref(dest_rect), θ * 180 / π, Ref(center), SDL_FLIP_NONE) 87 | 88 | # Clean up the texture 89 | SDL_DestroyTexture(offscreen_texture) 90 | end 91 | 92 | # Function to draw ellipse and display A, B, C, F values 93 | function drawEllipse(renderer, font, r, s, θ::Float64) 94 | rSq = r*r 95 | sSq = s*s 96 | c = sqrt(Float64(rSq - sSq)) 97 | Xf = c*cos(θ) 98 | Yf = c*sin(θ) 99 | XfSq = Xf*Xf 100 | YfSq = Yf*Yf 101 | 102 | A = rSq - XfSq 103 | B = -2Xf*Yf 104 | C = rSq - YfSq 105 | F = rSq*(YfSq - A) 106 | 107 | @assert(A > 0) 108 | 109 | sum = A + abs(B) + C 110 | sq = (2.0^23 - 4)/sum # so that rounded sum < 2^23 111 | fq = -(2.0^31 - 2)/F # so that rounded F < 2^31 112 | mq = min(sq, fq) 113 | 114 | A = Int(round(A*mq)) 115 | B = Int(round(B*mq)) 116 | C = Int(round(C*mq)) 117 | F = Int(round(F*mq)) 118 | 119 | Δ = B^2 - 4A*C 120 | 121 | k2 = -B/(2A) 122 | yN = sqrt(Float64(4F)*Float64(A)/Δ) 123 | xN = k2*yN 124 | 125 | k1 = -B/(2C) 126 | xE = sqrt(Float64(4F)*Float64(C)/Δ) 127 | yE = k1*xE 128 | 129 | xNE = sqrt(Float64(F)*Float64(2C-B)^2/(A+C-B)/Δ) 130 | yNE = (2A-B)*xNE/(2C-B) 131 | 132 | xNW = -sqrt(Float64(F)*Float64(2C+B)^2/(A+B+C)/Δ) 133 | yNW = -(2A+B)*xNW/(2C+B) 134 | 135 | xH = Int16(round(xN)) 136 | yH = Int16(round(yN)) 137 | 138 | xV = Int16(round(xE)) 139 | yV = Int16(round(yE)) 140 | 141 | xR = Int16(round(xNE)) 142 | yR = Int16(round(yNE)) 143 | 144 | xL = Int16(round(xNW)) 145 | yL = Int16(round(yNW)) 146 | 147 | # Draw the points of the ellipse 148 | drawPixel(renderer, xH + 160, yH + 100) 149 | drawPixel(renderer, -xH + 160, -yH + 100) 150 | 151 | drawPixel(renderer, xV + 160, yV + 100) 152 | drawPixel(renderer, -xV + 160, -yV + 100) 153 | 154 | drawPixel(renderer, xL + 160, yL + 100) 155 | drawPixel(renderer, -xL + 160, -yL + 100) 156 | 157 | drawPixel(renderer, xR + 160, yR + 100) 158 | drawPixel(renderer, -xR + 160, -yR + 100) 159 | 160 | # Starting Y position for the text (move it upwards a bit) 161 | start_y = 550 162 | 163 | # Vertical gap between lines 164 | line_gap = 10 165 | 166 | # Render text with a small gap between each line 167 | render_text(renderer, font, "A: $A", 10, start_y) 168 | render_text(renderer, font, "B: $B", 10, start_y + 48 + line_gap) # 48 is the font height, plus a gap 169 | render_text(renderer, font, "C: $C", 10, start_y + 2*(48 + line_gap)) 170 | render_text(renderer, font, "F: $F", 10, start_y + 3*(48 + line_gap)) 171 | 172 | render_text(renderer, font, "r: $r", 300, start_y) 173 | render_text(renderer, font, "s: $s", 300, start_y + 48 + line_gap) 174 | render_text(renderer, font, "theta: $θ", 300, start_y + 2*(48 + line_gap)) 175 | end 176 | 177 | # Main loop 178 | try 179 | r = 1 180 | s = 1 181 | θ = 0.0 182 | close = false 183 | while !close 184 | event_ref = Ref{SDL_Event}() 185 | while Bool(SDL_PollEvent(event_ref)) 186 | evt = event_ref[] 187 | evt_ty = evt.type 188 | if evt_ty == SDL_QUIT 189 | close = true 190 | break 191 | elseif evt_ty == SDL_KEYDOWN 192 | scan_code = evt.key.keysym.scancode 193 | if scan_code == SDL_SCANCODE_RIGHT 194 | r += 1 195 | break 196 | elseif scan_code == SDL_SCANCODE_LEFT 197 | if r > s 198 | r -= 1 199 | end 200 | break 201 | elseif scan_code == SDL_SCANCODE_UP 202 | if s < r 203 | s += 1 204 | end 205 | break 206 | elseif scan_code == SDL_SCANCODE_DOWN 207 | if s > 0 208 | s -= 1 209 | end 210 | break 211 | elseif scan_code == SDL_SCANCODE_EQUALS 212 | θ += 2*π/512 213 | break 214 | elseif scan_code == SDL_SCANCODE_MINUS 215 | θ -= 2*π/512 216 | break 217 | elseif scan_code == SDL_SCANCODE_ESCAPE 218 | close = true 219 | break 220 | else 221 | break 222 | end 223 | end 224 | end 225 | 226 | clear(renderer) 227 | 228 | # Draw the rotated red ellipse on the off-screen buffer 229 | draw_rotated_red_ellipse(renderer, r, s, θ) 230 | 231 | # Draw your custom ellipse 232 | drawEllipse(renderer, font, r, s, θ) 233 | 234 | SDL_RenderPresent(renderer) 235 | 236 | SDL_Delay(1000 ÷ 60) 237 | end 238 | finally 239 | SDL_DestroyRenderer(renderer) 240 | SDL_DestroyWindow(win) 241 | SimpleDirectMediaLayer.TTF_CloseFont(font) 242 | SimpleDirectMediaLayer.TTF_Quit() 243 | SDL_Quit() 244 | end 245 | -------------------------------------------------------------------------------- /HELLO.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .DATA 5 | HelloMessage DB 'Hello, world',13,10,'$' 6 | .CODE 7 | mov ax,@data 8 | mov ds,ax ;set DS to point to the data segment 9 | mov ah,9 ;DOS print string function 10 | mov dx,OFFSET HelloMessage ;point to "Hello, world" 11 | int 21h ;display "Hello, world" 12 | mov ah,4ch ;DOS terminate program function 13 | int 21h ;terminate the program 14 | END 15 |  -------------------------------------------------------------------------------- /HIRES.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; switch to +HRES+GRPH-1BPP 11 | mov al, 0bh 12 | mov dx, 03d8h 13 | out dx, al 14 | 15 | ; palette 0 16 | xor al, al 17 | mov dx, 03d9h 18 | out dx, al 19 | 20 | ; vertical total = 127 21 | mov dx, 03d4h 22 | mov ax, 127*256+4 23 | out dx, ax 24 | 25 | ; vertical displayed = 50 26 | mov ax, 50*256+6 27 | out dx, ax 28 | 29 | ; vertical sync = 87 30 | mov ax, 87*256+7 31 | out dx, ax 32 | 33 | ; max char scanline = 1 34 | mov ax, 1*256+9 35 | out dx, ax 36 | 37 | ; colour 1 38 | mov al, 85 39 | 40 | xor di, di 41 | 42 | ; fill first bank 43 | mov bx, 2 44 | hires_loop1: 45 | mov dx, 25 46 | scanline_loop1: 47 | mov cx, 160 48 | rep stosb 49 | dec dx 50 | jnz scanline_loop1 51 | 52 | add al, 85 53 | dec bx 54 | jnz hires_loop1 55 | 56 | ; blank remaining bytes 57 | xor al, al 58 | mov cx, 192 59 | rep stosb 60 | 61 | mov al, 170 62 | 63 | ; fill second bank 64 | mov bx, 2 65 | hires_loop2: 66 | mov dx, 25 67 | scanline_loop2: 68 | mov cx, 160 69 | rep stosb 70 | dec dx 71 | jnz scanline_loop2 72 | 73 | add al, 85 74 | dec bx 75 | jnz hires_loop2 76 | 77 | ; blank remaining bytes 78 | xor al, al 79 | mov cx, 192 80 | rep stosb 81 | 82 | ; get keypress 83 | xor ah, ah 84 | int 16h 85 | 86 | xor di, di 87 | 88 | mov bl, es:[di] 89 | mov BYTE PTR es:[di], 0 90 | 91 | cursor_loop: 92 | ; get keypress 93 | xor ah, ah 94 | int 16h 95 | 96 | ; check for q = quit 97 | cmp al, 113 98 | je hires_done 99 | 100 | ; check for d = next byte 101 | cmp al, 100 102 | jne cursor_not_d 103 | 104 | mov es:[di], bl 105 | inc di 106 | mov bl, es:[di] 107 | mov BYTE PTR es:[di], 0 108 | 109 | jmp cursor_loop 110 | 111 | cursor_not_d: 112 | ; check for s = next scanline 113 | cmp al, 115 114 | jne cursor_loop 115 | 116 | mov es:[di], bl 117 | sub di, 8032 118 | jnc d_even 119 | add di, 16224 120 | d_even: 121 | mov bl, es:[di] 122 | mov BYTE PTR es:[di], 0 123 | 124 | jmp cursor_loop 125 | 126 | hires_done: 127 | ; restore video mode 128 | xor ah, ah 129 | mov al, 3 130 | int 10h 131 | 132 | ; exit to DOS 133 | mov ah,4ch 134 | int 21h 135 | END 136 | -------------------------------------------------------------------------------- /HIRES2.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; switch to +HRES+GRPH-1BPP 11 | mov al, 0bh 12 | mov dx, 03d8h 13 | out dx, al 14 | 15 | ; vertical total = 127 16 | mov dx, 03d4h 17 | mov ax, 127*256+4 18 | out dx, ax 19 | 20 | ; vertical displayed = 50 21 | mov ax, 50*256+6 22 | out dx, ax 23 | 24 | ; vertical sync = 87 25 | mov ax, 87*256+7 26 | out dx, ax 27 | 28 | ; max char scanline = 1 29 | mov ax, 1*256+9 30 | out dx, ax 31 | 32 | ; fill video RAM 33 | xor di, di 34 | xor ax, ax 35 | 36 | mov bx, 50 37 | fill_loop: 38 | mov cx, 10 39 | rep stosb 40 | 41 | inc al 42 | and al, 15 43 | mov ah, al 44 | shl ah, 1 45 | shl ah, 1 46 | shl ah, 1 47 | shl ah, 1 48 | add al, ah 49 | 50 | jnz fill_loop 51 | dec bx 52 | jnz fill_loop 53 | 54 | ; zero remaining bytes 55 | mov cx, 192 56 | rep stosb 57 | 58 | mov bx, 50 59 | 60 | cmp di, 16384 61 | jne fill_loop 62 | 63 | ; iterate bg, intensity and palettes 64 | mov cx, 64 65 | mov dx, 03d9h 66 | bgpal_loop: 67 | mov al, cl 68 | dec al 69 | out dx, al 70 | 71 | ; wait for keypress 72 | xor ah, ah 73 | int 16h 74 | 75 | loop bgpal_loop 76 | 77 | ; switch to undoc. palette 78 | mov al, 0fh 79 | mov dx, 03d8h 80 | out dx, al 81 | 82 | mov dx, 03d9h 83 | mov cx, 32 84 | bgpal_loop2: 85 | mov al, cl 86 | add al, 31 87 | out dx, al 88 | 89 | ; wait for keypress 90 | xor ah, ah 91 | int 16h 92 | 93 | loop bgpal_loop2 94 | 95 | ; restore video mode 96 | xor ah, ah 97 | mov al, 3 98 | int 10h 99 | 100 | ; exit to DOS 101 | mov ah,4ch 102 | int 21h 103 | END 104 | -------------------------------------------------------------------------------- /HIRES2.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbhart/PCRetroProgrammer/c6832cf7f2d22fda14741a3d86d68e2aa29d81f3/HIRES2.EXE -------------------------------------------------------------------------------- /JITTER1.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL tiny 3 | .STACK 100h 4 | 5 | .DATA 6 | 7 | handler_offset DW 0 8 | handler_segment DW 0 9 | 10 | .CODE 11 | 12 | _wait_floppy_motor PROC 13 | push ax 14 | push ds 15 | 16 | mov ax, 040h ; BIOS data area 17 | mov ds, ax 18 | 19 | check_motor_status: 20 | mov al, ds:[03fh] 21 | test al, 0fh ; test if motor is running 22 | jnz check_motor_status 23 | 24 | pop ds 25 | pop ax 26 | ret 27 | _wait_floppy_motor ENDP 28 | 29 | start: 30 | call _wait_floppy_motor 31 | 32 | mov ax, 4 ; CGA mode 4 33 | int 10h 34 | 35 | cli ; clear interrupts 36 | 37 | xor ax, ax ; set offset for interrupt vector table 38 | mov ds, ax 39 | 40 | mov bx, WORD PTR ds:[8*4] ; get IRQ0 handler offset 41 | mov dx, WORD PTR ds:[8*4+2] ; get IRQ0 handler segment 42 | 43 | mov WORD PTR ds:[8*4], offset irq0_handler ; set offset of IRQ0 handler 44 | mov WORD PTR ds:[8*4+2], cs ; set segment of IRQ0 handler 45 | 46 | mov ax, cs ; restore DS 47 | mov ds, ax 48 | 49 | mov WORD PTR handler_offset, bx ; save handler offset 50 | mov WORD PTR handler_segment, dx ; save handler segment 51 | 52 | mov dx, 03dah ; CGA status register 53 | 54 | wait_vertical_sync: 55 | in al, dx 56 | test al, 8 57 | jz wait_vertical_sync 58 | 59 | wait_display_enable: 60 | in al, dx 61 | test al, 1 62 | jnz wait_display_enable 63 | 64 | nop 65 | nop 66 | nop 67 | nop 68 | nop 69 | 70 | mov al, 034h ; PIT channel 0, lo/hi byte, mode 2, binary 71 | out 043h, al ; PIT mode/command register 72 | 73 | mov al, 200 ; low byte = 200 74 | out 040h, al ; channel 0 data port 75 | mov al, 77 ; hi byte = 77 (77*256 + 200 = 19912) 76 | out 040h, al 77 | 78 | sti ; enable interrupts including timer 79 | 80 | check_key: 81 | jmp check_key 82 | 83 | mov ah, 01h ; check for keypress 84 | int 16h 85 | jz check_key 86 | 87 | xor ah, ah ; get keypress 88 | int 16h 89 | 90 | cli ; clear interrupts 91 | 92 | mov bx, handler_offset ; retrieve old handler offset 93 | mov dx, handler_segment ; retrieve old handler segment 94 | 95 | xor ax, ax ; set up offset for interrupt vector table 96 | mov ds, ax 97 | 98 | mov WORD PTR ds:[8*4], bx ; restore old handler offset 99 | mov WORD PTR ds:[8*4+2], dx ; restore old handler segment 100 | 101 | mov al, 0ffh ; low byte = FF 102 | out 040h, al ; channel 0 data port 103 | mov al, 0ffh ; hi byte = FF 104 | out 040h, al 105 | 106 | sti ; enable interrupts 107 | 108 | mov ax, 3 ; back to text mode 109 | int 10h 110 | 111 | mov ah, 04ch ; return to DOS 112 | int 21h 113 | 114 | irq0_handler: 115 | push ax 116 | push dx 117 | 118 | mov dx, 03d9h ; background colour 119 | 120 | mov al, 12 ; light red 121 | out dx, al 122 | 123 | xor al, al ; black 124 | out dx, al 125 | 126 | pop dx 127 | mov al, 020h ; EOI (End Of Interrupt) 128 | out 020h, al ; master PIC command register 129 | pop ax 130 | 131 | iret 132 | 133 | END start 134 | -------------------------------------------------------------------------------- /JITTER2.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL tiny 3 | .STACK 100h 4 | 5 | .DATA 6 | 7 | handler_offset DW 0 8 | handler_segment DW 0 9 | imr_save DB 0 10 | 11 | .CODE 12 | 13 | _wait_floppy_motor PROC 14 | push ax 15 | push ds 16 | 17 | mov ax, 040h ; BIOS data area 18 | mov ds, ax 19 | 20 | check_motor_status: 21 | mov al, ds:[03fh] 22 | test al, 0fh ; test if motor is running 23 | jnz check_motor_status 24 | 25 | pop ds 26 | pop ax 27 | ret 28 | _wait_floppy_motor ENDP 29 | 30 | start: 31 | call _wait_floppy_motor 32 | 33 | mov ax, 4 ; CGA mode 4 34 | int 10h 35 | 36 | cli ; clear interrupts 37 | 38 | xor ax, ax ; set segment for interrupt vector table 39 | mov ds, ax 40 | 41 | mov bx, WORD PTR ds:[8*4] ; get IRQ0 handler offset 42 | mov dx, WORD PTR ds:[8*4+2] ; get IRQ0 handler segment 43 | 44 | mov WORD PTR ds:[8*4], offset irq0_handler ; set offset of IRQ0 handler 45 | mov WORD PTR ds:[8*4+2], cs ; set segment of IRQ0 handler 46 | 47 | mov ax, cs ; restore DS 48 | mov ds, ax 49 | 50 | mov WORD PTR handler_offset, bx ; save handler offset 51 | mov WORD PTR handler_segment, dx ; save handler segment 52 | 53 | mov dx, 03dah ; CGA status register 54 | 55 | wait_vertical_sync: 56 | in al, dx 57 | test al, 8 58 | jz wait_vertical_sync 59 | 60 | wait_display_enable: 61 | in al, dx 62 | test al, 1 63 | jnz wait_display_enable 64 | 65 | nop 66 | nop 67 | nop 68 | nop 69 | nop 70 | nop 71 | nop 72 | nop 73 | nop 74 | nop 75 | nop 76 | nop 77 | nop 78 | nop 79 | nop 80 | nop 81 | nop 82 | nop 83 | nop 84 | nop 85 | 86 | mov al, 034h ; PIT channel 0, lo/hi byte, mode 2, binary 87 | out 043h, al ; PIT mode/command register 88 | 89 | mov al, 200 ; low byte = 200 90 | out 040h, al ; channel 0 data port 91 | mov al, 77 ; hi byte = 77 (77*256 + 200 = 19912) 92 | out 040h, al 93 | 94 | ; disable individual interrupts 95 | in al, 21h ; get IMR 96 | mov BYTE PTR [imr_save], al 97 | or al, 0fch ; disable everything except IRQ1 and IRQ0 98 | out 21h, al 99 | 100 | sti 101 | 102 | mov bl, 245 103 | xor cx, cx 104 | mov dx, 64000 105 | 106 | mov ax, 0b800h ; set up CGA segment 107 | mov es, ax 108 | 109 | frame_loop: 110 | hlt ; halt the CPU and wait for interrupt 111 | 112 | mov di, 4096 113 | 114 | mov cl, bl 115 | mov al, bl 116 | 117 | rep stosb 118 | 119 | add bl, 41 120 | 121 | dec dx 122 | 123 | jnz frame_loop 124 | 125 | cli 126 | 127 | ; enable individual interrupts 128 | mov al, BYTE PTR [imr_save] 129 | out 21h, al 130 | 131 | mov bx, handler_offset ; retrieve old handler offset 132 | mov dx, handler_segment ; retrieve old handler segment 133 | 134 | xor ax, ax ; set up offset for interrupt vector table 135 | mov ds, ax 136 | 137 | mov WORD PTR ds:[8*4], bx ; restore old handler offset 138 | mov WORD PTR ds:[8*4+2], dx ; restore old handler segment 139 | 140 | mov al, 0ffh ; low byte = FF 141 | out 040h, al ; channel 0 data port 142 | mov al, 0ffh ; hi byte = FF 143 | out 040h, al 144 | 145 | sti ; enable interrupts 146 | 147 | mov ax, 3 ; back to text mode 148 | int 10h 149 | 150 | mov ah, 04ch ; return to DOS 151 | int 21h 152 | 153 | irq0_handler: 154 | push ax 155 | push dx 156 | 157 | mov dx, 03d9h ; background colour 158 | 159 | mov al, 12 ; light red 160 | out dx, al 161 | 162 | xor al, al ; black 163 | out dx, al 164 | 165 | pop dx 166 | mov al, 020h ; EOI (End Of Interrupt) 167 | out 020h, al ; master PIC command register 168 | pop ax 169 | 170 | iret 171 | 172 | END start 173 | -------------------------------------------------------------------------------- /JITTER3C.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL tiny 3 | .STACK 100h 4 | 5 | .DATA 6 | 7 | handler_offset DW 0 8 | handler_segment DW 0 9 | imr_save DB 0 10 | 11 | .CODE 12 | 13 | _wait_floppy_motor PROC 14 | push ax 15 | push ds 16 | 17 | mov ax, 040h ; BIOS data area 18 | mov ds, ax 19 | 20 | check_motor_status: 21 | mov al, ds:[03fh] 22 | test al, 0fh ; test if motor is running 23 | jnz check_motor_status 24 | 25 | pop ds 26 | pop ax 27 | ret 28 | _wait_floppy_motor ENDP 29 | 30 | start: 31 | call _wait_floppy_motor 32 | 33 | mov ax, 4 ; CGA mode 4 34 | int 10h 35 | 36 | cli ; clear interrupts 37 | 38 | xor ax, ax ; set segment for interrupt vector table 39 | mov ds, ax 40 | 41 | mov bx, WORD PTR ds:[8*4] ; get IRQ0 handler offset 42 | mov dx, WORD PTR ds:[8*4+2] ; get IRQ0 handler segment 43 | 44 | mov WORD PTR ds:[8*4], offset irq0_handler ; set offset of IRQ0 handler 45 | mov WORD PTR ds:[8*4+2], cs ; set segment of IRQ0 handler 46 | 47 | mov ax, cs ; restore DS 48 | mov ds, ax 49 | 50 | mov WORD PTR handler_offset, bx ; save handler offset 51 | mov WORD PTR handler_segment, dx ; save handler segment 52 | 53 | mov dx, 03dah ; CGA status register 54 | 55 | wait_vertical_sync: 56 | in al, dx 57 | test al, 8 58 | jz wait_vertical_sync 59 | 60 | wait_display_enable: 61 | in al, dx 62 | test al, 1 63 | jnz wait_display_enable 64 | 65 | nop 66 | nop 67 | nop 68 | nop 69 | nop 70 | nop 71 | nop 72 | nop 73 | nop 74 | nop 75 | 76 | mov al, 034h ; PIT channel 0, lo/hi byte, mode 2, binary 77 | out 043h, al ; PIT mode/command register 78 | 79 | mov al, 200 ; low byte = 200 80 | out 040h, al ; channel 0 data port 81 | mov al, 77 ; hi byte = 77 (77*256 + 200 = 19912) 82 | out 040h, al 83 | 84 | ; disable individual interrupts 85 | in al, 21h ; get IMR 86 | mov BYTE PTR [imr_save], al 87 | or al, 0fch ; disable everything except IRQ1 and IRQ0 88 | out 21h, al 89 | 90 | ; disable DRAM refresh 91 | mov al, 072h ; PIT channel 1, lo/hi byte, mode 1, binary 92 | out 43h, al 93 | mov al, 01 ; low byte = 1 94 | out 41h, al ; channel 1 data port 95 | xor al, al ; high byte = 0 96 | out 41h, al 97 | 98 | sti 99 | 100 | frame_loop: 101 | hlt ; halt the CPU and wait for interrupt 102 | 103 | mov ah, 01h 104 | int 16h 105 | 106 | jz frame_loop 107 | 108 | xor ah, ah ; get keypress 109 | int 16h 110 | 111 | cli 112 | 113 | ; enable individual interrupts 114 | mov al, BYTE PTR [imr_save] 115 | out 21h, al 116 | 117 | mov bx, handler_offset ; retrieve old handler offset 118 | mov dx, handler_segment ; retrieve old handler segment 119 | 120 | xor ax, ax ; set up offset for interrupt vector table 121 | mov ds, ax 122 | 123 | mov WORD PTR ds:[8*4], bx ; restore old handler offset 124 | mov WORD PTR ds:[8*4+2], dx ; restore old handler segment 125 | 126 | mov al, 0ffh ; low byte = FF 127 | out 040h, al ; channel 0 data port 128 | mov al, 0ffh ; hi byte = FF 129 | out 040h, al 130 | 131 | sti ; enable interrupts 132 | 133 | mov ax, 3 ; back to text mode 134 | int 10h 135 | 136 | mov ah, 04ch ; return to DOS 137 | int 21h 138 | 139 | irq0_handler: 140 | push ax 141 | push dx 142 | 143 | mov dx, 03d9h ; background colour 144 | 145 | mov al, 12 ; light red 146 | out dx, al 147 | 148 | xor al, al ; black 149 | out dx, al 150 | 151 | pop dx 152 | mov al, 020h ; EOI (End Of Interrupt) 153 | out 020h, al ; master PIC command register 154 | pop ax 155 | 156 | iret 157 | 158 | END start 159 | -------------------------------------------------------------------------------- /JITTER3a.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL tiny 3 | .STACK 100h 4 | 5 | .DATA 6 | 7 | handler_offset DW 0 8 | handler_segment DW 0 9 | imr_save DB 0 10 | 11 | .CODE 12 | 13 | _wait_floppy_motor PROC 14 | push ax 15 | push ds 16 | 17 | mov ax, 040h ; BIOS data area 18 | mov ds, ax 19 | 20 | check_motor_status: 21 | mov al, ds:[03fh] 22 | test al, 0fh ; test if motor is running 23 | jnz check_motor_status 24 | 25 | pop ds 26 | pop ax 27 | ret 28 | _wait_floppy_motor ENDP 29 | 30 | start: 31 | call _wait_floppy_motor 32 | 33 | mov ax, 4 ; CGA mode 4 34 | int 10h 35 | 36 | cli ; clear interrupts 37 | 38 | xor ax, ax ; set segment for interrupt vector table 39 | mov ds, ax 40 | 41 | mov bx, WORD PTR ds:[8*4] ; get IRQ0 handler offset 42 | mov dx, WORD PTR ds:[8*4+2] ; get IRQ0 handler segment 43 | 44 | mov WORD PTR ds:[8*4], offset irq0_handler ; set offset of IRQ0 handler 45 | mov WORD PTR ds:[8*4+2], cs ; set segment of IRQ0 handler 46 | 47 | mov ax, cs ; restore DS 48 | mov ds, ax 49 | 50 | mov WORD PTR handler_offset, bx ; save handler offset 51 | mov WORD PTR handler_segment, dx ; save handler segment 52 | 53 | mov dx, 03dah ; CGA status register 54 | 55 | wait_vertical_sync: 56 | in al, dx 57 | test al, 8 58 | jz wait_vertical_sync 59 | 60 | wait_display_enable: 61 | in al, dx 62 | test al, 1 63 | jnz wait_display_enable 64 | 65 | nop 66 | nop 67 | nop 68 | nop 69 | nop 70 | 71 | mov al, 034h ; PIT channel 0, lo/hi byte, mode 2, binary 72 | out 043h, al ; PIT mode/command register 73 | 74 | mov al, 200 ; low byte = 200 75 | out 040h, al ; channel 0 data port 76 | mov al, 77 ; hi byte = 77 (77*256 + 200 = 19912) 77 | out 040h, al 78 | 79 | ; disable individual interrupts 80 | in al, 21h ; get IMR 81 | mov BYTE PTR [imr_save], al 82 | or al, 0fch ; disable everything except IRQ1 and IRQ0 83 | out 21h, al 84 | 85 | ; disable DRAM refresh 86 | mov al, 072h ; PIT channel 1, lo/hi byte, mode 1, binary 87 | out 43h, al 88 | mov al, 01 ; low byte = 1 89 | out 41h, al ; channel 1 data port 90 | xor al, al ; high byte = 0 91 | out 41h, al 92 | 93 | sti 94 | 95 | frame_loop: 96 | hlt ; halt the CPU and wait for interrupt 97 | 98 | mov ah, 01h ; check for keypress 99 | int 16h 100 | jnz frame_loop 101 | 102 | xor ah, ah ; get keypress 103 | int 16h 104 | 105 | cli 106 | 107 | ; enable individual interrupts 108 | mov al, BYTE PTR [imr_save] 109 | out 21h, al 110 | 111 | mov bx, handler_offset ; retrieve old handler offset 112 | mov dx, handler_segment ; retrieve old handler segment 113 | 114 | xor ax, ax ; set up offset for interrupt vector table 115 | mov ds, ax 116 | 117 | mov WORD PTR ds:[8*4], bx ; restore old handler offset 118 | mov WORD PTR ds:[8*4+2], dx ; restore old handler segment 119 | 120 | mov al, 0ffh ; low byte = FF 121 | out 040h, al ; channel 0 data port 122 | mov al, 0ffh ; hi byte = FF 123 | out 040h, al 124 | 125 | sti ; enable interrupts 126 | 127 | mov ax, 3 ; back to text mode 128 | int 10h 129 | 130 | mov ah, 04ch ; return to DOS 131 | int 21h 132 | 133 | irq0_handler: 134 | push ax 135 | push dx 136 | 137 | mov dx, 03d9h ; background colour 138 | 139 | mov al, 12 ; light red 140 | out dx, al 141 | 142 | xor al, al ; black 143 | out dx, al 144 | 145 | pop dx 146 | mov al, 020h ; EOI (End Of Interrupt) 147 | out 020h, al ; master PIC command register 148 | pop ax 149 | 150 | iret 151 | 152 | END start 153 | -------------------------------------------------------------------------------- /JITTER3b.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL tiny 3 | .STACK 100h 4 | 5 | .DATA 6 | 7 | handler_offset DW 0 8 | handler_segment DW 0 9 | imr_save DB 0 10 | 11 | .CODE 12 | 13 | _wait_floppy_motor PROC 14 | push ax 15 | push ds 16 | 17 | mov ax, 040h ; BIOS data area 18 | mov ds, ax 19 | 20 | check_motor_status: 21 | mov al, ds:[03fh] 22 | test al, 0fh ; test if motor is running 23 | jnz check_motor_status 24 | 25 | pop ds 26 | pop ax 27 | ret 28 | _wait_floppy_motor ENDP 29 | 30 | start: 31 | call _wait_floppy_motor 32 | 33 | mov ax, 4 ; CGA mode 4 34 | int 10h 35 | 36 | cli ; clear interrupts 37 | 38 | xor ax, ax ; set segment for interrupt vector table 39 | mov ds, ax 40 | 41 | mov bx, WORD PTR ds:[8*4] ; get IRQ0 handler offset 42 | mov dx, WORD PTR ds:[8*4+2] ; get IRQ0 handler segment 43 | 44 | mov WORD PTR ds:[8*4], offset irq0_handler ; set offset of IRQ0 handler 45 | mov WORD PTR ds:[8*4+2], cs ; set segment of IRQ0 handler 46 | 47 | mov ax, cs ; restore DS 48 | mov ds, ax 49 | 50 | mov WORD PTR handler_offset, bx ; save handler offset 51 | mov WORD PTR handler_segment, dx ; save handler segment 52 | 53 | mov dx, 03dah ; CGA status register 54 | 55 | wait_vertical_sync: 56 | in al, dx 57 | test al, 8 58 | jz wait_vertical_sync 59 | 60 | wait_display_enable: 61 | in al, dx 62 | test al, 1 63 | jnz wait_display_enable 64 | 65 | nop 66 | nop 67 | nop 68 | nop 69 | nop 70 | nop 71 | nop 72 | nop 73 | nop 74 | nop 75 | nop 76 | nop 77 | nop 78 | nop 79 | nop 80 | nop 81 | nop 82 | nop 83 | nop 84 | nop 85 | 86 | mov al, 034h ; PIT channel 0, lo/hi byte, mode 2, binary 87 | out 043h, al ; PIT mode/command register 88 | 89 | mov al, 200 ; low byte = 200 90 | out 040h, al ; channel 0 data port 91 | mov al, 77 ; hi byte = 77 (77*256 + 200 = 19912) 92 | out 040h, al 93 | 94 | ; disable individual interrupts 95 | in al, 21h ; get IMR 96 | mov BYTE PTR [imr_save], al 97 | or al, 0fch ; disable everything except IRQ1 and IRQ0 98 | out 21h, al 99 | 100 | ; disable DRAM refresh 101 | mov al, 072h ; PIT channel 1, lo/hi byte, mode 1, binary 102 | out 43h, al 103 | mov al, 01 ; low byte = 1 104 | out 41h, al ; channel 1 data port 105 | xor al, al ; high byte = 0 106 | out 41h, al 107 | 108 | sti 109 | 110 | mov bl, 245 111 | xor cx, cx 112 | mov dx, 64000 113 | 114 | mov ax, 0b800h ; set up CGA segment 115 | mov es, ax 116 | 117 | frame_loop: 118 | hlt ; halt the CPU and wait for interrupt 119 | 120 | mov di, 4096 121 | 122 | mov cl, bl 123 | mov al, bl 124 | 125 | rep stosb 126 | 127 | add bl, 41 128 | 129 | dec dx 130 | 131 | jnz frame_loop 132 | 133 | cli 134 | 135 | ; enable individual interrupts 136 | mov al, BYTE PTR [imr_save] 137 | out 21h, al 138 | 139 | mov bx, handler_offset ; retrieve old handler offset 140 | mov dx, handler_segment ; retrieve old handler segment 141 | 142 | xor ax, ax ; set up offset for interrupt vector table 143 | mov ds, ax 144 | 145 | mov WORD PTR ds:[8*4], bx ; restore old handler offset 146 | mov WORD PTR ds:[8*4+2], dx ; restore old handler segment 147 | 148 | mov al, 0ffh ; low byte = FF 149 | out 040h, al ; channel 0 data port 150 | mov al, 0ffh ; hi byte = FF 151 | out 040h, al 152 | 153 | sti ; enable interrupts 154 | 155 | mov ax, 3 ; back to text mode 156 | int 10h 157 | 158 | mov ah, 04ch ; return to DOS 159 | int 21h 160 | 161 | irq0_handler: 162 | push ax 163 | push dx 164 | 165 | mov dx, 03d9h ; background colour 166 | 167 | mov al, 12 ; light red 168 | out dx, al 169 | 170 | xor al, al ; black 171 | out dx, al 172 | 173 | pop dx 174 | mov al, 020h ; EOI (End Of Interrupt) 175 | out 020h, al ; master PIC command register 176 | pop ax 177 | 178 | iret 179 | 180 | END start 181 | -------------------------------------------------------------------------------- /KEYPRESS.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL tiny 3 | .STACK 100h 4 | 5 | .DATA 6 | 7 | handler_offset DW 0 8 | handler_segment DW 0 9 | imr_save DB 0 10 | 11 | .CODE 12 | 13 | _wait_floppy_motor PROC 14 | push ax 15 | push ds 16 | 17 | mov ax, 040h ; BIOS data area 18 | mov ds, ax 19 | 20 | check_motor_status: 21 | mov al, ds:[03fh] 22 | test al, 0fh ; test if motor is running 23 | jnz check_motor_status 24 | 25 | pop ds 26 | pop ax 27 | ret 28 | _wait_floppy_motor ENDP 29 | 30 | start: 31 | call _wait_floppy_motor 32 | 33 | mov ax, 4 ; CGA mode 4 34 | int 10h 35 | 36 | cli ; clear interrupts 37 | 38 | xor ax, ax ; set segment for interrupt vector table 39 | mov ds, ax 40 | 41 | mov bx, WORD PTR ds:[8*4] ; get IRQ0 handler offset 42 | mov dx, WORD PTR ds:[8*4+2] ; get IRQ0 handler segment 43 | 44 | mov WORD PTR ds:[8*4], offset irq0_handler ; set offset of IRQ0 handler 45 | mov WORD PTR ds:[8*4+2], cs ; set segment of IRQ0 handler 46 | 47 | mov ax, cs ; restore DS 48 | mov ds, ax 49 | 50 | mov WORD PTR handler_offset, bx ; save handler offset 51 | mov WORD PTR handler_segment, dx ; save handler segment 52 | 53 | mov dx, 03dah ; CGA status register 54 | 55 | wait_vertical_sync: 56 | in al, dx 57 | test al, 8 58 | jz wait_vertical_sync 59 | 60 | wait_display_enable: 61 | in al, dx 62 | test al, 1 63 | jnz wait_display_enable 64 | 65 | nop 66 | nop 67 | nop 68 | nop 69 | nop 70 | nop 71 | nop 72 | nop 73 | nop 74 | nop 75 | 76 | mov al, 034h ; PIT channel 0, lo/hi byte, mode 2, binary 77 | out 043h, al ; PIT mode/command register 78 | 79 | mov al, 200 ; low byte = 200 80 | out 040h, al ; channel 0 data port 81 | mov al, 77 ; hi byte = 77 (77*256 + 200 = 19912) 82 | out 040h, al 83 | 84 | ; disable individual interrupts 85 | in al, 21h ; get IMR 86 | mov BYTE PTR [imr_save], al 87 | or al, 0feh ; disable everything except IRQ0 88 | out 21h, al 89 | 90 | ; disable DRAM refresh 91 | mov al, 072h ; PIT channel 1, lo/hi byte, mode 1, binary 92 | out 43h, al 93 | mov al, 01 ; low byte = 1 94 | out 41h, al ; channel 1 data port 95 | xor al, al ; high byte = 0 96 | out 41h, al 97 | 98 | sti 99 | 100 | frame_loop: 101 | hlt ; halt the CPU and wait for interrupt 102 | 103 | mov al, 0ah ; select IRR 104 | out 20h, al 105 | in al, 20h ; get IRR 106 | test al, 02h ; check if IRQ1 107 | jz no_key 108 | jmp key_pressed 109 | no_key: 110 | 111 | jmp frame_loop 112 | 113 | key_pressed: 114 | in al, 60h ; read keyboard buffer 115 | mov dl, al 116 | 117 | in al, 61h ; get system crtl port 118 | mov ah, al 119 | or al, 80h ; reset keyboard 120 | out 61h, al 121 | mov al, ah ; rewrite original byte 122 | out 61h, al 123 | 124 | shl dl, 1 ; ignore key release 125 | jnc no_release 126 | jmp frame_loop 127 | no_release: 128 | shr dl, 1 129 | 130 | cmp dl, 16 ; q = quit 131 | je exit 132 | jmp frame_loop 133 | exit: 134 | 135 | cli 136 | 137 | ; enable individual interrupts 138 | mov al, BYTE PTR [imr_save] 139 | out 21h, al 140 | 141 | mov bx, handler_offset ; retrieve old handler offset 142 | mov dx, handler_segment ; retrieve old handler segment 143 | 144 | xor ax, ax ; set up offset for interrupt vector table 145 | mov ds, ax 146 | 147 | mov WORD PTR ds:[8*4], bx ; restore old handler offset 148 | mov WORD PTR ds:[8*4+2], dx ; restore old handler segment 149 | 150 | mov al, 0ffh ; low byte = FF 151 | out 040h, al ; channel 0 data port 152 | mov al, 0ffh ; hi byte = FF 153 | out 040h, al 154 | 155 | sti ; enable interrupts 156 | 157 | mov ax, 3 ; back to text mode 158 | int 10h 159 | 160 | mov ah, 04ch ; return to DOS 161 | int 21h 162 | 163 | irq0_handler: 164 | push ax 165 | push dx 166 | 167 | mov dx, 03d9h ; background colour 168 | 169 | mov al, 12 ; light red 170 | out dx, al 171 | 172 | xor al, al ; black 173 | out dx, al 174 | 175 | pop dx 176 | mov al, 020h ; EOI (End Of Interrupt) 177 | out 020h, al ; master PIC command register 178 | pop ax 179 | 180 | iret 181 | 182 | END start 183 | -------------------------------------------------------------------------------- /LINE.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _cga_line PROC 7 | ARG x0:WORD, y0:WORD, x1:WORD, y1:WORD, colour:BYTE 8 | ; assumes x1 >= x0, y1 >= y0, dx >= dy 9 | 10 | ; ax = accum, dx = 2dx, bp = 2dy, si = D, cx = iters 11 | ; di = offset, bl = mask, bh = colour 12 | 13 | push bp 14 | mov bp, sp 15 | push si 16 | push di 17 | 18 | ; set up CGA segment 19 | mov ax, 0b800h 20 | mov es, ax 21 | 22 | ; compute dx 23 | mov dx, x1 24 | mov di, x0 25 | sub dx, di 26 | 27 | ; compute x0 mod 4 and x0 / 4 28 | mov cx, di 29 | and cl, 3 30 | shr di, 1 31 | shr di, 1 32 | 33 | ; compute colour and mask 34 | mov bh, colour 35 | mov bl, 03fh 36 | shl cl, 1 37 | ror bl, cl 38 | inc cl 39 | inc cl 40 | ror bh, cl 41 | 42 | ; compute iterations 43 | mov cx, dx 44 | inc cx 45 | 46 | ; compute 2dy 47 | mov ax, y0 48 | mov bp, y1 49 | sub bp, ax 50 | shl bp, 1 51 | 52 | ; offset += 8192 if y0 odd 53 | shr ax, 1 54 | jnc line_even 55 | add di, 8192 56 | line_even: 57 | 58 | ; add 80*(y0/2) to offset 59 | shl ax, 1 60 | shl ax, 1 61 | shl ax, 1 62 | shl ax, 1 63 | add di, ax 64 | shl ax, 1 65 | shl ax, 1 66 | add di, ax 67 | 68 | ; compute initial D 69 | mov si, dx 70 | neg si 71 | 72 | ; compute 2*dx 73 | shl dx, 1 74 | 75 | line_loop: 76 | mov al, es:[di] ; get pixel 77 | and al, bl ; and with mask 78 | or al, bh ; or with colour 79 | stosb ; write pixel 80 | 81 | add si, bp ; D += 2dy 82 | jle line_skipy ; if D > 0 83 | 84 | sub di, 8112 ; increment y 85 | sbb ax, ax 86 | and ax, 16304 87 | add di, ax 88 | 89 | sub si, dx ; D -= 2dx 90 | 91 | line_skipy: 92 | ror bh, 1 93 | ror bh, 1 94 | ror bl, 1 95 | ror bl, 1 96 | sbb di, 0 97 | 98 | loop line_loop 99 | 100 | pop di 101 | pop si 102 | pop bp 103 | ret 104 | _cga_line ENDP 105 | 106 | start: 107 | ; set video mode = 4 (CGA 320x200x4) 108 | xor ah, ah 109 | mov al, 4 110 | int 10h 111 | 112 | mov al, 2 ; colour = 2 113 | push ax 114 | xor ah, ah 115 | mov al, 100 ; y1 = 100 116 | push ax 117 | mov al, 200 ; x1 = 200 118 | push ax 119 | xor al, al 120 | push ax ; y0 = 0 121 | push ax ; x0 = 0 122 | call _cga_line 123 | add sp, 10 124 | 125 | ; wait for keypress 126 | xor ah, ah 127 | int 16h 128 | 129 | ; restore video mode 130 | xor ah, ah 131 | mov al, 3 132 | int 10h 133 | 134 | mov ah, 4ch ; terminate program 135 | int 21h 136 | END start 137 | -------------------------------------------------------------------------------- /LINE2.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _cga_line2 PROC 7 | ARG x0:WORD, y0:WORD, x1:WORD, y1:WORD, colour:BYTE 8 | ; assumes x1 >= x0, y1 >= y0, dy >= dx 9 | 10 | ; ax = accum, dx = 2dx, bp = 2dy, si = D, cx = iters 11 | ; di = offset, bl = mask, bh = colour 12 | 13 | push bp 14 | mov bp, sp 15 | push si 16 | push di 17 | 18 | ; set up CGA segment 19 | mov ax, 0b800h 20 | mov es, ax 21 | 22 | ; compute dx 23 | mov dx, x1 24 | mov di, x0 25 | sub dx, di 26 | 27 | ; compute x0 mod 4 and x0 / 4 28 | mov cx, di 29 | and cl, 3 30 | shr di, 1 31 | shr di, 1 32 | 33 | ; compute colour and mask 34 | mov bh, colour 35 | mov bl, 03fh 36 | shl cl, 1 37 | ror bl, cl 38 | inc cl 39 | inc cl 40 | ror bh, cl 41 | 42 | ; compute dy 43 | mov ax, y0 44 | mov bp, y1 45 | sub bp, ax 46 | 47 | ; compute iterations 48 | mov cx, bp 49 | inc cx 50 | 51 | ; offset += 8192 if y0 odd 52 | shr ax, 1 53 | jnc line2_even 54 | add di, 8192 55 | line2_even: 56 | 57 | ; add 80*(y0/2) to offset 58 | shl ax, 1 59 | shl ax, 1 60 | shl ax, 1 61 | shl ax, 1 62 | add di, ax 63 | shl ax, 1 64 | shl ax, 1 65 | add di, ax 66 | 67 | ; compute initial D 68 | mov si, bp 69 | neg si 70 | 71 | ; compute 2dy and 2dx 72 | shl bp, 1 73 | shl dx, 1 74 | 75 | line2_loop: 76 | mov al, es:[di] ; get pixel 77 | and al, bl ; and with mask 78 | or al, bh ; or with colour 79 | stosb ; write pixel 80 | 81 | add si, dx ; D += 2dx 82 | jle line2_skipx ; if D > 0 83 | 84 | ror bh, 1 85 | ror bh, 1 86 | ror bl, 1 87 | ror bl, 1 88 | cmc 89 | adc di, 0 90 | 91 | sub si, bp ; D -= 2dy 92 | 93 | line2_skipx: 94 | 95 | sub di, 8113 ; increment y 96 | sbb ax, ax 97 | and ax, 16304 98 | add di, ax 99 | 100 | loop line2_loop 101 | 102 | pop di 103 | pop si 104 | pop bp 105 | ret 106 | _cga_line2 ENDP 107 | 108 | start: 109 | ; set video mode = 4 (CGA 320x200x4) 110 | xor ah, ah 111 | mov al, 4 112 | int 10h 113 | 114 | mov al, 2 ; colour = 2 115 | push ax 116 | xor ah, ah 117 | mov al, 199 ; y1 = 199 118 | push ax 119 | mov al, 100 ; x1 = 100 120 | push ax 121 | xor al, al 122 | push ax ; y0 = 0 123 | push ax ; x0 = 0 124 | call _cga_line2 125 | add sp, 10 126 | 127 | ; wait for keypress 128 | xor ah, ah 129 | int 16h 130 | 131 | ; restore video mode 132 | xor ah, ah 133 | mov al, 3 134 | int 10h 135 | 136 | mov ah, 4ch ; terminate program 137 | int 21h 138 | END start 139 | -------------------------------------------------------------------------------- /LINEAR.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; change into CGA mode 4 11 | mov ax, 4 12 | int 10h 13 | 14 | mov dx, 03d4h 15 | mov ax, (256*3)+5 ; vertical adjust = 3 16 | out dx, ax 17 | mov ax, (256*0)+9 ; max char scanline = 0 18 | out dx, ax 19 | 20 | ; offset = 0 21 | xor di, di 22 | 23 | ; draw horizontal bars at byte i on line i 24 | mov cx, 80 25 | mov al, 0ffh ; four white pixels 26 | bar_loop: 27 | stosb ; draw bar, inc. offset 28 | 29 | add di, 80 ; offset += 80 30 | loop bar_loop 31 | 32 | ; wait for keypress 33 | mov ah, ah 34 | int 16h 35 | 36 | ; restore text mode 37 | mov ax, 3 38 | int 10h 39 | 40 | ; exit to DOS 41 | mov ah, 4ch 42 | int 21h 43 | END 44 | 45 | -------------------------------------------------------------------------------- /LINEAR2.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; change into CGA mode 4 11 | mov ax, 4 12 | int 10h 13 | 14 | mov dx, 03d4h 15 | mov ax, (256*3)+5 ; vertical adjust = 3 16 | out dx, ax 17 | mov ax, (256*0)+9 ; max char scanline = 0 18 | out dx, ax 19 | 20 | ; offset = 0 21 | xor di, di 22 | 23 | ; draw vertical lines at edges of active region 24 | mov bx, 100 25 | 26 | bar_loop: 27 | mov al, 0c0h ; left bar 28 | stosb ; draw bar, inc. offset 29 | 30 | add di, 78 31 | 32 | mov al, 03h ; right bar 33 | stosb 34 | 35 | dec bx 36 | jnz bar_loop 37 | 38 | mov cx, 10000 39 | mov dx, 03dah 40 | 41 | frame_loop: 42 | await_vertical_retrace: 43 | in al, dx 44 | test al, 8 45 | jz await_vertical_retrace 46 | 47 | dec dx ; set green background 48 | mov al, 10 49 | out dx, al 50 | 51 | inc dx 52 | await_no_vertical_retrace: 53 | in al, dx 54 | test al, 8 55 | jnz await_no_vertical_retrace 56 | 57 | dec dx 58 | mov al, 12 ; set red background 59 | out dx, al 60 | 61 | mov bx, 100 62 | inc dx 63 | active_loop: 64 | await_active: 65 | in al, dx 66 | test al, 1 67 | jnz await_active 68 | 69 | dec dx 70 | mov al, 9 ; set blue background 71 | out dx, al 72 | 73 | inc dx 74 | await_no_active: 75 | in al, dx 76 | test al, 1 77 | jz await_no_active 78 | 79 | dec dx 80 | mov al, 13 ; set magenta background 81 | out dx, al 82 | 83 | inc dx 84 | dec bx 85 | jnz active_loop 86 | 87 | loop frame_loop 88 | 89 | ; wait for keypress 90 | mov ah, ah 91 | int 16h 92 | 93 | ; restore text mode 94 | mov ax, 3 95 | int 10h 96 | 97 | ; exit to DOS 98 | mov ah, 4ch 99 | int 21h 100 | END 101 | 102 | -------------------------------------------------------------------------------- /LINEAR3.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; intercept timer interrupt 11 | cli 12 | xor ax, ax 13 | mov ds, ax 14 | mov WORD PTR ds:[8*4], offset irq0_handler 15 | mov WORD PTR ds:[8*4+2], cs 16 | sti 17 | 18 | ; change into CGA mode 4 19 | mov ax, 4 20 | int 10h 21 | 22 | mov dx, 03d4h 23 | mov ax, (256*3)+5 ; vertical adjust = 3 24 | out dx, ax 25 | mov ax, (256*0)+9 ; max char scanline = 0 26 | out dx, ax 27 | 28 | ; offset = 0 29 | xor di, di 30 | 31 | ; draw vertical lines at edges of active region 32 | mov bx, 100 33 | 34 | bar_loop: 35 | mov al, 0c0h ; left bar 36 | stosb ; draw bar, inc. offset 37 | 38 | xor al, al ; blank remainder of line 39 | mov cx, 78 40 | rep stosb 41 | 42 | mov al, 03h ; right bar 43 | stosb 44 | 45 | dec bx 46 | jnz bar_loop 47 | 48 | mov cx, 10000 49 | mov dx, 03dah 50 | 51 | frame_loop: 52 | await_vertical_retrace: 53 | in al, dx 54 | test al, 8 55 | jz await_vertical_retrace 56 | 57 | dec dx ; set green background 58 | mov al, 10 59 | out dx, al 60 | 61 | inc dx 62 | await_no_vertical_retrace: 63 | in al, dx 64 | test al, 8 65 | jnz await_no_vertical_retrace 66 | 67 | dec dx 68 | mov al, 12 ; set red background 69 | out dx, al 70 | 71 | mov bx, 100 72 | inc dx 73 | active_loop: 74 | await_active: 75 | in al, dx 76 | test al, 1 77 | jnz await_active 78 | 79 | dec dx 80 | mov al, 9 ; set blue background 81 | out dx, al 82 | 83 | inc dx 84 | await_no_active: 85 | in al, dx 86 | test al, 1 87 | jz await_no_active 88 | 89 | dec dx 90 | mov al, 13 ; set magenta background 91 | out dx, al 92 | 93 | inc dx 94 | dec bx 95 | jnz active_loop 96 | 97 | loop frame_loop 98 | 99 | ; wait for keypress 100 | mov ah, ah 101 | int 16h 102 | 103 | ; restore text mode 104 | mov ax, 3 105 | int 10h 106 | 107 | ; exit to DOS 108 | mov ah, 4ch 109 | int 21h 110 | 111 | irq0_handler: 112 | ; acknowledge interrupt 113 | push ax 114 | mov al, 020h 115 | out 020h, al 116 | pop ax 117 | iret 118 | 119 | END 120 | 121 | -------------------------------------------------------------------------------- /LINEAR3a.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; wait for keypress 11 | xor ah, ah 12 | int 16h 13 | 14 | ; intercept timer interrupt 15 | cli 16 | xor ax, ax 17 | mov ds, ax 18 | mov ax, WORD PTR ds:[4*8] 19 | mov cs:[irq_off_save], ax 20 | mov ax, WORD PTR ds:[4*8+2] 21 | mov cs:[irq_seg_save], ax 22 | mov WORD PTR ds:[8*4], offset irq0_handler 23 | mov WORD PTR ds:[8*4+2], cs 24 | sti 25 | 26 | ; change into CGA mode 4 27 | mov ax, 4 28 | int 10h 29 | 30 | mov dx, 03d4h 31 | mov ax, (256*3)+5 ; vertical adjust = 3 32 | out dx, ax 33 | mov ax, (256*0)+9 ; max char scanline = 0 34 | out dx, ax 35 | mov ax, (256*109)+7 ; vertical sync = 109 36 | out dx, ax 37 | 38 | ; offset = 0 39 | xor di, di 40 | 41 | ; draw vertical lines at edges of active region 42 | mov bx, 100 43 | 44 | bar_loop: 45 | mov al, 0c0h ; left bar 46 | stosb ; draw bar, inc. offset 47 | 48 | add di, 78 49 | 50 | mov al, 03h ; right bar 51 | stosb 52 | 53 | dec bx 54 | jnz bar_loop 55 | 56 | mov cx, 10000 57 | mov dx, 03dah 58 | 59 | cli 60 | 61 | frame_loop: 62 | await_vertical_retrace: 63 | in al, dx 64 | test al, 8 65 | jz await_vertical_retrace 66 | 67 | dec dx ; set green background 68 | mov al, 10 69 | out dx, al 70 | 71 | inc dx 72 | await_no_vertical_retrace: 73 | in al, dx 74 | test al, 8 75 | jnz await_no_vertical_retrace 76 | 77 | dec dx 78 | mov al, 12 ; set red background 79 | out dx, al 80 | 81 | mov bx, 100 82 | inc dx 83 | active_loop: 84 | await_active: 85 | in al, dx 86 | test al, 1 87 | jnz await_active 88 | 89 | dec dx 90 | mov al, 9 ; set blue background 91 | out dx, al 92 | 93 | inc dx 94 | await_no_active: 95 | in al, dx 96 | test al, 1 97 | jz await_no_active 98 | 99 | dec dx 100 | mov al, 13 ; set magenta background 101 | out dx, al 102 | 103 | inc dx 104 | dec bx 105 | jnz active_loop 106 | 107 | loop frame_loop 108 | 109 | sti 110 | 111 | mov ax, cs:[irq_off_save] 112 | mov WORD PTR ds:[4*8], ax 113 | mov ax, cs:[irq_seg_save] 114 | mov WORD PTR ds:[4*8+2], ax 115 | 116 | ; restore text mode 117 | mov ax, 3 118 | int 10h 119 | 120 | ; exit to DOS 121 | mov ah, 4ch 122 | int 21h 123 | 124 | irq_off_save DW ? 125 | irq_seg_save DW ? 126 | 127 | irq0_handler: 128 | ; acknowledge interrupt 129 | push ax 130 | mov al, 020h 131 | out 020h, al 132 | pop ax 133 | iret 134 | 135 | END 136 | 137 | -------------------------------------------------------------------------------- /LINEAR4.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; wait for keypress 11 | xor ah, ah 12 | int 16h 13 | 14 | ; intercept timer interrupt 15 | cli 16 | xor ax, ax 17 | mov ds, ax 18 | mov ax, WORD PTR ds:[4*8] ; save old handler 19 | mov cs:[irq_off_save], ax 20 | mov ax, WORD PTR ds:[4*8+2] 21 | mov cs:[irq_seg_save], ax 22 | mov WORD PTR ds:[8*4], offset irq0_handler1 23 | mov WORD PTR ds:[8*4+2], cs 24 | 25 | ; change into CGA mode 4 26 | mov ax, 4 27 | int 10h 28 | 29 | ; wait for vertical retrace 30 | mov dx, 03dah 31 | wait_retrace: 32 | in al, dx 33 | test al, 8 34 | jz wait_retrace 35 | 36 | ; wait for active region 37 | wait_active: 38 | in al, dx 39 | test al, 1 40 | jnz wait_active 41 | 42 | ; set up timer for repeat 43 | mov al, 034h 44 | out 043h, al 45 | 46 | ; wait 120 scanlines 47 | mov al, 160 48 | out 040h, al 49 | mov al, 35 50 | out 040h, al 51 | 52 | mov dx, 03d4h 53 | mov ax, (256*0)+9 ; max char scanline = 0 54 | out dx, ax 55 | mov ax, (256*6)+5 ; vertical adjust = 6 56 | out dx, ax 57 | mov ax, (256*127)+4 ; vertical total = 127 58 | out dx, ax 59 | mov ax, (256*127)+6 ; vertical displayed = 127 60 | out dx, ax 61 | mov ax, (256*127)+7 ; vertical sync position = 127 62 | out dx, ax 63 | 64 | ; delay = 113 scanlines 65 | mov al, 140 66 | out 040h, al 67 | mov al, 33 68 | out 040h, al 69 | 70 | sti 71 | 72 | ; offset = 0 73 | xor di, di 74 | 75 | ; draw vertical lines at edges of active region 76 | mov bx, 100 77 | 78 | bar_loop1: 79 | mov al, 0c0h ; left bar 80 | stosb ; draw bar, inc. offset 81 | 82 | mov cx, 78 ; blank remainder of line 83 | xor al, al 84 | rep stosb 85 | 86 | mov al, 03h ; right bar 87 | stosb 88 | 89 | dec bx 90 | jnz bar_loop1 91 | 92 | ; draw vertical lines at edges of active region 93 | mov bx, 100 94 | 95 | bar_loop2: 96 | mov al, 080h ; left bar 97 | stosb ; draw bar, inc. offset 98 | 99 | mov cx, 78 ; blank remainder of line 100 | xor al, al 101 | rep stosb 102 | 103 | mov al, 02h ; right bar 104 | stosb 105 | 106 | dec bx 107 | jnz bar_loop2 108 | 109 | e: jmp e 110 | 111 | ; wait for keypress 112 | mov ah, ah 113 | int 16h 114 | 115 | ; restore timer interrupt 116 | mov ax, cs:[irq_off_save] 117 | mov WORD PTR ds:[4*8], ax 118 | mov ax, cs:[irq_seg_save] 119 | mov WORD PTR ds:[4*8+2], ax 120 | 121 | ; restore text mode 122 | mov ax, 3 123 | int 10h 124 | 125 | ; exit to DOS 126 | mov ah, 4ch 127 | int 21h 128 | 129 | irq_off_save DW ? 130 | irq_seg_save DW ? 131 | 132 | irq0_handler1: 133 | push ax 134 | push ds 135 | push dx 136 | 137 | mov dx, 03d4h 138 | mov ax, (256*110)+4 ; vertical total = 110 139 | out dx, ax 140 | mov ax, (256*72)+6 ; vertical displayed = 72 141 | out dx, ax 142 | mov ax, (256*95)+7 ; vertical sync position = 95 143 | out dx, ax 144 | 145 | ; wait 149 scanlines 146 | mov al, 60 147 | out 040h, al 148 | mov al, 44 149 | out 040h, al 150 | 151 | ; set handler 2 152 | xor ax, ax 153 | mov ds, ax 154 | mov WORD PTR ds:[8*4], offset irq0_handler2 155 | 156 | pop dx 157 | pop ds 158 | 159 | ; acknowledge interrupt 160 | mov al, 020h 161 | out 020h, al 162 | pop ax 163 | iret 164 | 165 | irq0_handler2: 166 | push ax 167 | push ds 168 | push dx 169 | 170 | mov dx, 03d4h 171 | mov ax, (256*127)+4 ; vertical total = 127 172 | out dx, ax 173 | mov ax, (256*127)+6 ; vertical displayed = 127 174 | out dx, ax 175 | mov ax, (256*127)+7 ; vertical sync position = 127 176 | out dx, ax 177 | 178 | ; delay = 113 scanlines 179 | mov al, 140 180 | out 040h, al 181 | mov al, 33 182 | out 040h, al 183 | 184 | ; set handler 1 185 | xor ax, ax 186 | mov ds, ax 187 | mov WORD PTR ds:[8*4], offset irq0_handler1 188 | 189 | pop dx 190 | pop ds 191 | 192 | ; acknowledge interrupt 193 | mov al, 020h 194 | out 020h, al 195 | pop ax 196 | iret 197 | 198 | END 199 | 200 | -------------------------------------------------------------------------------- /LINEAR5.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; wait for keypress 11 | xor ah, ah 12 | int 16h 13 | 14 | ; intercept timer interrupt 15 | cli 16 | xor ax, ax 17 | mov ds, ax 18 | mov ax, WORD PTR ds:[4*8] ; save old handler 19 | mov cs:[irq_off_save], ax 20 | mov ax, WORD PTR ds:[4*8+2] 21 | mov cs:[irq_seg_save], ax 22 | mov WORD PTR ds:[8*4], offset irq0_handler1 23 | mov WORD PTR ds:[8*4+2], cs 24 | 25 | ; change into CGA mode 4 26 | mov ax, 4 27 | int 10h 28 | 29 | ; wait for vertical retrace 30 | mov dx, 03dah 31 | wait_retrace: 32 | in al, dx 33 | test al, 8 34 | jz wait_retrace 35 | 36 | ; wait for active region 37 | wait_active: 38 | in al, dx 39 | test al, 1 40 | jnz wait_active 41 | 42 | ; set up timer for repeat 43 | mov al, 034h 44 | out 043h, al 45 | 46 | ; wait 120 scanlines 47 | mov al, 160 48 | out 040h, al 49 | mov al, 35 50 | out 040h, al 51 | 52 | mov dx, 03d4h 53 | mov ax, (256*32)+1 ; horizontal displayed = 32 54 | out dx, ax 55 | mov ax, (256*0)+9 ; max char scanline = 0 56 | out dx, ax 57 | mov ax, (256*6)+5 ; vertical adjust = 6 58 | out dx, ax 59 | mov ax, (256*41)+2 ; horizontal sync = 41 60 | out dx, ax 61 | mov ax, (256*127)+4 ; vertical total = 127 62 | out dx, ax 63 | mov ax, (256*127)+6 ; vertical displayed = 127 64 | out dx, ax 65 | mov ax, (256*127)+7 ; vertical sync position = 127 66 | out dx, ax 67 | 68 | ; delay = 113 scanlines 69 | mov al, 140 70 | out 040h, al 71 | mov al, 33 72 | out 040h, al 73 | 74 | sti 75 | 76 | ; offset = 0 77 | xor di, di 78 | 79 | ; draw vertical lines at edges of active region 80 | mov bx, 64 81 | 82 | bar_loop1: 83 | mov al, 0c0h ; left bar 84 | stosb ; draw bar, inc. offset 85 | 86 | mov cx, 62 ; blank remainder of line 87 | xor al, al 88 | rep stosb 89 | 90 | mov al, 03h ; right bar 91 | stosb 92 | 93 | dec bx 94 | jnz bar_loop1 95 | 96 | ; draw vertical lines at edges of active region 97 | mov bx, 64 98 | 99 | bar_loop2: 100 | mov al, 080h ; left bar 101 | stosb ; draw bar, inc. offset 102 | 103 | mov cx, 62 ; blank remainder of line 104 | xor al, al 105 | rep stosb 106 | 107 | mov al, 02h ; right bar 108 | stosb 109 | 110 | dec bx 111 | jnz bar_loop2 112 | 113 | e: jmp e 114 | 115 | ; wait for keypress 116 | mov ah, ah 117 | int 16h 118 | 119 | ; restore timer interrupt 120 | mov ax, cs:[irq_off_save] 121 | mov WORD PTR ds:[4*8], ax 122 | mov ax, cs:[irq_seg_save] 123 | mov WORD PTR ds:[4*8+2], ax 124 | 125 | ; restore text mode 126 | mov ax, 3 127 | int 10h 128 | 129 | ; exit to DOS 130 | mov ah, 4ch 131 | int 21h 132 | 133 | irq_off_save DW ? 134 | irq_seg_save DW ? 135 | 136 | irq0_handler1: 137 | push ax 138 | push ds 139 | push dx 140 | 141 | mov dx, 03d4h 142 | mov ax, (256*110)+4 ; vertical total = 110 143 | out dx, ax 144 | mov ax, (256*0)+6 ; vertical displayed = 0 145 | out dx, ax 146 | mov ax, (256*63)+7 ; vertical sync position = 63 147 | out dx, ax 148 | 149 | ; wait 149 scanlines 150 | mov al, 60 151 | out 040h, al 152 | mov al, 44 153 | out 040h, al 154 | 155 | ; set handler 2 156 | xor ax, ax 157 | mov ds, ax 158 | mov WORD PTR ds:[8*4], offset irq0_handler2 159 | 160 | pop dx 161 | pop ds 162 | 163 | ; acknowledge interrupt 164 | mov al, 020h 165 | out 020h, al 166 | pop ax 167 | iret 168 | 169 | irq0_handler2: 170 | push ax 171 | push ds 172 | push dx 173 | 174 | mov dx, 03d4h 175 | mov ax, (256*127)+4 ; vertical total = 127 176 | out dx, ax 177 | mov ax, (256*127)+6 ; vertical displayed = 127 178 | out dx, ax 179 | mov ax, (256*127)+7 ; vertical sync position = 127 180 | out dx, ax 181 | 182 | ; delay = 113 scanlines 183 | mov al, 140 184 | out 040h, al 185 | mov al, 33 186 | out 040h, al 187 | 188 | ; set handler 1 189 | xor ax, ax 190 | mov ds, ax 191 | mov WORD PTR ds:[8*4], offset irq0_handler1 192 | 193 | pop dx 194 | pop ds 195 | 196 | ; acknowledge interrupt 197 | mov al, 020h 198 | out 020h, al 199 | pop ax 200 | iret 201 | 202 | END 203 | 204 | -------------------------------------------------------------------------------- /LINEAR7.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; change into CGA mode 4 11 | mov ax, 4 12 | int 10h 13 | 14 | ; offset = 0 15 | xor di, di 16 | 17 | ; fill first bank with cyan black cyan black.... 18 | mov cx, 8192 19 | mov al, 044h 20 | 21 | rep stosb 22 | 23 | ; fill second bank with magenta black magenta black.... 24 | 25 | mov cx, 8192 26 | mov al, 088h 27 | 28 | rep stosb 29 | 30 | cli 31 | 32 | mov dx, 03d4h 33 | 34 | ; uncomment these lines at your own risk 35 | ; the monitor will lose sync, which can damage 36 | ; some monitors 37 | ; 38 | ; mov ax, 32*256+1 ; horizontal displayed = 32 39 | ; out dx, ax 40 | 41 | mov dl, 0dah 42 | 43 | ; wait for vertical retrace 44 | wait_v_retrace: 45 | in al, dx 46 | test al, 8 47 | jz wait_v_retrace 48 | 49 | ; wait for active region 50 | wait_active: 51 | in al, dx 52 | test al, 1 53 | jnz wait_active 54 | 55 | mov dl, 0d4h 56 | 57 | mov ax, 0*256+9 ; max char scanline = 0 58 | out dx, ax 59 | mov ax, 6*256+5 ; vertical adjust = 6 60 | out dx, ax 61 | mov ax, 127*256+4 ; vertical total = 127 62 | out dx, ax 63 | mov ax, 127*256+6 ; vertical displayed = 127 64 | out dx, ax 65 | 66 | jmp skip_first 67 | 68 | crt_loop: 69 | 70 | ; wait for vertical retrace 71 | mov dx, 03dah 72 | wait_retrace: 73 | in al, dx 74 | test al, 8 75 | jz wait_retrace 76 | 77 | ; wait for active region 78 | wait_active_0: 79 | in al, dx 80 | test al, 1 81 | jnz wait_active_0 82 | 83 | mov dl, 0d4h 84 | 85 | skip_first: 86 | 87 | mov ax, 127*256+7 ; vertical sync position = 127 (won't be reached) 88 | out dx, ax 89 | 90 | ; wait for non-active region 91 | mov dl, 0dah 92 | wait_non_active_0: 93 | in al, dx 94 | test al, 1 95 | jz wait_non_active_0 96 | 97 | mov cx, 96 98 | 99 | wait_1_96_loop: 100 | 101 | ; wait for active region 102 | wait_active_1_96: 103 | in al, dx 104 | test al, 1 105 | jnz wait_active_1_96 106 | 107 | ; wait for non-active region 108 | wait_non_active_1_96: 109 | in al, dx 110 | test al, 1 111 | jz wait_non_active_1_96 112 | 113 | loop wait_1_96_loop 114 | 115 | ; wait for active region 116 | wait_active_97: 117 | in al, dx 118 | test al, 1 119 | jnz wait_active_97 120 | 121 | mov dl, 0d4h 122 | 123 | mov ax, 87*256+4 ; vertical total = 87 (out of the way) 124 | out dx, ax 125 | mov ax, 72*256+6 ; vertical displayed = 72 (128 + 72 = 200) 126 | out dx, ax 127 | mov ax, 95*256+7 ; vertical sync position = 95 128 | out dx, ax 129 | 130 | ; wait for non-active region 131 | mov dl, 0dah 132 | wait_non_active_97: 133 | in al, dx 134 | test al, 1 135 | jz wait_non_active_97 136 | 137 | mov cx, 102 138 | 139 | wait_98_199_loop: 140 | 141 | ; wait for active region 142 | wait_active_98_199: 143 | in al, dx 144 | test al, 1 145 | jnz wait_active_98_199 146 | 147 | ; wait for non-active region 148 | wait_non_active_98_199: 149 | in al, dx 150 | test al, 1 151 | jz wait_non_active_98_199 152 | 153 | loop wait_98_199_loop 154 | 155 | mov dl, 0d4h 156 | 157 | mov ax, 127*256+4 ; vertical total = 127 158 | out dx, ax 159 | mov ax, 127*256+6 ; vertical displayed = 127 160 | out dx, ax 161 | 162 | ; read Interrupt Request Register 163 | mov al, 0ah ; next command read IRR 164 | out 20h, al 165 | in al, 20h 166 | 167 | ; is keyboard (IRQ1) requesting service 168 | test al, 02h 169 | jnz key_pressed 170 | 171 | jmp crt_loop 172 | 173 | key_pressed: 174 | 175 | sti 176 | 177 | ; restore text mode 178 | mov ax, 3 179 | int 10h 180 | 181 | ; exit to DOS 182 | mov ah, 4ch 183 | int 21h 184 | 185 | END 186 | -------------------------------------------------------------------------------- /LINEAR8.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; change into CGA mode 4 11 | mov ax, 4 12 | int 10h 13 | 14 | ; offset = 0 15 | xor di, di 16 | 17 | ; fill first bank with cyan black cyan black.... 18 | mov cx, 8192 19 | mov al, 044h 20 | 21 | rep stosb 22 | 23 | ; first scanline of 2nd bank white black white black... 24 | mov cx, 64 25 | mov al, 0cch 26 | 27 | rep stosb 28 | 29 | ; fill second bank with magenta black magenta black.... 30 | 31 | mov cx, 8128 32 | mov al, 088h 33 | 34 | rep stosb 35 | 36 | cli 37 | 38 | mov dx, 03d4h 39 | 40 | mov ax, 32*256+1 ; horizontal displayed = 32 41 | out dx, ax 42 | 43 | mov dl, 0dah 44 | 45 | ; wait for vertical retrace 46 | wait_v_retrace: 47 | in al, dx 48 | test al, 8 49 | jz wait_v_retrace 50 | 51 | ; wait for active region 52 | wait_active: 53 | in al, dx 54 | test al, 1 55 | jnz wait_active 56 | 57 | mov dl, 0d4h 58 | 59 | mov ax, 0*256+9 ; max char scanline = 0 60 | out dx, ax 61 | mov ax, 6*256+5 ; vertical adjust = 6 62 | out dx, ax 63 | mov ax, 127*256+4 ; vertical total = 127 64 | out dx, ax 65 | mov ax, 127*256+6 ; vertical displayed = 127 66 | out dx, ax 67 | 68 | jmp skip_first 69 | 70 | crt_loop: 71 | 72 | ; wait for vertical retrace 73 | mov dx, 03dah 74 | wait_retrace: 75 | in al, dx 76 | test al, 8 77 | jz wait_retrace 78 | 79 | ; wait for active region 80 | wait_active_0: 81 | in al, dx 82 | test al, 1 83 | jnz wait_active_0 84 | 85 | mov dl, 0d4h 86 | 87 | skip_first: 88 | 89 | mov ax, 127*256+7 ; vertical sync position = 127 (won't be reached) 90 | out dx, ax 91 | 92 | ; wait for non-active region 93 | mov dl, 0dah 94 | wait_non_active_0: 95 | in al, dx 96 | test al, 1 97 | jz wait_non_active_0 98 | 99 | mov cx, 96 100 | 101 | wait_1_96_loop: 102 | 103 | ; wait for active region 104 | wait_active_1_96: 105 | in al, dx 106 | test al, 1 107 | jnz wait_active_1_96 108 | 109 | ; wait for non-active region 110 | wait_non_active_1_96: 111 | in al, dx 112 | test al, 1 113 | jz wait_non_active_1_96 114 | 115 | loop wait_1_96_loop 116 | 117 | ; wait for active region 118 | wait_active_97: 119 | in al, dx 120 | test al, 1 121 | jnz wait_active_97 122 | 123 | mov dl, 0d4h 124 | 125 | mov ax, 87*256+4 ; vertical total = 87 (out of the way) 126 | out dx, ax 127 | mov ax, 72*256+6 ; vertical displayed = 72 (128 + 72 = 200) 128 | out dx, ax 129 | mov ax, 95*256+7 ; vertical sync position = 95 130 | out dx, ax 131 | 132 | ; wait for non-active region 133 | mov dl, 0dah 134 | wait_non_active_97: 135 | in al, dx 136 | test al, 1 137 | jz wait_non_active_97 138 | 139 | mov cx, 29 140 | 141 | wait_98_126_loop: 142 | 143 | ; wait for active region 144 | wait_active_98_126: 145 | in al, dx 146 | test al, 1 147 | jnz wait_active_98_126 148 | 149 | ; wait for non-active region 150 | wait_non_active_98_126: 151 | in al, dx 152 | test al, 1 153 | jz wait_non_active_98_126 154 | 155 | loop wait_98_126_loop 156 | 157 | ; *********** rasterline 127 ****************** 158 | 159 | ; wait for active region 160 | wait_active_127: 161 | in al, dx 162 | test al, 1 163 | jnz wait_active_127 164 | 165 | mov dl, 0d4h 166 | 167 | mov ax, 32*256+0 ; horizontal total = 32 168 | out dx, ax 169 | mov ax, 0*256+1 ; horizontal displayed = 0 170 | out dx, ax 171 | 172 | ; delay 173 | REPT 10 174 | nop 175 | ENDM 176 | 177 | mov ax, 12*256+2 ; horizontal sync pos = 12 178 | out dx, ax 179 | 180 | ; wait for non-active region 181 | mov dl, 0dah 182 | wait_non_active_127: 183 | in al, dx 184 | test al, 1 185 | jz wait_non_active_127 186 | 187 | mov dl, 0d4h 188 | 189 | mov ax, 1*256+9 ; max char scanline = 1 190 | out dx, ax 191 | mov ax, 23*256+0 ; horizontal total = 23 192 | out dx, ax 193 | mov ax, 32*256+1 ; horizontal displayed = 32 194 | out dx, ax 195 | 196 | ; *********** rasterline 128 ****************** 197 | 198 | ; wait for active region 199 | mov dl, 0dah 200 | wait_active_128: 201 | in al, dx 202 | test al, 1 203 | jnz wait_active_128 204 | 205 | mov dl, 0d4h 206 | 207 | mov ax, 45*256+2 ; horizontal sync pos = 45 208 | out dx, ax 209 | mov ax, 56*256+0 ; horizontal total = 56 210 | out dx, ax 211 | 212 | ; wait for non-active region 213 | mov dl, 0dah 214 | wait_non_active_128: 215 | in al, dx 216 | test al, 1 217 | jz wait_non_active_128 218 | 219 | ; *********** rasterline 129 ****************** 220 | 221 | ; wait for active region 222 | wait_active_129: 223 | in al, dx 224 | test al, 1 225 | jnz wait_active_129 226 | 227 | mov dl, 0d4h 228 | 229 | mov ax, 0*256+9 ; max char scanline = 0 230 | out dx, ax 231 | 232 | ; wait for non-active region 233 | mov dl, 0dah 234 | wait_non_active_129: 235 | in al, dx 236 | test al, 1 237 | jz wait_non_active_129 238 | 239 | ; *********** remaining rasterlines ****************** 240 | 241 | mov cx, 70 242 | 243 | wait_130_199_loop: 244 | 245 | ; wait for active region 246 | wait_active_130_199: 247 | in al, dx 248 | test al, 1 249 | jnz wait_active_130_199 250 | 251 | ; wait for non-active region 252 | wait_non_active_130_199: 253 | in al, dx 254 | test al, 1 255 | jz wait_non_active_130_199 256 | 257 | loop wait_130_199_loop 258 | 259 | ; delay 260 | mov cl, 100 261 | shl ax, cl 262 | 263 | mov dl, 0d4h 264 | 265 | mov ax, 127*256+4 ; vertical total = 127 266 | out dx, ax 267 | mov ax, 127*256+6 ; vertical displayed = 127 268 | out dx, ax 269 | 270 | ; read Interrupt Request Register 271 | mov al, 0ah ; next command read IRR 272 | out 20h, al 273 | in al, 20h 274 | 275 | ; is keyboard (IRQ1) requesting service 276 | test al, 02h 277 | jnz key_pressed 278 | 279 | jmp crt_loop 280 | 281 | key_pressed: 282 | 283 | sti 284 | 285 | ; restore text mode 286 | mov ax, 3 287 | int 10h 288 | 289 | ; exit to DOS 290 | mov ah, 4ch 291 | int 21h 292 | 293 | END 294 | -------------------------------------------------------------------------------- /LINEAR9.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; change into CGA mode 4 11 | mov ax, 4 12 | int 10h 13 | 14 | ; offset = 0 15 | xor di, di 16 | 17 | ; fill first bank with cyan black cyan black.... 18 | mov cx, 8192 19 | mov al, 044h 20 | 21 | rep stosb 22 | 23 | ; first scanline of 2nd bank white black white black... 24 | mov cx, 64 25 | mov al, 0cch 26 | 27 | rep stosb 28 | 29 | ; fill second bank with magenta black magenta black.... 30 | 31 | mov cx, 8128 32 | mov al, 088h 33 | 34 | rep stosb 35 | 36 | cli 37 | 38 | mov dx, 03d4h 39 | 40 | mov ax, 32*256+1 ; horizontal displayed = 32 41 | out dx, ax 42 | 43 | mov dl, 0dah 44 | 45 | ; wait for vertical retrace 46 | wait_v_retrace: 47 | in al, dx 48 | test al, 8 49 | jz wait_v_retrace 50 | 51 | ; wait for active region 52 | wait_active: 53 | in al, dx 54 | test al, 1 55 | jnz wait_active 56 | 57 | mov dl, 0d4h 58 | 59 | mov ax, 0*256+9 ; max char scanline = 0 60 | out dx, ax 61 | mov ax, 6*256+5 ; vertical adjust = 6 62 | out dx, ax 63 | mov ax, 127*256+4 ; vertical total = 127 64 | out dx, ax 65 | mov ax, 127*256+6 ; vertical displayed = 127 66 | out dx, ax 67 | 68 | jmp skip_first 69 | 70 | crt_loop: 71 | 72 | ; wait for vertical retrace 73 | mov dx, 03dah 74 | wait_retrace: 75 | in al, dx 76 | test al, 8 77 | jz wait_retrace 78 | 79 | ; wait for active region 80 | wait_active_0: 81 | in al, dx 82 | test al, 1 83 | jnz wait_active_0 84 | 85 | mov dl, 0d4h 86 | 87 | skip_first: 88 | 89 | mov ax, 127*256+7 ; vertical sync position = 127 (won't be reached) 90 | out dx, ax 91 | 92 | ; wait for non-active region 93 | mov dl, 0dah 94 | wait_non_active_0: 95 | in al, dx 96 | test al, 1 97 | jz wait_non_active_0 98 | 99 | mov cx, 96 100 | 101 | wait_1_96_loop: 102 | 103 | ; wait for active region 104 | wait_active_1_96: 105 | in al, dx 106 | test al, 1 107 | jnz wait_active_1_96 108 | 109 | ; wait for non-active region 110 | wait_non_active_1_96: 111 | in al, dx 112 | test al, 1 113 | jz wait_non_active_1_96 114 | 115 | loop wait_1_96_loop 116 | 117 | ; wait for active region 118 | wait_active_97: 119 | in al, dx 120 | test al, 1 121 | jnz wait_active_97 122 | 123 | mov dl, 0d4h 124 | 125 | mov ax, 87*256+4 ; vertical total = 87 (out of the way) 126 | out dx, ax 127 | mov ax, 72*256+6 ; vertical displayed = 72 (128 + 72 = 200) 128 | out dx, ax 129 | mov ax, 95*256+7 ; vertical sync position = 95 130 | out dx, ax 131 | 132 | ; wait for non-active region 133 | mov dl, 0dah 134 | wait_non_active_97: 135 | in al, dx 136 | test al, 1 137 | jz wait_non_active_97 138 | 139 | mov cx, 29 140 | 141 | wait_98_126_loop: 142 | 143 | ; wait for active region 144 | wait_active_98_126: 145 | in al, dx 146 | test al, 1 147 | jnz wait_active_98_126 148 | 149 | ; wait for non-active region 150 | wait_non_active_98_126: 151 | in al, dx 152 | test al, 1 153 | jz wait_non_active_98_126 154 | 155 | loop wait_98_126_loop 156 | 157 | ; *********** rasterline 127 ****************** 158 | 159 | ; wait for active region 160 | wait_active_127: 161 | in al, dx 162 | test al, 1 163 | jnz wait_active_127 164 | 165 | mov dl, 0d4h 166 | 167 | mov ax, 56*256+0 ; horizontal total = 56 168 | out dx, ax 169 | mov ax, 32*256+1 ; horizontal displayed = 32 170 | out dx, ax 171 | 172 | ; delay 173 | REPT 10 174 | nop 175 | ENDM 176 | 177 | mov ax, 45*256+2 ; horizontal sync pos = 45 178 | out dx, ax 179 | 180 | mov dl, 0d9h ; background colour 12 181 | mov al, 02ch 182 | out dx, al 183 | 184 | ; wait for non-active region 185 | mov dl, 0dah 186 | wait_non_active_127: 187 | in al, dx 188 | test al, 1 189 | jz wait_non_active_127 190 | 191 | mov dl, 0d4h 192 | 193 | mov ax, 0*256+9 ; max char scanline = 0 194 | out dx, ax 195 | mov ax, 56*256+0 ; horizontal total = 56 196 | out dx, ax 197 | mov ax, 32*256+1 ; horizontal displayed = 32 198 | out dx, ax 199 | 200 | ; *********** rasterline 128 ****************** 201 | 202 | ; wait for active region 203 | mov dl, 0dah 204 | wait_active_128: 205 | in al, dx 206 | test al, 1 207 | jnz wait_active_128 208 | 209 | mov dl, 0d4h 210 | 211 | mov ax, 45*256+2 ; horizontal sync pos = 45 212 | out dx, ax 213 | mov ax, 56*256+0 ; horizontal total = 56 214 | out dx, ax 215 | 216 | ; wait for non-active region 217 | mov dl, 0dah 218 | wait_non_active_128: 219 | in al, dx 220 | test al, 1 221 | jz wait_non_active_128 222 | 223 | ; *********** rasterline 129 ****************** 224 | 225 | ; wait for active region 226 | wait_active_129: 227 | in al, dx 228 | test al, 1 229 | jnz wait_active_129 230 | 231 | mov dl, 0d4h 232 | 233 | mov ax, 0*256+9 ; max char scanline = 0 234 | out dx, ax 235 | 236 | mov dl, 0d9h ; background colour 0 237 | mov al, 20h 238 | out dx, al 239 | 240 | ; wait for non-active region 241 | mov dl, 0dah 242 | wait_non_active_129: 243 | in al, dx 244 | test al, 1 245 | jz wait_non_active_129 246 | 247 | ; *********** remaining rasterlines ****************** 248 | 249 | mov cx, 70 250 | 251 | wait_130_199_loop: 252 | 253 | ; wait for active region 254 | wait_active_130_199: 255 | in al, dx 256 | test al, 1 257 | jnz wait_active_130_199 258 | 259 | ; wait for non-active region 260 | wait_non_active_130_199: 261 | in al, dx 262 | test al, 1 263 | jz wait_non_active_130_199 264 | 265 | loop wait_130_199_loop 266 | 267 | ; delay 268 | mov cl, 100 269 | shl ax, cl 270 | 271 | mov dl, 0d4h 272 | 273 | mov ax, 127*256+4 ; vertical total = 127 274 | out dx, ax 275 | mov ax, 127*256+6 ; vertical displayed = 127 276 | out dx, ax 277 | 278 | ; read Interrupt Request Register 279 | mov al, 0ah ; next command read IRR 280 | out 20h, al 281 | in al, 20h 282 | 283 | ; is keyboard (IRQ1) requesting service 284 | test al, 02h 285 | jnz key_pressed 286 | 287 | jmp crt_loop 288 | 289 | key_pressed: 290 | 291 | sti 292 | 293 | ; restore text mode 294 | mov ax, 3 295 | int 10h 296 | 297 | ; exit to DOS 298 | mov ah, 4ch 299 | int 21h 300 | 301 | END 302 | -------------------------------------------------------------------------------- /LINEARA.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | ; set up CGA segment 7 | mov ax, 0b800h 8 | mov es, ax 9 | 10 | ; change into CGA mode 4 11 | mov ax, 4 12 | int 10h 13 | 14 | ; offset = 0 15 | xor di, di 16 | 17 | ; fill first bank with cyan black cyan black.... 18 | mov cx, 8192 19 | mov al, 044h 20 | 21 | rep stosb 22 | 23 | ; first scanline of 2nd bank white black white black... 24 | mov cx, 64 25 | mov al, 0cch 26 | 27 | rep stosb 28 | 29 | ; fill second bank with magenta black magenta black.... 30 | 31 | mov cx, 8128 32 | mov al, 088h 33 | 34 | rep stosb 35 | 36 | cli 37 | 38 | mov dx, 03d4h 39 | 40 | mov ax, 32*256+1 ; horizontal displayed = 32 41 | out dx, ax 42 | 43 | mov dl, 0dah 44 | 45 | ; wait for vertical retrace 46 | wait_v_retrace: 47 | in al, dx 48 | test al, 8 49 | jz wait_v_retrace 50 | 51 | ; wait for active region 52 | wait_active: 53 | in al, dx 54 | test al, 1 55 | jnz wait_active 56 | 57 | mov dl, 0d4h 58 | 59 | mov ax, 0*256+9 ; max char scanline = 0 60 | out dx, ax 61 | mov ax, 6*256+5 ; vertical adjust = 6 62 | out dx, ax 63 | mov ax, 127*256+4 ; vertical total = 127 64 | out dx, ax 65 | mov ax, 127*256+6 ; vertical displayed = 127 66 | out dx, ax 67 | 68 | jmp skip_first 69 | 70 | crt_loop: 71 | 72 | ; wait for vertical retrace 73 | mov dx, 03dah 74 | wait_retrace: 75 | in al, dx 76 | test al, 8 77 | jz wait_retrace 78 | 79 | ; wait for active region 80 | wait_active_0: 81 | in al, dx 82 | test al, 1 83 | jnz wait_active_0 84 | 85 | mov dl, 0d4h 86 | 87 | skip_first: 88 | 89 | mov ax, 127*256+7 ; vertical sync position = 127 (won't be reached) 90 | out dx, ax 91 | 92 | ; wait for non-active region 93 | mov dl, 0dah 94 | wait_non_active_0: 95 | in al, dx 96 | test al, 1 97 | jz wait_non_active_0 98 | 99 | mov cx, 96 100 | 101 | wait_1_96_loop: 102 | 103 | ; wait for active region 104 | wait_active_1_96: 105 | in al, dx 106 | test al, 1 107 | jnz wait_active_1_96 108 | 109 | ; wait for non-active region 110 | wait_non_active_1_96: 111 | in al, dx 112 | test al, 1 113 | jz wait_non_active_1_96 114 | 115 | loop wait_1_96_loop 116 | 117 | ; wait for active region 118 | wait_active_97: 119 | in al, dx 120 | test al, 1 121 | jnz wait_active_97 122 | 123 | mov dl, 0d4h 124 | 125 | mov ax, 87*256+4 ; vertical total = 87 (out of the way) 126 | out dx, ax 127 | mov ax, 72*256+6 ; vertical displayed = 72 (128 + 72 = 200) 128 | out dx, ax 129 | mov ax, 95*256+7 ; vertical sync position = 95 130 | out dx, ax 131 | 132 | ; wait for non-active region 133 | mov dl, 0dah 134 | wait_non_active_97: 135 | in al, dx 136 | test al, 1 137 | jz wait_non_active_97 138 | 139 | mov cx, 29 140 | 141 | wait_98_126_loop: 142 | 143 | ; wait for active region 144 | wait_active_98_126: 145 | in al, dx 146 | test al, 1 147 | jnz wait_active_98_126 148 | 149 | ; wait for non-active region 150 | wait_non_active_98_126: 151 | in al, dx 152 | test al, 1 153 | jz wait_non_active_98_126 154 | 155 | loop wait_98_126_loop 156 | 157 | ; *********** rasterline 127 ****************** 158 | 159 | mov bx, 1*256+9 ; max char scanline = 1 160 | mov si, 23*256+0 ; horizontal total = 23 161 | mov di, 32*256+1 ; horizontal displayed = 32 162 | 163 | ; wait for active region 164 | wait_active_127: 165 | in al, dx 166 | test al, 1 167 | jnz wait_active_127 168 | 169 | mov dl, 0d4h 170 | 171 | mov ax, 32*256+0 ; horizontal total = 32 172 | out dx, ax 173 | mov ax, 1*256+1 ; horizontal displayed = 1 174 | out dx, ax 175 | 176 | REPT 10 177 | nop 178 | ENDM 179 | 180 | mov ax, 12*256+2 ; horizontal sync pos = 12 181 | out dx, ax 182 | 183 | ; wait for non-active region 184 | ; mov dl, 0dah 185 | ;wait_non_active_127: 186 | ; in al, dx 187 | ; test al, 1 188 | ; jz wait_non_active_127 189 | 190 | mov dl, 0d4h 191 | 192 | mov ax, bx ; max char scanline = 1 193 | out dx, ax 194 | mov ax, si ; horizontal total = 23 195 | out dx, ax 196 | mov ax, di ; horizontal displayed = 32 197 | out dx, ax 198 | 199 | ; *********** rasterline 128 ****************** 200 | 201 | ; wait for active region 202 | ; mov dl, 0dah 203 | ;wait_active_128: 204 | ; in al, dx 205 | ; test al, 1 206 | ; jnz wait_active_128 207 | 208 | mov dl, 0d4h 209 | 210 | mov ax, 45*256+2 ; horizontal sync pos = 45 211 | out dx, ax 212 | mov ax, 56*256+0 ; horizontal total = 56 213 | out dx, ax 214 | 215 | ; wait for non-active region 216 | mov dl, 0dah 217 | wait_non_active_128: 218 | in al, dx 219 | test al, 1 220 | jz wait_non_active_128 221 | 222 | ; *********** rasterline 129 ****************** 223 | 224 | ; wait for active region 225 | wait_active_129: 226 | in al, dx 227 | test al, 1 228 | jnz wait_active_129 229 | 230 | mov dl, 0d4h 231 | 232 | mov ax, 0*256+9 ; max char scanline = 0 233 | out dx, ax 234 | 235 | ; wait for non-active region 236 | mov dl, 0dah 237 | wait_non_active_129: 238 | in al, dx 239 | test al, 1 240 | jz wait_non_active_129 241 | 242 | ; *********** remaining rasterlines ****************** 243 | 244 | mov cx, 70 245 | 246 | wait_130_199_loop: 247 | 248 | ; wait for active region 249 | wait_active_130_199: 250 | in al, dx 251 | test al, 1 252 | jnz wait_active_130_199 253 | 254 | ; wait for non-active region 255 | wait_non_active_130_199: 256 | in al, dx 257 | test al, 1 258 | jz wait_non_active_130_199 259 | 260 | loop wait_130_199_loop 261 | 262 | ; delay 263 | mov cl, 100 264 | shl ax, cl 265 | 266 | mov dl, 0d4h 267 | 268 | mov ax, 127*256+4 ; vertical total = 127 269 | out dx, ax 270 | mov ax, 127*256+6 ; vertical displayed = 127 271 | out dx, ax 272 | 273 | ; read Interrupt Request Register 274 | mov al, 0ah ; next command read IRR 275 | out 20h, al 276 | in al, 20h 277 | 278 | ; is keyboard (IRQ1) requesting service 279 | test al, 02h 280 | jnz key_pressed 281 | 282 | jmp crt_loop 283 | 284 | key_pressed: 285 | 286 | sti 287 | 288 | ; restore text mode 289 | mov ax, 3 290 | int 10h 291 | 292 | ; exit to DOS 293 | mov ah, 4ch 294 | int 21h 295 | 296 | END 297 | -------------------------------------------------------------------------------- /MANDEL.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | 5 | .DATA 6 | 7 | iter DB 0 8 | endline DW 0 9 | 10 | .CODE 11 | 12 | ; set up data segment 13 | mov ax, @data 14 | mov ds, ax 15 | 16 | ; change to VGA mode 13h (320x200 256 colours) 17 | mov ax, 13h 18 | int 10h 19 | 20 | ; Mandelbrot set iterates z -> z^2 + c in the 21 | ; complex numbers, starting with z = 0, and 22 | ; where c = a + bi is a complex number with 23 | ; -2 <= a <= 2 and -2 <= b <= 2 24 | ; (this region is a square in the complex plane) 25 | 26 | ; We draw this square on the screen, setting 27 | ; the pixel colour to the number of iterations 28 | ; it takes for the iteration to leave the circle 29 | ; of radius 2 in the complex plane. We set the 30 | ; pixel to black if it does not leave the circle 31 | ; after a certain number of iterations 32 | 33 | ; We will divide all values by 4 and use the 34 | ; iteration Z -> 4Z^2 + C which means we'll need 35 | ; values from -0.5 to 0.5 instead of -2.0 to 2.0 36 | ; We use 16 bit values 37 | 38 | ; DX:AX = accum, result of multiplication 39 | ; DI = offset in VRAM, BX = a, CX = b, SI = x, BP = y 40 | ; where Z = x + yi and C = a + bi 41 | ; DS:[iter] = iterations (counting down to zero) 42 | ; DS:[endline] = offset of end of current line 43 | 44 | ; Pixel aspect ratio is 1:1.2, so we will use 240x200 45 | ; pixel region 46 | ; Moving in x-direction will add 1/240 = 0.0111h 47 | ; Moving in y-direction will add 1/200 = 0.0148h 48 | 49 | ; set up VRAM segment 50 | mov ax, 0a000h 51 | mov es, ax 52 | 53 | ; offset of first pixel 54 | xor di, di 55 | 56 | ; set a = -0.5 and b = -0.5 57 | mov bx, 8000h 58 | mov cx, bx 59 | 60 | ; set up offset of line end 61 | mov WORD PTR [endline], 240 62 | 63 | pixel_loop: 64 | 65 | ; Z -> Z^2 + C 66 | ; 67 | ; 68 | 69 | inc di 70 | cmp di, [endline] 71 | je end_of_line 72 | 73 | ; update a 74 | add bx, 0111h 75 | 76 | next_line: 77 | 78 | cmp di, 64000 79 | jne pixel_loop 80 | 81 | ; wait for keypress 82 | xor ah, ah 83 | int 16h 84 | 85 | ; change back to text mode 86 | mov ax, 3 87 | int 10h 88 | 89 | ; terminate program 90 | mov ah, 4ch 91 | int 21h 92 | 93 | end_of_line: 94 | ; move to start of next line 95 | add di, 80 96 | 97 | ; update a and b 98 | mov bx, 8000h 99 | add cx, 0148h 100 | 101 | ; update endline 102 | add WORD PTR [endline], 320 103 | 104 | jmp next_line 105 | 106 | END 107 | -------------------------------------------------------------------------------- /MANDEL2.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | 5 | .DATA 6 | 7 | iter DB 0 8 | endline DW 0 9 | 10 | .CODE 11 | 12 | ; set up data segment 13 | mov ax, @data 14 | mov ds, ax 15 | 16 | ; change to VGA mode 13h (320x200 256 colours) 17 | mov ax, 13h 18 | int 10h 19 | 20 | ; Mandelbrot set iterates z -> z^2 + c in the 21 | ; complex numbers, starting with z = 0, and 22 | ; where c = a + bi is a complex number with 23 | ; -2 <= a <= 2 and -2 <= b <= 2 24 | ; (this region is a square in the complex plane) 25 | 26 | ; We draw this square on the screen, setting 27 | ; the pixel colour to the number of iterations 28 | ; it takes for the iteration to leave the circle 29 | ; of radius 2 in the complex plane. We set the 30 | ; pixel to black if it does not leave the circle 31 | ; after a certain number of iterations 32 | 33 | ; We will divide all values by 4 and use the 34 | ; iteration Z -> 4Z^2 + C which means we'll need 35 | ; values from -0.5 to 0.5 instead of -2.0 to 2.0 36 | ; We use 16 bit values 37 | 38 | ; For most of the calculation we will even divide 39 | ; the values by an additional factor of 2 to make 40 | ; it easier to check for overflows 41 | 42 | ; DX:AX = accum, result of multiplication 43 | ; DI = offset in VRAM, BX = a, CX = b, SI = x, BP = y 44 | ; where Z = x + yi and C = a + bi 45 | ; DS:[iter] = iterations (counting down to zero) 46 | ; DS:[endline] = offset of end of current line 47 | 48 | ; Pixel aspect ratio is 1:1.2, so we will use 240x200 49 | ; pixel region 50 | ; Moving in x-direction will add 1/240 = 0.0111h 51 | ; Moving in y-direction will add 1/200 = 0.0148h 52 | 53 | ; set up VRAM segment 54 | mov ax, 0a000h 55 | mov es, ax 56 | 57 | ; offset of first pixel 58 | xor di, di 59 | 60 | ; set a = -0.5/2+eps and b = -0.5/2+eps 61 | mov bx, 0c00ch 62 | mov cx, 0c044h 63 | 64 | ; set up offset of line end 65 | mov WORD PTR [endline], 240 66 | 67 | pixel_loop: 68 | 69 | ; Z = 0 70 | xor si, si 71 | xor bp, bp 72 | 73 | mov [iter], 32 74 | 75 | iter_loop: 76 | ; Z = Z + C (values are divided by 2) 77 | add si, bx 78 | add bp, cx 79 | 80 | ; multiply by 2 to get actual z value 81 | shl si, 1 82 | jo outside_circle 83 | shl bp, 1 84 | jo outside_circle 85 | 86 | ; 4x^2 87 | mov ax, si 88 | imul ax 89 | shl ax, 1 90 | rcl dx, 1 91 | shl ax, 1 92 | rcl dx, 1 93 | 94 | ; 8xy/2 95 | mov ax, si 96 | mov si, dx 97 | imul bp 98 | shl ax, 1 99 | rcl dx, 1 100 | shl ax, 1 101 | rcl dx, 1 102 | 103 | ; 4y^2 104 | mov ax, bp 105 | mov bp, dx 106 | imul ax 107 | shl ax, 1 108 | rcl dx, 1 109 | shl ax, 1 110 | rcl dx, 1 111 | 112 | ; 4x^2 + 4y^2 113 | add si, dx 114 | jc outside_circle 115 | 116 | ; 4Z^2/2 117 | sub si, dx 118 | shr si, 1 119 | shr dx, 1 120 | sub si, dx 121 | 122 | dec BYTE PTR [iter] 123 | jnz iter_loop 124 | jmp done_iter 125 | 126 | outside_circle: 127 | ; draw pixel 128 | mov al, [iter] 129 | stosb 130 | dec di 131 | 132 | done_iter: 133 | inc di 134 | cmp di, [endline] 135 | je end_of_line 136 | 137 | ; update a 138 | add bx, 0089h 139 | 140 | next_line: 141 | 142 | cmp di, 64000 143 | jne pixel_loop 144 | 145 | ; wait for keypress 146 | xor ah, ah 147 | int 16h 148 | 149 | ; change back to text mode 150 | mov ax, 3 151 | int 10h 152 | 153 | ; terminate program 154 | mov ah, 4ch 155 | int 21h 156 | 157 | end_of_line: 158 | ; move to start of next line 159 | add di, 80 160 | 161 | ; update a and b 162 | mov bx, 0c00ch 163 | add cx, 00a4h 164 | 165 | ; update endline 166 | add WORD PTR [endline], 320 167 | 168 | jmp next_line 169 | 170 | END 171 | -------------------------------------------------------------------------------- /MCGA.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL small 3 | 4 | .CODE 5 | 6 | PUBLIC _mcga_start_address 7 | _mcga_start_address PROC 8 | ARG addr:WORD 9 | push bp 10 | mov bp, sp 11 | 12 | mov ax, addr 13 | mov cl, al 14 | mov al, 0ch 15 | 16 | mov dx, 03d4h 17 | 18 | out dx, ax 19 | 20 | inc al 21 | mov ah, cl 22 | out dx, ax 23 | 24 | pop bp 25 | ret 26 | _mcga_start_address ENDP 27 | 28 | PUBLIC _mcga_scroll 29 | _mcga_scroll PROC 30 | ARG buff:DWORD 31 | push bp 32 | mov bp, sp 33 | push di 34 | push si 35 | push ds 36 | 37 | lds si, buff 38 | add si, 320 39 | 40 | mov ax, 0a000h 41 | mov es, ax 42 | mov di, 320 43 | 44 | xor ax, ax ; start address 45 | 46 | mov bx, 320 47 | scroll_loop: 48 | 49 | push si 50 | push di 51 | push ax 52 | 53 | mov cx, ax 54 | 55 | mov dx, 03dah 56 | 57 | wait_no_retrace: 58 | in al, dx 59 | test al, 8 60 | jnz wait_no_retrace 61 | 62 | push cx 63 | call _mcga_start_address 64 | add sp, 2 65 | 66 | mov dx, 03dah 67 | 68 | wait_retrace: 69 | in al, dx 70 | test al, 8 71 | jz wait_retrace 72 | 73 | mov cx, 50 74 | scroll_loop1: 75 | movsw 76 | add si, 958 77 | add di, 318 78 | loop scroll_loop1 79 | 80 | mov ax, ds 81 | add ax, 3000 82 | mov ds, ax 83 | 84 | mov ax, es 85 | add ax, 1000 86 | mov es, ax 87 | 88 | sub si, 48000 89 | sub di, 16000 90 | 91 | mov cx, 50 92 | scroll_loop2: 93 | movsw 94 | add si, 958 95 | add di, 318 96 | loop scroll_loop2 97 | 98 | mov ax, ds 99 | add ax, 3000 100 | mov ds, ax 101 | 102 | mov ax, es 103 | add ax, 1000 104 | mov es, ax 105 | 106 | sub si, 48000 107 | sub di, 16000 108 | 109 | mov cx, 50 110 | scroll_loop3: 111 | movsw 112 | add si, 958 113 | add di, 318 114 | loop scroll_loop3 115 | 116 | mov ax, ds 117 | add ax, 3000 118 | mov ds, ax 119 | 120 | mov ax, es 121 | add ax, 1000 122 | mov es, ax 123 | 124 | sub si, 48000 125 | sub di, 16000 126 | 127 | mov cx, 50 128 | scroll_loop4: 129 | movsw 130 | add si, 958 131 | add di, 318 132 | loop scroll_loop4 133 | 134 | pop ax 135 | pop di 136 | pop si 137 | 138 | inc ax 139 | 140 | inc si 141 | inc si 142 | inc di 143 | inc di 144 | 145 | mov cx, ds 146 | sub cx, 9000 147 | mov ds, cx 148 | 149 | mov cx, es 150 | sub cx, 3000 151 | mov es, cx 152 | 153 | dec bx 154 | jz scroll_done 155 | jmp scroll_loop 156 | 157 | scroll_done: 158 | 159 | pop ds 160 | pop si 161 | pop di 162 | pop bp 163 | ret 164 | _mcga_scroll ENDP 165 | 166 | PUBLIC _mcga_invert 167 | _mcga_invert PROC 168 | ARG buff:DWORD 169 | 170 | push bp 171 | mov bp, sp 172 | push di 173 | push si 174 | push ds 175 | 176 | lds si, buff 177 | 178 | mov ax, ds 179 | add ax, 9000 180 | mov es, ax 181 | 182 | mov di, 47040 183 | 184 | mov dx, 50 185 | invert_loop1: 186 | 187 | mov cx, 480 188 | swap_loop1: 189 | 190 | mov ax, [si] 191 | xchg ax, es:[di] 192 | mov WORD PTR [si], ax 193 | 194 | inc si 195 | inc si 196 | inc di 197 | inc di 198 | 199 | loop swap_loop1 200 | 201 | sub di, 960*2 202 | 203 | dec dx 204 | jnz invert_loop1 205 | 206 | mov ax, ds 207 | add ax, 3000 208 | mov ds, ax 209 | 210 | sub si, 48000 211 | 212 | mov ax, es 213 | sub ax, 3000 214 | mov es, ax 215 | 216 | mov di, 47040 217 | 218 | mov dx, 50 219 | invert_loop2: 220 | 221 | mov cx, 480 222 | swap_loop2: 223 | 224 | mov ax, [si] 225 | xchg ax, es:[di] 226 | mov WORD PTR [si], ax 227 | 228 | inc si 229 | inc si 230 | inc di 231 | inc di 232 | 233 | loop swap_loop2 234 | 235 | sub di, 960*2 236 | 237 | dec dx 238 | jnz invert_loop2 239 | 240 | pop ds 241 | pop si 242 | pop di 243 | pop bp 244 | ret 245 | _mcga_invert ENDP 246 | 247 | PUBLIC _mcga_wide_load 248 | _mcga_wide_load PROC 249 | ARG buff:DWORD, disp:WORD 250 | 251 | push bp 252 | mov bp, sp 253 | push di 254 | push si 255 | push ds 256 | 257 | mov ax, 0a000h 258 | mov es, ax 259 | 260 | xor di, di 261 | 262 | lds si, buff 263 | 264 | mov bx, 50 265 | wide_loop1: 266 | 267 | mov cx, disp 268 | rep movsb 269 | 270 | sub si, disp 271 | add si, 960 272 | 273 | dec bx 274 | jnz wide_loop1 275 | 276 | mov ax, ds 277 | add ax, 3000 278 | mov ds, ax 279 | 280 | xor si, si 281 | 282 | mov bx, 50 283 | wide_loop2: 284 | 285 | mov cx, disp 286 | rep movsb 287 | 288 | sub si, disp 289 | add si, 960 290 | 291 | dec bx 292 | jnz wide_loop2 293 | 294 | mov ax, ds 295 | add ax, 3000 296 | mov ds, ax 297 | 298 | xor si, si 299 | 300 | mov bx, 50 301 | wide_loop3: 302 | 303 | mov cx, disp 304 | rep movsb 305 | 306 | sub si, disp 307 | add si, 960 308 | 309 | dec bx 310 | jnz wide_loop3 311 | 312 | mov ax, ds 313 | add ax, 3000 314 | mov ds, ax 315 | 316 | xor si, si 317 | 318 | mov bx, 50 319 | wide_loop4: 320 | 321 | mov cx, disp 322 | rep movsb 323 | 324 | sub si, disp 325 | add si, 960 326 | 327 | dec bx 328 | jnz wide_loop4 329 | 330 | pop ds 331 | pop si 332 | pop di 333 | pop bp 334 | ret 335 | _mcga_wide_load ENDP 336 | 337 | public _mcga_disp 338 | _mcga_disp PROC 339 | ARG disp:WORD 340 | 341 | push bp 342 | mov bp, sp 343 | 344 | mov dx, 03d4h 345 | mov al, 010h 346 | out dx, al 347 | mov dx, 03d5h 348 | in al, dx 349 | 350 | and al, 127 351 | mov dx, 03d4h 352 | xchg al, ah 353 | mov al, 010h 354 | out dx, ax 355 | 356 | mov ax, disp 357 | xchg ah, al 358 | mov al, 1 359 | out dx, ax 360 | 361 | pop bp 362 | ret 363 | _mcga_disp ENDP 364 | 365 | END 366 | -------------------------------------------------------------------------------- /MCGA1.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL small 3 | 4 | .CODE 5 | 6 | PUBLIC _mcga_start_address 7 | _mcga_start_address PROC 8 | ARG addr:WORD 9 | push bp 10 | mov bp, sp 11 | 12 | mov ax, addr 13 | mov cl, al 14 | mov al, 0ch 15 | 16 | mov dx, 03d4h 17 | 18 | out dx, ax 19 | 20 | inc al 21 | mov ah, cl 22 | out dx, ax 23 | 24 | pop bp 25 | ret 26 | _mcga_start_address ENDP 27 | 28 | PUBLIC _mcga_scroll 29 | _mcga_scroll PROC 30 | ARG buff:DWORD 31 | push bp 32 | mov bp, sp 33 | push di 34 | push si 35 | push ds 36 | 37 | lds si, buff 38 | add si, 320 39 | 40 | mov ax, 0a000h 41 | mov es, ax 42 | mov di, 320 43 | 44 | xor ax, ax ; start address 45 | 46 | mov bx, 320 47 | scroll_loop: 48 | 49 | push si 50 | push di 51 | push ax 52 | 53 | mov cx, ax 54 | 55 | mov dx, 03dah 56 | 57 | wait_no_retrace: 58 | in al, dx 59 | test al, 8 60 | jnz wait_no_retrace 61 | 62 | push cx 63 | call _mcga_start_address 64 | add sp, 2 65 | 66 | mov dx, 03dah 67 | 68 | wait_retrace: 69 | in al, dx 70 | test al, 8 71 | jz wait_retrace 72 | 73 | mov cx, 50 74 | scroll_loop1: 75 | movsw 76 | add si, 958 77 | add di, 318 78 | loop scroll_loop1 79 | 80 | mov ax, ds 81 | add ax, 3000 82 | mov ds, ax 83 | 84 | mov ax, es 85 | add ax, 1000 86 | mov es, ax 87 | 88 | sub si, 48000 89 | sub di, 16000 90 | 91 | mov cx, 50 92 | scroll_loop2: 93 | movsw 94 | add si, 958 95 | add di, 318 96 | loop scroll_loop2 97 | 98 | mov ax, ds 99 | add ax, 3000 100 | mov ds, ax 101 | 102 | mov ax, es 103 | add ax, 1000 104 | mov es, ax 105 | 106 | sub si, 48000 107 | sub di, 16000 108 | 109 | mov cx, 50 110 | scroll_loop3: 111 | movsw 112 | add si, 958 113 | add di, 318 114 | loop scroll_loop3 115 | 116 | mov ax, ds 117 | add ax, 3000 118 | mov ds, ax 119 | 120 | mov ax, es 121 | add ax, 1000 122 | mov es, ax 123 | 124 | sub si, 48000 125 | sub di, 16000 126 | 127 | mov cx, 50 128 | scroll_loop4: 129 | movsw 130 | add si, 958 131 | add di, 318 132 | loop scroll_loop4 133 | 134 | pop ax 135 | pop di 136 | pop si 137 | 138 | inc ax 139 | 140 | inc si 141 | inc si 142 | inc di 143 | inc di 144 | 145 | mov cx, ds 146 | sub cx, 9000 147 | mov ds, cx 148 | 149 | mov cx, es 150 | sub cx, 3000 151 | mov es, cx 152 | 153 | dec bx 154 | jz scroll_done 155 | jmp scroll_loop 156 | 157 | scroll_done: 158 | 159 | pop ds 160 | pop si 161 | pop di 162 | pop bp 163 | ret 164 | _mcga_scroll ENDP 165 | 166 | PUBLIC _mcga_invert 167 | _mcga_invert PROC 168 | ARG buff:DWORD 169 | 170 | push bp 171 | mov bp, sp 172 | push di 173 | push si 174 | push ds 175 | 176 | lds si, buff 177 | 178 | mov ax, ds 179 | add ax, 9000 180 | mov es, ax 181 | 182 | mov di, 47040 183 | 184 | mov dx, 50 185 | invert_loop1: 186 | 187 | mov cx, 480 188 | swap_loop1: 189 | 190 | mov ax, [si] 191 | xchg ax, es:[di] 192 | mov WORD PTR [si], ax 193 | 194 | inc si 195 | inc si 196 | inc di 197 | inc di 198 | 199 | loop swap_loop1 200 | 201 | sub di, 960*2 202 | 203 | dec dx 204 | jnz invert_loop1 205 | 206 | mov ax, ds 207 | add ax, 3000 208 | mov ds, ax 209 | 210 | sub si, 48000 211 | 212 | mov ax, es 213 | sub ax, 3000 214 | mov es, ax 215 | 216 | mov di, 47040 217 | 218 | mov dx, 50 219 | invert_loop2: 220 | 221 | mov cx, 480 222 | swap_loop2: 223 | 224 | mov ax, [si] 225 | xchg ax, es:[di] 226 | mov WORD PTR [si], ax 227 | 228 | inc si 229 | inc si 230 | inc di 231 | inc di 232 | 233 | loop swap_loop2 234 | 235 | sub di, 960*2 236 | 237 | dec dx 238 | jnz invert_loop2 239 | 240 | pop ds 241 | pop si 242 | pop di 243 | pop bp 244 | ret 245 | _mcga_invert ENDP 246 | 247 | PUBLIC _mcga_wide_load 248 | _mcga_wide_load PROC 249 | ARG buff:DWORD 250 | 251 | push bp 252 | mov bp, sp 253 | push di 254 | push si 255 | push ds 256 | 257 | mov ax, 0a000h 258 | mov es, ax 259 | 260 | xor di, di 261 | 262 | lds si, buff 263 | 264 | mov bx, 50 265 | wide_loop1: 266 | 267 | mov cx, 160 268 | rep movsw 269 | 270 | add si, 640 271 | 272 | dec bx 273 | jnz wide_loop1 274 | 275 | mov ax, ds 276 | add ax, 3000 277 | mov ds, ax 278 | 279 | xor si, si 280 | 281 | mov bx, 50 282 | wide_loop2: 283 | 284 | mov cx, 160 285 | rep movsw 286 | 287 | add si, 640 288 | 289 | dec bx 290 | jnz wide_loop2 291 | 292 | mov ax, ds 293 | add ax, 3000 294 | mov ds, ax 295 | 296 | xor si, si 297 | 298 | mov bx, 50 299 | wide_loop3: 300 | 301 | mov cx, 160 302 | rep movsw 303 | 304 | add si, 640 305 | 306 | dec bx 307 | jnz wide_loop3 308 | 309 | mov ax, ds 310 | add ax, 3000 311 | mov ds, ax 312 | 313 | xor si, si 314 | 315 | mov bx, 50 316 | wide_loop4: 317 | 318 | mov cx, 160 319 | rep movsw 320 | 321 | add si, 640 322 | 323 | dec bx 324 | jnz wide_loop4 325 | 326 | pop ds 327 | pop si 328 | pop di 329 | pop bp 330 | ret 331 | _mcga_wide_load ENDP 332 | 333 | END 334 | -------------------------------------------------------------------------------- /MYLINE.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | PUBLIC _cga_line 7 | _cga_line PROC 8 | ARG x0:WORD, y0:WORD, x1:WORD, y1:WORD, colour:BYTE 9 | ; ax = accum, dx = 2dx, si = 2dy, bp = D, cx = iters 10 | ; di = offset, bl = mask, bh = colour 11 | 12 | push bp 13 | mov bp, sp 14 | push si 15 | push di 16 | 17 | ; set up CGA segment 18 | mov ax, 0b800h 19 | mov es, ax 20 | 21 | ; get x0 and x1 22 | mov dx, x1 23 | mov bx, x0 24 | 25 | ; compute dy 26 | mov ax, y0 27 | mov si, y1 28 | sub si, ax 29 | 30 | ; ensure y1 >= y0 31 | jge line_dy_nonneg 32 | xchg dx, bx 33 | add ax, si 34 | neg si 35 | line_dy_nonneg: 36 | 37 | ; offset += 4*8192 if y0 odd 38 | xor di, di 39 | shr ax, 1 40 | rcr di, 1 41 | 42 | ; add 4*80*(y0/2) to offset 43 | xchg ah, al 44 | add di, ax 45 | shr ax, 1 46 | shr ax, 1 47 | add di, ax 48 | 49 | ; compute dx 50 | sub dx, bx 51 | 52 | jge line_right 53 | jmp line_left 54 | 55 | line_right: 56 | 57 | ; compute x0 mod 4 and x0 / 4 and divide di by 4 58 | mov cx, bx 59 | and cl, 3 60 | add di, bx 61 | shr di, 1 62 | shr di, 1 63 | 64 | ; compute colour and mask 65 | mov bh, colour 66 | mov bl, 03fh 67 | shl cl, 1 68 | ror bl, cl 69 | inc cl 70 | inc cl 71 | ror bh, cl 72 | 73 | cmp dx, si 74 | jae line_hr 75 | 76 | line_vr: 77 | 78 | ; compute iterations 79 | mov cx, si 80 | inc cx 81 | 82 | ; compute initial D 83 | mov bp, si 84 | neg bp 85 | 86 | ; compute 2dx and 2dy 87 | shl si, 1 88 | shl dx, 1 89 | 90 | line_vr_loop: 91 | mov al, es:[di] ; get pixel 92 | and al, bl ; and with mask 93 | or al, bh ; or with colour 94 | stosb ; write pixel 95 | 96 | add bp, dx ; D += 2dx 97 | jle line_vr_skipx ; if D > 0 98 | 99 | ror bh, 1 100 | ror bh, 1 101 | ror bl, 1 102 | ror bl, 1 103 | cmc 104 | adc di, 0 105 | 106 | sub bp, si ; D -= 2dy 107 | 108 | line_vr_skipx: 109 | 110 | sub di, 8113 ; increment y 111 | sbb ax, ax 112 | and ax, 16304 113 | add di, ax 114 | 115 | loop line_vr_loop 116 | 117 | pop di 118 | pop si 119 | pop bp 120 | ret 121 | 122 | line_hr: 123 | 124 | ; compute iterations 125 | mov cx, dx 126 | inc cx 127 | 128 | ; compute initial D 129 | mov bp, dx 130 | neg bp 131 | 132 | ; compute 2dx and 2dy 133 | shl si, 1 134 | shl dx, 1 135 | 136 | line_hr_loop: 137 | mov al, es:[di] ; get pixel 138 | and al, bl ; and with mask 139 | or al, bh ; or with colour 140 | stosb ; write pixel 141 | 142 | add bp, si ; D += 2dy 143 | jle line_hr_skipy ; if D > 0 144 | 145 | sub di, 8112 ; increment y 146 | sbb ax, ax 147 | and ax, 16304 148 | add di, ax 149 | 150 | sub bp, dx ; D -= 2dx 151 | 152 | line_hr_skipy: 153 | ror bh, 1 154 | ror bh, 1 155 | ror bl, 1 156 | ror bl, 1 157 | sbb di, 0 158 | 159 | loop line_hr_loop 160 | 161 | pop di 162 | pop si 163 | pop bp 164 | ret 165 | 166 | line_left: 167 | neg dx 168 | 169 | std 170 | 171 | ; compute x0 mod 4 and x0 / 4 and divide di by 4 172 | mov cx, bx 173 | and cl, 3 174 | add di, bx 175 | shr di, 1 176 | shr di, 1 177 | 178 | ; compute colour and mask 179 | mov bh, colour 180 | mov bl, 03fh 181 | shl cl, 1 182 | ror bl, cl 183 | inc cl 184 | inc cl 185 | ror bh, cl 186 | 187 | cmp dx, si 188 | jae line_hl 189 | 190 | line_vl: 191 | 192 | ; compute iterations 193 | mov cx, si 194 | inc cx 195 | 196 | ; compute initial D 197 | mov bp, si 198 | neg bp 199 | 200 | ; compute 2dx and 2dy 201 | shl si, 1 202 | shl dx, 1 203 | 204 | line_vl_loop: 205 | mov al, es:[di] ; get pixel 206 | and al, bl ; and with mask 207 | or al, bh ; or with colour 208 | stosb ; write pixel 209 | 210 | add bp, dx ; D += 2dx 211 | jle line_vl_skipx ; if D > 0 212 | 213 | rol bh, 1 214 | rol bh, 1 215 | rol bl, 1 216 | rol bl, 1 217 | cmc 218 | sbb di, 0 219 | 220 | sub bp, si ; D -= 2dy 221 | 222 | line_vl_skipx: 223 | 224 | sub di, 8111 ; increment y 225 | sbb ax, ax 226 | and ax, 16304 227 | add di, ax 228 | 229 | loop line_vl_loop 230 | 231 | cld 232 | 233 | pop di 234 | pop si 235 | pop bp 236 | ret 237 | 238 | line_hl: 239 | 240 | ; compute iterations 241 | mov cx, dx 242 | inc cx 243 | 244 | ; compute initial D 245 | mov bp, dx 246 | neg bp 247 | 248 | ; compute 2dx and 2dy 249 | shl si, 1 250 | shl dx, 1 251 | 252 | line_hl_loop: 253 | mov al, es:[di] ; get pixel 254 | and al, bl ; and with mask 255 | or al, bh ; or with colour 256 | stosb ; write pixel 257 | 258 | add bp, si ; D += 2dy 259 | jle line_hl_skipy ; if D > 0 260 | 261 | sub di, 8112 ; increment y 262 | sbb ax, ax 263 | and ax, 16304 264 | add di, ax 265 | 266 | sub bp, dx ; D -= 2dx 267 | 268 | line_hl_skipy: 269 | rol bh, 1 270 | rol bh, 1 271 | rol bl, 1 272 | rol bl, 1 273 | adc di, 0 274 | 275 | loop line_hl_loop 276 | 277 | cld 278 | 279 | pop di 280 | pop si 281 | pop bp 282 | ret 283 | _cga_line ENDP 284 | 285 | END 286 | -------------------------------------------------------------------------------- /POINT1.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .DATA 5 | .CODE 6 | 7 | ; set up CGA segment 8 | mov ax, 0b800h 9 | mov es, ax 10 | 11 | ; video mode 4 12 | mov ax, 4 13 | int 10h 14 | 15 | ; set palette = 0 16 | mov ah, 0bh 17 | mov bx, 0100h 18 | int 10h 19 | 20 | ; set offset 21 | xor di, di 22 | 23 | ; draw pixels 24 | mov al, 081h ; 10000001 25 | stosb 26 | 27 | ; wait for keypress 28 | xor ah, ah 29 | int 16h 30 | 31 | ; restore video mode 32 | mov ax, 3 33 | int 10h 34 | 35 | mov ah, 4ch ;DOS terminate program function 36 | int 21h ;terminate the program 37 | END 38 | -------------------------------------------------------------------------------- /POINT2.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .DATA 5 | .CODE 6 | 7 | _cga_point PROC 8 | ARG x:WORD, y:WORD, colour:BYTE 9 | push bp 10 | mov bp, sp 11 | push di 12 | 13 | ; set up CGA segment 14 | mov ax, 0b800h 15 | mov es, ax 16 | 17 | ; offset += 4*8192 if y odd 18 | xor di, di 19 | mov ax, y 20 | shr ax, 1 21 | rcr di, 1 22 | 23 | ; add 4*80*(y/2) to offset 24 | xchg ah, al 25 | add di, ax 26 | shr ax, 1 27 | shr ax, 1 28 | add di, ax 29 | 30 | ; compute x mod 4 and divide di by 4 31 | mov cx, x 32 | add di, cx 33 | and cl, 3 34 | shr di, 1 35 | shr di, 1 36 | 37 | ; compute colour and mask 38 | mov ah, colour 39 | mov al, 03fh 40 | shl cl, 1 41 | ror al, cl 42 | inc cl 43 | inc cl 44 | ror ah, cl 45 | 46 | ; draw pixels 47 | and al, es:[di] 48 | or al, ah 49 | stosb 50 | 51 | pop di 52 | pop bp 53 | ret 54 | _cga_point ENDP 55 | 56 | start: 57 | 58 | mov ax, 4 59 | int 10h 60 | 61 | mov si, 199 62 | 63 | point_loop: 64 | mov al, 1 65 | push ax 66 | push si 67 | push si 68 | call _cga_point 69 | add sp, 6 70 | 71 | dec si 72 | jns point_loop 73 | 74 | ; wait for keypress 75 | xor ah, ah 76 | int 16h 77 | 78 | ; restore video mode 79 | xor ah, ah 80 | mov al, 3 81 | int 10h 82 | 83 | mov ah,4ch ;DOS terminate program function 84 | int 21h ;terminate the program 85 | END start 86 | -------------------------------------------------------------------------------- /REFRESH.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL tiny 3 | .STACK 100h 4 | 5 | .DATA 6 | 7 | handler_offset DW 0 8 | handler_segment DW 0 9 | imr_save DB 0 10 | 11 | .CODE 12 | 13 | _refresh PROC 14 | rept 256 15 | nop 16 | endm 17 | ret 18 | _refresh ENDP 19 | 20 | _wait_floppy_motor PROC 21 | push ax 22 | push ds 23 | 24 | mov ax, 040h ; BIOS data area 25 | mov ds, ax 26 | 27 | check_motor_status: 28 | mov al, ds:[03fh] 29 | test al, 0fh ; test if motor is running 30 | jnz check_motor_status 31 | 32 | pop ds 33 | pop ax 34 | ret 35 | _wait_floppy_motor ENDP 36 | 37 | start: 38 | call _wait_floppy_motor 39 | 40 | mov ax, 4 ; CGA mode 4 41 | int 10h 42 | 43 | cli ; clear interrupts 44 | 45 | xor ax, ax ; set segment for interrupt vector table 46 | mov ds, ax 47 | 48 | mov bx, WORD PTR ds:[8*4] ; get IRQ0 handler offset 49 | mov dx, WORD PTR ds:[8*4+2] ; get IRQ0 handler segment 50 | 51 | mov WORD PTR ds:[8*4], offset irq0_handler ; set offset of IRQ0 handler 52 | mov WORD PTR ds:[8*4+2], cs ; set segment of IRQ0 handler 53 | 54 | mov ax, cs ; restore DS 55 | mov ds, ax 56 | 57 | mov WORD PTR handler_offset, bx ; save handler offset 58 | mov WORD PTR handler_segment, dx ; save handler segment 59 | 60 | mov dx, 03dah ; CGA status register 61 | 62 | wait_vertical_sync: 63 | in al, dx 64 | test al, 8 65 | jz wait_vertical_sync 66 | 67 | wait_display_enable: 68 | in al, dx 69 | test al, 1 70 | jnz wait_display_enable 71 | 72 | nop 73 | nop 74 | nop 75 | nop 76 | nop 77 | nop 78 | nop 79 | nop 80 | nop 81 | nop 82 | 83 | mov al, 034h ; PIT channel 0, lo/hi byte, mode 2, binary 84 | out 043h, al ; PIT mode/command register 85 | 86 | mov al, 200 ; low byte = 200 87 | out 040h, al ; channel 0 data port 88 | mov al, 77 ; hi byte = 77 (77*256 + 200 = 19912) 89 | out 040h, al 90 | 91 | ; disable individual interrupts 92 | in al, 21h ; get IMR 93 | mov BYTE PTR [imr_save], al 94 | or al, 0feh ; disable everything except IRQ0 95 | out 21h, al 96 | 97 | ; disable DRAM refresh 98 | mov al, 072h ; PIT channel 1, lo/hi byte, mode 1, binary 99 | out 43h, al 100 | mov al, 01 ; low byte = 1 101 | out 41h, al ; channel 1 data port 102 | xor al, al ; high byte = 0 103 | out 41h, al 104 | 105 | sti 106 | 107 | frame_loop: 108 | hlt ; halt the CPU and wait for interrupt 109 | 110 | mov al, 0ah ; select IRR 111 | out 20h, al 112 | in al, 20h ; get IRR 113 | test al, 02h ; check if IRQ1 114 | jz no_key 115 | jmp key_pressed 116 | no_key: 117 | 118 | call _refresh 119 | 120 | jmp frame_loop 121 | 122 | key_pressed: 123 | in al, 60h ; read keyboard buffer 124 | mov dl, al 125 | 126 | in al, 61h ; get system crtl port 127 | mov ah, al 128 | or al, 80h ; reset keyboard 129 | out 61h, al 130 | mov al, ah ; rewrite original byte 131 | out 61h, al 132 | 133 | shl dl, 1 ; ignore key release 134 | jnc no_release 135 | jmp frame_loop 136 | no_release: 137 | shr dl, 1 138 | 139 | cmp dl, 16 ; q = quit 140 | je exit 141 | jmp frame_loop 142 | exit: 143 | 144 | cli 145 | 146 | ; enable individual interrupts 147 | mov al, BYTE PTR [imr_save] 148 | out 21h, al 149 | 150 | mov bx, handler_offset ; retrieve old handler offset 151 | mov dx, handler_segment ; retrieve old handler segment 152 | 153 | xor ax, ax ; set up offset for interrupt vector table 154 | mov ds, ax 155 | 156 | mov WORD PTR ds:[8*4], bx ; restore old handler offset 157 | mov WORD PTR ds:[8*4+2], dx ; restore old handler segment 158 | 159 | mov al, 0ffh ; low byte = FF 160 | out 040h, al ; channel 0 data port 161 | mov al, 0ffh ; hi byte = FF 162 | out 040h, al 163 | 164 | ; enable DRAM refresh 165 | mov al, 074h ; PIT channel 1, lo/hi byte, mode 2, binary 166 | out 43h, al 167 | mov al, 18 ; low byte = 18 168 | out 41h, al ; channel 1 data port 169 | xor al, al ; high byte = 0 170 | out 41h, al 171 | 172 | sti ; enable interrupts 173 | 174 | mov bx, 1000h ; blank memory, starting at second bank of 64kb 175 | mov es, bx 176 | xor di, di 177 | xor ax, ax 178 | mov dx, 9 179 | 180 | clear_mem_loop: 181 | mov cx, 8000h 182 | rep stosw 183 | add bx, 1000h 184 | mov es, bx 185 | dec dx 186 | jnz clear_mem_loop 187 | 188 | mov ax, 3 ; back to text mode 189 | int 10h 190 | 191 | mov ah, 04ch ; return to DOS 192 | int 21h 193 | 194 | irq0_handler: 195 | push ax 196 | push dx 197 | 198 | mov dx, 03d9h ; background colour 199 | 200 | mov al, 12 ; light red 201 | out dx, al 202 | 203 | xor al, al ; black 204 | out dx, al 205 | 206 | pop dx 207 | mov al, 020h ; EOI (End Of Interrupt) 208 | out 020h, al ; master PIC command register 209 | pop ax 210 | 211 | iret 212 | 213 | END start 214 | -------------------------------------------------------------------------------- /SLOWREFR.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL tiny 3 | .STACK 100h 4 | .CODE 5 | 6 | start: 7 | cli 8 | 9 | mov al, 074h ; PIT channel 1, lo/hi byte, mode 2, binary 10 | out 43h, al 11 | mov al, 72 ; low byte = 72 12 | out 41h, al ; channel 1 data port 13 | xor al, al ; high byte = 0 14 | out 41h, al 15 | 16 | sti 17 | 18 | mov ah, 04ch 19 | int 21h 20 | 21 | END start -------------------------------------------------------------------------------- /TANDYDIT.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .DATA 5 | .CODE 6 | 7 | ; set up TGA segment 8 | mov ax, 0b800h 9 | mov es, ax 10 | 11 | ; video mode 9 = 320x200 16 colour mode 12 | mov ax, 9 13 | int 10h 14 | 15 | ; set offset 16 | xor di, di 17 | 18 | xor bx, bx 19 | mov dx, 0f00fh 20 | 21 | page_loop: 22 | 23 | mov si, 12 24 | block_loop: 25 | 26 | line_loop: 27 | 28 | mov ax, dx 29 | and ax, bx 30 | 31 | ; draw pixels 32 | mov cx, 10 33 | add al, ah 34 | rep stosb 35 | 36 | add bl, 17 37 | jnc line_loop 38 | 39 | xor bl, bl 40 | 41 | not dx 42 | add di, 8032 43 | 44 | cmp di, 32768 45 | jb skip_dec 46 | sub di, 32768-160 47 | skip_dec: 48 | 49 | dec si 50 | jnz block_loop 51 | 52 | add bh, 17 53 | jnc page_loop 54 | 55 | ; wait for keypress 56 | xor ah, ah 57 | int 16h 58 | 59 | ; restore video mode 60 | mov ax, 3 61 | int 10h 62 | 63 | mov ah, 4ch ;DOS terminate program function 64 | int 21h ;terminate the program 65 | END 66 | -------------------------------------------------------------------------------- /TANDYDOT.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .DATA 5 | .CODE 6 | 7 | _tga_point PROC 8 | ARG x:WORD, y:WORD, colour:BYTE 9 | push bp 10 | mov bp, sp 11 | push di 12 | 13 | ; set up TGA segment 14 | mov ax, 0b800h 15 | mov es, ax 16 | 17 | ; offset += 2*8192*bank 18 | mov ax, y 19 | ror ax, 1 20 | ror ax, 1 21 | mov di, ax 22 | xor ah, ah 23 | sub di, ax 24 | 25 | ; add 2*160*(y/4) to offset 26 | xchg ah, al 27 | add di, ax 28 | shr ax, 1 29 | shr ax, 1 30 | add di, ax 31 | 32 | ; compute x mod 2 and divide di by 2 33 | add di, x 34 | shr di, 1 35 | 36 | ; compute colour and mask 37 | sbb bl, bl 38 | xor bl, 0fh 39 | 40 | mov bh, colour 41 | mov al, bh 42 | shl al, 1 43 | shl al, 1 44 | shl al, 1 45 | shl al, 1 46 | add bh, al 47 | 48 | ; draw pixels 49 | mov ax, bx 50 | and al, es:[di] 51 | not bl 52 | and ah, bl 53 | or al, ah 54 | stosb 55 | 56 | pop di 57 | pop bp 58 | ret 59 | _tga_point ENDP 60 | 61 | start: 62 | 63 | ; set TGA video mode 9 = 320x200 16 colours 64 | mov ax, 9 65 | int 10h 66 | 67 | mov dx, 15 68 | colour_loop: 69 | mov si, 199 70 | 71 | point_loop: 72 | push dx 73 | push si 74 | add si, dx 75 | push si 76 | sub si, dx 77 | call _tga_point 78 | add sp, 6 79 | 80 | dec si 81 | jns point_loop 82 | 83 | dec dx 84 | jnz colour_loop 85 | 86 | ; wait for keypress 87 | xor ah, ah 88 | int 16h 89 | 90 | ; restore video mode 91 | xor ah, ah 92 | mov al, 3 93 | int 10h 94 | 95 | mov ah,4ch ;DOS terminate program function 96 | int 21h ;terminate the program 97 | END start 98 | -------------------------------------------------------------------------------- /TANDYLIN.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _tga_line PROC 7 | ARG x0:WORD, y0:WORD, x1:WORD, y1:WORD, colour:BYTE 8 | ; ax = accum, dx = 2dx, si = 2dy, bp = D, cx = iters 9 | ; di = offset, bl = mask, bh = colour 10 | 11 | push bp 12 | mov bp, sp 13 | push si 14 | push di 15 | 16 | ; set up TGA segment 17 | mov ax, 0b800h 18 | mov es, ax 19 | 20 | ; get x0 and x1 21 | mov dx, x1 22 | mov bx, x0 23 | 24 | ; compute dy 25 | mov ax, y0 26 | mov si, y1 27 | sub si, ax 28 | 29 | ; ensure y1 >= y0 30 | jge line_dy_nonneg 31 | xchg dx, bx 32 | add ax, si 33 | neg si 34 | line_dy_nonneg: 35 | 36 | ; offset += 2*8192*bank 37 | ror ax, 1 38 | ror ax, 1 39 | mov di, ax 40 | xor ah, ah 41 | sub di, ax 42 | 43 | ; add 2*160*(y0/4) to offset 44 | xchg ah, al 45 | add di, ax 46 | shr ax, 1 47 | shr ax, 1 48 | add di, ax 49 | 50 | ; compute dx 51 | sub dx, bx 52 | 53 | jge line_right 54 | jmp line_left 55 | 56 | line_right: 57 | 58 | ; compute x0 mod 2 and x0 / 2 and divide di by 2 59 | add di, bx 60 | shr di, 1 61 | 62 | ; compute colour and mask 63 | sbb bl, bl 64 | xor bl, 0fh 65 | mov bh, colour 66 | mov al, bh 67 | shl al, 1 68 | shl al, 1 69 | shl al, 1 70 | shl al, 1 71 | add bh, al 72 | 73 | cmp dx, si 74 | jae line_hr 75 | 76 | line_vr: 77 | 78 | ; compute iterations 79 | mov cx, si 80 | inc cx 81 | 82 | ; compute initial D 83 | mov bp, si 84 | neg bp 85 | 86 | ; compute 2dx and 2dy 87 | shl si, 1 88 | shl dx, 1 89 | 90 | line_vr_loop: 91 | mov ax, bx 92 | and al, es:[di] ; get pixel 93 | not bl ; complement mask 94 | and ah, bl ; and colour with mask complement 95 | or al, ah ; or with colour 96 | stosb ; write pixel 97 | not bl ; restore mask 98 | 99 | add bp, dx ; D += 2dx 100 | jle line_vr_skipx ; if D > 0 101 | 102 | not bl ; complement mask 103 | mov ah, bl 104 | sahf 105 | adc di, 0 106 | 107 | sub bp, si ; D -= 2dy 108 | 109 | line_vr_skipx: 110 | 111 | sub di, 3*8192-160+1 ; increment y 112 | sbb ax, ax 113 | and ax, 4*8192-160 114 | add di, ax 115 | 116 | loop line_vr_loop 117 | 118 | pop di 119 | pop si 120 | pop bp 121 | ret 122 | 123 | line_hr: 124 | 125 | ; compute iterations 126 | mov cx, dx 127 | inc cx 128 | 129 | ; compute initial D 130 | mov bp, dx 131 | neg bp 132 | 133 | ; compute 2dx and 2dy 134 | shl si, 1 135 | shl dx, 1 136 | 137 | line_hr_loop: 138 | mov ax, bx 139 | and al, es:[di] ; get pixel 140 | not bl ; complement mask 141 | and ah, bl ; and colour with mask complement 142 | or al, ah ; or with colour 143 | stosb ; write pixel 144 | not bl ; restore mask 145 | 146 | add bp, si ; D += 2dy 147 | jle line_hr_skipy ; if D > 0 148 | 149 | sub di, 3*8192-160 ; increment y 150 | sbb ax, ax 151 | and ax, 4*8192-160 152 | add di, ax 153 | 154 | sub bp, dx ; D -= 2dx 155 | 156 | line_hr_skipy: 157 | mov ah, bl 158 | not bl ; complement mask 159 | sahf 160 | sbb di, 0 161 | 162 | loop line_hr_loop 163 | 164 | pop di 165 | pop si 166 | pop bp 167 | ret 168 | 169 | line_left: 170 | neg dx 171 | 172 | std 173 | 174 | ; compute x0 mod 2 and x0 / 2 and divide di by 2 175 | add di, bx 176 | shr di, 1 177 | 178 | ; compute colour and mask 179 | sbb bl, bl 180 | xor bl, 0fh 181 | mov bh, colour 182 | mov al, bh 183 | shl al, 1 184 | shl al, 1 185 | shl al, 1 186 | shl al, 1 187 | add bh, al 188 | 189 | cmp dx, si 190 | jae line_hl 191 | 192 | line_vl: 193 | 194 | ; compute iterations 195 | mov cx, si 196 | inc cx 197 | 198 | ; compute initial D 199 | mov bp, si 200 | neg bp 201 | 202 | ; compute 2dx and 2dy 203 | shl si, 1 204 | shl dx, 1 205 | 206 | line_vl_loop: 207 | mov ax, bx 208 | and al, es:[di] ; get pixel 209 | not bl ; complement mask 210 | and ah, bl ; and colour with mask complement 211 | or al, ah ; or with colour 212 | stosb ; write pixel 213 | not bl ; restore mask 214 | 215 | add bp, dx ; D += 2dx 216 | jle line_vl_skipx ; if D > 0 217 | 218 | mov ah, bl 219 | not bl ; complement mask 220 | sahf 221 | sbb di, 0 222 | 223 | sub bp, si ; D -= 2dy 224 | 225 | line_vl_skipx: 226 | 227 | sub di, 3*8192-160-1 ; increment y 228 | sbb ax, ax 229 | and ax, 4*8192-160 230 | add di, ax 231 | 232 | loop line_vl_loop 233 | 234 | cld 235 | 236 | pop di 237 | pop si 238 | pop bp 239 | ret 240 | 241 | line_hl: 242 | 243 | ; compute iterations 244 | mov cx, dx 245 | inc cx 246 | 247 | ; compute initial D 248 | mov bp, dx 249 | neg bp 250 | 251 | ; compute 2dx and 2dy 252 | shl si, 1 253 | shl dx, 1 254 | 255 | line_hl_loop: 256 | mov ax, bx 257 | and al, es:[di] ; get pixel 258 | not bl ; complement mask 259 | and ah, bl ; and colour with mask complement 260 | or al, ah ; or with colour 261 | stosb ; write pixel 262 | not bl ; restore mask 263 | 264 | add bp, si ; D += 2dy 265 | jle line_hl_skipy ; if D > 0 266 | 267 | sub di, 3*8192-160 ; increment y 268 | sbb ax, ax 269 | and ax, 4*8192-160 270 | add di, ax 271 | 272 | sub bp, dx ; D -= 2dx 273 | 274 | line_hl_skipy: 275 | not bl ; complement mask 276 | mov ah, bl 277 | sahf 278 | adc di, 0 279 | 280 | loop line_hl_loop 281 | 282 | cld 283 | 284 | pop di 285 | pop si 286 | pop bp 287 | ret 288 | _tga_line ENDP 289 | 290 | start: 291 | ; set video mode = 9 (TGA 320x200 16 colours) 292 | mov ax, 9 293 | int 10h 294 | 295 | mov si, 199 296 | 297 | vline_right_loop: 298 | xor ah, ah 299 | mov al, 1 ; colour = 1 300 | push ax 301 | mov al, 199 ; y1 = 199 302 | push ax 303 | push si ; x1 = 199..0 304 | xor al, al 305 | push ax ; y0 = 0 306 | push ax ; x0 = 0 307 | call _tga_line 308 | add sp, 10 309 | 310 | dec si 311 | jge vline_right_loop 312 | 313 | ; wait for keypress 314 | xor ah, ah 315 | int 16h 316 | 317 | mov si, 199 318 | 319 | vline_left_loop: 320 | xor ah, ah 321 | mov al, 2 ; colour = 2 322 | push ax 323 | mov al, 199 ; y1 = 199 324 | push ax 325 | push si ; x1 = 199..0 326 | xor al, al 327 | push ax ; y0 = 0 328 | mov al, 199 329 | push ax ; x0 = 199 330 | call _tga_line 331 | add sp, 10 332 | 333 | dec si 334 | jge vline_left_loop 335 | 336 | ; wait for keypress 337 | xor ah, ah 338 | int 16h 339 | 340 | mov si, 199 341 | 342 | hline_right_loop: 343 | xor ah, ah 344 | mov al, 12 ; colour = 12 345 | push ax 346 | push si ; y1 = 199..0 347 | mov al, 199 ; x1 = 199 348 | push ax 349 | xor al, al 350 | push ax ; y0 = 0 351 | push ax ; x0 = 0 352 | call _tga_line 353 | add sp, 10 354 | 355 | dec si 356 | jge hline_right_loop 357 | 358 | ; wait for keypress 359 | xor ah, ah 360 | int 16h 361 | 362 | mov si, 199 363 | 364 | hline_left_loop: 365 | xor ah, ah 366 | mov al, 14 ; colour = 14 367 | push ax 368 | push si ; y1 = 199..0 369 | mov al, 0 ; x1 = 0 370 | push ax 371 | xor al, al 372 | push ax ; y0 = 0 373 | mov al, 199 374 | push ax ; x0 = 199 375 | call _tga_line 376 | add sp, 10 377 | 378 | dec si 379 | jge hline_left_loop 380 | 381 | ; wait for keypress 382 | xor ah, ah 383 | int 16h 384 | 385 | ; restore video mode 386 | xor ah, ah 387 | mov al, 3 388 | int 10h 389 | 390 | mov ah, 4ch ; terminate program 391 | int 21h 392 | END start 393 | -------------------------------------------------------------------------------- /TANDYSND.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .DATA 5 | 6 | last DB 0 7 | keystate DB 96 dup (0) 8 | extstate DB 96 dup (0) 9 | 10 | old_kb_off DW 0 11 | old_kb_seg DW 0 12 | 13 | old_irq0_off DW 0 14 | old_irq0_seg DW 0 15 | 16 | mode1 DB 0 ; 0 = nothing, 1 = freq., 2 = atten. 17 | mode2 DB 0 18 | mode3 DB 0 19 | 20 | count1 DW 0 21 | count2 DW 0 22 | count3 DW 0 23 | 24 | sound1 DB 242 dup (?) 25 | sound2 DB 242 dup (?) 26 | sound3 DB 242 dup (?) 27 | 28 | .CODE 29 | 30 | mov ax, 20 ; let floppy drive settle 31 | delay_loop_outer: 32 | mov cx, 65535 33 | delay_loop: 34 | loop delay_loop 35 | dec ax 36 | jnz delay_loop_outer 37 | 38 | cli 39 | xor ax, ax 40 | mov ds, ax 41 | 42 | mov si, ds:[8*4] ; save old handler 43 | mov di, ds:[8*4+2] 44 | 45 | mov cx, ds:[9*4] 46 | mov dx, ds:[9*4+2] 47 | 48 | mov WORD PTR ds:[8*4], offset irq0_handler ; set new handler 49 | mov WORD PTR ds:[8*4+2], cs 50 | 51 | mov WORD PTR ds:[9*4], offset kb_handler ; set new handler 52 | mov WORD PTR ds:[9*4+2], cs 53 | 54 | mov ax, @data 55 | mov ds, ax ; set DS to point to the data segment 56 | 57 | mov [old_irq0_off], si 58 | mov [old_irq0_seg], di 59 | 60 | mov [old_kb_off], cx 61 | mov [old_kb_seg], dx 62 | 63 | mov WORD PTR cs:[irq0_patch1+1], ax ; set ds for handler 64 | mov WORD PTR cs:[kb_patch1+1], ax ; set ds for handler 65 | 66 | mov al, 034h ; set timer for 1/120th sec, 9956 ticks 67 | out 043h, al 68 | mov al, 0e4h 69 | out 040h, al 70 | mov al, 026h 71 | out 040h, al 72 | 73 | sti 74 | 75 | mov ax, 1 ; channel 1 76 | push ax 77 | mov ax, 041eh 78 | push ax 79 | mov ax, 01eh 80 | push ax 81 | mov ax, 041eh 82 | push ax 83 | mov ax, 081eh 84 | push ax 85 | mov ax, 0feh 86 | push ax 87 | call ADSR 88 | add sp, 12 89 | 90 | runloop: 91 | 92 | cmp BYTE PTR [keystate+01h], 0 93 | jnz tandy_exit 94 | 95 | cmp BYTE PTR [keystate+039h], 0 96 | jz not_space 97 | 98 | mov BYTE PTR [mode1], 1 99 | mov BYTE PTR [keystate+039h], 0 100 | not_space: 101 | 102 | jmp runloop 103 | 104 | tandy_exit: 105 | 106 | cli 107 | 108 | mov al, 0ffh ; restore system timer value 109 | out 040h, al 110 | out 040h, al 111 | 112 | mov si, old_irq0_off 113 | mov di, old_irq0_seg 114 | 115 | mov cx, old_kb_off 116 | mov dx, old_kb_seg 117 | 118 | xor ax, ax 119 | mov ds, ax 120 | 121 | mov ds:[8*4], si ; restore old handler 122 | mov ds:[8*4+2], di 123 | 124 | mov ds:[9*4], cx 125 | mov ds:[9*4+2], dx 126 | 127 | mov ah, 04ch ; DOS terminate program function 128 | int 21h ; terminate the program 129 | 130 | ADSR PROC 131 | ARG freq:WORD, attack:WORD, decay:WORD, sustain:WORD, release:WORD, channel:BYTE 132 | ; freq = wave length, tone frequency = 3579545/32.0/freq Hz 133 | ; 0feh ~= 440Hz 134 | ; attack = hi byte: 4:4 bit att. dec. per 120Hz tick, 135 | ; lo byte: number of 120Hz ticks 136 | ; decay, sustain, release similar 137 | 138 | push bp 139 | mov bp, sp 140 | 141 | mov ax, ds ; duplicate ds into es 142 | mov es, ax 143 | 144 | mov al, channel ; channel 1 145 | cmp al, 1 146 | jbe channel_eq1 147 | 148 | jmp channel_ne1 149 | 150 | channel_eq1: 151 | mov di, offset sound1 152 | 153 | mov ax, freq ; convert freq to 6:4 format 154 | mov bx, ax 155 | and al, 0fh 156 | shr bx, 1 157 | shr bx, 1 158 | shr bx, 1 159 | shr bx, 1 160 | 161 | stosb ; write freq 162 | mov al, bl 163 | stosb 164 | 165 | mov bx, 0f00h ; max. att. = vol. 0 166 | xor cx, cx 167 | mov dx, attack 168 | mov cl, dl ; count 169 | 170 | xor dl, dl 171 | shr dx, 1 172 | shr dx, 1 173 | shr dx, 1 174 | shr dx, 1 175 | 176 | attack_loop: 177 | mov al, bh 178 | stosb 179 | 180 | sub bx, dx 181 | jge attack_ok 182 | xor bx, bx ; 0 = minimum value allowed 183 | attack_ok: 184 | 185 | loop attack_loop 186 | 187 | mov dx, decay 188 | mov cl, dl ; count 189 | 190 | xor dl, dl 191 | shr dx, 1 192 | shr dx, 1 193 | shr dx, 1 194 | shr dx, 1 195 | 196 | decay_loop: 197 | mov al, bh 198 | stosb 199 | 200 | add bx, dx 201 | cmp bx, 15 202 | jle decay_ok 203 | mov bx, 15 ; 15 = maximum value allowed 204 | decay_ok: 205 | 206 | loop decay_loop 207 | 208 | mov dx, sustain 209 | mov cl, dl ; count 210 | 211 | rep 212 | stosb 213 | 214 | mov dx, release 215 | mov cl, dl ; count 216 | 217 | xor dl, dl 218 | shr dx, 1 219 | shr dx, 1 220 | shr dx, 1 221 | shr dx, 1 222 | 223 | release_loop: 224 | mov al, bh 225 | stosb 226 | 227 | add bx, dx 228 | cmp bh, 15 229 | jle release_ok 230 | mov bh, 15 ; 15 = maximum value allowed 231 | release_ok: 232 | 233 | loop release_loop 234 | 235 | mov cx, offset sound1 ; attenuate to zero for remainder 236 | add cx, 242 237 | sub cx, di 238 | 239 | mov al, 15 240 | rep stosb 241 | 242 | channel_ne1: 243 | 244 | pop bp 245 | ret 246 | ADSR ENDP 247 | 248 | irq0_handler PROC 249 | push ax 250 | push ds 251 | push si 252 | 253 | irq0_patch1: 254 | mov ax, 1234h ; allow handler to access program ds 255 | mov ds, ax 256 | 257 | mov al, [mode1] 258 | cmp al, 1 259 | jb sound1_done 260 | je sound1_new 261 | 262 | mov si, [count1] ; set attenuation 263 | mov al, [sound1+si] 264 | or al, 090h 265 | 266 | out 0c0h, al ; output to sound chip 267 | 268 | inc si ; increment counter 269 | mov [count1], si 270 | 271 | cmp si, 242 272 | jne sound1_done 273 | 274 | mov [mode1], 0 275 | 276 | jmp sound1_done 277 | 278 | sound1_new: 279 | xor si, si 280 | 281 | mov al, [sound1+si] ; set tone count lo 4 bits 282 | or al, 080h 283 | 284 | out 0c0h, al ; output to sound chip 285 | 286 | inc si ; increment counter 287 | 288 | mov al, [sound1+si] ; set tone count hi 6 bits 289 | 290 | out 0c0h, al ; output to sound chip 291 | 292 | inc si ; increment counter 293 | 294 | mov al, [sound1+si] 295 | or al, 090h 296 | 297 | out 0c0h, al ; output to sound chip 298 | 299 | inc si 300 | mov [count1], si ; increment counter and save 301 | 302 | mov [mode1], 2 ; change to atten. mode 303 | 304 | sound1_done: 305 | 306 | pop si 307 | pop ds 308 | mov al, 020h ; interrupt done 309 | out 020h, al 310 | 311 | pop ax 312 | iret 313 | irq0_handler ENDP 314 | 315 | kb_handler PROC 316 | push ax 317 | push bx 318 | push ds 319 | 320 | kb_patch1: 321 | mov ax, 1234h ; allow handler to access program ds 322 | mov ds, ax 323 | 324 | in al, 060h ; read raw byte from kb 325 | xor bx, bx 326 | 327 | mov bl, al ; scancode 328 | and bl, 07fh 329 | 330 | mov ah, [last] 331 | cmp ah, 0e0h 332 | jne ignore_ext 333 | 334 | cmp bl, 060h 335 | jae nosave_ext 336 | 337 | and al, 080h 338 | xor al, 080h 339 | rol al, 1 340 | 341 | mov [bx+extstate], al 342 | 343 | nosave_ext: 344 | mov BYTE PTR [last], 0 345 | 346 | jmp key_done 347 | 348 | ignore_ext: 349 | cmp ah, 0e1h 350 | jne not_e1 351 | 352 | mov [last], 0 353 | 354 | jmp key_done 355 | 356 | not_e1: 357 | cmp ah, 0e2h 358 | jne not_e2 359 | 360 | mov [last], 0 361 | 362 | jmp key_done 363 | 364 | not_e2: 365 | 366 | cmp al, 0e0h 367 | jb scancode 368 | cmp al, 0e2h 369 | ja key_done 370 | 371 | mov [last], al 372 | 373 | jmp key_done 374 | 375 | scancode: 376 | 377 | cmp bl, 060h 378 | jae key_done 379 | 380 | and al, 080h 381 | xor al, 080h 382 | rol al, 1 383 | 384 | mov [keystate+bx], al 385 | 386 | key_done: 387 | 388 | in al, 061h 389 | or al, 080h 390 | out 061h, al 391 | xor al, 080h 392 | out 061h, al 393 | 394 | pop ds 395 | pop bx 396 | mov al, 020h ; interrupt done 397 | out 020h, al 398 | 399 | pop ax 400 | iret 401 | kb_handler ENDP 402 | 403 | END 404 | -------------------------------------------------------------------------------- /TETRA3D.COM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbhart/PCRetroProgrammer/c6832cf7f2d22fda14741a3d86d68e2aa29d81f3/TETRA3D.COM -------------------------------------------------------------------------------- /TIMELINE.BAS: -------------------------------------------------------------------------------- 1 | 10 SCREEN 1,1 2 | 20 TIME$="00:00:00" 3 | 30 S=0:GOSUB 100 4 | 40 FOR I=1 TO 10000 5 | 50 LINE (0,0)-(0,0) 6 | 60 NEXT 7 | 70 GOSUB 100 8 | 80 SCREEN 2,1:PRINT 18.206*(T1-T0)-364.12 9 | 90 END 10 | 100 T0=T1 11 | 110 T1=VAL(RIGHT$(TIME$,2)) 12 | 120 T1=T1+60*VAL(LEFT$(RIGHT$(TIME$,5),2)) 13 | 130 RETURN 14 | 15 | -------------------------------------------------------------------------------- /TIMELINE.C: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern void cga_line(int x0, int y0, int x1, int y1, unsigned char colour); 6 | 7 | int set_video_mode(int n) 8 | { 9 | union REGS regs; 10 | 11 | regs.h.ah = 0; 12 | regs.h.al = n; 13 | int86(0x10, ®s, ®s); 14 | } 15 | 16 | int main(int ac, char ** av) 17 | { 18 | int i; 19 | int x0, y0, x1, y1; 20 | struct time time1; 21 | double t; 22 | 23 | if (ac != 5) 24 | { 25 | printf("Usage:\n"); 26 | printf(" timeline x0 y0 x1 y1\n"); 27 | abort(); 28 | } 29 | 30 | x0 = atoi(av[1]); 31 | y0 = atoi(av[2]); 32 | x1 = atoi(av[3]); 33 | y1 = atoi(av[4]); 34 | 35 | time1.ti_hour = 0; 36 | time1.ti_min = 0; 37 | time1.ti_sec = 0; 38 | time1.ti_hund = 0; 39 | 40 | set_video_mode(4); 41 | 42 | settime(&time1); 43 | 44 | for (i = 0; i < 10000; i++) 45 | cga_line(x0, y0, x1, y1, 3); 46 | 47 | gettime(&time1); 48 | 49 | t = 60.0*time1.ti_min; 50 | t += time1.ti_sec; 51 | t += (time1.ti_hund/100.0); 52 | t *= 18.206; 53 | 54 | printf("%f\n", t); 55 | 56 | getch(); 57 | 58 | set_video_mode(3); 59 | 60 | return 0; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /TIMER.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .DATA 5 | 6 | .CODE 7 | 8 | old_timer_handler DD 0 9 | ticks DW 0 10 | timer_on DB 0 11 | 12 | _hook_timer PROC 13 | cli 14 | 15 | ; set ES to interrupt vector table segment 16 | xor ax, ax 17 | mov es, ax 18 | 19 | ; get old vector 20 | mov bx, es:[4*1ch] 21 | mov dx, es:[4*1ch+2] 22 | 23 | ; insert new vector 24 | mov WORD PTR es:[4*1ch], offset _timer_interrupt 25 | mov es:[4*1ch+2], cs 26 | 27 | ; save old vector 28 | mov WORD PTR cs:[old_timer_handler], bx 29 | mov WORD PTR cs:[old_timer_handler+2], dx 30 | 31 | sti 32 | 33 | ret 34 | _hook_timer ENDP 35 | 36 | _unhook_timer PROC 37 | cli 38 | 39 | ; get old vector 40 | mov bx, WORD PTR cs:[old_timer_handler] 41 | mov dx, WORD PTR cs:[old_timer_handler+2] 42 | 43 | ; set ES to interrupt vector table segment 44 | xor ax, ax 45 | mov es, ax 46 | 47 | ; reinsert old vector 48 | mov es:[1ch*4], bx 49 | mov es:[1ch*4+2], dx 50 | 51 | sti 52 | 53 | ret 54 | _unhook_timer ENDP 55 | 56 | _timer_interrupt PROC 57 | pushf 58 | call DWORD PTR cs:[old_timer_handler] 59 | 60 | ; if timer is on 61 | cmp BYTE PTR cs:[timer_on], 0 62 | je skip_tick 63 | 64 | ; increment timer 65 | inc WORD PTR cs:[ticks] 66 | 67 | skip_tick: 68 | 69 | iret 70 | _timer_interrupt ENDP 71 | 72 | _timer_start PROC 73 | mov WORD PTR cs:[ticks], 0 74 | mov BYTE PTR cs:[timer_on], 1 75 | 76 | ret 77 | _timer_start ENDP 78 | 79 | _timer_stop PROC 80 | mov BYTE PTR cs:[timer_on], 0 81 | 82 | ret 83 | _timer_stop ENDP 84 | 85 | _print_hex PROC 86 | ; value to print in AX 87 | 88 | mov cx, 4 89 | digit_loop: 90 | 91 | ; get leftmost digit in al 92 | rol ax, 1 93 | rol ax, 1 94 | rol ax, 1 95 | rol ax, 1 96 | 97 | ; convert to character 98 | mov dl, al 99 | and dl, 0fh 100 | add dl, '0' 101 | 102 | ; deal with digits A..F 103 | cmp dl, '9' 104 | jbe digit_is_number 105 | 106 | ; convert to letter 107 | add dl, 7 108 | 109 | digit_is_number: 110 | 111 | mov bx, ax 112 | 113 | ; DOS print character to stdout 114 | mov ah, 2 115 | int 21h 116 | 117 | mov ax, bx 118 | 119 | loop digit_loop 120 | ret 121 | _print_hex ENDP 122 | 123 | start: 124 | ; setup data segment 125 | mov ax, @data 126 | mov ds, ax 127 | 128 | ; hook new timer interrupt handler 129 | call _hook_timer 130 | 131 | ; start timer 132 | call _timer_start 133 | 134 | ; wait for keypress 135 | mov ah, 0 136 | int 16h 137 | 138 | ; stop timer 139 | call _timer_stop 140 | 141 | ; print hex ticks 142 | mov ax, cs:[ticks] 143 | call _print_hex 144 | 145 | ; restore old timer interrupt handler 146 | call _unhook_timer 147 | 148 | ; exit to DOS 149 | mov ah, 4ch 150 | int 21h 151 | 152 | END start 153 | -------------------------------------------------------------------------------- /TNDYLIN2.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .DATA 5 | .CODE 6 | 7 | _tga_point PROC 8 | ARG x:WORD, y:WORD, colour:BYTE 9 | push bp 10 | mov bp, sp 11 | push di 12 | 13 | ; set up TGA segment 14 | mov ax, 0b800h 15 | mov es, ax 16 | 17 | ; offset = 2*160*y 18 | mov ax, y 19 | xchg ah, al 20 | mov di, ax 21 | shr ax, 1 22 | shr ax, 1 23 | add di, ax 24 | 25 | ; compute x mod 2 and divide di by 2 26 | add di, x 27 | shr di, 1 28 | 29 | ; compute colour and mask 30 | sbb bl, bl 31 | xor bl, 0fh 32 | 33 | mov bh, colour 34 | mov al, bh 35 | shl al, 1 36 | shl al, 1 37 | shl al, 1 38 | shl al, 1 39 | add bh, al 40 | 41 | ; draw pixels 42 | mov ax, bx 43 | and al, es:[di] 44 | not bl 45 | and ah, bl 46 | or al, ah 47 | stosb 48 | 49 | pop di 50 | pop bp 51 | ret 52 | _tga_point ENDP 53 | 54 | start: 55 | 56 | ; set TGA video mode 9 = 320x200 16 colours 57 | mov ax, 9 58 | int 10h 59 | 60 | mov dx, 15 61 | 62 | colour_loop: 63 | mov si, 199 64 | 65 | point_loop: 66 | push dx 67 | push si 68 | add si, dx 69 | push si 70 | sub si, dx 71 | call _tga_point 72 | add sp, 6 73 | 74 | dec si 75 | jns point_loop 76 | 77 | dec dx 78 | jnz colour_loop 79 | 80 | ; wait for keypress 81 | xor ah, ah 82 | int 16h 83 | 84 | ; wait for vertical retrace 85 | mov dx, 03dah 86 | wait_retrace: 87 | in al, dx 88 | test al, 8 89 | jz wait_retrace 90 | 91 | ; get current CRT/CPU page register 92 | ; BH = CRT page, BL = CPU page 93 | mov ax, 0580h 94 | int 10h 95 | 96 | ; set CPU/CRT page register 97 | mov al, bl ; CPU page 98 | mov cl, 3 99 | shl al, cl 100 | or al, bh ; CRT page 101 | mov dx, 3dfh 102 | out dx, al 103 | 104 | ; set extended RAM page register 105 | mov al, 1 ; extended addressing mode bit 106 | mov dx, 3ddh 107 | out dx, al 108 | 109 | ; wait for active region 110 | mov dx, 03dah 111 | wait_active: 112 | in al, dx 113 | test al, 1 114 | jnz wait_active 115 | 116 | mov dl, 0d4h 117 | 118 | mov ax, 0*256+9 ; max. char scanline 119 | out dx, ax 120 | mov ax, 255*256+4 ; vert. total chars 121 | out dx, ax 122 | mov ax, 200*256+6 ; vert. disp. chars 123 | out dx, ax 124 | mov ax, 224*256+7 ; vert. sync. posn. 125 | out dx, ax 126 | 127 | ; wait for keypress 128 | xor ah, ah 129 | int 16h 130 | 131 | ; wait for vertical retrace 132 | mov dx, 03dah 133 | wait_retrace2: 134 | in al, dx 135 | test al, 8 136 | jz wait_retrace2 137 | 138 | ; get current CRT/CPU page register 139 | ; BH = CRT page, BL = CPU page 140 | mov ax, 0580h 141 | int 10h 142 | 143 | ; set CPU/CRT page register 144 | mov al, bl ; CPU page 145 | mov cl, 3 146 | shl al, cl 147 | or al, bh ; CRT page 148 | xor al, 192 ; set bits 6 and 7 149 | mov dx, 3dfh 150 | out dx, al 151 | 152 | ; set extended RAM page register 153 | xor al, al ; extended addressing mode bit 154 | mov dx, 3ddh 155 | out dx, al 156 | 157 | ; wait for active region 158 | mov dx, 03dah 159 | wait_active2: 160 | in al, dx 161 | test al, 1 162 | jnz wait_active2 163 | 164 | mov dl, 0d4h 165 | 166 | mov ax, 3*256+9 ; max. char scanline 167 | out dx, ax 168 | mov ax, 63*256+4 ; vert. total chars 169 | out dx, ax 170 | mov ax, 50*256+6 ; vert. disp. chars 171 | out dx, ax 172 | mov ax, 56*256+7 ; vert. sync. posn. 173 | out dx, ax 174 | 175 | ; wait for keypress 176 | xor ah, ah 177 | int 16h 178 | 179 | ; restore video mode 180 | xor ah, ah 181 | mov al, 3 182 | int 10h 183 | 184 | mov ah,4ch ;DOS terminate program function 185 | int 21h ;terminate the program 186 | END start 187 | -------------------------------------------------------------------------------- /TNDYLIN2.EXE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wbhart/PCRetroProgrammer/c6832cf7f2d22fda14741a3d86d68e2aa29d81f3/TNDYLIN2.EXE -------------------------------------------------------------------------------- /TNDYLINR.ASM: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .DATA 5 | .CODE 6 | 7 | _tga_point PROC 8 | ARG x:WORD, y:WORD, colour:BYTE 9 | push bp 10 | mov bp, sp 11 | push di 12 | 13 | ; set up TGA segment 14 | mov ax, 0b800h 15 | mov es, ax 16 | 17 | ; offset += 2*8192*bank 18 | mov ax, y 19 | ror ax, 1 20 | ror ax, 1 21 | mov di, ax 22 | xor ah, ah 23 | sub di, ax 24 | 25 | ; add 2*160*(y/4) to offset 26 | xchg ah, al 27 | add di, ax 28 | shr ax, 1 29 | shr ax, 1 30 | add di, ax 31 | 32 | ; compute x mod 2 and divide di by 2 33 | add di, x 34 | shr di, 1 35 | 36 | ; compute colour and mask 37 | sbb bl, bl 38 | xor bl, 0fh 39 | 40 | mov bh, colour 41 | mov al, bh 42 | shl al, 1 43 | shl al, 1 44 | shl al, 1 45 | shl al, 1 46 | add bh, al 47 | 48 | ; draw pixels 49 | mov ax, bx 50 | and al, es:[di] 51 | not bl 52 | and ah, bl 53 | or al, ah 54 | stosb 55 | 56 | pop di 57 | pop bp 58 | ret 59 | _tga_point ENDP 60 | 61 | start: 62 | 63 | ; set TGA video mode 9 = 320x200 16 colours 64 | mov ax, 9 65 | int 10h 66 | 67 | ; get current CRT/CPU page register 68 | ; BH = CRT page, BL = CPU page 69 | mov ax, 0580h 70 | int 10h 71 | 72 | ; set CPU/CRT page register 73 | mov al, bl ; CPU page 74 | mov cl, 3 75 | shl al, cl 76 | or al, bh ; CRT page 77 | mov dx, 3dfh 78 | out dx, al 79 | 80 | ; set extended RAM page register 81 | mov al, 1 ; extended addressing mode bit 82 | mov dx, 3ddh 83 | out dx, al 84 | 85 | mov dx, 15 86 | 87 | colour_loop: 88 | mov si, 199 89 | 90 | point_loop: 91 | push dx 92 | push si 93 | add si, dx 94 | push si 95 | sub si, dx 96 | call _tga_point 97 | add sp, 6 98 | 99 | dec si 100 | jns point_loop 101 | 102 | dec dx 103 | jnz colour_loop 104 | 105 | ; wait for keypress 106 | xor ah, ah 107 | int 16h 108 | 109 | ; restore video mode 110 | xor ah, ah 111 | mov al, 3 112 | int 10h 113 | 114 | mov ah,4ch ;DOS terminate program function 115 | int 21h ;terminate the program 116 | END start 117 | -------------------------------------------------------------------------------- /WILTON.C: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | extern void Line04(int x0, int y0, int x1, int y1, int colour); 6 | 7 | int set_video_mode(int n) 8 | { 9 | union REGS regs; 10 | 11 | regs.h.ah = 0; 12 | regs.h.al = n; 13 | int86(0x10, ®s, ®s); 14 | } 15 | 16 | int main(int ac, char ** av) 17 | { 18 | int i; 19 | int x0, y0, x1, y1; 20 | struct time time1; 21 | double t; 22 | 23 | if (ac != 5) 24 | { 25 | printf("Usage:\n"); 26 | printf(" wilton x0 y0 x1 y1\n"); 27 | abort(); 28 | } 29 | 30 | x0 = atoi(av[1]); 31 | y0 = atoi(av[2]); 32 | x1 = atoi(av[3]); 33 | y1 = atoi(av[4]); 34 | 35 | time1.ti_hour = 0; 36 | time1.ti_min = 0; 37 | time1.ti_sec = 0; 38 | time1.ti_hund = 0; 39 | 40 | set_video_mode(4); 41 | 42 | settime(&time1); 43 | 44 | for (i = 0; i < 10000; i++) 45 | Line04(x0, y0, x1, y1, 3); 46 | 47 | gettime(&time1); 48 | 49 | t = 60.0*time1.ti_min; 50 | t += time1.ti_sec; 51 | t += (time1.ti_hund/100.0); 52 | t *= 18.206; 53 | 54 | printf("%f\n", t); 55 | 56 | getch(); 57 | 58 | set_video_mode(3); 59 | 60 | return 0; 61 | } 62 | 63 | -------------------------------------------------------------------------------- /line3.asm: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _cga_line PROC 7 | ARG x0:WORD, y0:WORD, x1:WORD, y1:WORD, colour:BYTE 8 | ; assumes down-right or up-left 9 | 10 | ; ax = accum, dx = 2dx, si = 2dy, bp = D, cx = iters 11 | ; di = offset, bl = mask, bh = colour 12 | 13 | push bp 14 | mov bp, sp 15 | push si 16 | push di 17 | 18 | ; set up CGA segment 19 | mov ax, 0b800h 20 | mov es, ax 21 | 22 | ; get x0 and x1 23 | mov dx, x1 24 | mov bx, x0 25 | 26 | ; compute dy 27 | mov ax, y0 28 | mov si, y1 29 | sub si, ax 30 | 31 | ; ensure y1 >= y0 32 | jge line_dy_nonneg 33 | xchg dx, bx 34 | add ax, si 35 | neg si 36 | line_dy_nonneg: 37 | 38 | ; offset += 4*8192 if y0 odd 39 | xor di, di 40 | shr ax, 1 41 | rcr di, 1 42 | 43 | ; add 4*80*(y0/2) to offset 44 | xchg ah, al 45 | add di, ax 46 | shr ax, 1 47 | shr ax, 1 48 | add di, ax 49 | 50 | ; compute dx 51 | sub dx, bx 52 | 53 | ; compute x0 mod 4 and x0 / 4 and divide di by 4 54 | mov cx, bx 55 | and cl, 3 56 | add di, bx 57 | shr di, 1 58 | shr di, 1 59 | 60 | ; compute colour and mask 61 | mov bh, colour 62 | mov bl, 03fh 63 | shl cl, 1 64 | ror bl, cl 65 | inc cl 66 | inc cl 67 | ror bh, cl 68 | 69 | cmp dx, si 70 | jae line_hr 71 | 72 | line_vr: 73 | 74 | ; compute iterations 75 | mov cx, si 76 | inc cx 77 | 78 | ; compute initial D 79 | mov bp, si 80 | neg bp 81 | 82 | ; compute 2dx and 2dy 83 | shl si, 1 84 | shl dx, 1 85 | 86 | line_vr_loop: 87 | mov al, es:[di] ; get pixel 88 | and al, bl ; and with mask 89 | or al, bh ; or with colour 90 | stosb ; write pixel 91 | 92 | add bp, dx ; D += 2dx 93 | jle line_vr_skipx ; if D > 0 94 | 95 | ror bh, 1 96 | ror bh, 1 97 | ror bl, 1 98 | ror bl, 1 99 | cmc 100 | adc di, 0 101 | 102 | sub bp, si ; D -= 2dy 103 | 104 | line_vr_skipx: 105 | 106 | sub di, 8113 ; increment y 107 | sbb ax, ax 108 | and ax, 16304 109 | add di, ax 110 | 111 | loop line_vr_loop 112 | 113 | pop di 114 | pop si 115 | pop bp 116 | ret 117 | 118 | line_hr: 119 | 120 | ; compute iterations 121 | mov cx, dx 122 | inc cx 123 | 124 | ; compute initial D 125 | mov bp, dx 126 | neg bp 127 | 128 | ; compute 2dx and 2dy 129 | shl si, 1 130 | shl dx, 1 131 | 132 | line_hr_loop: 133 | mov al, es:[di] ; get pixel 134 | and al, bl ; and with mask 135 | or al, bh ; or with colour 136 | stosb ; write pixel 137 | 138 | add bp, si ; D += 2dy 139 | jle line_hr_skipy ; if D > 0 140 | 141 | sub di, 8112 ; increment y 142 | sbb ax, ax 143 | and ax, 16304 144 | add di, ax 145 | 146 | sub bp, dx ; D -= 2dx 147 | 148 | line_hr_skipy: 149 | ror bh, 1 150 | ror bh, 1 151 | ror bl, 1 152 | ror bl, 1 153 | sbb di, 0 154 | 155 | loop line_hr_loop 156 | 157 | pop di 158 | pop si 159 | pop bp 160 | ret 161 | _cga_line ENDP 162 | 163 | start: 164 | ; set video mode = 4 (CGA 320x200x4) 165 | xor ah, ah 166 | mov al, 4 167 | int 10h 168 | 169 | mov si, 199 170 | 171 | vline_loop: 172 | xor ah, ah 173 | mov al, 2 ; colour = 2 174 | push ax 175 | mov al, 199 ; y1 = 199 176 | push ax 177 | push si ; x1 = 199..0 178 | xor al, al 179 | push ax ; y0 = 0 180 | push ax ; x0 = 0 181 | call _cga_line 182 | add sp, 10 183 | 184 | dec si 185 | jge vline_loop 186 | 187 | mov si, 199 188 | 189 | hline_loop: 190 | xor ah, ah 191 | mov al, 2 ; colour = 2 192 | push ax 193 | push si ; y1 = 199..0 194 | mov al, 199 ; x1 = 199 195 | push ax 196 | xor al, al 197 | push ax ; y0 = 0 198 | push ax ; x0 = 0 199 | call _cga_line 200 | add sp, 10 201 | 202 | dec si 203 | jge hline_loop 204 | 205 | ; wait for keypress 206 | xor ah, ah 207 | int 16h 208 | 209 | ; restore video mode 210 | xor ah, ah 211 | mov al, 3 212 | int 10h 213 | 214 | mov ah, 4ch ; terminate program 215 | int 21h 216 | END start 217 | -------------------------------------------------------------------------------- /line4.asm: -------------------------------------------------------------------------------- 1 | DOSSEG 2 | .MODEL SMALL 3 | .STACK 100h 4 | .CODE 5 | 6 | _cga_line PROC 7 | ARG x0:WORD, y0:WORD, x1:WORD, y1:WORD, colour:BYTE 8 | ; ax = accum, dx = 2dx, si = 2dy, bp = D, cx = iters 9 | ; di = offset, bl = mask, bh = colour 10 | 11 | push bp 12 | mov bp, sp 13 | push si 14 | push di 15 | 16 | ; set up CGA segment 17 | mov ax, 0b800h 18 | mov es, ax 19 | 20 | ; get x0 and x1 21 | mov dx, x1 22 | mov bx, x0 23 | 24 | ; compute dy 25 | mov ax, y0 26 | mov si, y1 27 | sub si, ax 28 | 29 | ; ensure y1 >= y0 30 | jge line_dy_nonneg 31 | xchg dx, bx 32 | add ax, si 33 | neg si 34 | line_dy_nonneg: 35 | 36 | ; offset += 4*8192 if y0 odd 37 | xor di, di 38 | shr ax, 1 39 | rcr di, 1 40 | 41 | ; add 4*80*(y0/2) to offset 42 | xchg ah, al 43 | add di, ax 44 | shr ax, 1 45 | shr ax, 1 46 | add di, ax 47 | 48 | ; compute dx 49 | sub dx, bx 50 | 51 | jge line_right 52 | jmp line_left 53 | 54 | line_right: 55 | 56 | ; compute x0 mod 4 and x0 / 4 and divide di by 4 57 | mov cx, bx 58 | and cl, 3 59 | add di, bx 60 | shr di, 1 61 | shr di, 1 62 | 63 | ; compute colour and mask 64 | mov bh, colour 65 | mov bl, 03fh 66 | shl cl, 1 67 | ror bl, cl 68 | inc cl 69 | inc cl 70 | ror bh, cl 71 | 72 | cmp dx, si 73 | jae line_hr 74 | 75 | line_vr: 76 | 77 | ; compute iterations 78 | mov cx, si 79 | inc cx 80 | 81 | ; compute initial D 82 | mov bp, si 83 | neg bp 84 | 85 | ; compute 2dx and 2dy 86 | shl si, 1 87 | shl dx, 1 88 | 89 | line_vr_loop: 90 | mov al, es:[di] ; get pixel 91 | and al, bl ; and with mask 92 | or al, bh ; or with colour 93 | stosb ; write pixel 94 | 95 | add bp, dx ; D += 2dx 96 | jle line_vr_skipx ; if D > 0 97 | 98 | ror bh, 1 99 | ror bh, 1 100 | ror bl, 1 101 | ror bl, 1 102 | cmc 103 | adc di, 0 104 | 105 | sub bp, si ; D -= 2dy 106 | 107 | line_vr_skipx: 108 | 109 | sub di, 8113 ; increment y 110 | sbb ax, ax 111 | and ax, 16304 112 | add di, ax 113 | 114 | loop line_vr_loop 115 | 116 | pop di 117 | pop si 118 | pop bp 119 | ret 120 | 121 | line_hr: 122 | 123 | ; compute iterations 124 | mov cx, dx 125 | inc cx 126 | 127 | ; compute initial D 128 | mov bp, dx 129 | neg bp 130 | 131 | ; compute 2dx and 2dy 132 | shl si, 1 133 | shl dx, 1 134 | 135 | line_hr_loop: 136 | mov al, es:[di] ; get pixel 137 | and al, bl ; and with mask 138 | or al, bh ; or with colour 139 | stosb ; write pixel 140 | 141 | add bp, si ; D += 2dy 142 | jle line_hr_skipy ; if D > 0 143 | 144 | sub di, 8112 ; increment y 145 | sbb ax, ax 146 | and ax, 16304 147 | add di, ax 148 | 149 | sub bp, dx ; D -= 2dx 150 | 151 | line_hr_skipy: 152 | ror bh, 1 153 | ror bh, 1 154 | ror bl, 1 155 | ror bl, 1 156 | sbb di, 0 157 | 158 | loop line_hr_loop 159 | 160 | pop di 161 | pop si 162 | pop bp 163 | ret 164 | 165 | line_left: 166 | neg dx 167 | 168 | std 169 | 170 | ; compute x0 mod 4 and x0 / 4 and divide di by 4 171 | mov cx, bx 172 | and cl, 3 173 | add di, bx 174 | shr di, 1 175 | shr di, 1 176 | 177 | ; compute colour and mask 178 | mov bh, colour 179 | mov bl, 03fh 180 | shl cl, 1 181 | ror bl, cl 182 | inc cl 183 | inc cl 184 | ror bh, cl 185 | 186 | cmp dx, si 187 | jae line_hl 188 | 189 | line_vl: 190 | 191 | ; compute iterations 192 | mov cx, si 193 | inc cx 194 | 195 | ; compute initial D 196 | mov bp, si 197 | neg bp 198 | 199 | ; compute 2dx and 2dy 200 | shl si, 1 201 | shl dx, 1 202 | 203 | line_vl_loop: 204 | mov al, es:[di] ; get pixel 205 | and al, bl ; and with mask 206 | or al, bh ; or with colour 207 | stosb ; write pixel 208 | 209 | add bp, dx ; D += 2dx 210 | jle line_vl_skipx ; if D > 0 211 | 212 | rol bh, 1 213 | rol bh, 1 214 | rol bl, 1 215 | rol bl, 1 216 | cmc 217 | sbb di, 0 218 | 219 | sub bp, si ; D -= 2dy 220 | 221 | line_vl_skipx: 222 | 223 | sub di, 8111 ; increment y 224 | sbb ax, ax 225 | and ax, 16304 226 | add di, ax 227 | 228 | loop line_vl_loop 229 | 230 | cld 231 | 232 | pop di 233 | pop si 234 | pop bp 235 | ret 236 | 237 | line_hl: 238 | 239 | ; compute iterations 240 | mov cx, dx 241 | inc cx 242 | 243 | ; compute initial D 244 | mov bp, dx 245 | neg bp 246 | 247 | ; compute 2dx and 2dy 248 | shl si, 1 249 | shl dx, 1 250 | 251 | line_hl_loop: 252 | mov al, es:[di] ; get pixel 253 | and al, bl ; and with mask 254 | or al, bh ; or with colour 255 | stosb ; write pixel 256 | 257 | add bp, si ; D += 2dy 258 | jle line_hl_skipy ; if D > 0 259 | 260 | sub di, 8112 ; increment y 261 | sbb ax, ax 262 | and ax, 16304 263 | add di, ax 264 | 265 | sub bp, dx ; D -= 2dx 266 | 267 | line_hl_skipy: 268 | rol bh, 1 269 | rol bh, 1 270 | rol bl, 1 271 | rol bl, 1 272 | adc di, 0 273 | 274 | loop line_hl_loop 275 | 276 | cld 277 | 278 | pop di 279 | pop si 280 | pop bp 281 | ret 282 | _cga_line ENDP 283 | 284 | start: 285 | ; set video mode = 4 (CGA 320x200x4) 286 | xor ah, ah 287 | mov al, 4 288 | int 10h 289 | 290 | mov si, 199 291 | 292 | vline_right_loop: 293 | xor ah, ah 294 | mov al, 2 ; colour = 2 295 | push ax 296 | mov al, 199 ; y1 = 199 297 | push ax 298 | push si ; x1 = 199..0 299 | xor al, al 300 | push ax ; y0 = 0 301 | push ax ; x0 = 0 302 | call _cga_line 303 | add sp, 10 304 | 305 | dec si 306 | jge vline_right_loop 307 | 308 | ; wait for keypress 309 | xor ah, ah 310 | int 16h 311 | 312 | mov si, 199 313 | 314 | vline_left_loop: 315 | xor ah, ah 316 | mov al, 1 ; colour = 1 317 | push ax 318 | mov al, 199 ; y1 = 199 319 | push ax 320 | push si ; x1 = 199..0 321 | xor al, al 322 | push ax ; y0 = 0 323 | mov al, 199 324 | push ax ; x0 = 199 325 | call _cga_line 326 | add sp, 10 327 | 328 | dec si 329 | jge vline_left_loop 330 | 331 | ; wait for keypress 332 | xor ah, ah 333 | int 16h 334 | 335 | mov si, 199 336 | 337 | hline_right_loop: 338 | xor ah, ah 339 | mov al, 2 ; colour = 2 340 | push ax 341 | push si ; y1 = 199..0 342 | mov al, 199 ; x1 = 199 343 | push ax 344 | xor al, al 345 | push ax ; y0 = 0 346 | push ax ; x0 = 0 347 | call _cga_line 348 | add sp, 10 349 | 350 | dec si 351 | jge hline_right_loop 352 | 353 | ; wait for keypress 354 | xor ah, ah 355 | int 16h 356 | 357 | mov si, 199 358 | 359 | hline_left_loop: 360 | xor ah, ah 361 | mov al, 3 ; colour = 3 362 | push ax 363 | push si ; y1 = 199..0 364 | mov al, 0 ; x1 = 0 365 | push ax 366 | xor al, al 367 | push ax ; y0 = 0 368 | mov al, 199 369 | push ax ; x0 = 199 370 | call _cga_line 371 | add sp, 10 372 | 373 | dec si 374 | jge hline_left_loop 375 | 376 | ; wait for keypress 377 | xor ah, ah 378 | int 16h 379 | 380 | ; restore video mode 381 | xor ah, ah 382 | mov al, 3 383 | int 10h 384 | 385 | mov ah, 4ch ; terminate program 386 | int 21h 387 | END start 388 | --------------------------------------------------------------------------------