PDA

View Full Version : [Q] đọc FAT và FAT32, có ai biết không?



vth_bk
30-10-2002, 20:08
trong C++ có hàm absread và abswrite dùng để đọc và ghi sector của đĩa, có bác nào biết số ****** ổ đĩa nằm ở vị trí nào không, tui nhớ hình như là ở offset +27H, kích thước là 4bytes, nhưng đọc vào không được, có ai biết xin giúp đỡ, xin cám ơn trước...

ngocsale
30-10-2002, 23:16
Cái này thì phải giở sách ra xem thôi, chứ ít ai nhớ lắm.

CrazyKing
03-11-2002, 02:32
Một bài đọc bản fat hoàn chỉnh , bạn tham khảo :

#include <ctype.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "@fat.h"
#include "@dir.h"
#include "@disk.h"
#include "addconio.hpp"

// -----------------------------------------------------------------------
void Intro()
{
printf("Chuong trinh hien thi noi dung cac phan tu cua bang FAT tren Volume");
printf("\n Cu phap : ShowFAT.exe [drive:]");
printf("\n Vi du : ShowFAT A: \n");
exit(1);
}
// -----------------------------------------------------------------------
void Error(char * Msg, FATENTRY *FAT, DIRENTRY *DirEntry, WORD * DirSec)
{
printf("\n %s \n",Msg);
if (FAT!=NULL) free(FAT);
if (DirEntry!=NULL) free(DirEntry);
if (DirSec!=NULL) free(DirSec);
exit(1);
}
// -----------------------------------------------------------------------
ShowWordList(int x1,int y1,int x2,int y2, word *A,int lenA,int startpos,int chars)
{
int Rows=y2-y1+1;
int ElementPerRow=(x2-x1+1)/(chars+1);
int ElementPerPage=ElementPerRow*Rows;
char Ch, *FormatStr[4] = {"%01X ","%02X ","%03X ","%04X "};
char MoveKeys[] = {UP, DOWN, LEFT, RIGHT, PGUP, PGDOWN, 0};
char stemp[40];
int i, j, oldpos=-1, currentpos= startpos, wx, wy;
if (x1<=6 || y1<=2) return(-1);
textattr(BLUE);
gotoxy(x1,y1);
do {
wx = wherex(); wy= wherey();
if (oldpos!=startpos) {
i = 0;
SetWindows(x1-6,y1,x2,y2, ' ', LIGHTGRAY);
do {
gotoxy(x1-6,y1 + i/ElementPerRow);
cprintf("%04X: ", startpos+i);
for (j=0; j<ElementPerRow; j++, i++)
if(i<ElementPerPage && (startpos+i<lenA))
printf(FormatStr[chars-1],A[startpos+i]);
}while(i<ElementPerPage && (startpos+i<lenA));
oldpos = startpos;
gotoxy(wx,wy);
}
Ch = getch();
if (Ch==ESC) break; // InStr(Ch, FinishChars)...
if (Ch!=0) continue;
else Ch = getch(); // Ch la phim chuc nang
if (!InStr(Ch,MoveKeys)) continue;
switch (Ch) {
case UP:
if (wy > y1) wy--;
else if (startpos >= ElementPerRow)
startpos-=ElementPerRow;
break;
case LEFT:
if (wx > x1) wx -= (chars+1);
else
if (wy > y1) {
wx = x1 + (chars+1)*(ElementPerRow-1);
wy --;
}
else if (startpos >= ElementPerRow)
startpos -= ElementPerRow;
break;
case RIGHT:
if (currentpos + 1 >= lenA) break;
if (wx < x1 + (chars+1)*(ElementPerRow-1))
wx += (chars+1);
else
if (wy < y2) {
wx = x1;
wy ++;
}
else if (startpos + ElementPerPage + ElementPerRow < lenA)
startpos += ElementPerRow;
break;
case DOWN:
if (currentpos + ElementPerRow >= lenA)
break;
if (wy < y2)
wy++;
else startpos += ElementPerRow;
break;
case PGUP:
if (startpos <= ElementPerPage)
startpos = 0;
else startpos -= ElementPerPage;
break;
case PGDOWN:
if (startpos + ElementPerPage < lenA) {
startpos += ElementPerPage;
if (currentpos + ElementPerPage >= lenA) {
wx = x1;
wy = y1;
}
}
break;
}
currentpos = startpos + (wy-y1)*ElementPerRow + (wx-x1)/(chars+1);
sprintf(stemp, "Current position: %05d (%04Xh)", currentpos, currentpos);
Writexyattr(47,y1-1, stemp, LIGHTMAGENTA);
gotoxy(wx,wy);

}
while (1);
return 0;
}
// -----------------------------------------------------------------------
void ShowClusterList(FATTABLE FAT, unsigned StartClus)
{
int Old, NextClus;
Old = NextClus = StartClus;
if (StartClus == 0) return;
printf(" * Cluster list: %d",Old);
while (FAT[NextClus] < FAT[1]) { // FAT[1] = "EOF"
if (NextClus+1 != FAT[NextClus]) {
printf(" - %d, %d", NextClus, FAT[NextClus]);
Old = NextClus;
}
NextClus = FAT[NextClus];
}
if (Old+1 != NextClus) printf(" - %d.", NextClus);
else printf(", %d.", NextClus);
}

