From cb6c00f1a3dc82e68b0b35d4dcaf92fc47c14671 Mon Sep 17 00:00:00 2001 From: sparky4 Date: Mon, 20 Jul 2015 20:22:46 -0500 Subject: [PATCH] ok new file: 16/EMS.BAS modified: src/lib/16_mm.c --- 16/EMS.BAS | 425 ++++++++++++++++++++++++++++++++++++++++++++++++ src/lib/16_mm.c | 4 +- 2 files changed, 427 insertions(+), 2 deletions(-) create mode 100644 16/EMS.BAS diff --git a/16/EMS.BAS b/16/EMS.BAS new file mode 100644 index 00000000..a82b1be6 --- /dev/null +++ b/16/EMS.BAS @@ -0,0 +1,425 @@ +' Using EMS in QuickBASIC: Part 1 of 3 +' Source Code +' +' By Jon Petrosky (Plasma) +' www.phatcode.net +' +' [Remember to start QB with the /L switch to enable interrupts] + +DEFINT A-Z +'$DYNAMIC +'$INCLUDE: 'QB.BI' + +DIM SHARED Regs AS RegTypeX +DIM SHARED EMS.Error 'Holds the error code of the last operation + +DECLARE FUNCTION EMS.ErrorMsg$ () +DECLARE FUNCTION EMS.Init () +DECLARE FUNCTION EMS.Version$ () +DECLARE FUNCTION EMS.PageFrame () +DECLARE FUNCTION EMS.FreeHandles () +DECLARE FUNCTION EMS.FreePages () +DECLARE FUNCTION EMS.TotalPages () +DECLARE FUNCTION EMS.AllocPages (NumPages) +DECLARE SUB EMS.DeallocPages (Handle) +DECLARE SUB EMS.MapPage (Physical, Logical, Handle) +DECLARE SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle) +DECLARE SUB EMS.CopyMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset) +DECLARE SUB EMS.ExchMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset) + +CLS + +IF NOT EMS.Init THEN + PRINT "No EMM detected." + END +END IF + +COLOR 14, 1 +PRINT SPACE$(22); "Using EMS in QuickBasic: Part 1 of 3"; SPACE$(22) +COLOR 15, 0 +PRINT STRING$(31, 196); " EMS Information "; STRING$(32, 196) +COLOR 7 +PRINT "EMM Version: "; EMS.Version$ + +IF EMS.Version$ < "4.0" THEN + PRINT + PRINT "EMM 4.0 or later must be present to use some of the EMS functions." + END +END IF + +PRINT "Page frame at: "; HEX$(EMS.PageFrame); "h" +PRINT "Free handles:"; EMS.FreeHandles + +IF EMS.FreeHandles = 0 THEN + PRINT + PRINT "You need at least one free handle to run this demo." + END +END IF + +PRINT "Total EMS:"; EMS.TotalPages; "pages /"; EMS.TotalPages * 16&; "KB /"; EMS.TotalPages \ 64; "MB" +PRINT "Free EMS:"; EMS.FreePages; "pages /"; EMS.FreePages * 16&; "KB /"; EMS.FreePages \ 64; "MB" + +IF EMS.FreePages < 64 THEN + PRINT + PRINT "You need at least 64 pages (1 MB) free EMS to run this demo." + END +END IF + +PRINT +COLOR 15, 0 +PRINT STRING$(31, 196); " Allocation Test "; STRING$(32, 196) +COLOR 7 +PRINT "Allocating 64 pages (1 MB) of EMS..."; + +Handle = EMS.AllocPages(64) +IF EMS.Error THEN + PRINT "error!" + PRINT EMS.ErrorMsg$ + END +ELSE + PRINT "ok!" +END IF + +PRINT "Pages allocated to handle"; Handle +PRINT +COLOR 15, 0 +PRINT STRING$(30, 196); " Page Map/Copy Test "; STRING$(30, 196) +COLOR 7 +PRINT "Mapping logical page 0 to physical page 0..."; + +EMS.MapPage 0, 0, Handle +IF EMS.Error THEN + PRINT "error!" + PRINT EMS.ErrorMsg$ + END +ELSE + PRINT "ok!" +END IF + +PRINT "Mapping logical pages 0-3 to physical pages 0-3..."; + +EMS.MapXPages 0, 0, 4, Handle +IF EMS.Error THEN + PRINT "error!" + PRINT EMS.ErrorMsg$ + END +ELSE + PRINT "ok!" +END IF + +PRINT "Copying logical pages 0-31 to logical pages 32-63..."; + +EMS.CopyMem 512288, Handle, 0, 0, Handle, 32, 0 +IF EMS.Error THEN + PRINT "error!" + PRINT EMS.ErrorMsg$ + END +ELSE + PRINT "ok!" +END IF + +PRINT "Exchanging logical pages 0-31 with logical pages 32-63..."; + +EMS.ExchMem 512288, Handle, 0, 0, Handle, 32, 0 +IF EMS.Error THEN + PRINT "error!" + PRINT EMS.ErrorMsg$ + END +ELSE + PRINT "ok!" +END IF + +PRINT +COLOR 15, 0 +PRINT STRING$(22, 196); " 10-Second Speed Test (Please Wait) "; STRING$(22, 196) +COLOR 7 + +Mapped& = 0 +StartTime! = TIMER +DO UNTIL StartTime! + 5 <= TIMER + EMS.MapXPages 0, 0, 4, Handle + Mapped& = Mapped& + 4 +LOOP + +Copied& = 0 +StartTime! = TIMER +DO UNTIL StartTime! + 5 <= TIMER + EMS.CopyMem 512288, Handle, 0, 0, Handle, 32, 0 + Copied& = Copied& + 1 +LOOP + +PRINT "Pages Mapped/Sec:"; Mapped& \ 5 +PRINT "Bytes copied/Sec:"; (Copied& * 512288) \ 5 +PRINT +COLOR 15, 0 +PRINT STRING$(30, 196); " Deallocation Test "; STRING$(31, 196) +COLOR 7 +PRINT "Deallocating 64 pages..."; + +EMS.DeallocPages (Handle) +IF EMS.Error THEN + PRINT "error!" + PRINT EMS.ErrorMsg$ + END +ELSE + PRINT "ok!"; +END IF + +KeyPress$ = INPUT$(1) +CLS +END + +FUNCTION EMS.AllocPages (NumPages) + + 'Allocates the number of pages in [NumPages] and + 'returns the EMS handle the memory is allocated to. + + Regs.ax = &H4300 'Allocate [NumPages] pages of EMS + Regs.bx = NumPages + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Store the status code + + EMS.AllocPages = Regs.dx 'Return the handle + +END FUNCTION + +SUB EMS.CopyMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset) + + 'Copies memory from EMS or base memory to EMS or base memory, where: + ' + 'Length& = Length of memory to copy in bytes + 'SrcHandle = EMS handle of source memory (use 0 if source is base memory) + 'SrcSegment = Segment of source memory (or page number if source is EMS) + 'SrcOffset = Offset of source memory + 'DstHandle = EMS handle of destination memory (use 0 if destination is base memory) + 'DstSegment = Segment of destination memory (or page number if destination is EMS) + 'DstOffset = Offset of destination memory + + 'Determine the source and destination memory types by checking the handles + IF SrcHandle = 0 THEN SrcType$ = CHR$(0) ELSE SrcType$ = CHR$(1) + IF DstHandle = 0 THEN DstType$ = CHR$(0) ELSE DstType$ = CHR$(1) + + 'Create a buffer containing the copy information + CopyInfo$ = MKL$(Length&) + SrcType$ + MKI$(SrcHandle) + MKI$(SrcOffset) + MKI$(SrcSegment) + DstType$ + MKI$(DstHandle) + MKI$(DstOffset) + MKI$(DstSegment) + + Regs.ax = &H5700 'Copy the memory region + Regs.ds = VARSEG(CopyInfo$) 'described in the buffer + Regs.si = SADD(CopyInfo$) + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Store the status code + +END SUB + +SUB EMS.DeallocPages (Handle) + + 'Deallocates the EMS pages allocated the EMS handle [Handle]. + 'You MUST remember to call the sub before your program ends + 'if you allocate any memory! + + Regs.ax = &H4500 'Release the pages allocated to [Handle] + Regs.dx = Handle + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Store the status code + +END SUB + +FUNCTION EMS.ErrorMsg$ + + 'Returns a text string describing the error code in EMS.Error. + + SELECT CASE EMS.Error + CASE &H0: Msg$ = "successful" + CASE &H80: Msg$ = "internal error" + CASE &H81: Msg$ = "hardware malfunction" + CASE &H82: Msg$ = "busy -- retry later" + CASE &H83: Msg$ = "invalid handle" + CASE &H84: Msg$ = "undefined function requested by application" + CASE &H85: Msg$ = "no more handles available" + CASE &H86: Msg$ = "error in save or restore of mapping context" + CASE &H87: Msg$ = "insufficient memory pages in system" + CASE &H88: Msg$ = "insufficient memory pages available" + CASE &H89: Msg$ = "zero pages requested" + CASE &H8A: Msg$ = "invalid logical page number encountered" + CASE &H8B: Msg$ = "invalid physical page number encountered" + CASE &H8C: Msg$ = "page-mapping hardware state save area is full" + CASE &H8D: Msg$ = "save of mapping context failed" + CASE &H8E: Msg$ = "restore of mapping context failed" + CASE &H8F: Msg$ = "undefined subfunction" + CASE &H90: Msg$ = "undefined attribute type" + CASE &H91: Msg$ = "feature not supported" + CASE &H92: Msg$ = "successful, but a portion of the source region has been overwritten" + CASE &H93: Msg$ = "length of source or destination region exceeds length of region allocated to either source or destination handle" + CASE &H94: Msg$ = "conventional and expanded memory regions overlap" + CASE &H95: Msg$ = "offset within logical page exceeds size of logical page" + CASE &H96: Msg$ = "region length exceeds 1 MB" + CASE &H97: Msg$ = "source and destination EMS regions have same handle and overlap" + CASE &H98: Msg$ = "memory source or destination type undefined" + CASE &H9A: Msg$ = "specified alternate map register or DMA register set not supported" + CASE &H9B: Msg$ = "all alternate map register or DMA register sets currently allocated" + CASE &H9C: Msg$ = "alternate map register or DMA register sets not supported" + CASE &H9D: Msg$ = "undefined or unallocated alternate map register or DMA register set" + CASE &H9E: Msg$ = "dedicated DMA channels not supported" + CASE &H9F: Msg$ = "specified dedicated DMA channel not supported" + CASE &HA0: Msg$ = "no such handle name" + CASE &HA1: Msg$ = "a handle found had no name, or duplicate handle name" + CASE &HA2: Msg$ = "attempted to wrap around 1M conventional address space" + CASE &HA3: Msg$ = "source array corrupted" + CASE &HA4: Msg$ = "operating system denied access" + CASE ELSE: Msg$ = HEX$(EMS.Error) '"undefined error" + END SELECT + + EMS.ErrorMsg$ = Msg$ + +END FUNCTION + +SUB EMS.ExchMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset) + + 'Exhanges memory from EMS or base memory to EMS or base memory, where: + ' + 'Length& = Length of memory to exchange in bytes + 'SrcHandle = EMS handle of source memory (use 0 if source is base memory) + 'SrcSegment = Segment of source memory (or page number if source is EMS) + 'SrcOffset = Offset of source memory + 'DstHandle = EMS handle of destination memory (use 0 if destination is base memory) + 'DstSegment = Segment of destination memory (or page number if destination is EMS) + 'DstOffset = Offset of destination memory + + 'Determine the source and destination memory types by checking the handles + IF SrcHandle = 0 THEN SrcType$ = CHR$(0) ELSE SrcType$ = CHR$(1) + IF DstHandle = 0 THEN DstType$ = CHR$(0) ELSE DstType$ = CHR$(1) + + 'Create a buffer containing the copy information + ExchInfo$ = MKL$(Length&) + SrcType$ + MKI$(SrcHandle) + MKI$(SrcOffset) + MKI$(SrcSegment) + DstType$ + MKI$(DstHandle) + MKI$(DstOffset) + MKI$(DstSegment) + + Regs.ax = &H5701 'Exchange the memory region + Regs.ds = VARSEG(ExchInfo$) 'described in the buffer + Regs.si = SADD(ExchInfo$) + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Store the status code + +END SUB + +FUNCTION EMS.FreeHandles + + 'Returns the number of free (available) EMS handles. + + Regs.ax = &H4B00 'Get the # of handles in use + InterruptX &H67, Regs, Regs + UsedHandles = Regs.bx + + Regs.ax = &H5402 'Get the total # of handles + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Store the status code + TotalHandles = Regs.bx + + EMS.FreeHandles = TotalHandles - UsedHandles 'Subtract to get the # of free handles + +END FUNCTION + +FUNCTION EMS.FreePages + + 'Returns the number of free (available) EMS pages + '(Multiply by 16 to get the amount free EMS in KB.) + + Regs.ax = &H4200 'Get the # of free pages + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Store the status code + EMS.FreePages = Regs.bx + +END FUNCTION + +FUNCTION EMS.Init + + 'Returns true (-1) if an EMM is installed + 'or false (0) if an EMM is not installed. + + Regs.ax = &H3567 'Get the interrupt vector for int 67h + InterruptX &H21, Regs, Regs + DEF SEG = Regs.es 'Point to the interrupt segment + FOR x = 10 TO 17 'Store the 8 bytes at ES:0A in EMM$ + EMM$ = EMM$ + CHR$(PEEK(x)) + NEXT + IF EMM$ <> "EMMXXXX0" THEN + EMS.Init = 0 'EMM not installed + ELSE + EMS.Init = -1 'EMM installed + END IF + +END FUNCTION + +SUB EMS.MapPage (Physical, Logical, Handle) + + 'Maps the logical EMS page [Logical] (allocated to the handle [Handle]) + 'to the physical page [Physical] in the EMS page frame. + + Regs.ax = &H4400 + Physical 'Map the logical page [Logical] + Regs.bx = Logical 'to the physical page [Physical] + Regs.dx = Handle + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Store the status code + +END SUB + +SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle) + + 'Maps up to 4 logical EMS pages to physical pages in the page frame, where: + ' + 'PhysicalStart = Physical page first logical page is mapped to + 'LogicalStart = First logical page to map + 'NumPages = Number of pages to map (1 to 4) + 'Handle = EMS handle logical pages are allocated to + + 'Create a buffer containing the page information + FOR x = 0 TO NumPages - 1 + MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x) + NEXT + + Regs.ax = &H5000 'Map the pages in the buffer + Regs.cx = NumPages 'to the pageframe + Regs.dx = Handle + Regs.ds = VARSEG(MapInfo$) + Regs.si = SADD(MapInfo$) + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Store the status code + +END SUB + +FUNCTION EMS.PageFrame + + 'Returns the segment of the EMS page frame + + Regs.ax = &H4100 'Get the segment of the page frame + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Save the status code + EMS.PageFrame = Regs.bx + +END FUNCTION + +FUNCTION EMS.TotalPages + + 'Returns the total number of EMS pages + '(Multiply by 16 to get the total amount of EMS in KB.) + + Regs.ax = &H4200 'Get the # of total pages + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Store the status code + EMS.TotalPages = Regs.dx + +END FUNCTION + +FUNCTION EMS.Version$ + + 'Returns a string containing the EMM version. + '(Must be "4.0" or greater to use our routines.) + + Regs.ax = &H4600 'Get the EMM version + InterruptX &H67, Regs, Regs + EMS.Error = (Regs.ax AND &HFF00&) \ &H100 'Save the status code + + Version = Regs.ax AND &HFF 'Split the version number into + Major = (Version AND &HF0) \ &H10 'its major and minor counterparts + Minor = Version AND &HF + EMS.Version$ = LTRIM$(STR$(Major)) + "." + LTRIM$(STR$(Minor)) + +END FUNCTION + diff --git a/src/lib/16_mm.c b/src/lib/16_mm.c index 78aa5185..d6ce8743 100644 --- a/src/lib/16_mm.c +++ b/src/lib/16_mm.c @@ -313,10 +313,10 @@ void MM_MapXEMS(mminfo_t *mm) //NumPages = Number of pages to map (1 to 4) //Handle = EMS handle logical pages are allocated to - //Create a buffer containing the page information + /*//Create a buffer containing the page information // FOR x = 0 TO NumPages - 1 // MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x) -// NEXT +// NEXT*/ // Regs.ax = &H5000 //Map the pages in the buffer // Regs.cx = NumPages //to the pageframe -- 2.39.5