#ifndef GUARD_GBA_MULTI_BOOT_H
#define GUARD_GBA_MULTI_BOOT_H

#define MULTIBOOT_NCHILD        3       // Maximum number of slaves
#define MULTIBOOT_HEADER_SIZE   0xc0    // Header size
#define MULTIBOOT_SEND_SIZE_MIN 0x100   // Minimum transmission size
#define MULTIBOOT_SEND_SIZE_MAX 0x40000 // Maximum transmission size

struct MultiBootParam
{
    /* 0x00 */ u32 system_work[5];                   // Can be rewritten within system call. 
                                                     // Used with library also.
    /* 0x14 */ u8 handshake_data;                    // Handshake data from client
    /* 0x15 */ u8 padding;
    /* 0x16 */ u16 handshake_timeout;                // Handshake timeout check counter
    /* 0x18 */ u8 probe_count;                       // If not 0, during client recognition or  
                                                     // boot program transfer
    /* 0x19 */ u8 client_data[MULTIBOOT_NCHILD];     // Handshake data from client
    /* 0x1C */ u8 palette_data;                      // Palette's flashing parameter during load 
                                                     // for client
    /* 0x1D */ u8 response_bit;                      // When high probability that slave  
                                                     // connected, 4P-2P: d3-d1 is 1.
    /* 0x1E */ u8 client_bit;                        // For slave distinguished as client, 
                                                     // 4P-2P: d3-d1 is 1. 
    /* 0x1F */ u8 reserved1;                         // Reserved
    /* 0x20 */ const u8 *boot_srcp;                  // Boot program start (after header)
    /* 0x24 */ const u8 *boot_endp;                  // Boot program end pointer
    /* 0x28 */ const u8 *masterp;                    // Pointer to header referenced and output 
                                                     // by master
    /* 0x2C */ u8 *reserved2[MULTIBOOT_NCHILD];      // Reserved
    /* 0x38 */ u32 system_work2[4];                  // Can be rewritten within system call. 
    /* 0x48 */ u8 sendflag;                          // If SC7=1 and during send, not 0
    /* 0x49 */ u8 probe_target_bit;                  // If target recognized with client, 
                                                     // 4P-2P: d3-d1 is 1.
    /* 0x4A */ u8 check_wait;                        // Wait frame until recoginition with client
    /* 0x4B */ u8 server_type;                       // client recognize method   0= Low Speed
                                                     // 1= High Speed
};

/* Error Code
 * If value returned by MultiBootMain() is not 0, an error listed
 * below has occurred. However, there is no need to have separate error
 * messages for all error code types.
 * "Communication Error. Please check connection. Retry with START."
 * "Turn off power, check connection, and turn on again."
 * "Slave is not connected."
 * "Cannot recognize the slave."
 * ,etc.  Messages easy for the player to understand are good.
 * NO_PROBE_TARGET: When recognizing client all machines returned 
 * abnormal data and there is no target.
 * NO_DLREADY: client did not return a download preparations 
 * possible message.
 * BOOT_FAILURE: MultiBoot() system call returned an error.
 * HANDSHAKE_FAILURE: Failed to do handshake with master which should 
 * occur immediately after boot of slave.
 * (Slave may be in infinite loop, request that power be turned off 
 * and on again.)
 */
#define MULTIBOOT_ERROR_04                0x04
#define MULTIBOOT_ERROR_08                0x08
#define MULTIBOOT_ERROR_0c                0x0c
#define MULTIBOOT_ERROR_40                0x40
#define MULTIBOOT_ERROR_44                0x44
#define MULTIBOOT_ERROR_48                0x48
#define MULTIBOOT_ERROR_4c                0x4c
#define MULTIBOOT_ERROR_80                0x80
#define MULTIBOOT_ERROR_84                0x84
#define MULTIBOOT_ERROR_88                0x88
#define MULTIBOOT_ERROR_8c                0x8c
#define MULTIBOOT_ERROR_NO_PROBE_TARGET   0x50
#define MULTIBOOT_ERROR_NO_DLREADY        0x60
#define MULTIBOOT_ERROR_BOOT_FAILURE      0x70
#define MULTIBOOT_ERROR_HANDSHAKE_FAILURE 0x71

/* After an error, or when a value other than 0xffff is returned,
 * the avoid chattering wait(frames) until redo connection check.
 * The client timeout is about 11 frames so use value sufficiently
 * longer than this.
 * Usually during this time the MASTER_INFO is sent, but when there
 * is a system call error, nothing is sent at this time and it waits.
 * Then, during this time period MASTER_INFO is sent.
 */
#define MULTIBOOT_CONNECTION_CHECK_WAIT 15

/* Recognition of Slave
 * Value set in MultiBootParam structure member server_type 
 * MULTIBOOT_SERVER_TYPE_NORMAL: Slow speed recognition mode
 *   The MultiBootMain() function communicates 2 bytes with one call.
 *   Therefore, processing returns from MultiBootMain() function 
 *   in short time.
 * MULTIBOOT_SERVER_TYPE_QUICK: High speed recognition mode
 *   In MultiBootMain() function as many consecutive communications
 *    are done as possible.
 *   Therefore, processing may not return from MultiBootMain() for 
 *   several dozen frames.
 *   During this time, there is no problem if processing for sound and 
 *   display cannot be done.  If processing for sound and display is 
 *   done with timer interrupt processing, you can use.
 */
#define MULTIBOOT_SERVER_TYPE_NORMAL 0
#define MULTIBOOT_SERVER_TYPE_QUICK  1

/* Timeout for slave's final start up check   400 frames  */
#define MULTIBOOT_HANDSHAKE_TIMEOUT 400

#endif // GUARD_GBA_MULTI_BOOT_H
