/********************************************************************/
/*          AgbDacs.h                                               */
/*            1Mbit DACS Library Header    ver. 1.2.4               */
/*                                                                  */
/*                                         last modified 2002.12.04 */
/*                                                                  */
/*          Copyright (C) 2000-2001 NINTENDO Co.,Ltd.               */
/********************************************************************/
#ifndef __AGBDACS_H__
#define __AGBDACS_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <AgbTypes.h>

//#define __DACS_DEBUG

// define data---------------------------------- 
#define DACS_RETRY_MAX      3   // ProgramDacsSectorEx function maximum retry number

typedef struct dacsSectorTag {
    u32         size;           // Sector size in bytes
    u8          shift;          // The sector byte size converted into a shift count
                                // (sector.size = 2<<sector.shift)
    u16         count;          // Sector Count
    u16         top;            // Starting sector No.
}dacsSector;

typedef struct dacsTypeTag {
    u32         topAdr;         // Starting address
    u32         romSize;        // Size of save region
    u16         totalSector;    // Total Sector Count
    dacsSector  sector1;        // Structure information for sector 1
                                //  (The sector from the start of memory)
    dacsSector  sector2;        // Structure information for sector 2
                                //  (* Valid when there are sectors of different sizes)
    u16         agbWait[2];     // Read/write wait value of AGB Game Pak bus (ROM2 area)
                                //  (Used inside the library)
    u16         makerID;        // Maker ID
    u16         deviceID;       // Device ID
}dacsType;

/******************************************************************* 
Information about the composition of the 1Mbit DACS device is defined 
in the library in the above-mentioned dacsType in the format shown below.

These constants can be accessed by executing IdentifyDacs() and then 
referencing the global variable [const dacsType *dacs].



1Mbit DACS (8kbyte sector x 14 from starting address)
{
    0x0dfe4000,                                 Start address
    0x0001c000,                                 Size of save region
    14,                                         Total number of sectors
    {0x00002000,13,14, 0},                      Sector 1's structure information
    {0x00000000, 0, 0, 0},                      Sector 2's structure information
    {CST_ROM2_1ST_3WAIT|CST_ROM2_2ND_1WAIT,     Read cycle 3/1
     CST_ROM2_1ST_8WAIT|CST_ROM2_2ND_8WAIT},    Write cycle 8/8
    0x00b0,                                     Maker ID
    0x0093,                                     Device ID
}

Caution: When using 8Mbit DACS, you must use the "AGB 8MDACS Library."
*********************************************************************/


/*------------------------------------------------------------------*/
/*          Global Variable                                         */
/*------------------------------------------------------------------*/

extern const dacsType *dacs;    // Pointer to the data that shows the structure of the
                                // DACS which is stored after IdentifyDacs is executed. 
                                // (See definition of above data for details)
extern u32 dacs_remainder;      // Barometer showing progress during DACS write

/*------------------------------------------------------------------*/
/*          Device Identification and Initial Settings              */
/*------------------------------------------------------------------*/

extern u16 IdentifyDacs();

/*   Identifies DACS device being used with Game Pak. Gets flash capacity 
     and sector size, and sets up access speed. The obtained data can be 
     referenced using the global variable, dacsType *dacs.
     (See the header file dacs.h for more details on dacsType.)
     Call once prior to accessing DACS (including reads).
     If the device cannot be identified, an error is returned and the 
     subsequent access functions can no longer be used.
    
    <Arguments>
     None
    <Return Values>
     u16 result : 0 is a normal end, not 0 is an error
*/

/*------------------------------------------------------------------*/
/*          Access Timer Interrupt Settings                         */
/*------------------------------------------------------------------*/

extern u16 SetDacsTimerIntr(u8 timerNo, void (**IntrFunc)(void));

/*   Selects timer interrupt for determining timeouts during access to DACS. 
     Transfers the timeout determination function and the DACS status polling 
     function to a buffer set aside in WRAM.
     You must call at least once before each access routine is called. Once 
     you have set the timer interrupt to be used with this routine, and as 
     long as you don't use the timer interrupt for the set No. with other 
     processing, or use a different interrupt table, it is not necessary to 
     call this routine again. However, if you overlay and use the RAM area of 
     this library, beware that it is possible that the functions transfered 
     to the RAM were overwritten. 
     If the timer No. is not between 0 and 3, an error is returned.
     *According to the library specifications, when this routine is called, a 
     specific timer interrupt routine is forcibly set for the library functions
     so the interrupt table when accessing DACS must be in the RAM area.
    <Arguments>
     u8 timerNo :Number of the timer used by the timeout routine.
     void (**IntrFunc)(void):Pointer to a compatible timer interrupt 
                                 address in the interrupt table.
    <Return Values>
     u16 result :0 is the normal end, Not 0 is an error

*/
/*-------------------------------------------------------------------*/
/*  Address conversion (DACS sector No. -> CPU memory map address)   */
/*-------------------------------------------------------------------*/

extern u32 ExchangeSectorToPhysAdr(u16 secNo);

