├── README.md ├── tandy13h.asm └── tandy13h.com /README.md: -------------------------------------------------------------------------------- 1 | Tandy13h 2 | ======== 3 | 4 | Tandy13h is an experimental VGA/MCGA mode 13h emulation TSR driver for the 5 | Tandy Video II adapter that can be found in the Tandy 1000 RL, SL and TL 6 | series of computers. 7 | 8 | Usage 9 | ----- 10 | The TSR driver can be loaded via 11 | 12 | TANDY13H.COM 13 | 14 | It can be unloaded via 15 | 16 | TANDY13H.COM /U 17 | 18 | Once the driver has been loaded, programs can switch to mode 13h as if 19 | they were running on a system equipped with an MCGA or VGA card. 20 | 21 | How it works 22 | ------------ 23 | This driver maps the 256 color mode of VGA and MCGA cards with its 320x200 24 | pixels to the Tandy Video II adapter's 16 color mode with 640x200 pixels. 25 | Both those modes use segment A000h as frame buffer and share practically 26 | the same memory model. 27 | Every 256 color pixel will show up as a pair of 16 color pixels. 28 | 29 | Limitations 30 | ----------- 31 | The output on-screen will look similar to a 256 color picture with a 32 | palette that consists of the average colors of all possible pairs of CGA 33 | colors, albeit with vertical stripes. This implicit palette cannot be 34 | changed. 35 | Furthermore, any functionality that bypasses the video BIOS cannot be 36 | reproduced. 37 | -------------------------------------------------------------------------------- /tandy13h.asm: -------------------------------------------------------------------------------- 1 | ; experimental VGA/MCGA mode 13h emulation TSR driver for Tandy Video II 2 | ; will use 640x200x16 mode 3 | ; assemble with yasm/nasm 4 | 5 | [bits 16] 6 | [org 0x100] 7 | 8 | jmp main 9 | 10 | tsr10: 11 | cmp ah,00h 12 | je intercept_00h 13 | cmp ah,0fh 14 | je intercept_0fh 15 | cmp ax,1a00h 16 | je intercept_1a00h 17 | normal_int_10h: 18 | push word [cs:int10seg] 19 | push word [cs:int10ofs] 20 | retf 21 | 22 | intercept_00h: 23 | mov [cs:display_mode],al 24 | cmp al,13h 25 | je mode_13h_requested 26 | cmp al,93h 27 | je mode_13h_requested 28 | jmp normal_int_10h 29 | 30 | intercept_0fh: 31 | cmp byte [cs:display_mode],13h 32 | je is_13h 33 | cmp byte [cs:display_mode],93h 34 | jne normal_int_10h 35 | is_13h: 36 | mov ah,40 ; number of character columns 37 | mov al,[cs:display_mode] 38 | mov bl,0 ; active page 39 | iret 40 | 41 | intercept_1a00h: 42 | mov al,ah 43 | mov bx,0a0ah ; MCGA with digital color display 44 | iret 45 | 46 | mode_13h_requested: 47 | call set_mode_640x200x16 48 | mov al,20h 49 | iret 50 | 51 | int10seg dw 0000h 52 | int10ofs dw 0000h 53 | display_mode db 0 54 | 55 | ; data for CRTC registers 0-18, index port 3d4h, data port 3d4h 56 | crtc_tab db 71h,50h,5ah,0efh,0ffh,6,0c8h,0e2h,1ch,0,0,0,0,0,0,0,18h,0,46h 57 | 58 | ; data for control registers, index in low byte 59 | ctrl_tab dw 0f01h,2,1003h,105h,208h 60 | 61 | ; keep a signature somewhere to prevent double loading 62 | signature db "TANDY13H" 63 | 64 | ; switch to 640x200x16 Tandy mode -- this is not EGA mode 0eh 65 | set_mode_640x200x16: 66 | push ax 67 | push dx 68 | 69 | ; switch to mode 3 70 | mov ax,3 71 | int 10h 72 | 73 | ; select 640 dot graphics mode with hi-res clock, disable video 74 | mov dx,3d8h 75 | mov al,13h 76 | out dx,al 77 | 78 | ; set CRTC registers 79 | 80 | push ds 81 | push si 82 | 83 | push cs 84 | pop ds 85 | mov si,crtc_tab 86 | 87 | xor ax,ax 88 | cld ; will be restored by iret 89 | 90 | crtc_loop: 91 | mov dl,0d4h ; dx=3d4h 92 | out dx,al 93 | inc ax 94 | push ax 95 | lodsb 96 | inc dx 97 | out dx,al 98 | pop ax 99 | cmp al,19 100 | jb crtc_loop 101 | 102 | ; set control registers 103 | mov si,ctrl_tab 104 | ctrl_loop: 105 | mov dl,0dah ; dx=3dah 106 | lodsw 107 | out dx,al 108 | mov dl,0deh ; dx=3deh 109 | xchg al,ah 110 | out dx,al 111 | cmp ah,8 112 | jne ctrl_loop 113 | 114 | pop si 115 | pop ds 116 | 117 | ; clear color select register 118 | mov dl,0d9h ; dx=3d9h 119 | mov al,0 120 | out dx,al 121 | 122 | ; disable extended RAM paging 123 | mov dl,0ddh ; dx=3ddh 124 | mov al,0 125 | out dx,al 126 | 127 | ; select page 2 for CRT & CPU 128 | mov dl,0dfh ; dx=3dfh 129 | mov al,24h 130 | out dx,al 131 | 132 | cmp byte [cs:display_mode],93h 133 | je skip_clear_screen 134 | ; clear screen 135 | push es ; save es 136 | mov ax,0a000h 137 | mov es,ax ; es=0a000h 138 | push di ; save di 139 | xor di,di ; di=0 140 | xor ax,ax ; ax=0 141 | push cx ; save cx 142 | mov cx,32000 143 | rep stosw ; write 64000 black pixels (technically 128000) 144 | pop cx ; restore cx 145 | pop di ; restore di 146 | pop es ; restore es 147 | skip_clear_screen: 148 | 149 | ; select 640 dot graphics mode with hi-res clock, enable video 150 | mov dl,0d8h ; dx = 3d8h 151 | mov al,1bh 152 | out dx,al 153 | 154 | pop dx ; restore dx 155 | pop ax ; restore ax 156 | 157 | ret 158 | 159 | ; calculate number of paragraphs to be kept resident from this label 160 | behind_tsr_end: 161 | 162 | main: 163 | ; print title 164 | mov dx,msg_title 165 | mov ah,9 166 | int 21h 167 | 168 | ; get interrupt vector for 10h (stores result in es:bx) 169 | mov ax,3510h 170 | int 21h 171 | 172 | ; try to figure out whether the TSR is already installed 173 | mov cx,8 174 | mov di,signature 175 | mov si,signature 176 | repe cmpsb 177 | ; store old interrupt vector 178 | mov word [int10seg],es 179 | mov word [int10ofs],bx 180 | ; install TSR if signature check failed 181 | jne install_tsr 182 | 183 | ; TSR removal requested? (case insensitive /u) 184 | cmp word [81h]," /" 185 | jne already_loaded 186 | mov ax,[83h] 187 | or al,20h 188 | cmp ax,'u'+(13<<8) 189 | jne already_loaded 190 | ; restore original interrupt vector 191 | mov ax,2510h 192 | push ds ; save ds 193 | push word [es:int10seg] 194 | pop ds 195 | mov dx,[es:int10ofs] 196 | int 21h 197 | ; free TSR memory; TSR segment already in es 198 | mov ah,49h 199 | int 21h 200 | pop ds ; restore ds 201 | mov dx,msg_success_rem 202 | jmp output_msg_and_exit 203 | already_loaded: 204 | mov dx,msg_error_already_loaded 205 | jmp output_msg_and_exit 206 | 207 | install_tsr: 208 | ; find out whether the active graphics adapter is Tandy Video II 209 | 210 | ; check whether it supports VGA's "read combination code" 211 | mov ax,1a00h 212 | int 10h 213 | ; if this is a VGA it cannot be a Tandy Video II 214 | cmp al,1ah 215 | je incompat_vid 216 | ; if this is an EGA it cannot be a Tandy Video II 217 | mov ah,12h 218 | mov bl,10h 219 | int 10h 220 | cmp bl,10h 221 | jne incompat_vid 222 | ; if it is neither VGA nor EGA and runs in mode 7, it cannot be a Tandy Video II with color screen 223 | mov ax,0f00h 224 | int 10h 225 | cmp al,7 226 | je incompat_vid 227 | ; check magic numbers in BIOS area to rule out PCjr and older Tandy 1000 228 | mov ax,0fc00h 229 | mov es,ax 230 | mov ah,[es:3ffeh] 231 | mov al,[es:0] 232 | cmp ax,0ff21h 233 | jne incompat_vid 234 | ; newer Tandy 1000 detected; check whether it supports "get configuration" 235 | mov ah,0c0h 236 | int 15h 237 | jc incompat_vid 238 | ; it does => Tandy Video II detected (RL, SL and TL series) 239 | ; go on and install the TSR 240 | mov ax,2510h 241 | mov dx,tsr10 242 | int 21h 243 | 244 | ; print success message 245 | mov dx,msg_success 246 | mov ah,9 247 | int 21h 248 | 249 | ; terminate and stay resident 250 | mov ax,3100h 251 | mov dx,(behind_tsr_end+15)>>4 252 | int 21h 253 | 254 | ; incompatible graphics adapter detected 255 | incompat_vid: 256 | mov dx,msg_error_incompat_vid 257 | output_msg_and_exit: 258 | mov ah,9 259 | int 21h 260 | mov ah,0 261 | int 21h 262 | 263 | 264 | msg_title db "MCGA 13h emulator for Tandy Video II - TSR $" 265 | msg_error_already_loaded db "already loaded",10,13,"$" 266 | msg_success db "loaded",10,13,"$" 267 | msg_success_rem db "removed",10,13,"$" 268 | msg_error_incompat_vid db "error: Wrong graphics adapter",10,13,"$" 269 | -------------------------------------------------------------------------------- /tandy13h.com: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roybaer/tandy13h/679e267342688abaa778f42d652321c01722a980/tandy13h.com --------------------------------------------------------------------------------