English, French, German
Pocket-Viewer.ru for users and developers
Google
 
Web pocket-viewer.ru
Главная · Программы · Пользователям · Разработчикам · Конкурсы · Партнерство · Информация · Форум   

Библиотека РАзных ВОпросов разработчику


Вернуться к Маленькие ценности PVOS - Add-Ins.

Маленькие ценности PVOS - Add-Ins. Исходник.

J. Steingraber
27 февраля 2001

перевод Олега Шаталова, sov-dusik@mail.ru



AddInInfo.h 
/*
 * AddInInfo.h
 *
 * Author: J. Steingraeber
 * Date: 2001/02/27
 *
 * Released to the public domain
 */


#ifndef AddInInfo_h_included
#define AddInInfo_h_included

/*
 * AddInInfo
 *
 * structure to receive Add-In data of a specific Add-In
 *
 * this structure is filled from the header of an Add-In
 * by GetAddInInfo
 *
 */
typedef struct tagAddInInfo
{
  char name[16];                /* zero terminated string */
  unsigned long size;           /* длина в байтах */
  unsigned int date_year;       /* год создания */
  unsigned char date_month;     /* месяц создания */
  unsigned char date_day;       /* день создания */
  unsigned char date_hour;      /* часы создания */
  unsigned char date_minute;    /* минуты создания */
  unsigned int version;         /* Версия, т.е. 100 означает версию 1.00 */
  unsigned int lib_year;        /* год библиотеки компиляции */
  unsigned char lib_month;      /* месяц библиотеки компиляции */
  unsigned char lib_day;        /* день библиотеки компиляции */
  unsigned char lib_hour;       /* часы библиотеки компиляции */ 
  unsigned char lib_minute;     /* минуты библиотеки компиляции against */
  unsigned int lib_version;      /* версия библиотеки компиляции */
  unsigned char menuicon[176];  /* готовность к LibPutGraph() данным 45*28 pixels */
  unsigned char listicon[84];   /* готовность к LibPutGraph() данным 27*20 pixels */
  unsigned int flags;           /* дополнительная информация: удалено (deleted), упаковано ("packed") */
  unsigned long address;        /* линейный адрес Add-In (для StartAddIn) */
} AddInInfo;


/*
 * flags for AddInInfo.flags
 */
#define ADDININFO_DELETED 1 /* "packed" Add-Ins уже помечен как удаленный */
#define ADDININFO_PACKED 2


/*
 * GetAddInInfo
 *
 * fills an AddInInfo structure with information from
 * requested Add-In iNr
 *
 * iNr is of range 0..63 with regular Add-Ins at 0,4,8,...,60
 * and packed Add-Ins possibly in between
 *
 * returns 1 if Add-In is found and AddInInfo valid
 * returns 0 otherwise, e.g. there is no Add-In starting at the slot
 *
 * The strategy to look for regular Add-Ins is to call GetAddInInfo
 * for slot 0,4,8,...,60 and check the flags if the Add-In is deleted
 *
 * Example:
 *
 * int i;
 * int k, maxsub; // needed for "packed" Add-In search only
 * AddInInfo info;
 *
 * for (i=0;i/lt;64;i+=4)
 * {
 *     if (GetAddInInfo(i,&info) && ((info.flags & ADDININFO_DELETED) == 0))
 *     {
 *         // regular not deleted Add-In found
 *         // ...
 *     }
 * }
 *
 * The strategy to look for "packed" Add-Ins is to examine the
 * size of each not deleted regular Add-In found and test for
 * the next (size / 0x4000) Add-Ins
 *
 * Example:
 *
 * // continuation of above example if regular Add-In was found
 *
 * maxsub = info.size / 0x4000;
 *
 * for (k=1;k/lt;maxsub;++k)
 * {
 *     if (GetAddInInfo(i+k,&info))
 *     {
 *         // "packed" Add-In found
 *         // ADDININFO_DELETED is always set
 *     }
 * }
 *
 */
int GetAddInInfo(int iNr, AddInInfo far * pInfo);