void ShowDIREntry(DIRENTRY e, FATTABLE FAT)
{
int i;
unsigned StartClus;

for (i=0; i<8; i++)
putch(e.Name[i]);
putch('.');
for (i=8; i<11; i++)
putch(e.Name[i]);
StartClus = e.FirstCluster;
ShowClusterList(FAT,StartClus);
putch(13); putch(10);
}
// -----------------------------------------------------------------------
int main(int argc, char *argv[])
{
FATTABLE FAT;
DIRTABLE DIR;
DISKINFO vol;
int drive, i, pos;
unsigned ch;
char *pathfile = argv[1];

if (argc==1) Intro(); //thieu tham so dong lenh
GetParam(argv[1], drive, pathfile);
if (GetDiskInfo(drive,vol)==FALSE) Error("Disk error!",NULL,NULL,NULL);
if ((FAT=ReadFAT(drive, vol.FATSec, vol.SecPerFAT, vol.bitPerFATEntry))==NULL)
Error("FAT error!",NULL,NULL,NULL);
clrscr();
Writexyattr(1,1,"Content of FAT:",LIGHTBLUE);
pos = 0;
ShowWordList(7,3,80,24, FAT, 2848, pos, vol.bitPerFATEntry/4);
// freeFAT(FAT);
// return 1;

clrscr();
DIR = ReadRootDir(drive,vol.DIRSec,vol.SecPerDir);
if (DIR.EntryList==NULL) Error("Error on RootDir",FAT,NULL,NULL);
i = 0;
while (DIR.EntryList[i].Name[0] && (i<vol.EntryPerDir))
{
if (DIR.EntryList[i].Name[0] != 0xE5 && DIR.EntryList[i].Name[2] != 0) {
ShowDIREntry(DIR.EntryList[i],FAT);
if (getch()==27) break;
}
i++;

}

freeFAT(FAT); freeDIR(DIR);
return 2;
}

chuchuotnhat
03-11-2002, 09:07
cám ơn CrazyKing rất nhiều, mình cũng vừa tìm được cách đọc bảng FAT, viết bằng pascal...

Quý
17-11-2002, 11:07
CrazyKing ơi bạn có thể cho mình mấy cái thư viện của bạn viết để tham khảo không ?

ngoccong2001
17-11-2002, 13:46
mình viết bằng assembler, cũng nhanh lắm đó.

CrazyKing
18-11-2002, 18:44
Bài viết được gửi bởi Quý
CrazyKing ơi bạn có thể cho mình mấy cái thư viện của bạn viết để tham khảo không ?
Đây là dir.H
#include "@FAT.H"
#include "vheader.h"
#if !defined __DIR
#define __DIR

typedef struct {
BYTE Name[11];
BYTE Attr;
BYTE Unused[10];
WORD Time;
WORD Date;
WORD FirstCluster; //Vi tri cluster dau tien cua tap tin
LONG Size;
} DIRENTRY;

typedef struct {
DIRENTRY * EntryList; // danh sach cac entry thu muc
WORD * SecList; // danh sach cac sector thuoc bang thu muc,
//trong do phan tu cuoi co gia tri 0 (dau hieu cuoi danh sach)
} DIRTABLE;

// -------------------------------------------------------
// Ham ReadRootDir doc noi dung bang thu muc goc tren dia
//
DIRTABLE ReadRootDir(int drive,int DirSec,int SecPerDir);

// -------------------------------------------------------
// Ham ReadSubDir doc noi dung 1 bang thu muc con tren dia
//
DIRTABLE ReadSubDir(int drive,int FirstClus,int SecPerClus,
int DATASec, FATTABLE FAT);