/*  Converts the DACS sector No. to an address in the CPU memory map.
    When the sector No. is abnormal, a parameter error is generated and 0 is returned.
    
    <Arguments>
      u16 secNo     : Target sector No.
    <Return value>
    u32 physAdr   : Normal end -> Starting address of target sector No. in 
                                    the AGB-CPU memory map
                      Parameter error -> 0

*/
/*------------------------------------------------------------------*/
/*               Address conversion                                 */
/*  (CPU memory map address -> DACS sector No. + offset in sector)  */
/*------------------------------------------------------------------*/

extern u32 ExchangePhysAdrToSector(u32 physAdr);

/*  Converts the DACS address in the AGB-CPU memory map into a 
    DACS sector No. + offset inside the sector.
    In the return value, bits 31-24 are the sector No. and bits 23-0 
    are the offset inside the sector.
    When an address is specified that is outside the range assigned
    to DACS, a parameter error is generated and 0 is returned.

     <Arguments>
    u32 physAdr      : The DACS address in the AGB-CPU memory map
     <Return value>
    u32 secNo_offset : Normal end -> (Sector No. <<24 | (Offset in sector)
                         Parameter error -> 0
*/

/*------------------------------------------------------------------*/
/*          Read data in 2 byte units                               */
/*------------------------------------------------------------------*/

extern void ReadDacs(u16 secNo, u32 byteOffset,u16 *dst, u32 byteSize);

/* This reads "byteSize" bytes of data starting at the address "byteOffset" 
   bytes away from the start of the target sector No., and loads the data 
   into the region starting from address "dst."
   The function operates normally even when the specified read size 
   straddles a sector boundary.
   Specify an even number of bytes for "byteOffset" and "byteSize", and 
   specify an address with a 16 bit boundary for "*dst".
    
     <Arguments>
     u16 secNo     : Target sector No.
     u32 byteOffset: Offset inside the sector in units of bytes 
                      (Specified as an even number of bytes)
     u16 *src      : Transfer destination address of the read data 
                      (An address with a 16 bit boundary in the AGB memory map)
     u32 byteSize  : Read byte size (Specified as an even number of bytes)
     <Return value>
     None
*/

/*------------------------------------------------------------------*/
/*          Erase Chip                                              */
/*------------------------------------------------------------------*/

extern u16 EraseDacsChip();
/*  Erase entire chip.
    Do not use DMAs which start up automatically with specified timing such as
    direct sound, V/H blank synchronization, display synchronization, or Game 
    Pak request when this function is called.   
      * All interrupts with the exception of the timer used for time-out 
    processing are prohibited for part of the time inside this function.  Be 
    aware that any interrupt that was enabled prior to the call of this function
    will occur immediately after the end of this prohibition period (which lasts 
    for several hundred milliseconds to several seconds).

    <Arguments>
      None
    <Return value>
     u16 result : 0 is normal end, non-zero is an error
*/

/*------------------------------------------------------------------*/
/*          Erase Sector                                            */
/*------------------------------------------------------------------*/

extern u16 EraseDacsSector(u16 secNo);

/*   Erase sector of target sector No.
     This routine is called in write routine, so usually you don't
     need to call it before a write.
     A parameter error occurs when the target sector No. is outside the 
     range of sector numbers for this particular device.
     Do not use DMAs which start up automatically with specified timing such as
     direct sound, V/H blank synchronization, display synchronization, or Game 
     Pak request when this function is called.  
     * All interrupts with the exception of the timer used for time-out 
     processing are prohibited for part of the time inside this function.  Be 
     aware that any interrupt that was enabled prior to the call of this function
     will occur immediately after the end of this prohibition period (which lasts 
     for several hundred milliseconds to several seconds).
     <Arguments>
     u16 secNo  : Target sector No.
     <Return value>
     u16 result : 0 is normal end, non-zero is an error.
*/

/*--------------------------------------------------------------------*/
/*  Write data in 2 byte units (without erasing inside function)      */
/*--------------------------------------------------------------------*/

extern u16 ProgramDacs_NE(u16 secNo, u32 byteOffset, u16 *src, u32 byteSize);

/* This function takes "byteSize" bytes of data from the address "src" and 
   writes it to the address "byteOffset" bytes away from the start of the target 
   sector No.
   Note that the EraseDacsSector routine is not called from inside this 
   function, so if data is already written to the destination area, then the 
   value that is written to this address is the AND of the existing data and the 
   new data. Thus, for example, if 0x3333 is written to an address where 0x5555 
   is already written, the result will be 0x1111.
   The function operates normally even when the specified write size straddles
   a sector boundary. However, a parameter error occurs when the specified size 
   exceeds the region allocated to the device.
   A parameter error occurs when the target sector No. is outside the range of 
   the pertinent device.
   Specify an even number of bytes for "byteOffset" and "byteSize", and specify 
   an address with a 16 bit boundary for "*src".
   Do not use DMAs which start up automatically with specified timing such as
   direct sound, V/H blank synchronization, display synchronization, or Game 
   Pak request when this function is called. 
    * All interrupts with the exception of the timer used for time-out 
   processing are prohibited for part of the time inside this function. Be 
   aware that any interrupt that was enabled prior to the call of this function
   will occur immediately after the end of this prohibition period (which lasts 
   for several dozen microseconds).

    <Arguments>
    u16 secNo     : Target sector No.
    u32 byteOffset: Offset inside the sector in units of bytes 
                     (Specified as an even number of bytes)
    u16 *src      : Write source address 
                     (An address with a 16 bit boundary in the AGB memory map)
    u32 byteSize  : Write byte size (Specified as an even number of bytes)
    <Return value>
    u16 result    : 0 is a normal end, non-zero is an error.
*/