/*
 * StartAddIn
 *
 * calls the Add-In at address lLinAddr
 *
 * sets some PVOS internal variables so that PV can savely switch off and on
 *
 * lLinAddr should be taken from AddInInfo
 */
void StartAddIn(unsigned long lLinAddr);


#endif
AddInInfo.c 
/*
 * AddInInfo
 *
 * Author: J. Steingraeber
 * Date: 2001/02/27
 *
 * Released to the public domain
 */

#include 
#include "define.h"
#include "libc.h"

#include "AddInInfo.h"

/*
 * SwitchBank
 *
 * makes RAM or FLASH memory accessible at certain bank
 *
 * addr A31-A16 of source address (must be even)
 *      use 0000 - 00FE for RAM (only 0000 will work)
 *      use 0100 - 010E for program flash (1st MB, PVOS)
 *      use 0110 - 011E for program flash (2nd MB, Add-In)
 *      use 0120 - 013E for data flash (4MB data)
 *
 * bank destination bank
 *      use 0 for address space 0000:0000 (forbidden)
 *      use 1 for address space 2000:0000
 *      use 2 for address space 4000:0000
 *      use 3 for address space 6000:0000
 *      use 4 for address space 8000:0000 (forbidden)
 *      use 5 for address space A000:0000
 *      use 6 for address space C000:0000 (forbidden)
 *
 * remarks:
 *   you can not switch bank 0, 4 and 6, because that will crash your
 *   PV; bank 0 contains the interrupt vectors, and every program
 *   expects to find RAM here; bank 4 contains your Add-In, so
 *   switching this would make your Add-In vanishing; bank 6 contains
 *   the BIOS, your PV can not operate without it
 *
 * examples:
 *
 *   SwitchBank(0x0000,3);
 *     will make 128kB RAM accessible at address 6000:0000 so RAM can
 *     be accessed at 0000:0000 and 6000:0000 in the same way (which
 *     is possible but stupid, you still have only 128kB of RAM)
 *
 *   SwitchBank(0x0104,5);
 *     will make Fonts accessible at address A000:0000 and Graphics
 *     accessible at B000:0000
 *
 *   SwitchBank(0x0120,1);
 *     will make first 128kB of data flash accessible at 2000:0000
 *
 */
void _asm_switchbank(char *,int,int);
#define SwitchBank(addr,bank) _asm_switchbank("\n MOV BH,AL\n MOV AL,AH\n MOV AH,BL\n OR AH,80h\n INT 0C8h\n MOV AL,BH\n MOV AH,BL\n INT 0C8h\n",addr,bank);

void far startaddin(unsigned char StartSegHighByte,
                    unsigned int FirstBlock, int n);

void StartAddIn(unsigned long lLinAddr)
{
  unsigned int far * p;
  
  lLinAddr = lLinAddr >> 14;
  lLinAddr = lLinAddr & 0xFFFF;

  p = MK_FP(0xC400,0x115C);
  if (p[0] == 0x6682)
  {
        /* S-Series */
    p = MK_FP(0x0000,0x6682);
    p[0] = lLinAddr;
    p[1] = 8;
  }
  else
  {
    p = MK_FP(0xC400,0x10DA);
    if (p[0] == 0x6ABA)
    {
          /* X-Series */
      p = MK_FP(0x0000,0x6ABA);
      p[0] = lLinAddr;
      p[1] = 8;
    }
    else
    {
      p = MK_FP(0xC400,0x10F8);
      if (p[0] == 0x6682)
      {
            /* 750-Series */
        p = MK_FP(0x0000,0x6682);
        p[0] = lLinAddr;
        p[1] = 8;
      }
      else
      {
            /* unknown model */
        LibPutMsgDlg("WARNING!\r\rUnrecognized PVOS!\rUse on your own risk!\rBetter switch off now!");
      }
    }
  }
    
  lLinAddr = lLinAddr | 0x8000;
  startaddin(0x80,lLinAddr,8);
}