// ------------------------------------------------------------------------
// Ham SearchEntry tim trong bang thu muc DIR entry co ten chua trong chuoi
// pathfile. Neu pathfile la mot duong dan, chang han "BC31\BIN\BC.EXE" thi
// sau khi tim duoc entry "BC31" trong DIR, bang thu muc con cua "BC31" se
// duoc nap lai vao bien DIR va pathfile duoc cap nhat lai la "BIN\BC.EXE",
// cong viec cu tiep tuc cho den khi tim duoc entry cuoi "BC.EXE", DIR khi
// do la bang thu muc con chua entry tren (thu muc "BIN").
//* Gia tri tra ve cua ham la chi so cua entry tim duoc tren DIR, hoac (-1)
// neu khong co entry tuong ung.
//
int SearchEntry(DIRTABLE &DIR, char *pathfile,int drive,
FATTABLE FAT,int DataSec,int SecPerClus );

// -----------------------------------------------------------------------
// Ham SearchFreeEntry tim entry trong dau tien trong bang thu muc DIR va
// tra ve vi tri tim duoc /* can xu ly them trong truong hop khong co */
//
int SearchFreeEntry(DIRTABLE DIR);

// -------------------------------------------------------
// Ham WriteDirEntry ghi 1 entry vao bang thu muc tren dia
//
BOOL WriteDirEntry(int drive, DIRTABLE DIR, int i);

// -------------------------------------------------------------------------
// Ham GetParam phan tich chuoi duong dan inSt va lay ra o dia drive, chuoi
// duong dan con lai duoc dua vao bien outSt
// Vi du : inSt = "A:\HDH\DIR.CPP" ==> drive=0, outSt = "HDH\DIR.CPP"
//
void GetParam(char *inSt, int &drive, char *&outSt);

// -------------------------------------------------------
// Ham freeDir giai phong cac vung nho tuong ung da cap phat
//
void freeDIR(DIRTABLE DIR);

#endif

CrazyKing
18-11-2002, 18:47
Bài viết được gửi bởi Quý
CrazyKing ơi bạn có thể cho mình mấy cái thư viện của bạn viết để tham khảo không ?

@DIR.CPP
// ----------------------------- @DIR.CPP -------------------------------
// Module chua cac thao tac tren bang DIR - Dung cho dia kich thuoc nho
// (chuong trinh co the duoc dich o model Small)
// De dung duoc mang DIR va cac ham tuong ung o module khac phai khai bao
// header_file DIR.H trong module do va include module nay vao project
// kem khai bao "DIRTABLE DIR"
// ----------------------------------------------------------------------
#include <dos.h>
#include <ctype.h>
#include <alloc.h>
#include <stdio.h>
#include <string.h>
#include "vheader.h"
#include "@disk.h"
#include "@dir.h"


// -------------------------------------------------------------------------
// Ham GetParam phan tich chuoi duong dan inSt va lay ra o dia drive, chuoi
// duong dan con lai duoc dua vao bien *outSt
// Vi du : inSt = "A:\HDH\DIR.CPP" ==> drive=0, outSt = "HDH\DIR.CPP"
// -------------------------------------------------------------------------
void GetParam(char *inSt, int &drive, char *&outSt)
{
if (inSt[1] == ':') {
drive = toupper(inSt[0]) - 'A'; // lay o dia
outSt = inSt + 2;
}
else drive = GetCurrentDrive(); // lay o dia hien hanh
if (outSt[0] == '\\') outSt++;
}

