
#include "stdafx.h"
#include <ctype.h>
#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>

#include "abiextfn.h"
#include "srcexp.h"
#include "ldrsvr.h"
#include "ldrhex.h"        
#include "bankinit.h" 
#include "hosterrs.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CLdrHex96

CLdrHex96::CLdrHex96(LPCSTR lpsczFile , int nFlag, int where)
{
// Load File Full Path
 m_strFile = lpsczFile; 
 // Compiler Type
 m_nCompilerType = LDR_HEX196;  
 // flag of loader
 m_nLdrOptFlag = nFlag;
 // Hi Byte before or after 
 m_bHiLoFlag = 0;
 
 where = 0; //for eleminate warning
 m_nMemMode = DllLdrGetMemMode();
 m_nBankNumber = DllLdrGetBankNumber();

 if(nFlag&0xff00) m_nLoadToBank = U8((nFlag&0xff00)>>8);

#ifndef _LONG_
 SymRemoveSymbols();
#endif 
}

CLdrHex96::~CLdrHex96()
{       
}

BOOL CLdrHex96::LoadProcess()
{
    if(!LOAD_CODE(m_nLdrOptFlag)) return 1;
    
	unsigned int old_pc;
	int dw_byte , err;
	unsigned char *ptr;
	unsigned int next_pc;
	int i,j;    
	CString sss;

    dw_byte = 0;
    next_pc = 0;
    ptr = dw_buf2;                              
    if ( m_where == LOAD_FROM_SHELL) {
    	ErrGetErrorText(ERI_LDR_DOWNLOAD,(LPSTR)dw_buf);
    	DLLLdrShowLine((LPSTR)dw_buf);
	}
    for (;;) {
        if ( (err = TestKey(VK_ESCAPE)) == 1 ) {
             m_dwErrMsg = ER_LDR_ABORT;		
             return 0;
        } 
        if ( (m_where == LOAD_FROM_DIALOG)&&(m_nLdrOptFlag & LDR_STATUS) ) {
            if(SrcIsLoadAbort()){
               m_dwErrMsg = ER_LDR_ABORT;	
               return 0;
            }                  
            TestMessage();
        }
        if (!GetBytes(dw_buf , 9)) {
             m_dwErrMsg = ER_LDR_FILE_FORMAT;		
             return 0;                        
        }                            
        switch (dw_buf[8]) {
        case '2':
              if (!GetBytes(dw_buf , 8)) {
                  m_dwErrMsg = ER_LDR_FILE_FORMAT;	
                  return 0;                        
              }    
              break;                        
        case '0':
              old_pc = 0;
              for (i=0;i<4;i++) old_pc = (old_pc << 4) + asc__h(dw_buf[3+i]);
              if (dw_byte && (old_pc != next_pc)) {
                  if(!FillCodeToMem(next_pc, dw_byte, dw_buf2))
                     return 0;
                  ptr = dw_buf2;
                  m_dwLoadBytes += (U32)dw_byte;
                  dw_byte = 0;
              }
              j = (int) asc2hex(dw_buf[1],dw_buf[2]);
            
              dw_byte += j;
              next_pc = old_pc + (unsigned int) j;
              j = j*2;
              if (!GetBytes(&dw_buf[9] , j+4)){
                   m_dwErrMsg = ER_LDR_READ_FILE;	
                   return 0;                        
              }
#ifndef _LINK_ABI           
              else {            
                  dw_buf[j+11] = '\0';
                  if(m_where == LOAD_FROM_SHELL) 
                     DLLLdrShowLine( (char *) dw_buf );
              } 
#endif          
              for (i=0; i < j; i += 2)
                  *ptr++ = asc2hex(dw_buf[9+i], dw_buf[i+10]);
            
              if (dw_byte >= LOAD_HEX_BUFFER_NUMBER) {
                  unsigned int fill_pc;
                  fill_pc = next_pc-(dw_byte-LOAD_HEX_BUFFER_NUMBER);
                  if(!FillCodeToMem(fill_pc, LOAD_HEX_BUFFER_NUMBER, dw_buf2))
                     return 0;
                  m_dwLoadBytes += LOAD_HEX_BUFFER_NUMBER;
                  dw_byte -= LOAD_HEX_BUFFER_NUMBER;
                  ptr = &dw_buf2[dw_byte];
                  if ( dw_byte ) {
                      memcpy( dw_buf2 , &dw_buf2[LOAD_HEX_BUFFER_NUMBER] , dw_byte );
                }   
              }
              break;
        case '1':
              if (dw_byte) {
                  if(!FillCodeToMem(next_pc, dw_byte, dw_buf2))
                     return 0;
                  ptr = dw_buf2;
                  m_dwLoadBytes += (U32)dw_byte;
                  dw_byte = 0;
              }
              m_uBufPos =  (U16)m_lFileLen-m_uBufInFilePos;
              return 1;
        case '3':
              j = (int) asc2hex(dw_buf[1],dw_buf[2]);
              j *= 2;
              if (!GetBytes(dw_buf , j+4)){
                   m_dwErrMsg = ER_LDR_READ_FILE;	
                   return 0;                        
              }    
              old_pc = 0;
              for (i=0;i<4;i++) old_pc = (old_pc << 4) + asc__h(dw_buf[i]);
              m_lStartAddress = (U32) old_pc;
#ifdef _DUMP_
			  Message("	Starting Address: %lx",m_lStartAddress);
#endif
              break;          
        default:
#ifdef _DUMP_
			  Message("\r\n???Unknown hex tag at file %lx",
							GetFileCurPos()-9);
#endif
              m_dwErrMsg = ER_LDR_FILE_FORMAT;		
              return 0;
        }
    }
 //   return 1;		// unreachable code
}        /* end of downrecord() */