int GetAddInInfo(int iNr, AddInInfo far * pInfo)
{
  char far * p;
  int i;
  unsigned int n;
  unsigned long LinAddr, lTemp;
  unsigned long lIcon;
  unsigned int wSeg, wOffs;
  
      /* do some sanity checks */
  if ((iNr < 0) || (iNr > 63) || (pInfo == NULL))
  {
    return 0;
  }

      /* calculate start address of requested Add-In */
  lTemp = iNr;
  lTemp = lTemp << 14; /* each slot has a size of 16kB */
  LinAddr = 0x01100000; /* Address of first Add-In */
  LinAddr += lTemp;

  pInfo->address = LinAddr;
  
      /* make selected memory visible at 2000:0000 */
  SwitchBank((((LinAddr) >> 16) & 0xFFFE),1);

  wSeg = 0x2000;
  wOffs = LinAddr & 0xFFFF;
  if (LinAddr & 0x00010000)
  {
    wSeg = 0x3000;
  }
      
  p = MK_FP(wSeg,wOffs);

      /* test for Add-In header */
  if ((far_strncmp(&p[2],"CASIO",5) == 0)
      && (far_strncmp(&p[8],"Z486",4) == 0))
  {
        /* Add-In found, get header information */
    pInfo->flags = 0;
    if (p[1] == 0)
    {
      pInfo->flags |= ADDININFO_DELETED;
    }
    if ((iNr % 4) != 0)
    {
      pInfo->flags |= ADDININFO_PACKED;
    }

    far_strncpy(pInfo->name,&p[20],16);
    pInfo->name[15] = 0;
    
    pInfo->size = ((unsigned long far *)p)[9];

    n = 0;
    for (i=0;i<4;++i)
    {
      n = (n * 10) + p[40+i] - '0';
    }
    pInfo->date_year = n;
    
    n = 0;
    for (i=0;i<2;++i)
    {
      n = (n * 10) + p[44+i] - '0';
    }
    pInfo->date_month = n;
    
    n = 0;
    for (i=0;i<2;++i)
    {
      n = (n * 10) + p[46+i] - '0';
    }
    pInfo->date_day = n;
    
    n = 0;
    for (i=0;i<2;++i)
    {
      n = (n * 10) + p[48+i] - '0';
    }
    pInfo->date_hour = n;
    
    n = 0;
    for (i=0;i<2;++i)
    {
      n = (n * 10) + p[50+i] - '0';
    }
    pInfo->date_minute = n;
    
    n = 0;
    for (i=0;i<4;++i)
    {
      n = (n * 10) + p[52+i] - '0';
    }
    pInfo->version = n;
    
    n = 0;
    for (i=0;i<4;++i)
    {
      n = (n * 10) + p[56+i] - '0';
    }
    pInfo->lib_year = n;
    
    n = 0;
    for (i=0;i<2;++i)
    {
      n = (n * 10) + p[60+i] - '0';
    }
    pInfo->lib_month = n;
    
    n = 0;
    for (i=0;i<2;++i)
    {
      n = (n * 10) + p[62+i] - '0';
    }
    pInfo->lib_day = n;
    
    n = 0;
    for (i=0;i<2;++i)
    {
      n = (n * 10) + p[64+i] - '0';
    }
    pInfo->lib_hour = n;
    
    n = 0;
    for (i=0;i<2;++i)
    {
      n = (n * 10) + p[66+i] - '0';
    }
    pInfo->lib_minute = n;
    
    n = 0;
    for (i=0;i<4;++i)
    {
      n = (n * 10) + p[68+i] - '0';
    }
    pInfo->lib_version = n;

        /* calculate address of menuicon */
    lTemp = ((unsigned long far *)p)[18];
    lTemp += LinAddr;

        /* calculate address of listicon */
    lIcon = ((unsigned long far *)p)[19];
    lIcon += LinAddr;

        /* make  memory for menuicon visible at 2000:0000 */
    SwitchBank((((lTemp) >> 16) & 0xFFFE),1);
    
    wSeg = 0x2000;
    wOffs = lTemp & 0xFFFF;
    if (lTemp & 0x00010000)
    {
      wSeg = 0x3000;
    }
    
    p = MK_FP(wSeg,wOffs);

    far_memcpy(pInfo->menuicon,p,176);
        /* force standard dimension */
    pInfo->menuicon[0] = 0x2D;
    pInfo->menuicon[1] = 0x00;
    pInfo->menuicon[2] = 0x1C;
    pInfo->menuicon[3] = 0x00;
    wOffs += 176;
    if ((wOffs != 0) && (wOffs < 176))
    {
          /* 64kB overflow */
      wSeg += 0x1000;
      if (wSeg == 0x4000)
      {
            /* correct bank */
        lTemp += 0x4000;
        SwitchBank((((lTemp) >> 16) & 0xFFFE),1);
        wSeg = 0x2000;
      }
      p = MK_FP(wSeg,0);
      far_memcpy(&(pInfo->menuicon[176-wOffs]),p,wOffs);
    }
    
        /* make  memory for menuicon visible at 2000:0000 */
    SwitchBank((((lIcon) >> 16) & 0xFFFE),1);
    
    wSeg = 0x2000;
    wOffs = lIcon & 0xFFFF;
    if (lIcon & 0x00010000)
    {
      wSeg = 0x3000;
    }
    
    p = MK_FP(wSeg,wOffs);

    far_memcpy(pInfo->listicon,p,84);
        /* force standard dimension */
    pInfo->listicon[0] = 0x1B;
    pInfo->listicon[1] = 0x00;
    pInfo->listicon[2] = 0x14;
    pInfo->listicon[3] = 0x00;
    wOffs += 84;
    if ((wOffs != 0) && (wOffs < 84))
    {
          /* 64kB overflow */
      wSeg += 0x1000;
      if (wSeg == 0x4000)
      {
            /* correct bank */
        lIcon += 0x4000;
        SwitchBank((((lIcon) >> 16) & 0xFFFE),1);
        wSeg = 0x2000;
      }
      p = MK_FP(wSeg,0);
      far_memcpy(&(pInfo->listicon[84-wOffs]),p,wOffs);
    }

    return 1;
  }

  return 0;
}
startaddin.a86 
;;;
;;; startaddin
;;;
;;; Author: J. Steingraeber
;;; Date: 2001/02/27
;;;
;;; Released to the public domain

