├── PORT.ASM ├── TNDY.ASM ├── TNDY.COM ├── 386PDEF.ASM ├── 386PDT.ASM ├── 386PINT.ASM ├── 386PLIB.ASM ├── 386PDATA.ASM ├── 386PREAL.ASM ├── 386RDATA.ASM ├── LICENSE ├── README.md └── STRINGS.INC /PORT.ASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JKnipperts/TNDY/HEAD/PORT.ASM -------------------------------------------------------------------------------- /TNDY.ASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JKnipperts/TNDY/HEAD/TNDY.ASM -------------------------------------------------------------------------------- /TNDY.COM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JKnipperts/TNDY/HEAD/TNDY.COM -------------------------------------------------------------------------------- /386PDEF.ASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JKnipperts/TNDY/HEAD/386PDEF.ASM -------------------------------------------------------------------------------- /386PDT.ASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JKnipperts/TNDY/HEAD/386PDT.ASM -------------------------------------------------------------------------------- /386PINT.ASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JKnipperts/TNDY/HEAD/386PINT.ASM -------------------------------------------------------------------------------- /386PLIB.ASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JKnipperts/TNDY/HEAD/386PLIB.ASM -------------------------------------------------------------------------------- /386PDATA.ASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JKnipperts/TNDY/HEAD/386PDATA.ASM -------------------------------------------------------------------------------- /386PREAL.ASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JKnipperts/TNDY/HEAD/386PREAL.ASM -------------------------------------------------------------------------------- /386RDATA.ASM: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JKnipperts/TNDY/HEAD/386RDATA.ASM -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Jan Knipperts, i386 protected mode library by Andrew Zabolotny 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TNDY 2 | Driver for Matze79's TNDY and Serdaco's TNDLPT sound devices. Still in development. 3 | 4 | This is a small DOS TSR program that redirects access to the I/O ports 0C0h or 205h (Tandy and PS/2 ports for audio) to the possible I/O ports of Matze79's TNDY ISA card or the parallel port for Serdacos's TNDLPT adapter. 5 | To make this possible, the processor is switched to V86 mode. Does not work if EMM386 or another memory manager is loaded. 6 | 7 | This driver is still in development and you might run into some bugs testing it. Many games already work very well with it but some crash or cause a Genereal Protection Fault. The use of smartdrv also causes a GPF. 8 | 9 | I would like to point out that the code I use to switch the computer into protected / V86 mode is not my own work. I am using the i386 protected mode library with only minor modifications for this. This library was written back in 1993 by Andrew Zabolotny. Kindly, he decided to release his source code to the public and all he reasonably asks for in return is his continued attribution for his work. See the source of TEMU Tandy emulator and VSB Visual Sound Blaster for more details: https://github.com/volkertb/temu-vsb 10 | 11 | And see the TNDLPT driver by Peter De Wachter for for a different approach using memory mangers port forwarding routines: https://github.com/pdewacht/tndlpt 12 |        13 | 14 | -------------------------------------------------------------------------------- /STRINGS.INC: -------------------------------------------------------------------------------- 1 | ;String handling routines 2 | ;v 1.0 - June 2000 by Jan Knipperts 3 | ;Note: Strings must be 0 terminated 4 | 5 | 6 | ; ================================================================== 7 | ; string_length - Return length of a string 8 | ; 9 | ; IN: AX = string location 10 | ; 11 | ; OUT: AX = length (other regs preserved) 12 | ; ==========================7======================================== 13 | string_length: 14 | push gs ; The GS register can be used as temp store (386+) 15 | pusha 16 | 17 | mov bx, ax ; Move location of string to BX 18 | 19 | xor cx, cx ; Counter CX = 0 20 | 21 | .l_more: 22 | xor al,al 23 | cmp byte [bx], al ; Zero (end of string) yet? 24 | je .l_done 25 | inc bx ; If not, keep adding 26 | inc cx 27 | jmp .l_more 28 | 29 | .l_done: 30 | mov gs, cx ; Store count before restoring other registers 31 | popa 32 | 33 | mov ax, gs ; Put count back into AX before returning 34 | pop gs 35 | ret 36 | 37 | ; ================================================================== 38 | ; string_uppercase - Convert zero-terminated string to upper case 39 | ; 40 | ; IN: AX = string location 41 | ; 42 | ; OUT: AX = string location 43 | ; ================================================================== 44 | string_uppercase: 45 | pusha 46 | mov si, ax ; Use SI to access string 47 | 48 | .u_more: 49 | mov al,0 50 | cmp byte [si], al ; Zero-termination of string? 51 | je .done ; If so, quit 52 | 53 | mov al,'a' 54 | cmp byte [si], al ; In the lower case A to Z range? 55 | jb .noatoz 56 | mov al,'z' 57 | cmp byte [si], al 58 | ja .noatoz 59 | 60 | mov al,20h 61 | sub byte [si], al ; If so, convert input char to upper case 62 | 63 | inc si 64 | jmp .u_more 65 | 66 | .noatoz: 67 | inc si 68 | jmp .u_more 69 | 70 | .done: 71 | popa 72 | ret 73 | 74 | 75 | ; ------------------------------------------------------------------ 76 | ; string_parse -- Take string (eg "run foo bar baz") and return 77 | ; pointers to zero-terminated strings (eg AX = "run", BX = "foo" etc.) 78 | ; IN: SI = string; OUT: AX, BX, CX, DX = individual strings 79 | 80 | string_parse: 81 | push si 82 | 83 | mov ax, si ; AX = start of first string 84 | 85 | lodsb ; Get a byte 86 | cmp al,0 ; End of string? 87 | je .finish 88 | cmp al, ' ' ; A space? 89 | jne .clear_adr 90 | mov ax,si ; Update start of first string 91 | 92 | .clear_adr: 93 | xor bx, bx ; By default, other strings start empty 94 | xor cx, cx ; Therefore we set BX, CX and DX to 0 95 | xor dx, dx 96 | 97 | push ax ; Save to retrieve at end 98 | 99 | .loop1: 100 | lodsb ; Get a byte 101 | cmp al,0 ; End of string? 102 | je .finish 103 | cmp al, ' ' ; A space? 104 | jne .loop1 105 | sub si,2 106 | mov al,0 107 | mov byte [si],al ; If so, zero-terminate this bit of the string 108 | 109 | add si,2 ; Store start of next string in BX 110 | mov bx, si 111 | 112 | .loop2: ; Repeat the above for CX and DX... 113 | lodsb 114 | cmp al,0 115 | je .finish 116 | cmp al, ' ' 117 | jne .loop2 118 | sub si,2 119 | mov al,0 120 | mov byte [si], al 121 | 122 | add si,2 123 | mov cx, si 124 | 125 | .loop3: 126 | lodsb 127 | cmp al,0 128 | je .finish 129 | cmp al,' ' 130 | jne .loop3 131 | sub si,2 132 | mov al,0 133 | mov byte [si], al 134 | add si,2 135 | mov dx, si 136 | 137 | .finish: 138 | pop ax 139 | 140 | pop si 141 | ret 142 | 143 | 144 | ; ------------------------------------------------------------------ 145 | ; write_string -- Writes 0 terminated string to the screen and returns 146 | ; IN: SI = string; 147 | 148 | write_string: 149 | push dx 150 | push cx 151 | push ax 152 | 153 | xor cx,cx 154 | Length_Loop: 155 | lodsb 156 | inc cx 157 | cmp al,0 158 | jne Length_Loop 159 | sub si,cx 160 | 161 | Write_Loop: 162 | lodsb 163 | mov dl,al 164 | mov ah,2 165 | int 21h 166 | loop Write_Loop 167 | 168 | pop dx 169 | pop cx 170 | pop ax 171 | 172 | ret 173 | 174 | ; ------------------------------------------------------------------ 175 | ; string_compare -- See if two strings match 176 | ; IN: SI = string one, DI = string two 177 | ; OUT: carry set if same, clear if different 178 | 179 | string_compare: 180 | pusha 181 | 182 | .c_more: 183 | mov al, [si] ; Retrieve string contents 184 | mov bl, [di] 185 | 186 | cmp al, bl ; Compare characters at current location 187 | jne .not_same 188 | 189 | cmp al, 0 ; End of first string? Must also be end of second 190 | je .terminated 191 | 192 | inc si 193 | inc di 194 | jmp .c_more 195 | 196 | .not_same: ; If unequal lengths with same beginning, the byte 197 | popa ; comparison fails at shortest string terminator 198 | clc ; Clear carry flag 199 | ret 200 | 201 | .terminated: ; Both strings terminated at the same position 202 | popa 203 | stc ; Set carry flag 204 | ret 205 | --------------------------------------------------------------------------------