⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c64-fs.c

📁 伟大的Contiki工程, 短小精悍 的操作系统, 学习编程不可不看
💻 C
字号:
/** * \defgroup c64fs C64 file system and disk functions. * @{ * * The C64 file system functions are divided into two categories: * those that deal with C64 files and the C64 disk directory, and * those that allow direct block access to the disk. The former * functions can be used for accessing regular files, whereas the * latter functions are used e.g. to download D64 files onto 1541 * disks. * * \note The C64 filesystem functions currently only work with the * 1541/1541-II/1571 and compatible drives, and not with the IDE64 * hard disks or the 1581/FD2000 3.5" drives. * *  *//** * \file * C64 file system operations interface for Contiki. * \author Adam Dunkels <adam@dunkels.com> * *//* * Copyright (c) 2003, Adam Dunkels. * All rights reserved.  * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  * 2. Redistributions in binary form must reproduce the above *    copyright notice, this list of conditions and the following *    disclaimer in the documentation and/or other materials provided *    with the distribution.  * 3. The name of the author may not be used to endorse or promote *    products derived from this software without specific prior *    written permission.   * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   * * This file is part of the Contiki desktop environment  * * $Id: c64-fs.c,v 1.1 2007/05/23 23:11:28 oliverschmidt Exp $ * */#include "c64-dio.h"#include "c64-dio-asm.h"#include "c64-fs.h"#include <string.h>#include <stdio.h>struct directory_entry {  unsigned char type;  unsigned char track, sect;  unsigned char name[16];  unsigned char reltrack, relsect, relreclen;  unsigned char unused1, unused2, unused3, unused4;  unsigned char tmptrack, tmpsect;  unsigned char blockslo, blockshi;};unsigned char _c64_fs_dirbuf[256];unsigned char _c64_fs_dirbuftrack = 0, _c64_fs_dirbufsect = 0;unsigned char _c64_fs_filebuf[256];unsigned char _c64_fs_filebuftrack = 0, _c64_fs_filebufsect = 0;static struct c64_fs_dirent lastdirent;static struct c64_fs_dir opendir;static struct c64_fs_dirent opendirent;/*-----------------------------------------------------------------------------------*//** * Open a file. * * The file description must be allocated by the caller and a pointer * to it is passed to this function. * * \param name A pointer to the name of the file to be opened. * \param f A pointer to the file descriptor struct. * * \retval 0 If the file was successfully opened. * \retval -1 If the file does not exist. *//*-----------------------------------------------------------------------------------*/intc64_fs_open(const char *name, register struct c64_fs_file *f){  /* First check if we already have the file cached. If so, we don't     need to do an expensive directory lookup. */  if(strncmp(lastdirent.name, name, 16) == 0) {    f->track = lastdirent.track;    f->sect = lastdirent.sect;    f->ptr = 2;    return 0;  }  /* Not in cache, so we walk through directory instead. */  c64_fs_opendir(&opendir);  do {    c64_fs_readdir_dirent(&opendir, &opendirent);    if(strncmp(opendirent.name, name, 16) == 0) {      f->track = opendirent.track;      f->sect = opendirent.sect;      f->ptr = 2;      return 0;    }  } while(c64_fs_readdir_next(&opendir) == 0);  /* The file was not found in the directory. We flush the directory     buffer cache now in order to prevent a nasty problem from     happening: If the first directory block of an empty disk was     cached, *all* subsequent file opens would return "file not     found". */  _c64_fs_dirbuftrack = 0; /* There are no disk blocks on track 0. */  return -1;}/*-----------------------------------------------------------------------------------*//** * Read data from an open file. * * This function reads data from an open file into a buffer than must * be allocated by the caller. * * \param f A pointer to a file descriptor structure that must have * been opened with c64_fs_open(). * * \param buf A pointer to the buffer in which the data should be placed. * * \param len The maxiumum amount of bytes to read. * * \return The number of bytes that actually was read, or 0 if an end * of file was encountered. *//*-----------------------------------------------------------------------------------*/#if !NOASM#pragma optimize(push, off)#endif /* !NOASM */int __fastcall__c64_fs_read(register struct c64_fs_file *f, char *buf, int len){  static int i;  /* Check if current block is already in buffer, and if not read it     from disk. */#if NOASM  if(f->track != _c64_fs_filebuftrack ||     _c64_fs_filebufsect != f->sect) {    _c64_fs_filebuftrack = f->track;    _c64_fs_filebufsect = f->sect;    c64_dio_read_block(_c64_fs_filebuftrack, _c64_fs_filebufsect,		       _c64_fs_filebuf);  }#else /* NOASM */  asm("ldy #%b", offsetof(struct c64_fs_file, track));  asm("lda (regbank+%b),y", 4);  asm("cmp %v", _c64_fs_filebuftrack);  asm("bne doblock");    asm("ldy #%b", offsetof(struct c64_fs_file, sect));  asm("lda (regbank+%b),y", 4);  asm("cmp %v", _c64_fs_filebufsect);  asm("bne doblock");  asm("jmp noblock");  asm("doblock:");    asm("ldy #%b", offsetof(struct c64_fs_file, track));  asm("lda (regbank+%b),y", 4);  asm("sta %v", _c64_fs_filebuftrack);  asm("sta %v", c64_dio_asm_track);    asm("ldy #%b", offsetof(struct c64_fs_file, sect));  asm("lda (regbank+%b),y", 4);  asm("sta %v", _c64_fs_filebufsect);  asm("sta %v", c64_dio_asm_sector);  asm("lda #<(%v)", _c64_fs_filebuf);  asm("sta %v", c64_dio_asm_ptr);  asm("lda #>(%v)", _c64_fs_filebuf);  asm("sta %v+1", c64_dio_asm_ptr);  asm("jsr %v", c64_dio_asm_read_block);  asm("noblock:");#endif /* NOASM */  if(_c64_fs_filebuf[0] == 0 &&     f->ptr == _c64_fs_filebuf[1]) {    return 0; /* EOF */  }  for(i = 0; i < len; ++i) {#if NOASM        *buf = _c64_fs_filebuf[f->ptr];    ++f->ptr;#else /* NOASM */	    asm("ldy #%o+1", buf);    asm("jsr ldaxysp");    asm("sta ptr2");    asm("stx ptr2+1");    asm("ldy #%b", offsetof(struct c64_fs_file, ptr));    asm("lda (regbank+%b),y", 4);        asm("tax");    asm("ldy #0");    asm("lda %v,x", _c64_fs_filebuf);    asm("sta (ptr2),y");    asm("inx");    asm("txa");    asm("ldy #%b", offsetof(struct c64_fs_file, ptr));    asm("sta (regbank+%b),y", 4);    #endif /* NOASM */        if(_c64_fs_filebuf[0] == 0) {      if(f->ptr == _c64_fs_filebuf[1]) {	/* End of file reached, we return the amount of bytes read so	   far. */	return i + 1;      }    } else if(f->ptr == 0) {      /* Read new block into buffer and set buffer state	 accordingly. */      _c64_fs_filebuftrack = f->track = _c64_fs_filebuf[0];      _c64_fs_filebufsect = f->sect = _c64_fs_filebuf[1];      f->ptr = 2;      c64_dio_read_block(_c64_fs_filebuftrack,			 _c64_fs_filebufsect, _c64_fs_filebuf);    }        ++buf;  }  return i;}#if !NOASM    #pragma optimize(pop)#endif /* !NOASM *//*-----------------------------------------------------------------------------------*//** * Close an open file. * * \param f A pointer to a file descriptor struct that previously has * been opened with c64_fs_open(). *//*-----------------------------------------------------------------------------------*/voidc64_fs_close(struct c64_fs_file *f){  }/*-----------------------------------------------------------------------------------*//** * \internal * Read a directory buffer into the _c64_fs_dirbuf buffer. * * This function is shared between this and  the c64-fs-raw module. * * \param track The track of the directory block. * \param sect The sector of the directory block. *//*-----------------------------------------------------------------------------------*/void_c64_fs_readdirbuf(unsigned char track, unsigned char sect){  if(_c64_fs_dirbuftrack == track &&     _c64_fs_dirbufsect == sect) {    /* Buffer already contains requested block, return. */    return;  }  c64_dio_read_block(track, sect, _c64_fs_dirbuf);  _c64_fs_dirbuftrack = track;  _c64_fs_dirbufsect = sect;}/*-----------------------------------------------------------------------------------*//** * Open the disk directory for reading. * * The caller must supply a pointer to a directory descriptor. * * \param d A pointer to a directory description that must be * allocated by the caller. *//*-----------------------------------------------------------------------------------*/unsigned charc64_fs_opendir(register struct c64_fs_dir *d){  d->track = 18;  d->sect = 1;  d->ptr = 2;  return 0;}/*-----------------------------------------------------------------------------------*//** * Read the current directory entry. * * This function reads the directory entry to which the directory * descriptor currently points into a struct c64_fs_dirent supplied by * the caller. * * The function c64_fs_readdir_next() is used to move the directory * entry pointer forward in the directory. * * \param d A pointer to a directory descriptor previously opened with c64_fs_opendir(). * * \param f A pointer to a directory entry that must have been * previously allocated by the caller. *//*-----------------------------------------------------------------------------------*/voidc64_fs_readdir_dirent(register struct c64_fs_dir *d,		      register struct c64_fs_dirent *f){  struct directory_entry *de;  int i;  register char *nameptr;    _c64_fs_readdirbuf(d->track, d->sect);  de = (struct directory_entry *)&_c64_fs_dirbuf[d->ptr];  nameptr = de->name;  for(i = 0; i < 16; ++i) {    if(*nameptr == 0xa0) {      *nameptr = 0;      break;    }    ++nameptr;  }  strncpy(f->name, de->name, 16);  f->track = de->track;  f->sect = de->sect;  f->size = de->blockslo + (de->blockshi >> 8);  memcpy(&lastdirent, f, sizeof(struct c64_fs_dirent));}/*-----------------------------------------------------------------------------------*//** * Move the directory pointer forward. * * This function moves the directory entry pointer in the directory * descriptor forward so that it points to the next file. * * \param d A pointer to a directory descriptor previously opened with * c64_fs_opendir(). * * \retval 1 If there are no more directory entried in the directory. * \retval 0 There were more directory entries and the pointer has * been moved to point to the next one. *//*-----------------------------------------------------------------------------------*/unsigned charc64_fs_readdir_next(struct c64_fs_dir *d){  struct directory_entry *de; again:  _c64_fs_readdirbuf(d->track, d->sect);  if(d->ptr == 226) {    if(_c64_fs_dirbuf[0] == 0) {      return 1;    }    d->track = _c64_fs_dirbuf[0];    d->sect = _c64_fs_dirbuf[1];    d->ptr = 2;  } else {    d->ptr += 32;  }  de = (struct directory_entry *)&_c64_fs_dirbuf[d->ptr];  if(de->type == 0) {    goto again;  }  return 0;}/*-----------------------------------------------------------------------------------*//** * Close a directory descriptor previously opened by c64_fs_opendir(). * * \param d A poitner to a directory descriptor previously opened with * c64_fs_opendir(). *//*-----------------------------------------------------------------------------------*/voidc64_fs_closedir(struct c64_fs_dir *d){  }/*-----------------------------------------------------------------------------------*//** @} */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -