;----------------------------------------------------------------------------
;This is not an documentation how to use the .mcm modules in your own
;software! Its an documentation about how to write modules for other
;card reader.
;----------------------------------------------------------------------------
TABLE OF CONTENTS

MCControlModule/General
MCControlModule/Module_Delay
MCControlModule/Module_Open
MCControlModule/Module_FrameOpen
MCControlModule/Module_FrameClose
MCControlModule/Module_ReadCommand
MCControlModule/Module_WriteCommand
MCControlModule/Module_PADOpen
MCControlModule/Module_PADClose
MCControlModule/Module_PADCommand
MCControlModule/Module_DirectFrame
MCControlModule/Module_DirectPage
;----------------------------------------------------------------------------
 *General*

First the main structure:

        RSRESET
Module_RTS                   rs.w 1 ;to avoid crash when user is starting module
Module_Version               rs.w 1 ;Currently 1
Module_ID                    rs.l 1 ;must be "MCCM"
Module_Flags                 rs.l 1 ;see below (unused flags must be zero)
Module_Exec_Base             rs.l 1 ;Filled by MCControl
Module_Dos_Base              rs.l 1 ;Filled by MCControl
Module_Intuition_Base        rs.l 1 ;Filled by MCControl
;--- Card Data
Module_DelayReadByte         rs.l 1 ;Filled by MCControl
Module_DelayReadBit          rs.l 1 ;Filled by MCControl
Module_DelayWriteByte        rs.l 1 ;Filled by MCControl
Module_DelayWriteBit         rs.l 1 ;Filled by MCControl
Module_Reserved1             rs.l 10 ;reserved (must be ZERO)
;--- Jump Table
Module_Delay                 rs.w 3 ;Filled by MCControl
Module_Open                  rs.w 3
Module_Close                 rs.w 3
Module_FrameOpen             rs.w 3
Module_FrameClose            rs.w 3
Module_ReadCommand           rs.w 3
Module_WriteCommand          rs.w 3
Module_PADOpen               rs.w 3
Module_PADClose              rs.w 3
Module_PADCommand            rs.w 3
Module_DirectFrame           rs.w 3
Module_DirectPage            rs.w 3
Module_Reserved2             rs.w 3*8 ;reserved
Module_SIZEOF                rs.b 0
;----------------------------------------------------------------------------
 BITDEF Module,Delay,0         ;Tell MCControl you require timing data.
 BITDEF Module,Device,1        ;Tell MCControl you require an Device/Unit
                               ;selector
 BITDEF Module,MultiPage,2     ;Tell MCControl you support MultiPage cards
 BITDEF Module,DirectAccess,3  ;Tell MCControl you support DirectAccess support
 BITDEF Module,MultiSlot,4     ;Tell MCControl you support more than one slot.
;----------------------------------------------------------------------------
Module_Error_NoError       = 0
Module_Error_OpenDevice    = 1
Module_Error_NotCompatible = 2 ;If hardware supports identification!
Module_Error_NoTimerDevice = 3 ;If you need the timer.device and opening fails
Module_Error_OutOfMemory   = 20
;----------------------------------------------------------------------------
Module_DirectFrame_Read    = 0
Module_DirectFrame_Write   = 1
;----------------------------------------------------------------------------
Module_DirectPage_Next     = 0
Module_DirectPage_Prev     = 1
;----------------------------------------------------------------------------

 NOTES 

   The exec, dos and intuition  bases  are  for  free  usage.  This  saves
   memory,  time and of cource code size. The card data is for free usage,
   too.

   Beside the arguments delivered for  each  function  youīll  receive  an
   pointer on the module itself in register A4!

   Make sure to backup a2-a5 and d2-d7 just like the Amiga-OS is doing!

   You must implement port and device allocation into Module_Open()! Donīt
   try  to  play  with  the hardware without owning the right to do so. If
   possible try to use parallel.device or serial.device. (The user defined
   device will be given during Module_Open().
       
   Itīs not required to create an real  jumptable,  by  using  JMPs.  Feel
   free, to use an BRA followed by an NOP. (See RamCard.mcm)
       
   Itīs strongly required  to  implement  all  given  jumps.  (except  the
   Module_Delay).

   Implement the code as fast as possible, because its used for many times
   during reading and writing memory cards. Try to avoid overhead by using
   Module_Open, or if not possible Module_FrameOpen.

   Feel free to use the Module_Delay function even  if  the  ModuleF_Delay
   flags  isnīt  set!  The  flag  only  deactivates the gadgets and avoids
   filling out the timing sheet (Module_DelayXY)!
       
   Your reader expects only a frame number and returns a  complete  frame?
   Well,  this  isnīt  a problem. Set the Module_Flag ModuleF_DirectAccess
   and MCControl is using Module_DirectFrame insteed of  Module_FrameOpen,
   Module_FrameClose,    Module_ReadCommand    and    Module_WriteCommand!
   Module_DirectFrame is doing the same job for reading and writing.  Just
   take a look on my RamCard.mcm as an DirectFrame example.

   If you need help then ask me and Iīam telling you what to  do.  If  you
   donīt  know how to code a driver then send me your information and Iīll
   do my very best.

;----------------------------------------------------------------------------
MCControlModule/Module_Delay

   NAME
                 Module_Delay
        
   SYNOPSIS
                 Module_Delay(Time);
                              D0

                 Module_Delay(ULONG);

   FUNCTION
                 Standard MCControl timer for high speed delay
                 calculations.

   INPUTS
                 Time faktor (use Module_Delay#? field for getting
                 values. The delay is on all systems nearly identicaly.
   WARNING
                 Due multi tasking it is possible that this delay is
                 much longer, but this should be no problem.
;----------------------------------------------------------------------------
MCControlModule/Module_Open

   NAME
                 Module_Open -- open and inits the module

   SYNOPSIS
                 Error   = Module_Open(Device, Unit)
                 D0                    a0,     d0

                 (ULONG) = Module_Open(*UBYTE,ULONG)
   FUNCTION
                 Open the required device and alloc additional memory
                 if needed.
   INPUTS
                 Device: Pointer on device name (STRING IS READ ONLY!!!)
                 Unit:   Unit of the given device
   RESULT
                  0 = No Error
                  1 = Open device error
                  2 = Not compatible
                 20 = Out of memory

                 Other results are currently not allowed!!
   NOTES
                 Device and Unit are only valid if the Device-Flag within
                 the module structure (Module_Flags) is set.

   SEE ALSO
                 Module_Close()
;----------------------------------------------------------------------------
MCControlModule/Module_Close

   NAME
                 Module_Close -- free all data and close all devices.

   SYNOPSIS
                 Module_Close()

   FUNCTION
                 Close all devices and free all allocated memory .
   NOTES
                 Module_Close must be save to be called more than
                 one time. This means you must detect an closing of
                 an just closed module. In this case you must return
                 without any action.
   SEE ALSO
                 Module_Open()
;----------------------------------------------------------------------------
MCControlModule/Module_FrameOpen

   NAME
                 Module_FrameOpen -- Prepare for frame read/write

   SYNOPSIS
                 Error   = Module_FrameOpen(Slot)
                 D0                          D0

                 (ULONG) = Module_FrameOpen(UWORD);

   INPUTS
                 Slot: (0-x) Number of slot to access!

   RESULT
                  0 = No Error
                  1 = Slot not available
                 -1 = Other Error (you shouldnīt need to use this)

                 Other results are currently not allowed!!

   FUNCTION
                 No special function. Just do what is required to
                 access the given slot. Standard.mcm is using this
                 function to active the select line of the given
                 slot. RamCard.mcm is resetting data buffers only.
   SEE ALSO
                 Module_FrameClose()
;----------------------------------------------------------------------------
MCControlModule/Module_FrameClose

   NAME
                 Module_FrameClose -- frame read/write done

   SYNOPSIS
                 Module_FrameClose()

   FUNCTION
                 No special function. Just do what is required after
                 reading a frame. Standard.mcm is using this
                 function to deactive all select lines slot.
   SEE ALSO
                 Module_FrameOpen()
;----------------------------------------------------------------------------
MCControlModule/Module_ReadCommand

   NAME
                 Module_ReadCommand -- Send command and get answer

   SYNOPSIS
                 Result = Module_ReadCommand(Command)
                 D0                          D0

                 BYTE   = Module_ReadCommand(BYTE)

   FUNCTION
                 Command will be transfered to memory card. The
                 card answer will be returned to Result.

   NOTES
                 There is no need to implement different routines
                 for Module_ReadCommand and Module_WriteCommand.
                 Internaly these commands are working equal. The
                 only difference is that the ReadCommand is used
                 when reading frames and the WriteCommand on writing
                 frames. This allows to use different delays for
                 reading and writing. If you hardware isnīt using
                 any different delays use the same routine
                 for both commands.

   SEE ALSO
                 Module_WriteCommand()
;----------------------------------------------------------------------------
MCControlModule/Module_WriteCommand

   NAME
                 Module_WriteCommand -- Send command and get answer

   SYNOPSIS
                 Result = Module_WriteCommand(Command)
                 D0                           D0

                 BYTE = Module_WriteCommand(BYTE)

   FUNCTION
                 Command will be transfered to memory card. The
                 card answer will be returned to Result.

   NOTES
                 There is no need to implement different routines
                 for Module_ReadCommand and Module_WriteCommand.
                 Internaly these commands are working equal. The
                 only difference is that the ReadCommand is used
                 when reading frames and the WriteCommand on writing
                 frames. This allows to use different delays for
                 reading and writing. If you hardware isnīt using
                 any different delays use the same routine
                 for both commands.
                       
   SEE ALSO
                 Module_ReadCommand()
;----------------------------------------------------------------------------
MCControlModule/Module_PADOpen

   NAME
                 Module_PADOpen -- Prepare for PAD emulation

   SYNOPSIS
                 Error   = Module_PADOpen()
                 d0

                 (LONG)  = Module_PADOpen()

   RESULT
                 0 = No Error
                 Other results are currently not allowed!!

   FUNCTION
                 Again! There is no predefined function for this
                 function. Just do what is required or even nothing.
                 Standard.mcm is using this function to set all
                 IO ports to output.
   SEE ALSO
                 Module_PADClose()
;----------------------------------------------------------------------------
MCControlModule/Module_PADClose

   NAME
                 Module_PADClose -- PAD emulation done

   SYNOPSIS
                 Module_PADClose()

   FUNCTION
                 Again there is no predefined function for this
                 function. Just do what is required or even nothing.
                 Standard.mcm is using this function to reset all
                 IO ports to default.
   SEE ALSO
                 Module_PADClose()
;----------------------------------------------------------------------------
MCControlModule/Module_PADCommand

   NAME
                 Module_PADCommand -- Simulate PAD

   SYNOPSIS
                 Module_PADCommand(Command,Answer)
                                   D0,     D1

                 Module_PADCommand(BYTE   ,BYTE)
        
   FUNCTION
                 Well, this is a little tricky. You must send the
                 Command on the command line, while simulating
                 an PSX Pad answer on the Dataline by using Answer.
                        
                 The card will think its hearing the playstation is
                 talking to a card and vice versa.
   SEE ALSO
                 Module_PADOpen(), Module_PADClose()
;----------------------------------------------------------------------------
MCControlModule/Module_DirectFrame

   NAME
                 Module_DirectFrame -- Handle 1 frame at once

   SYNOPSIS
                 Error   = Module_DirectFrame(Frame,Mode,Data)
                 D0                           D0,   D1,  A0

                 (LONG)  = Module_DirectFrame(WORD, LONG,*Byte)

   INPUTS
                 Frame: Frame number to read or write!
                 Mode:  Module_DirectFrame_Read or Module_DirectFrame_Write
                 Data:  Pointer on Buffer!

   RESULT
                  0 = Ok
                 -1 = ERROR

                 Other results are currently not allowed!!

   FUNCTION
                 Read or write the given frame (128 bytes)!

   NOTE
                 Data must be 128 bytes long!
                 This function requires the flag: ModuleF_DirectAccess!
                 Otherwise MCControl is ignoring this routine.
;----------------------------------------------------------------------------
MCControlModule/Module_DirectPage

   NAME
                 Module_DirectPage -- Handle page swapping

   SYNOPSIS
                 Error   = Module_DirectPage(Offset,Mode)
                 D0                          D0,    D1

                 (LONG)  = Module_DirectPage(WORD, LONG)

   INPUTS
                 Offset: Number of pages to jump!
                 Mode:   Module_DirectPage_Next or Module_DirectPage_Prev

   RESULT
                  0 = Ok
                 -1 = ERROR

                 Other results are currently not allowed!!
   FUNCTION
                 Change activ card page of an multipage MemoryCard!

   NOTE
                 This function requires the flag: ModuleF_DirectAccess!
                 Otherwise MCControl is ignoring this routine.

;----------------------------------------------------------------------------

