// ldrmgr.cpp : implementation file
//
 #include "stdafx.h"       
 
 #include "address.h"
 #include "ldrmgr.h"
 #include "ldromf96.h"
 #include "ldricc.h"
 #include "ldrhex.h" 
 #include "bankinit.h"
 #include "uicom2.h"
 #include "srcexp.h"
 
 #ifdef _DEBUG
 #undef THIS_FILE
 static char BASED_CODE THIS_FILE[] = __FILE__;
 #endif                                     
 
 DWORD g_dwLoadInitPC = -1;

/////////////////////////////////////////////////////////////////////////////
// CLdrMgr
// global instance
  

 CLdrMgr::CLdrMgr()
 {  
  m_nWhere = 0;
  m_pLdrSvr = NULL;
  m_pLdrOpt = NULL;           
  GetBankInfo();
 }

 CLdrMgr::~CLdrMgr()
 {                  
  CloseLoader();
 }
  
 void CLdrMgr::GetBankInfo()
 {
  
  m_nComOrSep = DllLdrGetMemMode();
  m_nBankNumber = DllLdrGetBankNumber();
  m_nLowPort = DllLdrGetLowPort();
  m_nLowBit = DllLdrGetLowBit();
  m_nHighPort = DllLdrGetHighPort();
  m_nHighBit = DllLdrGetHighBit();
  m_nHighSignal = DllLdrGetHighSignal();
  m_nLowSignal = DllLdrGetLowSignal();
 } 
 
 BOOL CLdrMgr::LoadFile(LPCSTR lpsczFile, int nOption)
 {                  
  //judge whether loader is Demand or not
  CloseLoader();
  
  ASSERT(m_pLdrSvr == NULL&&m_pLdrOpt == NULL);

  //place of loader  
  m_nWhere = 0;   //from dialog

  // Set options of loader
  SetLoadOption(nOption); 
  
 //distinguish compiler and creat derive class of loader
  if(!WhatisCompiler(lpsczFile)){
     CloseLoader();
     return 0;
   }
   
  if(!m_pLdrSvr->LoadFile()){
     CloseLoader();
     return 0;
   }  
  
  RepaintCPU();    
  RepaintMemory();
  RepaintWindows();
  RepaintStack();
  RepaintVariable(); 

  return 1;
 }
       
 BOOL CLdrMgr::LoadCmd(int argc , char * argv[])
   { 
     
     CloseLoader();
     ASSERT( m_pLdrSvr == NULL );
     
     char temp[ARGLEN];
     
     lstrcpy(temp, argv[1]);    
    
     m_nWhere = 1;
    //distinguish compiler and creat derive class of loader
     if(!WhatisCompiler((LPCSTR)temp)){
       CloseLoader();
       return 0;
      }  
      
     ASSERT(m_pLdrSvr!=NULL);
     if(!m_pLdrSvr->LoadCmd(argc , argv)){
       CloseLoader();
       return 0;
      }
     RepaintCPU();    
     RepaintMemory();
     RepaintStack();
     RepaintVariable(); 
   
     return 1;
   }
    