// -------------------------------------------------------------------------
// Ham ReadDIRfromFile doc noi dung bang thu muc da duoc luu tren file
// -------------------------------------------------------------------------
DIRENTRY * ReadDIR(int drive, WORD * DirSecList, BYTE SecPerDir)
{
int sec = 0;
DIRENTRY * DE = (DIRENTRY *)malloc(512*SecPerDir);
if (DE==NULL) return (NULL);
do { //doc moi lan 1 sector (~16 entry)
if (absread(drive,1,DirSecList[sec],DE+(512/sizeof(DIRENTRY))*sec)!=0) {
free(DE);
return (NULL);
}
sec++;
}
while (DirSecList[sec]!=NULL);
return (DE);
}
// -------------------------------------------------------------------------
// Ham ReadRootDir doc noi dung bang thu muc goc tren dia
// -------------------------------------------------------------------------
DIRTABLE ReadRootDir(int drive,int DirSec,int SecPerDir)
{
DIRTABLE DIR;

DIR.SecList = (WORD *)malloc((SecPerDir+1)*sizeof(WORD));
for (int i=0; i<SecPerDir; i++)
DIR.SecList[i] = DirSec + i;
DIR.SecList[i] = NULL; // phan tu cuoi danh sach

DIR.EntryList = ReadDIR(drive, DIR.SecList, SecPerDir);
return (DIR);
}
// ----------------------------------------------------------------------
// Ham ReadSubDir doc noi dung 1 bang thu muc con tren dia
// ----------------------------------------------------------------------
DIRTABLE ReadSubDir(int drive, int FirstClus, int SecPerClus,
int DATASec, FATTABLE FAT)
{
DIRTABLE DIR;
BYTE SecPerDir = 0;
long i,j,k = FirstClus;
// unsigned Mask = (FAT[1]==0xFFFF? 0xFFFF:0xFFF);

while (k != FAT[1]) { // FAT[1] = "EOF"
SecPerDir+=SecPerClus;
k = FAT[k];
}
DIR.SecList = (WORD*) malloc((SecPerDir+1)*sizeof(WORD));
i = 0;
k = FirstClus;
while (k != FAT[1]) {
for (j=0; j<SecPerClus; j++)
DIR.SecList[i++] = DATASec + (k-2)*SecPerClus + j;
k = FAT[k];
}
DIR.SecList[i] = NULL; // phan tu cuoi danh sach

DIR.EntryList = ReadDIR(drive, DIR.SecList, SecPerDir);
return (DIR);
}
// ----------------------------------------------------------------------
// Ham WriteDirEntry ghi entry i tren mang DIR vao bang thu muc tren dia
// ----------------------------------------------------------------------
BOOL WriteDirEntry(int drive, DIRTABLE DIR, int i)
{
int pos; // vi tri (sector) chua entry thu muc i can ghi
int EntryPerSec = 512/sizeof(DIRENTRY);
int sec = i/EntryPerSec; //chi so sector chua entry thu muc

pos = DIR.SecList[sec];
if (abswrite(drive,1,pos,(DIR.EntryList+(i/EntryPerSec)*EntryPerSec))!=0)
return FALSE;
return TRUE;
}
// ------------------------------------------------------------------------
// Ham SearchEntry tim trong bang thu muc DIR entry co ten chua trong chuoi
// pathfile. Neu pathfile la mot duong dan, chang han "BC31\BIN\BC.EXE" thi
// sau khi tim duoc entry "BC31" trong DIR, bang thu muc con cua "BC31" se
// duoc nap lai vao bien DIR va pathfile duoc cap nhat lai la "BIN\BC.EXE",
// cong viec cu tiep tuc cho den khi tim duoc entry cuoi "BC.EXE", DIR khi
// do la bang thu muc con chua entry tren (thu muc "BIN").
//* Gia tri tra ve cua ham la chi so cua entry tim duoc tren DIR, hoac (-1)
// neu khong co entry tuong ung.
// ------------------------------------------------------------------------
int SearchEntry(DIRTABLE &DIR, char *pathfile,int drive,
FATTABLE FAT,int DataSec,int SecPerClus )
{
char filename[11];
BYTE len, found;
WORD i,j,k,FirstClus;

do {
i = j = 0; len = strlen(pathfile); // lay EntryName tu pathfile
while (pathfile[i]=='.') // truong hop dac biet : thu muc la "." hoac ".."
filename[j++] = pathfile[i++];
while ((pathfile[i]!='.')&&(pathfile[i]!='\\')&&(i<len)) // va cap nhat lai
filename[j++] = toupper(pathfile[i++]); // pathfile chi den dau EntryName moi
while (j < 8) filename[j++] = ' ';
if (pathfile[i] == '.') i++;
while ((pathfile[i]!='\\')&&(i<len))
filename[j++] = toupper(pathfile[i++]);
while (j < 11) filename[j++] = ' ';
pathfile += i;
if (pathfile[0] == '\\') pathfile++;

k = 0; found = FALSE;
while (DIR.EntryList[k].Name[0]!=0 && !found) { // tim entry tuong ung
i=0;
while (DIR.EntryList[k].Name[i]==filename[i]) i++;
if (i==11) found = TRUE;
else k++;
}
if (!found) return(-1); // Entry not found!

FirstClus = DIR.EntryList[k].FirstCluster;
if (pathfile[0]!=NULL) { //tim tiep trong thu muc con
freeDIR(DIR);
DIR = ReadSubDir(drive,FirstClus,SecPerClus,DataSec,FAT) ;
}
}
while (pathfile[0]!=NULL);
return (k);
}
// -----------------------------------------------------------------------
// Ham SearchFreeEntry tim entry trong dau tien trong bang thu muc DIR va
// tra ve vi tri tim duoc /* can xu ly them trong truong hop khong co */
// -----------------------------------------------------------------------
int SearchFreeEntry(DIRTABLE DIR)
{
int i=0;
while (DIR.EntryList[i].Name[0]!=0)
if ((BYTE)(DIR.EntryList[i].Name[0])!=0xE5) i++;
else break;
return (i);
}

