{ This is the doc file of mapper.inc }
{Kari Lammassaari /Finland }

MAPPER.INC requires MSXDOS2, beacuse it uses EXTBIO hook at #ffca .

MAPPER.INC makes possible to allocate, free ,read , write and call any of 
the pages in memory mappers available . So Your Turbo Pascal can use and 
utilize all the memory of Your MSX computer.

MAPPER.INC allows your program to load a machine code on any page and call it 
from there (Input/return values in a,bc,de,hl,ix and iy ). 


REM ! USE MapperSupport function to check availability of mapper support and 
      initialize mapper.inc variables !

REM ! All procedures and functions use temporary stack at #fbaf (at the end 
      of VCBC)

MAPPER.INC contains following contants, types, variables, procedures and
fuctions:

Const UserPage = 0 ; {This pagetype is automaticly free'ed upon the end of the
		      user program.}
      SystemPage = 1;{This pagetype remains allocated until free'ed by 
		      FreeMapperPage.
                      LoadChnFile and LoadMCFile use this type.} 
	
Type MapperTableType = Record       {Every memory mapper has this table entry.}   
                         SlotId     :Byte;
			 PagesTotal :Byte;
                         PagesFree  :Byte;
                         PagesSystem:Byte; 
                         PagesUser :Byte; 
                         Dummy1,Dummy2,Dummy3 :Byte;
                       End;

    MapperTablePtrType = ^MapperTableType;  {Used internally}

Var MapperCount     :Byte;
    MapperTablePtr  :MapperTablePtrType;
    MapperTableAddr :Integer Absolute MapperTablePtr;
    PrimaryMapper   :Byte;     {Updated by function MapperSupport} 
    SecondaryMapper :Byte;     {If there is only one mapper SecondM = PrimM }

    WantedMapper    :Byte;     {You can set this to Primary/SecondaryMapper.} 	
                               {Defaults PrimaryMapper, which is faster.}

    JumpTablePtr    :Integer;  {Addr of mapper support routine jump table}
			   
    bc,de,hl,ix,iy  :Integer; {These return values from CallMapperPage. }


Function MapperSupport(Var MapperCount:Byte):Boolean; 
   {
   Checks the existence of mapper support and initializes Turbo Pascal
   mapper variables MapperCount,MapperTablePtr,MapperTableAddr,PrimaryMapper
   SecondaryMapper,WantedMapper and JumpTablePtr.

   The WantedMapper defaults faster PrimaryMapper, but You can set it to
   SecondaryMapper, if You prefer it in some cases.
 
   MapperCount returns, ofcourse, the number of memory mappers available.

   If You have more than 2 mappers, Secondary mapper Refers actually the last 
   mapper, but don't worry: System will use all memory available ! First the
   WantedMapper then the others.
 
   REM PrimaryMapper (slot_id) contains some extra bits (bit 5 is set) to
       force search annother mapper if primary mapper is already exhausted.)

    } 


Function AllocateMapperPage(    SlotType,PageType :Byte;
    			    Var PageId            :Integer ):Boolean;
   {
    Allocates one Mapper page. PageType can be UserPage (0) or SystemPage (1).
    SlotType can be PrimaryMapper, SecondaryMapper, WantedMapper or
    any legal (and reasonable ) slot id. 

    Returns an true,if there was a free mapperpage to allocate. 

    The returned integer value, PageId, will be used with WriteMapperPage,
    RadMapperpage, FreeMapperPage and CallMapperPage-procedures.

    Low byte of integer contains slot id of allocated page. High byte
    contains the page number. 
   }


Function FreeMapperPage(PageId:Integer):Boolean;
   {
    Frees allocated mapperpage back to system. The pages allocated as 
    SystemPage will remain allocated after the program end. So free them,
    if they are no more needed. UserPages will be free'ed automaticly.
    
    Returns true if freeing succeeded. If not, the PageId was invalid.
   }


Procedure CallMapperPage(   SlotId,PageNumber :Byte;
			    CallAddress       :Integer;
                        Var A		      :Byte;
			Var BC,DE,HL,IX,IY    :Integer
                         );

   {
    Calls an routine in any mapper page in any slot.

    Ofcourse there must be an allocated page containig reasonable code 
    before using this procedure.
    If You , for some reason, want to use this procedure, use syntax:
    'CallMapperPage( Lo(PageId),Hi(PageId),CallAddress,a,bc,de,hl,ix,iy);'.

    The called routine can set return values in registers A,BC,DE,HL,IX and IY.
   }


Function GetPage(MemoryAddress:Integer):Byte ;

   {
    Gets the current page number of the mapper page.
    Used Internally.
   }


Procedure PutPage(MemoryAddress:Integer;Page:Byte);
  
   {
    Sets the  mapper page.
    Used Internally.

    REM. You are not allowed to change the page on MemorySegmet at
         address range #c000 - #ffff.
    REM. This procedure changes the page, but NOT the slot configuration.

   }


Procedure WriteMapperPage(PageId,
			  SourceAddress,DestinationAddress,
			  ByteCount :Integer);

   {
    Writes bytes on any page in any slot.
    The written page must first allocated by function AllocateMapperPage, which
    returns the legal page id. Otherwise owerwriting can occur to ramdisk or
    pages used by MSX operating system .
    
   }


Procedure ReadMapperPage( PageId,
			  SourceAddress,DestinationAddress,
			  ByteCount :Integer);

   {
    Reads bytes from any page in any slot.
    You can read even MSXDOS2 and ramdisk internal pages, if You find them.
    PageId := SlotId + 256 * PageNumber;
   }


Function LoadMcFile(FileName:StringType):Integer; 

{ 
  Allocates a mapper page from the mapper pointed by WantedMapper-variable;
  If there is no free page, tries annother mapper.
  After allocation loads a machine code program file on allocated page
  and returns an integer value. Lo(value) = Mapper slotId,
  Hi(value) = Page number.

  If NO free pages available or file NOT found value 0000 returned.

  The mc-code must fit in page , ie. must be smaller than 16Kb.
 
  REM. Disk i/o and some BIOS ROM codes cause problems if chn-code is loaded
       on secondary mapper. To avid this, use primary mapper.
 
  The Mc - code must return stackpointer in good condition ! 
 
  When the code is no more needed, the allocated page must be free'ed by
  FreeMapperPage procedure.

 The loading starts from the first byte of the page. If You want to use 
 other loading address, You must write a new loader using msxdos2.inc and
 WriteMapperPage.
 }


Procedure CallMcPage(
          PageId,Address:Integer;Var a:Byte;Var bc,de,hl,ix,iy:Integer
                    );
 {
  Calls a Machine code on any mapper page in any slot.
  Remember that MC must have been compiled to operate at Address given to
  CallMcPage.
  Input/Output values can be transferred with predefined variables a,bc,de,hl,
  ix,iy ,which correspond the Z80 registers or via absolute variables in high 
  memory .
 }