BOOL CLdrMgr::WhatisCompiler(LPCSTR lpsczFile)
   {
    ASSERT(m_pLdrSvr == NULL);
    
    int nFlag = 0;
    HFILE   hFile;              
    unsigned char *  pByte;
  
   //open load file,and read the first byte  
   if((hFile=_lopen(lpsczFile,READ | OF_SHARE_DENY_WRITE))
       == HFILE_ERROR){
    if(m_nWhere==0){
       AfxMessageBox("Error: File may not exist or be conrupted");
       return 0;                                                  
    }
    else{
       DLLLdrShowLine("Error: File may not exist or be conrupted");
       return 0;
    }          
   }
   pByte = new unsigned char;
   if( _lread(hFile, pByte, 1) == HFILE_ERROR){
     delete (pByte);
     goto FAIL;
    }
  if(m_nWhere == 0){
     ASSERT(m_pLdrOpt != NULL); 
    //setting flags of loader   
     if(m_pLdrOpt->m_isCode)    nFlag |= LDR_CODE;
     if(m_pLdrOpt->m_isStatus)  nFlag |= LDR_STATUS;
     if(m_pLdrOpt->m_isSymbol)  nFlag |= LDR_SYMBOL;
     if(m_pLdrOpt->m_isWarnings)    nFlag |= LDR_WARNING;   
     if(m_pLdrOpt->m_isSystem)    nFlag |= LDR_SYSTEM;   
     if(m_pLdrOpt->m_isBank)    nFlag |= U16(m_pLdrOpt->m_isBank<<8);   
  }
  else nFlag = LDR_DEFAULT; 
   //distinguish compiler
  switch(*pByte)
    {
     case 0x70:
     case 0x02:
          m_pLdrSvr = new CLdrOMF96(lpsczFile , nFlag, m_nWhere);
          break;
     case 0xA5:
     case 0x4D:
          m_pLdrSvr = new CLdrICC196(lpsczFile , nFlag, m_nWhere);
          break;
     case ':':
          m_pLdrSvr = new CLdrHex96(lpsczFile , nFlag, m_nWhere);
          break;
     default: 
          if(m_nWhere==0)
          AfxMessageBox("Loader file format is not yet supported");
	      else
	      DLLLdrShowLine("Loader file format is not yet supported");
	      break;
    }
   if(_lclose(hFile)==HFILE_ERROR){
      if(m_nWhere==0)
      AfxMessageBox("Given file can't be closed"); 
      else
      DLLLdrShowLine("Given file can't be closed"); 
      return 0;  
   }
   if(m_pLdrSvr == NULL){
     if(pByte) delete (pByte);
     goto FAIL;
    }  
   if(pByte) delete (pByte); 
   return 1;
FAIL:
   return 0;
  }   
 
 void CLdrMgr::SetLoadOption(int nOption)
  {
   if(m_pLdrOpt == NULL){
      m_pLdrOpt = new CLdrOpt;
      ASSERT( m_pLdrOpt );
   }
   m_pLdrOpt->m_isCode = int(nOption & 0x01);
   m_pLdrOpt->m_isStatus = int((nOption & 0x04)>>2);
   m_pLdrOpt->m_isSymbol = int((nOption & 0x02)>>1);
   m_pLdrOpt->m_isWarnings = int((nOption & 0x08)>>3);
   m_pLdrOpt->m_isSystem = int(nOption & 0x20)?1:0;
   m_pLdrOpt->m_isBank = int(nOption>>8);                            
  }
   
 void CLdrMgr::CloseLoader()
  {
   if(m_pLdrSvr != NULL) 
    delete m_pLdrSvr;
   m_pLdrSvr = NULL;
   if(m_pLdrOpt!=NULL) 
    delete m_pLdrOpt;
   m_pLdrOpt = NULL;
  }

 BOOL CLdrMgr::SrcIsLoaded(void)
 {
     if(m_pLdrSvr == NULL) return 0;
        
     if( m_pLdrSvr->m_bSymLoaded ){
         return 1;
     }
     else{
         return 0;
     }
 }

 BOOL CLdrMgr::SrcIsOmf96(void)
 {
     if( m_pLdrSvr== NULL ) return 0;
     
     if( m_pLdrSvr->m_nCompilerType == LDR_OMF96){
         return 1; 
     }
     else{
         return 0;
     }
 }                                             

 BOOL CLdrMgr::SrcIsIEEE()
 {
   return 0;
 }
 BOOL CLdrMgr::SrcIsUbrof(void)
 {
    if( m_pLdrSvr== NULL ) return 0;

    if( m_pLdrSvr->m_nCompilerType == LDR_ICC196){
         return 1; 
     }
     else{
         return 0;
     }
 }
 
 void CLdrMgr::GetFileLength(long& l)
 { 
   if(m_pLdrSvr==NULL){
      l=0;
      return ;
   }
   ASSERT(m_pLdrSvr != NULL);
   l = m_pLdrSvr->m_lFileLen;    
 }
                              
 void CLdrMgr::GetFileCurPos(long& l)                           
 {
   if(m_pLdrSvr==NULL){
      l=0;
      return;
   }

   ASSERT(m_pLdrSvr != NULL);
   l = (m_pLdrSvr->m_uBufInFilePos) + (m_pLdrSvr->m_uBufPos);
 }
       
 void CLdrMgr::GetStartAddress(U32& addr, int& m) 
 { 
   
  if (g_dwLoadInitPC != -1){
  		addr = g_dwLoadInitPC & 0xffff;
  		m = ((g_dwLoadInitPC >> 16) & 7) + 1;
  		return;
  }
  		
  m_nBankNumber = DllLdrGetBankNumber();
   
   if(m_nBankNumber==0) m=1;
   else if(m_nBankNumber==1) m=2;
   else if(m_nBankNumber==2) m=4;
   else
     ASSERT(FALSE);

   if(m_pLdrSvr==NULL){
      addr = 0x2080;
      return;
   }
	
   ASSERT(m_pLdrSvr != NULL);
   addr = m_pLdrSvr->m_lStartAddress;
 } 
 
 U32 CLdrMgr::GetCurLdrBytes()
 {
   if(m_pLdrSvr==NULL) return 0;
   
   ASSERT(m_pLdrSvr != NULL);
   return m_pLdrSvr->m_dwLoadBytes;
 }
                                    