// ----------------------------------------------------------------------
// Ham freeDIR giai phong vung nho da cap phat
// ----------------------------------------------------------------------
void freeDIR(DIRTABLE DIR)
{
if (DIR.EntryList!=NULL) {
free(DIR.EntryList);
free(DIR.SecList);
}
return;
}

CrazyKing
18-11-2002, 18:48
Bài viết được gửi bởi Quý
CrazyKing ơi bạn có thể cho mình mấy cái thư viện của bạn viết để tham khảo không ?
// ------------------------------ @FAT.CPP ------------------------------
// Module chua cac thao tac tren bang FAT
// .................................................. ....................
// De dung duoc mang FAT va cac ham tuong ung o module khac phai khai bao
// header_file @FAT.H trong module do va include module nay vao project
// kem khai bao "FATTABLE FAT"
// ----------------------------------------------------------------------
#include <dos.h>
#include <mem.h>
#include <alloc.h>
#include <stdio.h>
#include "vheader.h"
#include "@fat.h"
// ----------------------------------------------------------------------
FATTABLE ReadFAT12(int drive,int FATsec,int secperFAT)
{
WORD temp, offset, cluster;
WORD FATsize = secperFAT*512 * 2/3; // so luong phan tu tren bang FAT
BYTE * buf = (BYTE *)malloc(secperFAT*512);
FATTABLE FAT = (FATENTRY *)malloc(FATsize*sizeof(FATENTRY));
if (buf==NULL || FAT==NULL) return NULL;

if (absread(drive,secperFAT,FATsec,buf) !=0) {
free(buf); free(FAT);
return NULL;
}
/* for (cluster=0; cluster<FATsize; cluster++) {
offset = (cluster)*3/2; //
temp = 0x100*buf[offset+1] + buf[offset];
if (cluster%2!=0)
FAT[cluster] = temp>>4;
else FAT[cluster] = temp & 0x0FFF;
*/
// Thay vi dung vong lap tren co the dung 2 vong lap nhung nhanh hon nhu sau:
for (cluster=0,offset=0; cluster<FATsize; cluster+=2) {
temp = *(FATENTRY *)(buf+offset);// = 0x100*buf[offset+1] + buf[offset];
FAT[cluster] = temp&0x0FFF;
offset += 3; // 2 cluster chiem 3 byte
}
for (cluster=1,offset=1; cluster<FATsize; cluster+=2) {
temp = *(FATENTRY *)(buf+offset);
FAT[cluster] = temp>>4;
offset += 3; // 2 cluster chiem 3 byte
}
free (buf);
return (FAT);
}
// ----------------------------------------------------------------------
FATTABLE ReadFAT16(int drive,int FATsec,int secperFAT)
{
int i,num = 0;
long k=0;
WORD buf[256*16]; // moi lan doc 16 sector
long FATsize = (512L/2)*secperFAT;
// FATTABLE FAT = (FATENTRY far*)farmalloc(FATsize*sizeof(FATENTRY));
FATTABLE FAT = (FATENTRY *)malloc(FATsize*sizeof(FATENTRY));
if (FAT==NULL) return NULL;
while (num+16 <= secperFAT) {
if (absread(drive,16,FATsec+num, buf)!=0) {
farfree(FAT);
return NULL;
}
for (i=0; i<256*16; i++) {
FAT[k] = buf[i];
k++;
}
num += 16;
}
if (num < secperFAT) {
absread(drive,secperFAT-num,FATsec+num, buf);
for (i=0; i<256*(secperFAT-num); i++)
FAT[k++] = buf[i];
}
printf("FAT[32768]=%ld %ld",(long)FAT[32761] ,(long) FAT[32768]);
return (FAT);
}
// ----------------------------------------------------------------------
FATTABLE ReadFAT(int drive,int FATsec,int secperFAT,int numofbit)
{
FATTABLE FAT;

if (numofbit==12)
FAT = ReadFAT12(drive, FATsec, secperFAT);
else // (numofbit==16)
FAT = ReadFAT16(drive, FATsec, secperFAT);
return (FAT);
}
// ----------------------------------------------------------------------
BOOL WriteFAT12(int drive,int FATsec,int secperFAT, FATTABLE FAT)
{
WORD offset, cluster;
WORD FATsize = secperFAT*512 * 2/3;
BYTE * buf = (BYTE *)malloc(secperFAT*512);
if (buf==NULL) return FALSE;
for (cluster=0,offset=0; cluster<FATsize; cluster+=2) {
buf[offset] = FAT[cluster] & 0xFF;
buf[offset+2] = FAT[cluster+1] >> 4;
buf[offset+1] = ((FAT[cluster+1]&0x0F)<<4) + (FAT[cluster] >> 8);
offset += 3;
}
if (abswrite(drive, secperFAT, FATsec, buf)!=0) return FALSE;
free (buf);
return TRUE;
}
// ----------------------------------------------------------------------
BOOL WriteFAT16(int drive,int FATsec,int secperFAT, FATTABLE FAT)
{
BYTE num = 0;
while (num++ < secperFAT)
if (abswrite(drive,1,FATsec+num, (BYTE *)(FAT+256*num))!=0) return FALSE;
return TRUE;
}
// ----------------------------------------------------------------------
BOOL WriteFAT(int drive,int FATsec,int secperFAT,int numofbit, FATTABLE FAT)
{
BOOL result;
if (numofbit==12)
result = WriteFAT12(drive, FATsec, secperFAT, FAT);
else // (numofbit==16)
result = WriteFAT16(drive, FATsec, secperFAT, FAT);
return (result);
}
// ----------------------------------------------------------------------
int SearchFreeCluster(FATTABLE FAT,int pos)
{
int cluster = pos;
while (FAT[cluster] != 0)
cluster++;
return (cluster);
}
// ----------------------------------------------------------------------
void freeFAT(FATTABLE FAT)
{
if (FAT!=NULL) free(FAT);
return;
}
// ----------------------------------------------------------------------