/*------------------------------------------------------------------*/
/*   Write data in sector units (with erasing in the function)      */
/*------------------------------------------------------------------*/

extern u16 ProgramDacsSector(u16 secNo,u16 *src);


/* Writes one sector of data from the src address to the target sector 
   number. The sector size for 1Mbit DACS is fixed at 8kb, so blocks of 
   that size are written.  This routine internally calls the above-mentioned 
   EraseDacsSector, erases the sector, and then writes.  When the target 
   sector number is outside of the range of the sector numbers for the 
   device, an error will occur. Designate a 16bit boundary address for *src.
   Do not use DMAs which start up automatically with specified timing such 
   as direct sound, V/H blank synchronization, display synchronization, or 
   Game Pak request when this function is called.  
* All interrupts with the exception of the timer used for time-out 
   processing are prohibited for part of the time inside this function. Be 
   aware that any interrupt that was enabled prior to the call of this 
   function will occur immediately after the end of this prohibition period 
   (lasting from tens of microseconds to a few seconds)


    <Arguments>
     u16 secNo  : Target sector No.
     u8 *src    : Write source address
    <Return value>
     u16 result : 0 is a normal end, non-zero is an error.
*/
/*------------------------------------------------------------------*/
/*          Verify data in 2byte units                              */
/*------------------------------------------------------------------*/

extern u32 VerifyDacs(u16 secNo, u16 byteOffset, u16 *src, u32 byteSize);

/* This verifies "byteSize" worth of data at the address "src" and at the
   address "byteOffset" bytes away from the start of the target sector No.
   The function operates normally even when the specified verify size 
   straddles a sector boundary.
   Specify an even number of bytes for byteOffset and byteSize, and 
   specify an address with a 16 bit boundary for "*src".
   This routine does not perform a parameter check.
    <Arguments>
    u16 secNo     : Target sector No.
    u32 byteOffset: Offset inside the sector in units of bytes 
                     (Specified as an even number of bytes)
    u16 *src      : Verify source address (16bit boundary address on AGB memory map)
    u32 byteSize  : Verify byte size (Specified as an even number of bytes) 
    <Return value> 
    u32 errorAdr  : Normal end -> 0
                    Verify error -> Error address on device side
*/

/*------------------------------------------------------------------*/
/*          Verify data in sector units                             */
/*------------------------------------------------------------------*/

extern u32 VerifyDacsSector(u16 secNo, u16 *src);


/* Verifies the contents of the src address and its corresponding sector 
   number in units the size of the specified sector.
   All 1Mbit DACS sectors are 8kbyte, so verification occurs according to 
   their size sections.
   Designate a 16bit boundary address for *src.
   Parameter checks are not performed with this routine.


   <Arguments>
    u16 secNo    : Target sector No.
    u16 *src     : Verify source address 
   <Return value> 
    u32 errorAdr : Normal end -> 0
                   Verify error -> Error address on device side
*/



/*------------------------------------------------------------------*/
/*          Write & verify data in sector units        */
/*------------------------------------------------------------------*/

extern u32 ProgramDacsSectorEx(u16 secNo,u16 *src);

/* This function writes internally using ProgramDacsSector and then 
   verifies using VerifyDacsSector. In case of an error, it retries 
   a maximum of DACS_RETRY_MAX (defined by AgbDacs.h) times.
   Do not use DMAs which start up automatically with specified timing such as
   direct sound, V/H blank synchronization, display synchronization, or Game 
   Pak request when this function is called.  
   *All interrupts with the exception of the timer used for time-out 
   processing are prohibited for part of the time inside this function. Be 
   aware that any interrupt that was enabled prior to the call of this function
   will occur immediately after the end of this prohibition period (which lasts 
   for several hundred milliseconds to several seconds). 
   *This function returns an error code in 16 bits out of 32 bits during a write
   error; however, it returns a 32 bit error address on the device side during 
   a verify error. Keep this in mind when checking the error code. 
    <Argument>
     u16 secNo  :Target sector No.
     u16 *src   :Write source address 
    <Return value>
     u32 result : 0 is a normal end. 
                  16bit error code when write error 
                  Error address on device side when a verify error occurs
*/

#ifdef __cplusplus
}      /* extern "C" */
#endif

#endif  // __AGBDACS_H__
