
#include <Shinobi.h>
#include <NjDef.h>
#include <nuBinary.h>

/*-- Read File from GD & Create Work Buff ----------------------*/
Uint8 *nuOpenBinary(char *fname)
{
    GDFS fid;
    Sint32 sn;
    Uint8 *wbuff;
    Uint8 *rptr;
    
    fid = gdFsOpen(fname, NULL);
    gdFsGetFileSctSize(fid, &sn);
    wbuff = (Uint8 *)syMalloc(sn*2048+8);
    gdFsRead(fid, sn, wbuff);
    gdFsClose(fid);
    return wbuff;
}

void nuCloseBinary(Uint8 *wbuff)
{
    syFree(wbuff);
}

/*-- General Funtion for Read Binary CNK NJA -------------------*/
Uint32 nuSwapCNK(Uint32 cnk)
{
    Uint32 rv;
    rv = (cnk&0x000000ff)<<24|(cnk&0x0000ff00)<<8|(cnk&0x00ff0000)>>8|(cnk&0xff000000)>>24;
    return rv;
}

/*-- Read Binary CNK NJA from Work Buff-------------------------*/
void *nuReadBinaryChunk(Uint8 *wbuff, Uint32 *fpos, Uint32 *ptype)
{
    Uint8 *current;
    Uint8 *tmp;
    Uint8 buf0, buf1, buf2, buf3;
    Uint32 *addr;
    Uint32 cnk, size;
    Uint32 offset,  offset_from_base = 0;


    current = &wbuff[*fpos];
    
    memcpy(&cnk, current, 4);
    current += 4;
    
    memcpy(&size, current, 4);
    current += 4;


    *fpos += 8;
    cnk = nuSwapCNK(cnk);
    switch(cnk){
        case iff_NJINFO:
            *ptype = iff_NJINFO;
            goto _allocate_data_area_;
        case iff_NJCM:
            *ptype = iff_NJCM;
            goto _allocate_data_area_;
        case iff_NJBM:
            *ptype = iff_NJBM;
            goto _allocate_data_area_;
        case iff_NJTL:
            *ptype = iff_NJTL;
            goto _allocate_data_area_;
        case iff_NJLI:
            *ptype = iff_NJLI;
            goto _allocate_data_area_;
        case iff_NJCA:
            *ptype = iff_NJCA;
            goto _allocate_data_area_;
        case iff_NMDM:
            *ptype = iff_NMDM;
            goto _allocate_data_area_;
        case iff_NLIM:
            *ptype = iff_NLIM;
            goto _allocate_data_area_;
        case iff_NCAM:
            *ptype = iff_NCAM;
            goto _allocate_data_area_;
        case iff_NSSM:
            *ptype = iff_NSSM;
        _allocate_data_area_:
            tmp = (Uint8 *)syMalloc(size);
            memcpy(tmp, current, size);
            current += size;
            *fpos += size;
            break;
        default:
            *ptype = '****';
            return NULL;
    }
    /*-- Add BaseAddr ---------------------------------------*/
    memcpy(&cnk, current, 4);
    current += 4;
    *fpos += 4;
    cnk = nuSwapCNK(cnk);
    if(cnk == 'POF0'){
        memcpy(&size, current, 4);
        current += 4;
        *fpos += 4;
        while(size > 0){
            memcpy(&buf0, current, 1);
            current += 1;
            *fpos += 1;
            size--;
            switch(buf0&NJ_POF_CHAR_MASK){
                case NJ_POF_TYPE_PAD:
                    break;
                case NJ_POF_TYPE_CHAR:
                    offset = (Uint32)(buf0&NJ_POF_DATA_MASK);
                    goto _ADD_BASE_ADDRESS_;
                case NJ_POF_TYPE_SHORT:
                    memcpy(&buf1, current, 1);
                    current += 1;
                    size--;
                    *fpos += 1;
                    offset = (Uint32)((buf0&NJ_POF_DATA_MASK)<<8|buf1);
                    goto _ADD_BASE_ADDRESS_;
                case NJ_POF_TYPE_LONG:
                    memcpy(&buf1, current, 1);
                    current += 1;
                    size--;
                    memcpy(&buf2, current, 1);
                    current += 1;
                    size--;
                    memcpy(&buf3, current, 1);
                    current += 1;
                    size--;
                    *fpos += 3;
                    offset = (Uint32)((buf0&NJ_POF_DATA_MASK)<<24|(buf1<<16)|(buf2<<8)|buf3);
                _ADD_BASE_ADDRESS_:
                    offset *= 4;
                    offset_from_base += offset;
                    addr = (Uint32 *)(tmp+offset_from_base);
                    if(*addr)
                        *addr += (Uint32)tmp;
                    break;
            }
        }
    }
    return tmp;
}


/*-------------------------------------------------------------*/