CrazyKing
18-11-2002, 18:50
Bài viết được gửi bởi Quý
CrazyKing ơi bạn có thể cho mình mấy cái thư viện của bạn viết để tham khảo không ?
ADDconio.hpp

/* Danh muc cac ham cua modul nay:
void Writexy(int x, int y, char * s);
void Writexyattr(int x, int y, char * s, unsigned attr);
void WritexyattrK(int x, int y, char * s, unsigned attr,int k, unsigned attrK);
void Box(byte x1,byte y1,byte x2,byte y2, byte mode);
void SetWindows(int x1,int y1,int x2,int y2,byte ch,byte attr);
void SetCursor(int status);
void SetBlink(word status);
void Clear();
unsigned GetKey();
void GetKey2(byte &scan, byte &ascii);
void OutKey(unsigned key);
void SaveScreen();
void RestoreScreen();
int InStr(char Ch, char * St); // kiem tra ky tu Ch co nam trong chuoi St
int IsSpecialKey(unsigned key, unsigned SpecialKey[], int numkey)
int ReadInt(int inf, int sup);
byte Get1HexByteAtPos(int x, int y);
long ReadDecValueAtPos(int x,int y,int maxchar,char *FinishChars,char &ch);
char * ReadStringAtPos(int x,int y,int maxchar,char *ValidChars,char *FinishChars,char &ch);
char * ReadStringAtPos_(int x,int y,int maxchar,char *ValidChars,char *FinishChars,char &ch);
char * TrimBlank(char *s);
int String2DecValue(char *s, long &value);


*/

#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>
#include <ctype.h>