int CLdrMgr::StkNumConvToBank(int ul)
{
     GetBankInfo();

	 if(!m_nBankNumber){
	    return -1;
	 }
	 
	 int LowBit, HighBit;
	 //ASSERT(m_nLowPort==m_nHighPort&&m_nLowSignal==m_nHighSignal);
	       	    
	 LowBit = int((ul >> m_nLowBit) & 1);
	 HighBit = int((ul >> m_nHighBit) & 1);
	 
	 switch(m_nComOrSep){
	  case 1:
	        return JustifyBank(LowBit, HighBit, 1);
      case 0:
	       if(m_nBankNumber==1){
              return JustifyBank(LowBit, HighBit, 1);
           }
           else{
              return JustifyBank(LowBit, HighBit, 2);
           }
      default:
           return -1;
    }
 }
  
 int CLdrMgr::JustifyBank(int LowBit, int HighBit, int nBank)
  {
   int nBankNum; 
   
   GetBankInfo();
             
   nBankNum = LowBit+HighBit*2+1;             
   if(nBank==1){
      if(m_nLowSignal) return nBankNum;
      else return 3-nBankNum;
   }
  else{
       if(m_nLowSignal) return nBankNum;
       else return 5-nBankNum; 
   }
 }
 
 U32  CLdrMgr::StkAddrConvToBank(U32 ul)
 {
   return ul;
 }
 
 BOOL CLdrMgr::SrcSupportBankSwitch()
 {
  if(m_pLdrSvr==NULL||SrcIsOmf96()) return 0;
  if(m_pLdrSvr->m_bSwitchOn || m_pLdrSvr->m_nLoadToBank)
     return 1;
  else return 0;
 } 
  
 int CLdrMgr::SrcGetLoadPath(CString& strPath)
 {
  if(m_pLdrSvr==NULL) return -1;
  
  strPath = m_pLdrSvr->m_strFilePath;
  return 0;
 }

 U32 CLdrMgr::GetRegOff(U16 regIndex)
 {
  if(m_pLdrSvr==NULL||!SrcIsUbrof()) return -1;

  if(regIndex >= 0x100&& regIndex <= 0x107){
     return m_pLdrSvr->m_uGROff + regIndex -0x100;
  }
  else if(regIndex >= 0x108&& regIndex <= 0x127){
     return m_pLdrSvr->m_uLROff + regIndex -0x108;
  }
  else return -1;
 }
 
 BOOL CLdrMgr::GetBankAddr(unsigned long& uCallAddr,unsigned long& uRetAddr)
 {
   if(m_pLdrSvr==NULL||!SrcIsUbrof()||!m_pLdrSvr->m_bSwitchOn) return 0;
   
   uCallAddr = m_pLdrSvr->m_uCallAddr;
   uRetAddr = m_pLdrSvr->m_uRetAddr;
   return 1;
 }
 
 void CLdrMgr::GetRootBankValue(ADDRESS& addr)
 {
   if(m_pLdrSvr==NULL||!SrcIsUbrof()||!m_pLdrSvr->m_bSwitchOn) return ;
   
   if(addr.adrAddress < m_pLdrSvr->m_uBankLow) addr.adrSpace = 1; 
   return;
 }
   
  
 ////////////////////////////////////////////
  
  
  
  
  
  
  