startaddin_TEXT	CSEG

	.186

startaddin_::
	push bp
	mov bp,sp
	sub sp,stopaddin_ - startaddin_
	push ax
	push bx
	push cx
	mov di,sp
	add di,6
	mov cx,bp
	sub cx,di
	mov si,startaddin_
copy:	mov al,cs:[si]
	inc si
	mov ss:[di],al
	inc di
	loop copy
	mov dx,entry - startaddin_
	pop cx
	pop bx
	pop ax
	mov di,sp
	add dx,di
	push ss
	push dx
	retf
entry:	out 0x6C,al
	add al,4
	push ax
	mov ax,bx
	out 0x6E,ax
	inc bx
	pop ax
	loop entry
	pushf
	pop bx
	cli
	mov ax,0x7000
	mov sp,ax
	mov ax,0x5000
	mov bp,ax
	push bx
	push 0x8000
	push 0x0100
	iret
	nop
	nop
	nop
	nop
stopaddin_::
	nop
	
	END


Надеюсь, что эта маленькая подпрограмма будет так или иначе полезна...

продолжение следует ;-)

Идея принадлежит Michael D. (OrganiZer), www.pocket-viewer.de


Вернуться к
Маленькие ценности PVOS - Add-Ins.
Все права связанные с торговыми марками, упоминаемыми на страницах этого ресурса, принадлежат их владельцам.
Полное или частичное воспроизведение любых материалов, содержащихся на этом сайте, допускается только с условием размещения ссылки на этот сайт.
Пишите нам: admin@pocket-viewer.ru © Алексей Ананьев-Миляр, 2001
www.melar.ru
Hosted by valueHOST: Лидер Вэб-Хостинга



Rambler's Top100 Rambler's Top100 Информационная Деловая Сеть