#ifndef __cplusplus
printf( "This Modul must compile in C++ mode. (/Option/Compiler/C++ option/ C++ always)
#endif
#if!defined(_AddCONIO_H)
#define _AddCONIO_H


#define ON 1
#define OFF 0
#define UP 0x48
#define DOWN 0x50
#define LEFT 0x4B
#define RIGHT 0x4D
#define PGUP 0x49
#define PGDOWN 0x51
#define BACK 0x08
#define TAB 0x09
#define DEL 0x53
#define INS 0x52
#define ESC 0x1B
#define ENTER 0x0D
#define BLANK 0x20
#define F1 0x3B
#define F2 0x3C
#define F3 0x3D
#define F4 0x3E
#define F5 0x3F
#define F6 0x40
#define F7 0x41
#define F8 0x42
#define F9 0x43
#define F10 0x44
//#define F11 0x3B
//#define F12 0x3B

#define UP_ 0x4800
#define DOWN_ 0x5000
#define LEFT_ 0x4B00
#define RIGHT_ 0x4D00
#define ENTER_ 0x1C0D
#define ESC_ 0x011B
#define PGUP_ 0x4900
#define PGDOWN_ 0x5100
#define TAB_ 0x0809
#define BACK_ 0x0E08

typedef unsigned char byte;
typedef unsigned int word;

typedef struct ScreenMemory
{
byte ascii;
byte attrib;
};
struct ScreenMemory far * Screen = (struct ScreenMemory far *)MK_FP(0xB800,0);
//---------------------------------------------------------------------------
void Writexy(int x, int y, char * s)
{
for (int i=0, pos = (y-1)*80 + (x-1); i < strlen(s); i++, pos++)
Screen[pos].ascii = s[i];
}
//---------------------------------------------------------------------------
void Writexyattr(int x, int y, char * s, unsigned attr)
{
for (int i=0, pos = (y-1)*80 + (x-1); i < strlen(s); i++, pos++) {
Screen[pos].attrib = attr;
Screen[pos].ascii = s[i];
}
}
//---------------------------------------------------------------------------
void WritexyattrK(int x, int y, char * s, unsigned attr,int k, unsigned attrK)
{
for (int i=0, pos = (y-1)*80 + (x-1); i < strlen(s); i++, pos++) {
Screen[pos].attrib = attr;
Screen[pos].ascii = s[i];
}
Screen[(y-1)*80 + (x-1) + k].attrib = attrK;
}
//---------------------------------------------------------------------------
void Box(byte x1,byte y1,byte x2,byte y2, byte mode)
{
char LeftTop[4] = {'Ú','Õ','Ö','É'};
char RightTop[4]= {'¿','¸','·','»'};
char LeftBot[4] = {'À','Ô','Ó','È'};
char RightBot[4]= {'Ù','¾','½','¼'};
char LineRec[4] = {'Ä','Í','Ä','Í'};
char SideRec[4] = {'³','³','º','º'};
byte i;
gotoxy(x1,y1); putch(LeftTop[mode]);
for (i=x1+1; i<x2; i++) putch(LineRec[mode]);
putch(RightTop[mode]);
gotoxy(x1,y2); putch(LeftBot[mode]);
for (i=x1+1; i<x2; i++) putch(LineRec[mode]);
putch(RightBot[mode]);
for (i=y1+1; i<y2; i++) {
gotoxy(x1,i); putch(SideRec[mode]);
gotoxy(x2,i); putch(SideRec[mode]);
}
}
//---------------------------------------------------------------------------
void SetWindows(int x1,int y1,int x2,int y2,byte ch,byte attr)
//Dat lai 1 cua so voi ky tu Ch , thuoc tinh Attr
{
int x, y, pos;
for (y=y1; y<=y2; y++) {
pos = (y-1)*80 + (x1-1);
for (x=x1; x<=x2; x++,pos++) {
Screen[pos].attrib = attr;
Screen[pos].ascii = ch;
}
}
}
// -----------------------------------------------------------------------
void SetBlink(word status)
{
_BX = (status&1);
_AX = 0x1003;
geninterrupt(0x10);
}
// -----------------------------------------------------------------------
void Clear()
{
_AH = 0x0F;
geninterrupt(0x10);
_AH = 0;
geninterrupt(0x10);
}
// ------------------------------------------------------------------------
void SetCursor(int status)
{
if (status==OFF) { // tat con tro
_AH = 1;
_CX = 0x0C0D;
geninterrupt(0x10);
}
else {
_AH = 1;
_CX = 0x2020;
geninterrupt(0x10);
}
}
//---------------------------------------------------------------------------
unsigned GetKey()
{
_AH = 0;
geninterrupt(0x16);
return (_AX);
}
// ---------------------------------------------------------------------------
void GetKey2(byte &scan, byte &ascii)
{
_AH = 0;
geninterrupt(0x16);
scan = _AH;
ascii= _AL;
}
//---------------------------------------------------------------------------
void OutKey(unsigned key) // gui 1 phim ra vung dem ban phim
{
_AH = 5;
_CX = key;
geninterrupt(0x16);
}
// -----------------------------------------------------------------------
word oldscr[2000];
// -----------------------------------------------------------------------
void SaveScreen()
{
_fmemcpy(oldscr,Screen,4000);
}
// -----------------------------------------------------------------------
void RestoreScreen()
{
_fmemcpy(Screen,oldscr,4000);
}
// -----------------------------------------------------------------------
int InStr(char Ch, char * St) // kiem tra ky tu Ch co nam trong chuoi St
{
for (int i=0; i<strlen(St); i++)
if (St[i]==Ch) return (i+1);
return 0;
}
// -----------------------------------------------------------------------
int IsSpecialKey(unsigned key, unsigned SpecialKey[], int numkey)
{
for (int i=0; i<numkey; i++)
if (key==SpecialKey[i]) return (i+1);
return (0);
}
// -----------------------------------------------------------------------
int ReadInt(int inf, int sup)
{
char s[10];
byte i, oldX, oldY;
int t;
oldX = wherex(); oldY = wherey();
while(1) {
gets(s);
t = atoi(s);
if (t<inf || t>sup) {
gotoxy(oldX,oldY);
for (i=1; i<strlen(s); i++) putch(' ');
gotoxy(oldX,oldY);
}
else break;
}
return t;
}
//---------------------------------------------------------------------------
byte Get1HexByteAtPos(int x, int y)
{
int pos = (y-1)*80 + (x-1);
byte a = Screen[pos].ascii, b = Screen[pos+1].ascii;
a = a<='9'? a-'0': a-'A';
b = b<='9'? b-'0': b-'A';
return((a<<4) + b);
}
//---------------------------------------------------------------------------
long ReadDecValueAtPos(int x,int y,int maxchar,char *FinishChars,char &ch)
{
char c, * savebuf = (char*)malloc(maxchar);
int i, pos = (y-1)*80+(x-1);
long value;
for (i=0; i<maxchar; i++) {
savebuf[i] = Screen[pos+i].ascii;
Screen[pos+i].ascii = ' ';
}
gotoxy(x,y);
do
{
ch = getch();
if (ch==BACK || ch==LEFT) {
if (wherex()>x) {
Screen[(y-1)*80+wherex()-2].ascii = ' ';
gotoxy(wherex()-1,y);
}
}
if (ch>='0' && ch<='9'&& (wherex()<x+maxchar))
putch(ch);
}
while (!InStr(ch, FinishChars)); //(ch!=9 && ch!=13 && ch!=27);
if (wherex()==x) // phuc hoi trang thai cu
for (i=0; i<maxchar; i++)
Screen[pos+i].ascii = savebuf[i];

value = 0;
for (i=0; i<maxchar; i++) {
c = Screen[pos+i].ascii;
if (c != ' ')
value = value*10 + (c - '0');
}
free(savebuf);
return (value);
}
//---------------------------------------------------------------------------
char * ReadStringAtPos(int x,int y,int maxchar,char *ValidChars,char *FinishChars,char &ch)
{
char * save, *buff;
int i, pos = (y-1)*80+(x-1);
save = (char*)malloc(maxchar);
buff = (char*)malloc(maxchar+1);
if (save==NULL || buff==NULL) return(NULL);
for (i=0; i<maxchar; i++) {
save[i] = Screen[pos+i].ascii;
Screen[pos+i].ascii = ' ';
}
gotoxy(x, y);
do
{
ch = toupper(getch());
if (ch==BACK || ch==LEFT) {
if (wherex()>x) {
Screen[(y-1)*80+wherex()-2].ascii = ' ';
gotoxy(wherex()-1,y);
}
}
if (InStr(ch,ValidChars) && (wherex()<x+maxchar))
putch(ch);
}
while (!InStr(ch, FinishChars)); //(ch!=9 && ch!=13 && ch!=27);
if (wherex()==x) // phuc hoi trang thai cu
for (i=0; i<maxchar; i++)
Screen[pos+i].ascii = save[i];
for (i=0; i<maxchar; i++)
buff[i] = Screen[pos+i].ascii;
buff[i] = 0;
free(save);
return (buff);
}
//---------------------------------------------------------------------------
char * ReadStringAtPos_(int x,int y,int maxchar,char *ValidChars,char *FinishChars,char &ch)
{
char * save, *buff;
int i, pos = (y-1)*80+(x-1);
if ((buff = (char*)malloc(maxchar+1))==NULL) return(NULL);
gotoxy(x, y);
do
{
ch = toupper(getch());
if (ch==BACK || ch==LEFT)
if (wherex()>x)
gotoxy(wherex()-1,y);
if (InStr(ch,ValidChars) && (wherex()<x+maxchar))
putch(ch);
}
while (!InStr(ch, FinishChars)); //(ch!=9 && ch!=13 && ch!=27);
for (i=0; i<wherex()-x; i++)
buff[i] = Screen[pos+i].ascii;
buff[wherex()-x] = 0;
return (buff);
}

// --------------------------------------------------------------------------
char * TrimBlank(char *s)
{
char * p;
int head=0, tail=strlen(s)-1;
while (s[head]==' ') head++;
while (s[tail]==' ') tail--;
if ((p=(char*)malloc(tail-head+2))!=NULL) {
memcpy(p,s+head,tail-head+1);
p[tail-head+1] = 0;
}
return(p);
}
// --------------------------------------------------------------------------
int String2DecValue(char *s, long &value)
{
char *p = TrimBlank(s);
value = 0;
for (int i=0; i<strlen(p); i++)
if (p[i]<'0' || p[i]>'9') {
free(p);
return (0);
}
else value = value*10 + (p[i]-'0');
free(p);
return(1);
}

#endif