BOOL CLdrHex96::FillCodeToMem(unsigned int next_pc, int dw_byte, U8* buf)
 {
  
    ADDR stAddr , endAddr;
    RET_ADDR ret;
    int err;
    
    //for bank switching   
    if(!JustifyBank()) return 0;
                
    if(m_nLoadToBank)
       stAddr.addrType = endAddr.addrType = U16(m_nLoadToBank);    
    else
       stAddr.addrType = endAddr.addrType = 1;
    //for load to x area                    
    if(LOAD_TODATA( m_nLdrOptFlag)){
       stAddr.addrType = endAddr.addrType = U16(m_nLoadToBank+4);
    }

#ifdef _LINK_ABI                    
    int pos=0;            
    while(dw_byte>120){
	    stAddr.addr=(unsigned short)(next_pc-(unsigned int) dw_byte);
	    endAddr.addr=stAddr.addr+119;
	    err=emuSetMemN(stAddr, &buf[pos] , 120, &ret);
	    if(err != ICE_OK){
	       m_dwErrMsg = ER_ICE_ERROR_WRITE;	
	       return 0;
	    }
	    pos += 120;
	    dw_byte -=120;
	}
    stAddr.addr=(unsigned short)(next_pc-(unsigned int) dw_byte);
    endAddr.addr=(unsigned short)(next_pc - 1);
    err=emuSetMemN(stAddr, &buf[pos] , U16(dw_byte) , &ret);
    if(err != ICE_OK){
       m_dwErrMsg = ER_ICE_ERROR_WRITE;	
       return 0;          
    }
    displayPC( U16(stAddr.addr) );
#endif
    return 1;
}

BOOL CLdrHex96::JustifyBank()
{
   if(m_nLoadToBank){
      if(m_nMemMode&&m_nLoadToBank>2) return 0;
      else if(m_nLoadToBank > 2*m_nBankNumber) return 0;
      else return 1; 
   }
   return 1;
}
 
void CLdrHex96::displayPC(U16 addr)
{
    char tempStr[100];
    int l , i , j;

    ErrGetErrorText(ERI_LDR_DOWNLOAD, tempStr);
    l = strlen(tempStr);
    for(i=0; i < 4;i++) {
        j = addr & 0x000F;
        if ( j < 10 ) tempStr[3-i+l] = (char) ('0' + j);
        else tempStr[3-i+l] = (char) ('A' + j - 10);
        addr = addr >> 4;
    }
    tempStr[4+l] = '\0';                         

    if(m_where == LOAD_FROM_SHELL ) {
        if(LOAD_WARNING(m_nLdrOptFlag)){
           DLLLdrShlReshowLine(tempStr , 4+l);
        }
    }
}        /* end of displayCSIP() */
 
/***************************************************************************
*                                                                          *
*  asc__h - convert a ascii char to hex value                              *
*  parameter :                                                             *
*       a     ----     ascii char '0'-'F'                                  *
*  return value :                                                          *
*       value of a                                                         *
*                                                                          *
***************************************************************************/
unsigned char CLdrHex96::asc__h(unsigned char a)
{
    if ( (a>='0')&&(a<='9') ) a = (unsigned char)(a-'0');
    else if ( (a>='A')&&(a<='F') ) a = (unsigned char)(a-'A'+10);
    else if ( (a>='a')&&(a<='f') ) a = (unsigned char)(a-'a'+10);
    else a = 0;
    return( a );
}

/***************************************************************************
*                                                                          *
*  asc2hex - convert two ascii char to hex value                           *
*  parameter :                                                             *
*       a     ----     high half-byte char '0'-'F'                         *
*       b     ----     low  half-byte char '0'-'F'                         *
*  return value :                                                          *
*       value of ab                                                        *
*                                                                          *
***************************************************************************/
unsigned char CLdrHex96::asc2hex(unsigned char a,unsigned char b)
{
   unsigned char r;
   r = asc__h(a);
   r = (unsigned char) ((r << 4) | asc__h(b));
   return(r);
}
 


