Библиотека РАзных ВОпросов разработчику
Вернуться к Маленькие ценности 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.