+++ /dev/null
-;; Error messages\r
-ERR_OK EQU 0\r
-msgErr0 db 'Later!',13,10,'$'\r
-ERR_MEM EQU 1\r
-msgErr1 db 'Error 001: Out of memory?',13,10,'$'\r
-ERR_CPU EQU 2\r
-msgErr2 db 'Error 002: CPU must be at least an 80386.',13,10,'$'\r
-ERR_FILE EQU 3\r
-msgErr3 db 'Error 003: File error.',13,10,'$'\r
-ERR_FILENOTFOUND EQU 4\r
-msgErr4 db 'Error 004: File not found.',13,10,'$'\r
-msgtblError dw offset msgErr0, offset msgErr1, offset msgErr2,\r
- offset msgErr3, offset msgErr4\r
-nError db 0\r
-\r
-;; CPU name strings\r
-CPUName86 DB "8088/8086$"\r
-CPUName286 DB "80286DX/SX$"\r
-CPUName386 DB "80386DX/SX$"\r
-CPUName486 DB "80486DX/SX or better$"\r
-CPUNameTable DW CPUName86,CPUName286,CPUName386,CPUName486\r
-\r
-EVEN\r
-msgCPUTypeIs DB "Your CPU type: $"\r
-EVEN\r
-msgCPUTypeIsEnd DB 13,10,'$'\r
-nCPU DB 0\r
-\r
-EVEN\r
-msgPages DB 'Pages displayed: '\r
-strNumPages DB 6 dup (?),13,10,'$'\r
-\r
-EVEN\r
-bufText DW 80*50 DUP (?) ; Needs this much to hold\r
- ; a 50-line screen...\r
-wCPos DW 0\r
-nDisplay DB 0\r
-\r
-EVEN\r
-fnMap1 db 'DIAGONAL.MAP',0\r
-fnTiles1 db 'DIAGONAL.TIL',0\r
-fnPalette db 'DIAGONAL.PAL',0 ; only one allowed, for now\r
-fnMap2 db 'SCROLL.MAP',0\r
-fnTiles2 db 'SCROLL.TIL',0\r
-\r
-fntblMap dw offset fnMap1,offset fnMap2\r
-fntblTiles dw offset fnTiles1,offset fnTiles2\r
-nMap dw 0\r
-\r
-;; CPUType routine snatched from Ray Duncan's _Power Programming MASM_\r
-;; chapter 14. Reformatted to my style, but I left the code alone\r
-;; except that it used to push a bunch of stuff, but doesn't any more\r
-;; because I don't care what gets destroyed.\r
-CPUType PROC near\r
- pushf ; now try to clear bits 12-15\r
- pop ax ; of CPU flags\r
- and ax,0fffh\r
- push ax ; set modified CPU flags\r
- popf\r
- pushf\r
- pop ax ; get flags again\r
- and ax,0f000h ; if bits 12-15 are still\r
- cmp ax,0f000h ; set, this is 8086/88\r
- jne cpu1 ; jump, not 8086/88\r
- mov nCPU,CPU8086 ; set nCPU = 86/88 CPU type\r
- jmp cpux ; and exit\r
-\r
-cpu1: or ax,0f000h ; must be 286 or later,\r
- push ax ; now try to set bits 12-15\r
- popf ; of CPU flags\r
- pushf\r
- pop ax ; if bits 12-15 can't be\r
- and ax,0f000h ; set, this is a 286\r
- jnz cpu2 ; jump, not 80286\r
- mov nCPU,CPU80286 ; set nCPU = 286 CPU type\r
- jmp cpux ; and exit\r
-\r
-cpu2: mov bx,sp ; 386 or later, save SP\r
- and sp,not 3 ; avoid stack alignment fault\r
- pushfd ; get value of EFLAGS\r
- pop eax\r
- mov ecx,eax ; save copy of EFLAGS\r
- xor eax,40000h ; flip AC bit in EFLAGS\r
- push eax ; try and force EFLAGS\r
- popfd\r
- pushfd ; get back EFLAGS value\r
- pop eax\r
- mov sp,bx ; restore old stack pointer\r
- xor eax,ecx ; can AC bit be changed?\r
- jnz cpu3 ; no, jump, not a 386\r
- mov nCPU,CPU80386 ; set nCPU = 386 CPU type\r
- jmp cpux ; and exit\r
-\r
-cpu3: mov nCPU,CPU80486 ; set nCPU = 486 CPU type\r
-\r
-cpux: mov bl,nCPU\r
- xor bh,bh\r
- shl bx,1\r
- DOSPRINT <offset msgCPUTypeIs>\r
- DOSPRINT CPUNameTable[bx]\r
- DOSPRINT <offset msgCPUTypeIsEnd>\r
- ret ; return with nCPU = CPU type\r
-CPUType ENDP\r
-\r
-;; Initialize: So far, all it does is make sure you have a 386 +\r
-;; (because that's what I assembled the code for).\r
-Initialize PROC near\r
- ; Set DS = CS in this program, since data is local\r
- mov ax,cs\r
- mov segCode,ax ; Store the Code Segment\r
- mov bx,ds\r
- mov segPSP,bx ; Store the PSP Segment\r
- mov ds,ax ; Set DS = CS\r
-\r
- ; Resize code to 64K\r
- CODE_SIZE EQU 64 ; <- this is arbitrary.\r
- ; ES already -> allocated segment\r
- mov ah,4ah\r
- mov bx,64*CODE_SIZE\r
- int 21h\r
- mov nError,ERR_MEM\r
- jc TerminateError\r
-\r
-;; I've chosen not to implement sprites yet so that I can get this out\r
-;; the door...\r
-;; ; 320x200 buffer for sprite drawing. To draw sprites, first draw them\r
-;; ; into this buffer, adding rectangles to the current rectangle list.\r
-;; ; Then, use BUFFER_COPY to put out the buffers with the current\r
-;; ; rectangle list to the screen. BUFFER_COPY will ensure minimal VGA\r
-;; ; writing.\r
-;; ; Create a buffer segment\r
-;; mov bx,(320 * 200) / 16\r
-;; mov ah,48h\r
-;; int 21h\r
-;; mov nError,ERR_MEM\r
-;; jc TerminateError\r
-;; mov segBuffer,ax\r
-\r
- call CPUType\r
- mov nError,ERR_CPU\r
- cmp nCPU,2\r
- jl TerminateError\r
-\r
- mov ds,segCode\r
- mov dx,offset fnPalette\r
- call LoadPaletteFile\r
- jc TerminateError\r
-\r
- call LoadIndex\r
- jc TerminateError\r
-\r
- KEYB_START\r
-\r
- call Beginning ; Can display an entry screen here\r
-\r
- ; This is linked in from Michael Abrash's zen timer code.\r
- ; (But I wrote the Click myself)\r
- call Click\r
- call ZTimerOn\r
-\r
- call MainLoop\r
-\r
- call ZTimerOff\r
- call Click\r
-\r
- call Ending ; Can display an exit screen here\r
-\r
- KEYB_END\r
-\r
-Terminate: mov nError,ERR_OK\r
-TerminateError:\r
- mov ax,cs ;DOS functions require that DS point\r
- mov ds,ax ; to text to be displayed on the screen\r
- mov bh,0\r
- mov bl,nError\r
- shl bx,1\r
- DOSPRINT msgtblError[bx]\r
-\r
- mov ax,pages\r
- mov ds,segCode\r
- mov si,offset strNumPages\r
- call Int2Ascii\r
- DOSPRINT <offset msgPages>\r
-\r
- call ZTimerReport\r
-\r
- mov al,nError\r
- mov ah,4ch ; DOS Terminate\r
- int 21h\r
- ; Don't need to RET! We're outta here\r
-Initialize ENDP\r
-\r
-;; Clicks the internal speaker. I use this to indicate that page timing\r
-;; has started.\r
-Click PROC\r
- in al,61h\r
- mov ah,al\r
- or al,3\r
- out 61h,al\r
-\r
- mov cx,5000 ; (this is an arbitrary delay!)\r
-spkr_on: loop spkr_on\r
- mov al,ah\r
- out 61h,al\r
- ret\r
-Click ENDP\r
-\r
-;; Copied from an old 8088 "Learn Assembly" book and changed a bit\r
-Int2Ascii PROC\r
- mov cx,6\r
- mov byte ptr cs:[si],' '\r
- mov byte ptr cs:[si+1],'0'\r
- mov byte ptr cs:[si+2],'0'\r
- mov byte ptr cs:[si+3],'0'\r
- mov byte ptr cs:[si+4],'0'\r
- mov byte ptr cs:[si+5],'0'\r
- add si,6\r
- mov cx,10\r
- or ax,ax\r
- jns clear_divide\r
- neg ax\r
- mov byte ptr cs:[si-6],'-'\r
-clear_divide: mov dx,0\r
- div cx\r
- add dx,'0'\r
- dec si\r
- mov cs:[si],dl\r
- or ax,ax\r
- jnz clear_divide\r
- ret\r
-Int2Ascii ENDP\r
-\r
-;; Given a filename at DS:DX, reads the file into memory and returns\r
-;; a pointer to it as DX:0000.\r
-;; Note that this routine obviously will only work correctly for\r
-;; a file < 640k in size, but you can bring in files bigger than 64k.\r
-;; This code comes from Future Crew's STMIK sampler "Mental Surgery"\r
-;; and I commented it up to make it fit in with my stuff a little better.\r
-;; Thank you, FC, for releasing that code! Several of the routines\r
-;; in this program were inspired or helped along by having that source...\r
-;; Most recently, added in error codes.\r
-EVEN\r
-LoadFile PROC NEAR\r
- ;set: DX=offset to filename\r
- ;return: DX=segment of file\r
-\r
- ; Open the datafile at DS:DX.\r
- mov ax,3D00h ; 3D,00 -> Open file, read only\r
- ; DS:DX already points at filename\r
- int 21h ; returns AX=file handle\r
- mov cl,ERR_FILENOTFOUND\r
- jc ferror\r
- mov bx,ax ; Store file handle in BX\r
- mov si,bx ; and also in a variable\r
-\r
- ; Get the length of the file so we know how much to allocate\r
- mov ax,4202h ; 42,02 -> Seek, signed from end\r
- mov cx,0 ; CX:DX is a long file offset,\r
- ; BX is already set as file handle\r
- mov dx,0 ; zero in this case = end of file\r
- int 21h ; (returns long offset in DX:AX)\r
- mov cl,ERR_FILE\r
- jc ferror\r
-\r
-;;; shr dx,1 ; This is original FC code,\r
-;;; rcr ax,1 ; which I removed because the\r
-;;; shr dx,1 ; 386 has a nice instruction\r
-;;; rcr ax,1 ; to do this all!\r
-;;; shr dx,1 ; But 286 users will want to\r
-;;; rcr ax,1 ; return to this code, instead\r
-;;; shr dx,1 ; of SHRD dx,ax,4\r
-;;; rcr ax,1 ;\r
-\r
- ; Now turn that long DX:AX into a number of paragraphs to allocate\r
- ; for when we read the file.\r
- shrd ax,dx,4 ; Divides long DX:AX by 4,\r
- mov bx,ax ; and stores this in BX\r
- inc bx ; HHMMMM? One more needed for small #'s\r
- mov ah,48h ; 48 -> Allocate memory\r
- ; BX already = # of paragraphs\r
- int 21h\r
- mov cl,ERR_MEM\r
- jc ferror\r
- mov di,ax ; store this in a variable\r
-\r
- ; Seek the file back to the beginning in order to read it into\r
- ; the memory we just allocated.\r
- mov ax,4200h ; 42,00 -> Seek, absolute offset\r
- mov bx,si ; BX is the file handle.\r
- mov cx,0 ; CX:DX is a long offset\r
- mov dx,0\r
- int 21h\r
- jc ferror\r
-\r
- ; Now read the file into memory\r
- mov ds,di ; DS points at alloc'd memory\r
-ReadBlock: mov ah,3fh ; 3F -> Read file\r
- mov cx,32768 ; read 32768 bytes at a time\r
- mov dx,0 ; DS:DX points at beginning of\r
- int 21h ; this block of memory.\r
- mov cl,ERR_FILE\r
- jc ferror\r
- mov dx,ds ; Offset DS by (32768/16), which\r
- add dx,800h ; is the number of paragraphs in\r
- mov ds,dx ; each block of 32768 bytes.\r
- cmp ax,32768 ; Did we actually read 32768 bytes?\r
- je ReadBlock ; If so, there's more to read...\r
- ; Otherwise, we've read all the\r
- ; data in the file.\r
-\r
- ; So now, close the file handle.\r
- mov ah,3Eh ; 3E -> Close file\r
- ; BX still is the file handle\r
- int 21h\r
-\r
- ; Everything went ok. Return the segment in DX.\r
- mov dx,di\r
- mov nError,ERR_OK\r
- ret\r
-ferror: mov nError,cl\r
- ret\r
-LoadFile ENDP\r
-\r
-;; Eventually, this should load in an index of all data files to\r
-;; allow for filenames to be specified outside of the program. The\r
-;; goal is to make the program have no hardcoded filenames...\r
-;; Of course, the structure of this index and its entries will be\r
-;; hardcoded, as will the structures of all of the files it includes.\r
-LoadIndex PROC near\r
- ret\r
-LoadIndex ENDP\r
-\r
-;; Save the current video mode and cursor position with standard\r
-;; BIOS calls\r
-SaveVideo PROC near\r
- mov ah,0Fh\r
- int 10h ; Get current display Mode\r
- mov nDisplay,al\r
- mov ah,03h\r
- mov bh,0\r
- int 10h\r
- mov wCPos,dx\r
-\r
- mov ds,segText\r
- mov si,0\r
- mov es,segCode\r
- mov di,offset bufText\r
- mov cx,80*50\r
- rep movsw\r
- ret\r
-SaveVideo ENDP\r
-\r
-;; Restore the current video mode and cursor position with standard\r
-;; BIOS calls\r
-RestoreVideo PROC near\r
- mov ah,00h\r
- mov al,nDisplay\r
- int 10h ; Get current display Mode\r
- mov ah,02h\r
- mov bh,0\r
- mov dx,wCPos\r
- int 10h\r
-\r
- PAL_UPDATE ; When flipping into text mode, re-do the\r
- ; palette because the BIOS changes it.\r
-\r
- mov es,segText\r
- mov di,0\r
- mov ds,segCode\r
- mov si,offset bufText\r
- mov cx,80*50\r
- rep movsw\r
- ret\r
-RestoreVideo ENDP\r
-\1a
\ No newline at end of file