Language C to PB, Trying adapt D64,D71,D81 DiskImage Source

Just starting out? Need help? Post your questions and find answers here.
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Language C to PB, Trying adapt D64,D71,D81 DiskImage Source

Post by Marty2PB »

Hallo -- hello @ all

I trying to adapt .. convert a c Source for D64,D71,D80 DiskImages to Purebasic for my C64 File Lister. Thta use c1541.exe and openCBM.

Update: My progress is further down in this thread.

I have a Problem with the line in the c Source procedure

int di_track_blocks_free(DiskImage *di, int track)
.......
unsigned char *bam; << is this a pointer or just a byte because the return code
.......
return(bam [track * 4] ); what have i to do ?

The Header

Code: Select all

typedef enum imagetype {
  D64 = 1,
  D71,
  D81
} ImageType;

typedef enum filetype {
  T_DEL = 0,
  T_SEQ,
  T_PRG,
  T_USR,
  T_REL,
  T_CBM,
  T_DIR
} FileType;

typedef struct ts {
  unsigned char track;
  unsigned char sector;
} TrackSector;

typedef struct diskimage {
  char *filename;
  int size;
  ImageType type;
  unsigned char *image;
  TrackSector bam;
  TrackSector bam2;
  TrackSector dir;
  int openfiles;
  int blocksfree;
  int modified;
  int status;
  TrackSector statusts;
} DiskImage;

typedef struct rawdirentry {
  TrackSector nextts;
  unsigned char type;
  TrackSector startts;
  unsigned char rawname[16];
  TrackSector relsidets;
  unsigned char relrecsize;
  unsigned char unused[4];
  TrackSector replacetemp;
  unsigned char sizelo;
  unsigned char sizehi;
} RawDirEntry;

typedef struct imagefile {
  DiskImage *diskimage;
  RawDirEntry *rawdirentry;
  char mode;
  int position;
  TrackSector ts;
  TrackSector nextts;
  unsigned char *buffer;
  int bufptr;
  int buflen;
} ImageFile;


DiskImage *di_load_image(char *name);
DiskImage *di_create_image(char *name, int size);
void di_free_image(DiskImage *di);
void di_sync(DiskImage *di);

int di_status(DiskImage *di, char *status);

ImageFile *di_open(DiskImage *di, unsigned char *rawname, FileType type, char *mode);
void di_close(ImageFile *imgfile);
int di_read(ImageFile *imgfile, unsigned char *buffer, int len);
int di_write(ImageFile *imgfile, unsigned char *buffer, int len);

int di_format(DiskImage *di, unsigned char *rawname, unsigned char *rawid);
int di_delete(DiskImage *di, unsigned char *rawpattern, FileType type);
int di_rename(DiskImage *di, unsigned char *oldrawname, unsigned char *newrawname, FileType type);

int di_sectors_per_track(ImageType type, int track);
int di_tracks(ImageType type);
int di_get_block_num(ImageType type, TrackSector ts);

unsigned char *di_title(DiskImage *di);
int di_track_blocks_free(DiskImage *di, int track);
int di_is_ts_free(DiskImage *di, TrackSector ts);
void di_alloc_ts(DiskImage *di, TrackSector ts);
void di_free_ts(DiskImage *di, TrackSector ts);

int di_rawname_from_name(unsigned char *rawname, char *name);
int di_name_from_rawname(char *name, unsigned char *rawname);

The C Source

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "diskimage.h"


typedef struct errormessage {
  signed int number;
  char *string;
} ErrorMessage;


ErrorMessage error_msg[] = {
  /* non-errors */
  { 0, "ok" },
  { 1, "files scratched" },
  { 2, "partition selected" },
  /* errors */
  { 20, "read error (block header not found)" },
  { 21, "read error (drive not ready)" },
  { 22, "read error (data block not found)" },
  { 23, "read error (crc error in data block)" },
  { 24, "read error (byte sector header)" },
  { 25, "write error (write-verify error)" },
  { 26, "write protect on" },
  { 27, "read error (crc error in header)" },
  { 30, "syntax error (general syntax)" },
  { 31, "syntax error (invalid command)" },
  { 32, "syntax error (long line)" },
  { 33, "syntax error (invalid file name)" },
  { 34, "syntax error (no file given)" },
  { 39, "syntax error (invalid command)" },
  { 50, "record not present" },
  { 51, "overflow in record" },
  { 52, "file too large" },
  { 60, "write file open" },
  { 61, "file not open" },
  { 62, "file not found" },
  { 63, "file exists" },
  { 64, "file type mismatch" },
  { 65, "no block" },
  { 66, "illegal track and sector" },
  { 67, "illegal system t or s" },
  { 70, "no channel" },
  { 71, "directory error" },
  { 72, "disk full" },
  { 73, "dos mismatch" },
  { 74, "drive not ready" },
  { 75, "format error" },
  { 76, "controller error" },
  { 77, "selected partition illegal" },
  { -1, NULL }
};


/* convert to rawname */
int di_rawname_from_name(unsigned char *rawname, char *name) {
  int i;

  memset(rawname, 0xa0, 16);
  for (i = 0; i < 16 && name[i]; ++i) {
    rawname[i] = name[i];
  }
  return(i);
}


/* convert from rawname */
int di_name_from_rawname(char *name, unsigned char *rawname) {
  int i;

  for (i = 0; i < 16 && rawname[i] != 0xa0; ++i) {
    name[i] = rawname[i];
  }
  name[i] = 0;
  return(i);
}


/* return status string */
int di_status(DiskImage *di, char *status) {
  ErrorMessage *err = error_msg;

  /* special case for power up */
  if (di->status == 254) {
    switch (di->type) {
    case D64:
      sprintf(status, "73,cbm dos v2.6 1541,00,00");
      break;
    case D71:
      sprintf(status, "73,cbm dos v3.0 1571,00,00");
      break;
    case D81:
      sprintf(status, "73,copyright cbm dos v10 1581,00,00");
      break;
    }
    return(73);
  }

  while (err->number >= 0) {
    if (di->status == err->number) {
      sprintf(status, "%02d,%s,%02d,%02d", di->status, err->string, di->statusts.track, di->statusts.sector);
      return(di->status);
    }
    err++;
  }
  sprintf(status, "%02d,unknown error,%02d,%02d", di->status, di->statusts.track, di->statusts.sector);
  return(di->status);
}


int set_status(DiskImage *di, int status, int track, int sector) {
  di->status = status;
  di->statusts.track = track;
  di->statusts.sector = sector;
  return(status);
}


/* return write interleave */
int interleave(ImageType type) {
  switch (type) {
  case D64:
    return(10);
    break;
  case D71:
    return(6);
    break;
  default:
    return(1);
    break;
  }
}


/* return number of tracks for image type */
int di_tracks(ImageType type) {
  switch (type) {
  case D64:
    return(35);
    break;
  case D71:
    return(70);
    break;
  case D81:
    return(80);
    break;
  }
  return(0);
}


/* return disk geometry for track */
int di_sectors_per_track(ImageType type, int track) {
  switch (type) {
  case D71:
    if (track > 35) {
      track -= 35;
    }
    // fall through
  case D64:
    if (track < 18) {
      return(21);
    } else if (track < 25) {
      return(19);
    } else if (track < 31) {
      return(18);
    } else {
      return(17);
    }
    break;
  case D81:
    return(40);
    break;
  }
  return(0);
}

/* convert track, sector to blocknum */
int di_get_block_num(ImageType type, TrackSector ts) {
  int block;

  switch (type) {
  case D64:
    if (ts.track < 18) {
      block = (ts.track - 1) * 21;
    } else if (ts.track < 25) {
      block = (ts.track - 18) * 19 + 17 * 21;
    } else if (ts.track < 31) {
      block = (ts.track - 25) * 18 + 17 * 21 + 7 * 19;
    } else {
      block = (ts.track - 31) * 17 + 17 * 21 + 7 * 19 + 6 * 18;
    }
    return(block + ts.sector);
    break;
  case D71:
    if (ts.track > 35) {
      block = 683;
      ts.track -= 35;
    } else {
      block = 0;
    }
    if (ts.track < 18) {
      block += (ts.track - 1) * 21;
    } else if (ts.track < 25) {
      block += (ts.track - 18) * 19 + 17 * 21;
    } else if (ts.track < 31) {
      block += (ts.track - 25) * 18 + 17 * 21 + 7 * 19;
    } else {
      block += (ts.track - 31) * 17 + 17 * 21 + 7 * 19 + 6 * 18;
    }
    return(block + ts.sector);
    break;
  case D81:
    return((ts.track - 1) * 40 + ts.sector);
    break;
  }
  return(0);
}


/* get a pointer to block data */
unsigned char *get_ts_addr(DiskImage *di, TrackSector ts) {
  return(di->image + di_get_block_num(di->type, ts) * 256);
}


/* return a pointer to the next block in the chain */
TrackSector next_ts_in_chain(DiskImage *di, TrackSector ts) {
  unsigned char *p;
  TrackSector newts;

  p = get_ts_addr(di, ts);
  newts.track = p[0];
  newts.sector = p[1];
  if (p[0] > di_tracks(di->type)) {
    newts.track = 0;
    newts.sector = 0;
  } else if (p[1] > di_sectors_per_track(di->type, p[0])) {
    newts.track = 0;
    newts.sector = 0;
  }
  return(newts);
}


/* return a pointer to the disk title */
unsigned char *di_title(DiskImage *di) {
  switch (di->type) {
  default:
  case D64:
  case D71:
    return(get_ts_addr(di, di->dir) + 144);
    break;
  case D81:
    return(get_ts_addr(di, di->dir) + 4);
    break;
  }
}


/* return number of free blocks in track */
int di_track_blocks_free(DiskImage *di, int track) {
  unsigned char *bam;

  switch (di->type) {
  default:
  case D64:
    bam = get_ts_addr(di, di->bam);
    break;
  case D71:
    bam = get_ts_addr(di, di->bam);
    if (track >= 36) {
      return(bam[track + 185]);
    }
    break;
  case D81:
    if (track <= 40) {
      bam = get_ts_addr(di, di->bam);
    } else {
      bam = get_ts_addr(di, di->bam2);
      track -= 40;
    }
    return(bam[track * 6 + 10]);
    break;
  }
  return(bam[track * 4]);
}


/* count number of free blocks */
int blocks_free(DiskImage *di) {
  int track;
  int blocks = 0;

  for (track = 1; track <= di_tracks(di->type); ++track) {
    if (track != di->dir.track) {
      blocks += di_track_blocks_free(di, track);
    }
  }
  return(blocks);
}


/* check if track, sector is free in BAM */
int di_is_ts_free(DiskImage *di, TrackSector ts) {
  unsigned char mask;
  unsigned char *bam;

  switch (di->type) {
  case D64:
    bam = get_ts_addr(di, di->bam);
    if (bam[ts.track * 4]) {
      mask = 1<<(ts.sector & 7);
      return(bam[ts.track * 4 + ts.sector / 8 + 1] & mask ? 1 : 0);
    } else {
      return(0);
    }
    break;
  case D71:
    mask = 1<<(ts.sector & 7);
    if (ts.track < 36) {
      bam = get_ts_addr(di, di->bam);
      return(bam[ts.track * 4 + ts.sector / 8 + 1] & mask ? 1 : 0);
    } else {
      bam = get_ts_addr(di, di->bam2);
      return(bam[(ts.track - 35) * 3 + ts.sector / 8 - 3] & mask ? 1 : 0);
    }
    break;
  case D81:
    mask = 1<<(ts.sector & 7);
    if (ts.track < 41) {
      bam = get_ts_addr(di, di->bam);
    } else {
      bam = get_ts_addr(di, di->bam2);
      ts.track -= 40;
    }
    return(bam[ts.track * 6 + ts.sector / 8 + 11] & mask ? 1 : 0);
    break;
  }
  return(0);
}


/* allocate track, sector in BAM */
void di_alloc_ts(DiskImage *di, TrackSector ts) {
  unsigned char mask;
  unsigned char *bam;

  di->modified = 1;
  switch (di->type) {
  case D64:
    bam = get_ts_addr(di, di->bam);
    bam[ts.track * 4] -= 1;
    mask = 1<<(ts.sector & 7);
    bam[ts.track * 4 + ts.sector / 8 + 1] &= ~mask;
    break;
  case D71:
    mask = 1<<(ts.sector & 7);
    if (ts.track < 36) {
      bam = get_ts_addr(di, di->bam);
      bam[ts.track * 4] -= 1;
      bam[ts.track * 4 + ts.sector / 8 + 1] &= ~mask;
    } else {
      bam = get_ts_addr(di, di->bam);
      bam[ts.track + 185] -= 1;
      bam = get_ts_addr(di, di->bam2);
      bam[(ts.track - 35) * 3 + ts.sector / 8 - 3] &= ~mask;
    }
    break;
  case D81:
    if (ts.track < 41) {
      bam = get_ts_addr(di, di->bam);
    } else {
      bam = get_ts_addr(di, di->bam2);
      ts.track -= 40;
    }
    bam[ts.track * 6 + 10] -= 1;
    mask = 1<<(ts.sector & 7);
    bam[ts.track * 6 + ts.sector / 8 + 11] &= ~mask;
    break;
  }
}


/* allocate next available block */
TrackSector alloc_next_ts(DiskImage *di, TrackSector prevts) {
  unsigned char *bam;
  int spt, s1, s2, t1, t2, bpt, boff, res1, res2;
  TrackSector ts;

  switch (di->type) {
  default:
  case D64:
    s1 = 1;
    t1 = 35;
    s2 = 1;
    t2 = 35;
    res1 = 18;
    res2 = 0;
    bpt = 4;
    boff = 0;
    break;
  case D71:
    s1 = 1;
    t1 = 35;
    s2 = 36;
    t2 = 70;
    res1 = 18;
    res2 = 53;
    bpt = 4;
    boff = 0;
    break;
  case D81:
    s1 = 1;
    t1 = 40;
    s2 = 41;
    t2 = 80;
    res1 = 40;
    res2 = 0;
    bpt = 6;
    boff = 10;
    break;
  }

  bam = get_ts_addr(di, di->bam);
  for (ts.track = s1; ts.track <= t1; ++ts.track) {
    if (ts.track != res1) {
      if  (bam[ts.track * bpt + boff]) {
	spt = di_sectors_per_track(di->type, ts.track);
	ts.sector = (prevts.sector + interleave(di->type)) % spt;
	for (; ; ts.sector = (ts.sector + 1) % spt) {
	  if (di_is_ts_free(di, ts)) {
	    di_alloc_ts(di, ts);
	    return(ts);
	  }
	}
      }
    }
  }

  if (di->type == D71 || di->type == D81) {
    bam = get_ts_addr(di, di->bam2);
    for (ts.track = s2; ts.track <= t2; ++ts.track) {
      if (ts.track != res2) {
	if  (bam[(ts.track - t1) * bpt + boff]) {
	  spt = di_sectors_per_track(di->type, ts.track);
	  ts.sector = (prevts.sector + interleave(di->type)) % spt;
	  for (; ; ts.sector = (ts.sector + 1) % spt) {
	    if (di_is_ts_free(di, ts)) {
	      di_alloc_ts(di, ts);
	      return(ts);
	    }
	  }
	}
      }
    }
  }

  ts.track = 0;
  ts.sector = 0;
  return(ts);
}


/* allocate next available directory block */
TrackSector alloc_next_dir_ts(DiskImage *di) {
  unsigned char *p;
  int spt;
  TrackSector ts, lastts;

  if (di_track_blocks_free(di, di->bam.track)) {
    ts.track = di->bam.track;
    ts.sector = 0;
    while (ts.track) {
      lastts = ts;
      ts = next_ts_in_chain(di, ts);
    }
    ts.track = lastts.track;
    ts.sector = lastts.sector + 3;
    spt = di_sectors_per_track(di->type, ts.track);
    for (; ; ts.sector = (ts.sector + 1) % spt) {
      if (di_is_ts_free(di, ts)) {
	di_alloc_ts(di, ts);
	p = get_ts_addr(di, lastts);
	p[0] = ts.track;
	p[1] = ts.sector;
	p = get_ts_addr(di, ts);
	memset(p, 0, 256);
	p[1] = 0xff;
	di->modified = 1;
	return(ts);
      }
    }
  } else {
    ts.track = 0;
    ts.sector = 0;
    return(ts);
  }
}


/* free a block in the BAM */
void di_free_ts(DiskImage *di, TrackSector ts) {
  unsigned char mask;
  unsigned char *bam;

  di->modified = 1;
  switch (di->type) {
  case D64:
    mask = 1<<(ts.sector & 7);
    bam = get_ts_addr(di, di->bam);
    bam[ts.track * 4 + ts.sector / 8 + 1] |= mask;
    bam[ts.track * 4] += 1;
    break;
  case D71:
    mask = 1<<(ts.sector & 7);
    if (ts.track < 36) {
      bam = get_ts_addr(di, di->bam);
      bam[ts.track * 4 + ts.sector / 8 + 1] |= mask;
      bam[ts.track * 4] += 1;
    } else {
      bam = get_ts_addr(di, di->bam);
      bam[ts.track + 185] += 1;
      bam = get_ts_addr(di, di->bam2);
      bam[(ts.track - 35) * 3 + ts.sector / 8 - 3] |= mask;
    }
    break;
  case D81:
    if (ts.track < 41) {
      bam = get_ts_addr(di, di->bam);
    } else {
      bam = get_ts_addr(di, di->bam2);
      ts.track -= 40;
    }
    mask = 1<<(ts.sector & 7);
    bam[ts.track * 6 + ts.sector / 8 + 11] |= mask;
    bam[ts.track * 6 + 10] += 1;
    break;
  default:
    break;
  }
}


/* free a chain of blocks */
void free_chain(DiskImage *di, TrackSector ts) {
  while (ts.track) {
    di_free_ts(di, ts);
    ts = next_ts_in_chain(di, ts);
  }
}


DiskImage *di_load_image(char *name) {
  FILE *file;
  int filesize, l, read;
  DiskImage *di;

  /* open image */
  if ((file = fopen(name, "rb")) == NULL) {
    //puts("fopen failed");
    return(NULL);
  }

  /* get file size*/
  if (fseek(file, 0, SEEK_END)) {
    //puts("fseek failed");
    fclose(file);
    return(NULL);
  }
  filesize = ftell(file);
  fseek(file, 0, SEEK_SET);

  if ((di = malloc(sizeof(*di))) == NULL) {
    //puts("malloc failed");
    fclose(file);
    return(NULL);
  }

  /* check image type */
  switch (filesize) {
  case 174848: // standard D64
  case 175531: // D64 with error info (which we just ignore)
    di->type = D64;
    di->bam.track = 18;
    di->bam.sector = 0;
    di->dir = di->bam;
    break;
  case 349696:
    di->type = D71;
    di->bam.track = 18;
    di->bam.sector = 0;
    di->bam2.track = 53;
    di->bam2.sector = 0;
    di->dir = di->bam;
    break;
  case 819200:
    di->type = D81;
    di->bam.track = 40;
    di->bam.sector = 1;
    di->bam2.track = 40;
    di->bam2.sector = 2;
    di->dir.track = 40;
    di->dir.sector = 0;
    break;
  default:
    //puts("unknown type");
    free(di);
    fclose(file);
    return(NULL);
  }

  di->size = filesize;

  /* allocate buffer for image */
  if ((di->image = malloc(filesize)) == NULL) {
    //puts("image malloc failed");
    free(di);
    fclose(file);
    return(NULL);
  }

  /* read file into buffer */
  read = 0;
  while (read < filesize) {
    if ((l = fread(di->image, 1, filesize - read, file))) {
      read += l;
    } else {
      //puts("fread failed");
      free(di->image);
      free(di);
      fclose(file);
      return(NULL);
    }
  }

  di->filename = malloc(strlen(name) + 1);
  strcpy(di->filename, name);
  di->openfiles = 0;
  di->blocksfree = blocks_free(di);
  di->modified = 0;
  fclose(file);
  set_status(di, 254, 0, 0);
  return(di);
}


DiskImage *di_create_image(char *name, int size) {
  DiskImage *di;

  if ((di = malloc(sizeof(*di))) == NULL) {
    //puts("malloc failed");
    return(NULL);
  }

  /* check image type */
  switch (size) {
  case 174848: // standard D64
  case 175531: // D64 with error info (which we just ignore)
    di->type = D64;
    di->bam.track = 18;
    di->bam.sector = 0;
    di->dir = di->bam;
    break;
  case 349696:
    di->type = D71;
    di->bam.track = 18;
    di->bam.sector = 0;
    di->bam2.track = 53;
    di->bam2.sector = 0;
    di->dir = di->bam;
    break;
  case 819200:
    di->type = D81;
    di->bam.track = 40;
    di->bam.sector = 1;
    di->bam2.track = 40;
    di->bam2.sector = 2;
    di->dir.track = 40;
    di->dir.sector = 0;
    break;
  default:
    //puts("unknown type");
    free(di);
    return(NULL);
  }

  di->size = size;

  /* allocate buffer for image */
  if ((di->image = malloc(size)) == NULL) {
    //puts("image malloc failed");
    free(di);
    return(NULL);
  }
  memset(di->image, 0, size);

  di->filename = malloc(strlen(name) + 1);
  strcpy(di->filename, name);
  di->openfiles = 0;
  di->blocksfree = blocks_free(di);
  di->modified = 1;
  set_status(di, 254, 0, 0);
  return(di);
}


void di_sync(DiskImage *di) {
  FILE *file;
  int l, left;
  unsigned char *image;

  if ((file = fopen(di->filename, "wb"))) {
    image = di->image;
    left = di->size;
    l = 0;
    while (left) {
      if ((l = fwrite(image, 1, left, file)) == 0) {
	fclose(file);
	return;
      }
      left -= l;
      image += l;
    }
    fclose(file);
    di->modified = 0;
  }
}


void di_free_image(DiskImage *di) {
  if (di->modified) {
    di_sync(di);
  }
  if (di->filename) {
    free(di->filename);
  }
  free(di->image);
  free(di);
}


int match_pattern(unsigned char *rawpattern, unsigned char *rawname) {
  int i;

  for (i = 0; i < 16; ++i) {
    if (rawpattern[i] == '*') {
      return(1);
    }
    if (rawname[i] == 0xa0) {
      if (rawpattern[i] == 0xa0) {
	return(1);
      } else {
	return(0);
      }
    } else {
      if (rawpattern[i] == '?' || rawpattern[i] == rawname[i]) {
      } else {
	return(0);
      }
    }
  }
  return(1);
}


RawDirEntry *find_file_entry(DiskImage *di, unsigned char *rawpattern, FileType type) {
  unsigned char *buffer;
  TrackSector ts;
  RawDirEntry *rde;
  int offset;

  ts = next_ts_in_chain(di, di->bam);
  while (ts.track) {
    buffer = get_ts_addr(di, ts);
    for (offset = 0; offset < 256; offset += 32) {
      rde = (RawDirEntry *)(buffer + offset);
      if ((rde->type & ~0x40) == (type | 0x80)) {
	if (match_pattern(rawpattern, rde->rawname)) {
	  return(rde);
	}
      }
    }
    ts = next_ts_in_chain(di, ts);
  }
  return(NULL);
}


RawDirEntry *alloc_file_entry(DiskImage *di, unsigned char *rawname, FileType type) {
  unsigned char *buffer;
  TrackSector ts, lastts;
  RawDirEntry *rde;
  int offset;

  /* check if file already exists */
  ts = next_ts_in_chain(di, di->bam);
  while (ts.track) {
    buffer = get_ts_addr(di, ts);
    for (offset = 0; offset < 256; offset += 32) {
      rde = (RawDirEntry *)(buffer + offset);
      if (rde->type & 0x3f) { // cv: mask out file type to ignore closed/locked DEL files
	if (strncmp(rawname, rde->rawname, 16) == 0) {
	  set_status(di, 63, 0, 0);
	  //puts("file exists");
	  return(NULL);
	}
      }
    }
    ts = next_ts_in_chain(di, ts);
  }

  /* allocate empty slot */
  ts = next_ts_in_chain(di, di->bam);
  while (ts.track) {
    buffer = get_ts_addr(di, ts);
    for (offset = 0; offset < 256; offset += 32) {
      rde = (RawDirEntry *)(buffer + offset);
      if (rde->type == 0) {
	memset((unsigned char *)rde + 2, 0, 30);
	memcpy(rde->rawname, rawname, 16);
	rde->type = type;
	di->modified = 1;
	return(rde);
      }
    }
    lastts = ts;
    ts = next_ts_in_chain(di, ts);
  }

  /* allocate new dir block */
  ts = alloc_next_dir_ts(di);
  if (ts.track) {
    rde = (RawDirEntry *)get_ts_addr(di, ts);
    memset((unsigned char *)rde + 2, 0, 30);
    memcpy(rde->rawname, rawname, 16);
    rde->type = type;
    di->modified = 1;
    return(rde);
  } else {
    set_status(di, 72, 0, 0);
    //puts("directory full");
    return(NULL);
  }
}


/* open a file */
ImageFile *di_open(DiskImage *di, unsigned char *rawname, FileType type, char *mode) {
  ImageFile *imgfile;
  RawDirEntry *rde;
  unsigned char *p;

  set_status(di, 255, 0, 0);

  if (strcmp("rb", mode) == 0) {

    if ((imgfile = malloc(sizeof(*imgfile))) == NULL) {
      //puts("malloc failed");
      return(NULL);
    }
    if (strcmp("$", rawname) == 0) {
      imgfile->mode = 'r';
      imgfile->ts = di->dir;
      p = get_ts_addr(di, di->dir);
      imgfile->buffer = p + 2;
      if ((di->type == D64) || (di->type == D71)) {
	imgfile->nextts.track = 18; // 1541/71 ignores bam t/s link
	imgfile->nextts.sector = 1;
      } else {
	imgfile->nextts.track = p[0];
	imgfile->nextts.sector = p[1];
      }
      imgfile->buflen = 254;
      rde = NULL;
    } else {
      if ((rde = find_file_entry(di, rawname, type)) == NULL) {
	set_status(di, 62, 0, 0);
	//puts("find_file_entry failed");
	free(imgfile);
	return(NULL);
      }
      imgfile->mode = 'r';
      imgfile->ts = rde->startts;
      if (imgfile->ts.track > di_tracks(di->type)) {
	return(NULL);
      }
      p = get_ts_addr(di, rde->startts);
      imgfile->buffer = p + 2;
      imgfile->nextts.track = p[0];
      imgfile->nextts.sector = p[1];
      if (imgfile->nextts.track == 0) {
	imgfile->buflen = imgfile->nextts.sector - 1;
      } else {
	imgfile->buflen = 254;
      }
    }

  } else if (strcmp("wb", mode) == 0) {

    if ((rde = alloc_file_entry(di, rawname, type)) == NULL) {
      //puts("alloc_file_entry failed");
      return(NULL);
    }
    if ((imgfile = malloc(sizeof(*imgfile))) == NULL) {
      //puts("malloc failed");
      return(NULL);
    }
    imgfile->mode = 'w';
    imgfile->ts.track = 0;
    imgfile->ts.sector = 0;
    if ((imgfile->buffer = malloc(254)) == NULL) {
      free(imgfile);
      //puts("malloc failed");
      return(NULL);
    }
    imgfile->buflen = 254;
    di->modified = 1;

  } else {
    return(NULL);
  }

  imgfile->diskimage = di;
  imgfile->rawdirentry = rde;
  imgfile->position = 0;
  imgfile->bufptr = 0;

  ++(di->openfiles);
  set_status(di, 0, 0, 0);
  return(imgfile);
}


int di_read(ImageFile *imgfile, unsigned char *buffer, int len) {
  unsigned char *p;
  int bytesleft;
  int counter = 0;

  while (len) {
    bytesleft = imgfile->buflen - imgfile->bufptr;
    if (bytesleft == 0) {
      if (imgfile->nextts.track == 0) {
	return(counter);
      }
      if (((imgfile->diskimage->type == D64) || (imgfile->diskimage->type == D71)) && imgfile->ts.track == 18 && imgfile->ts.sector == 0) {
	imgfile->ts.track = 18;
	imgfile->ts.sector = 1;
      } else {
	imgfile->ts = next_ts_in_chain(imgfile->diskimage, imgfile->ts);
      }
      if (imgfile->ts.track == 0) {
	return(counter);
      }
      p = get_ts_addr(imgfile->diskimage, imgfile->ts);
      imgfile->buffer = p + 2;
      imgfile->nextts.track = p[0];
      imgfile->nextts.sector = p[1];
      if (imgfile->nextts.track == 0) {
	imgfile->buflen = imgfile->nextts.sector - 1;
      } else {
	imgfile->buflen = 254;
      }
      imgfile->bufptr = 0;
    } else {
      if (len >= bytesleft) {
		while (bytesleft) {
		  *buffer++ = imgfile->buffer[imgfile->bufptr++];
		  --len;
		  --bytesleft;
		  ++counter;
		  ++(imgfile->position);
		}
      } else {
		while (len) {
		  *buffer++ = imgfile->buffer[imgfile->bufptr++];
		  --len;
		  --bytesleft;
		  ++counter;
		  ++(imgfile->position);
		}
      }
    }
  }
  return(counter);
}


int di_write(ImageFile *imgfile, unsigned char *buffer, int len) {
  unsigned char *p;
  int bytesleft;
  int counter = 0;

  while (len) {
    bytesleft = imgfile->buflen - imgfile->bufptr;
    if (bytesleft == 0) {
      if (imgfile->diskimage->blocksfree == 0) {
	set_status(imgfile->diskimage, 72, 0, 0);
	return(counter);
      }
      imgfile->nextts = alloc_next_ts(imgfile->diskimage, imgfile->ts);
      if (imgfile->ts.track == 0) {
	imgfile->rawdirentry->startts = imgfile->nextts;
      } else {
	p = get_ts_addr(imgfile->diskimage, imgfile->ts);
	p[0] = imgfile->nextts.track;
	p[1] = imgfile->nextts.sector;
      }
      imgfile->ts = imgfile->nextts;
      p = get_ts_addr(imgfile->diskimage, imgfile->ts);
      p[0] = 0;
      p[1] = 0xff;
      memcpy(p + 2, imgfile->buffer, 254);
      imgfile->bufptr = 0;
      if (++(imgfile->rawdirentry->sizelo) == 0) {
	++(imgfile->rawdirentry->sizehi);
      }
      --(imgfile->diskimage->blocksfree);
    } else {
      if (len >= bytesleft) {
	while (bytesleft) {
	  imgfile->buffer[imgfile->bufptr++] = *buffer++;
	  --len;
	  --bytesleft;
	  ++counter;
	  ++(imgfile->position);
	}
      } else {
	while (len) {
	  imgfile->buffer[imgfile->bufptr++] = *buffer++;
	  --len;
	  --bytesleft;
	  ++counter;
	  ++(imgfile->position);
	}
      }
    }
  }
  return(counter);
}


void di_close(ImageFile *imgfile) {
  unsigned char *p;

  if (imgfile->mode == 'w') {
    if (imgfile->bufptr) {
      if (imgfile->diskimage->blocksfree) {
	imgfile->nextts = alloc_next_ts(imgfile->diskimage, imgfile->ts);
	if (imgfile->ts.track == 0) {
	  imgfile->rawdirentry->startts = imgfile->nextts;
	} else {
	  p = get_ts_addr(imgfile->diskimage, imgfile->ts);
	  p[0] = imgfile->nextts.track;
	  p[1] = imgfile->nextts.sector;
	}
	imgfile->ts = imgfile->nextts;
	p = get_ts_addr(imgfile->diskimage, imgfile->ts);
	p[0] = 0;
	p[1] = 0xff;
	memcpy(p + 2, imgfile->buffer, 254);
	imgfile->bufptr = 0;
	if (++(imgfile->rawdirentry->sizelo) == 0) {
	  ++(imgfile->rawdirentry->sizehi);
	}
	--(imgfile->diskimage->blocksfree);
	imgfile->rawdirentry->type |= 0x80;
      }
    } else {
      imgfile->rawdirentry->type |= 0x80;
    }
    free(imgfile->buffer);
  }
  --(imgfile->diskimage->openfiles);
  free(imgfile);
}


int di_format(DiskImage *di, unsigned char *rawname, unsigned char *rawid) {
  unsigned char *p;
  TrackSector ts;

  di->modified = 1;

  switch (di->type) {

  case D64:
    /* erase disk */
    if (rawid) {
      memset(di->image, 0, 174848);
    }

    /* get ptr to bam */
    p = get_ts_addr(di, di->bam);

    /* setup header */
    p[0] = 18;
    p[1] = 1;
    p[2] = 'A';
    p[3] = 0;

    /* clear bam */
    memset(p + 4, 0, 0x8c);

    /* free blocks */
    for (ts.track = 1; ts.track <= di_tracks(di->type); ++ts.track) {
      for (ts.sector = 0; ts.sector < di_sectors_per_track(di->type, ts.track); ++ts.sector) {
	di_free_ts(di, ts);
      }
    }

    /* allocate bam and dir */
    ts.track = 18;
    ts.sector = 0;
    di_alloc_ts(di, ts);
    ts.sector = 1;
    di_alloc_ts(di, ts);

    /* copy name */
    memcpy(p + 0x90, rawname, 16);

    /* set id */
    memset(p + 0xa0, 0xa0, 2);
    if (rawid) {
      memcpy(p + 0xa2, rawid, 2);
    }
    memset(p + 0xa4, 0xa0, 7);
    p[0xa5] = '2';
    p[0xa6] = 'A';

    /* clear unused bytes */
    memset(p + 0xab, 0, 0x55);

    /* clear first dir block */
    memset(p + 256, 0, 256);
    p[257] = 0xff;
    break;

  case D71:
    /* erase disk */
    if (rawid) {
      memset(di->image, 0, 349696);
    }

    /* get ptr to bam2 */
    p = get_ts_addr(di, di->bam2);

    /* clear bam2 */
    memset(p, 0, 256);

    /* get ptr to bam */
    p = get_ts_addr(di, di->bam);

    /* setup header */
    p[0] = 18;
    p[1] = 1;
    p[2] = 'A';
    p[3] = 0x80;

    /* clear bam */
    memset(p + 4, 0, 0x8c);

    /* clear bam2 counters */
    memset(p + 0xdd, 0, 0x23);

    /* free blocks */
    for (ts.track = 1; ts.track <= di_tracks(di->type); ++ts.track) {
      if (ts.track != 53) {
	for (ts.sector = 0; ts.sector < di_sectors_per_track(di->type, ts.track); ++ts.sector) {
	  di_free_ts(di, ts);
	}
      }
    }

    /* allocate bam and dir */
    ts.track = 18;
    ts.sector = 0;
    di_alloc_ts(di, ts);
    ts.sector = 1;
    di_alloc_ts(di, ts);

    /* copy name */
    memcpy(p + 0x90, rawname, 16);

    /* set id */
    memset(p + 0xa0, 0xa0, 2);
    if (rawid) {
      memcpy(p + 0xa2, rawid, 2);
    }
    memset(p + 0xa4, 0xa0, 7);
    p[0xa5] = '2';
    p[0xa6] = 'A';

    /* clear unused bytes */
    memset(p + 0xab, 0, 0x32);

    /* clear first dir block */
    memset(p + 256, 0, 256);
    p[257] = 0xff;
    break;

  case D81:
    /* erase disk */
    if (rawid) {
      memset(di->image, 0, 819200);
    }

    /* get ptr to bam */
    p = get_ts_addr(di, di->bam);

    /* setup header */
    p[0] = 0x28;
    p[1] = 0x02;
    p[2] = 0x44;
    p[3] = 0xbb;
    p[6] = 0xc0;

    /* set id */
    if (rawid) {
      memcpy(p + 4, rawid, 2);
    }

    /* clear bam */
    memset(p + 7, 0, 0xfa);

    /* get ptr to bam2 */
    p = get_ts_addr(di, di->bam2);

    /* setup header */
    p[0] = 0x00;
    p[1] = 0xff;
    p[2] = 0x44;
    p[3] = 0xbb;
    p[6] = 0xc0;

    /* set id */
    if (rawid) {
      memcpy(p + 4, rawid, 2);
    }

    /* clear bam2 */
    memset(p + 7, 0, 0xfa);

    /* free blocks */
    for (ts.track = 1; ts.track <= di_tracks(di->type); ++ts.track) {
      for (ts.sector = 0; ts.sector < di_sectors_per_track(di->type, ts.track); ++ts.sector) {
	di_free_ts(di, ts);
      }
    }

    /* allocate bam and dir */
    ts.track = 40;
    ts.sector = 0;
    di_alloc_ts(di, ts);
    ts.sector = 1;
    di_alloc_ts(di, ts);
    ts.sector = 2;
    di_alloc_ts(di, ts);
    ts.sector = 3;
    di_alloc_ts(di, ts);

    /* get ptr to dir */
    p = get_ts_addr(di, di->dir);

    /* copy name */
    memcpy(p + 4, rawname, 16);

    /* set id */
    memset(p + 0x14, 0xa0, 2);
    if (rawid) {
      memcpy(p + 0x16, rawid, 2);
    }
    memset(p + 0x18, 0xa0, 5);
    p[0x19] = '3';
    p[0x1a] = 'D';

    /* clear unused bytes */
    memset(p + 0x1d, 0, 0xe3);

    /* clear first dir block */
    memset(p + 768, 0, 256);
    p[769] = 0xff;
    break;

  }

  di->blocksfree = blocks_free(di);

  return(set_status(di, 0, 0, 0));
}


int di_delete(DiskImage *di, unsigned char *rawpattern, FileType type) {
  RawDirEntry *rde;
  int delcount = 0;

  switch (type) {

  case T_SEQ:
  case T_PRG:
  case T_USR:
  case T_DEL: // cv: allow to delete special closed/locked DEL files
    while ((rde = find_file_entry(di, rawpattern, type))) {
      free_chain(di, rde->startts);
      rde->type = 0;
      ++delcount;
    }
    if (delcount) {
      return(set_status(di, 1, delcount, 0));
    } else {
      return(set_status(di, 62, 0, 0));
    }
    break;

  default:
    return(set_status(di, 64, 0, 0));
    break;

  }
}


int di_rename(DiskImage *di, unsigned char *oldrawname, unsigned char *newrawname, FileType type) {
  RawDirEntry *rde;

  if ((rde = find_file_entry(di, oldrawname, type))) {
    memcpy(rde->rawname, newrawname, 16);
    return(set_status(di, 0, 0, 0));
  } else {
    return(set_status(di, 62, 0, 0));
  }
}


Code Test Directory

Code: Select all

/*

  directory listing

 */

#include <stdio.h>
#include <string.h>
#include "diskimage.h"

static char *ftype[] = {
  "del",
  "seq",
  "prg",
  "usr",
  "rel",
  "cbm",
  "dir",
  "???"
};

static char usage[] = "test_dir <diskimage>";


void ptoa(unsigned char *s) {
  unsigned char c;

  while ((c = *s)) {
    c &= 0x7f;
    if (c >= 'A' && c <= 'Z') {
      c += 32;
    } else if (c >= 'a' && c <= 'z') {
      c -= 32;
    } else if (c == 0x7f) {
      c = 0x3f;
    }
    *s++ = c;
  }
}


int main(int argc, char *argv[]) {
  DiskImage *di;
  unsigned char buffer[254];
  ImageFile *dh;
  int offset;
  char quotename[19];
  char name[17];
  char id[6];
  int type;
  int closed;
  int locked;
  int size;

  /* Check usage */
  if (argc != 2) {
    puts(usage);
    return(1);
  }

  /* Load image into ram */
  if ((di = di_load_image(argv[1])) == NULL) {
    puts("di_load_image failed");
    return(1);
  }

  /* Open directory for reading */
  if ((dh = di_open(di, "$", T_PRG, "rb")) == NULL) {
    puts("Couldn't open directory");
    goto CloseImage;
  }

  /* Convert title to ascii */
  di_name_from_rawname(name, di_title(di));
  ptoa(name);

  /* Convert ID to ascii */
  memcpy(id, di_title(di) + 18, 5);
  id[5] = 0;
  ptoa(id);

  /* Print title and disk ID */
  printf("0 \"%-16s\" %s\n", name, id);

  /* Read first block into buffer */
  if (di_read(dh, buffer, 254) != 254) {
    printf("BAM read failed\n");
    goto CloseDir;
  }

  /* Read directory blocks */
  while (di_read(dh, buffer, 254) == 254) {
    for (offset = -2; offset < 254; offset += 32) {

      /* If file type != 0 */
      if (buffer[offset+2]) {

	di_name_from_rawname(name, buffer + offset + 5);
	type = buffer[offset + 2] & 7;
	closed = buffer[offset + 2] & 0x80;
	locked = buffer[offset + 2] & 0x40;
	size = buffer[offset + 31]<<8 | buffer[offset + 30];

	/* Convert to ascii and add quotes */
	ptoa(name);
	sprintf(quotename, "\"%s\"", name);

	/* Print directory entry */
	printf("%-4d  %-18s%c%s%c\n", size, quotename, closed ? ' ' : '*', ftype[type], locked ? '<' : ' ');
      }
    }
  }

  /* Print number of blocks free */
  printf("%d blocks free\n", di->blocksfree);

 CloseDir:
  /* Close file */
  di_close(dh);

 CloseImage:
  /* Release image */
  di_free_image(di);

  /* Done */
  return(0);
}




My Gui in PB with OpenCBM and c1541 support

Image
Last edited by Marty2PB on Fri Sep 13, 2019 6:07 pm, edited 4 times in total.
User avatar
skywalk
Addict
Addict
Posts: 3972
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by skywalk »

.......
unsigned char *bam; << is this a pointer or just a byte because the return code
.......
return(bam [track * 4] ); what have i to do ?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Yes, *bam is a pointer.
They use it to "walk" through memory.
You can do the same.

Code: Select all

Structure myChar
  c.c[0]
EndStructure
Define *bam.myChar
Define.s x$ = "Hello World!"
*bam = @x$
Debug Chr(*bam\c[0])
Debug Chr(*bam\c[2])
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by Marty2PB »

Hey Skywalk :)

Great, thanks it works.

Image

I get now the free Blocks of the C64 Diskimage. The lister uses at time c1541.exe from sdl2vice

Code: Select all

    ; /* return number of free blocks in track */
   
    Procedure.i di_track_blocks_free(*di.DiskImage, track.i)
        
        Structure UnsignedChar
            b.b[0]
        EndStructure
            
        Define *bam.UnsignedChar
        
        Select *di\Type
            Case "D64":
                *bam = get_ts_addr(*di, *di\bam)
                Debug *bam
            Case "D71":
                *bam = get_ts_addr(*di, *di\bam)
                If (track >= 36)
                   ProcedureReturn bam + (track + 185)
                EndIf    
            Case "D81":
            Default
        EndSelect        
        
        ProcedureReturn ( *bam\b [track * 4]  )
        
    EndProcedure    
i changed the Readfile Macro

Code: Select all

Macro LoadDiskImage(diFileName, diFileSize)
        
        *di\image = AllocateMemory(diFileSize)
        
        Define DiskImage = OpenFile( #PB_Any, diFileName )
        If DiskImage
            While Not Eof( DiskImage )              
                ReadData(DiskImage, *di\image, diFileSize)
            Wend
            CloseFile(DiskImage)
        EndIf
    EndMacro
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by Marty2PB »

in the "Procdure di_open(*di.DiskImage, rawname.s, Mode.s)"
Purebasic Combilation crasht "somtimes" at "Debug *p\c[0]" :?
What could it be?

and I'm a confused with char *name, unsigned char *rawname as procdure arguement?

Code: Select all

int di_name_from_rawname(char *name, unsigned char *rawname) {
  int i;

  for (i = 0; i < 16 && rawname[i] != 0xa0; ++i) {
    name[i] = rawname[i];
  }
  name[i] = 0;
  return(i);
}

is this right?

Code: Select all

;---------------------------------------------------------------------------------------------------------
; /* convert from rawname */
;---------------------------------------------------------------------------------------------------------
Procedure di_name_from_rawname(*name.char, *rawname.char)
        Protected i.i
        
        For i = 0 To 16 
            If ( *rawname\c[i] ! $a0 )
                *name\c[i] = *rawname\c[i];
            EndIf
            
        Next    
        
        *name\c[i] = 0
        ProcedureReturn i
     EndProcedure
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by infratec »

Code: Select all

for (i = 0; i < 16
is in PB:

Code: Select all

For i = 0 To 15 
:wink:

Code: Select all

Structure char
  c.a[0]
EndStructure


Procedure.i di_name_from_rawname(*name.char, *rawname.char)
  
  Protected i.i

  For i = 0 To 15
    If *rawname\c[i] = $a0
      Break
    EndIf
    *name\c[i] = *rawname\c[i]
  Next i
  *name\c[i] = 0
  
  ProcedureReturn i
  
EndProcedure
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by Marty2PB »

Hello infratec

Great, it work. i dunno ....

Image :D

The other thing is:

Code: Select all

  /* Read first block into buffer */
  if (di_read(dh, buffer, 254) != 254) {
    printf("BAM read failed\n");
    goto CloseDir;
  }

  /* Read directory blocks */
  while (di_read(dh, buffer, 254) == 254) {
    for (offset = -2; offset < 254; offset += 32) {

      /* If file type != 0 */
      if (buffer[offset+2]) {

		di_name_from_rawname(name, buffer + offset + 5);
		type = buffer[offset + 2] & 7;
		closed = buffer[offset + 2] & 0x80;
		locked = buffer[offset + 2] & 0x40;
		size = buffer[offset + 31]<<8 | buffer[offset + 30];

		/* Convert to ascii and add quotes */
		ptoa(name);
		sprintf(quotename, "\"%s\"", name);

		/* Print directory entry */
		printf("%-4d  %-18s%c%s%c\n", size, quotename, closed ? ' ' : '*', ftype[type], locked ? '<' : ' ');
      }
    }
  }
i converted to pb and add the filtype in this procedure.
I get the titleheader and Disk ID but not the filename. I get various mixed ascii signs.
I think i do any false wiht the buffer size [254] and or in combination with offset.
The Buffer in the C source is set to 254. My buffer goes out of the box to 261?
:shock:

The counter procedure " di_read(*imgfile.ImageFile, *buffer.CharBuffer, len.i)" is right and goes to 254.

Code: Select all

;---------------------------------------------------------------------------------------------------------
    ; /* Read directory blocks */
;---------------------------------------------------------------------------------------------------------     
    Procedure.i di_read_directory_blocks(*imgfile.ImageFile)
               
        Protected offset.i, type.i, closed.i, locked.i, size.i, C64FileLen.i, C64File.s, ftype.s

        If ( di_read(*imgfile, @buffer.OffsetBuffer, 254) ! 254)
            
            Debug "BAM Read failed"
            
        Else
            ;/* Read directory blocks */
            While ( di_read(*imgfile,  @buffer.OffsetBuffer, 254) = 254)
                
                
                For offset = -2 To 253                    
                    offset + 32
                    
                    ; If file type != 0                     
                    If ( @buffer\c[ offset +2 ] )
                        C64FileLen = di_name_from_rawname(@name.OffsetBuffer,@buffer.OffsetBuffer + offset + 5)
                        type    = @buffer\c[ offset + 2 ] &   7
                        closed  = @buffer\c[ offset + 2 ] & $80
                        locked  = @buffer\c[ offset + 2 ] & $40
                        size    = @buffer\c[ offset + 31 ] << 8 | @buffer\c[ offset + 30 ]
                        
                        Select type
                            Case 0: ftype = "del"
                            Case 1: ftype = "seq"
                            Case 2: ftype = "prg"
                            Case 3: ftype = "usr"                                
                            Case 4: ftype = "rel"
                            Case 5: ftype = "cbm"                                  
                            Case 6: ftype = "dir"                                  
                            Default:ftype = "???"                                  
                        EndSelect
                        
                        If ( closed )
                            ftype = "*"+ftype
                        Else
                            ftype = " "+ftype
                        EndIf
                        
                        If ( locked )
                            ftype + "<"
                        Else
                            ftype + " "
                        EndIf     
                                                        
                        ; /* Convert To ascii  */
                        C64File.s = PeekS(@name, C64FileLen )
                        Debug C64File + ftype
                    EndIf    
                    
                    Debug offset
                Next offset                                
            Wend    
        EndIf        
    EndProcedure    
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by infratec »

Try

Code: Select all

C64File.s = PeekS(@name, C64FileLen, #PB_Ascii)
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by Marty2PB »

Hm.. this and other variants i have test it. UTF and Unicode is really nonsense but No changes. Only Ascii Mismatch. I try other things

This is really strange? the For loop should only go to 254. But breaks at offset with "size.i" at 228 [+31] where I'm totally on it.

in c
unsigned char buffer[254];

is in pb?

Structure buffer
c.a[254]
EndStructure
.....
@b.buffer and or *b.buffer
.....
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by Mijikai »

Iirc. uchar is 1 byte so it looks correct :)
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by Marty2PB »

Next C to PB :mrgreen:

Code: Select all

RawDirEntry *find_file_entry(DiskImage *di, unsigned char *rawpattern, FileType type) {
  unsigned char *buffer;
  TrackSector ts;
  RawDirEntry *rde;
  int offset;

  ts = next_ts_in_chain(di, di->bam);
  while (ts.track) {
    buffer = get_ts_addr(di, ts);
    
	for (offset = 0; offset < 256; offset += 32) {
    
	rde = (RawDirEntry *)(buffer + offset);

	if ((rde->type & ~0x40) == (type | 0x80)) {
	
		if (match_pattern(rawpattern, rde->rawname)) {
		  return(rde);
		}
      }
    }
    ts = next_ts_in_chain(di, ts);
  }
  return(NULL);
}

rde is "big" a pointer with structure. buffer + offeset = ok but this: (RawDirEntry *)
how do interpret this line

rde = (RawDirEntry *)(buffer + offset); ??

*rde.RawDirEntry * ( *buffer + offset ).... so?
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by infratec »

Code: Select all

Procedure.i next_ts_in_chain(*di.DiskImageStructure, *ts.TrackSectorStructure)
  
  Protected *p.CharStructure
  Static newts.TrackSectorStructure
  
  
  *p = get_ts_addr(*di, *ts)
  newts\track = *p\c[0]
  newts\sector = *p\c[1]
  If *p\c[0] > di_tracks(*di\type)
    newts\track = 0
    newts\sector = 0
  ElseIf *p\c[1] > di_sectors_per_track(*di\type, *p\c[0])
    newts\track = 0
    newts\sector = 0
  EndIf
  
  ProcedureReturn @newts
  
EndProcedure


Procedure.i find_file_entry(*di.DiskImageStructure, *rawpattern, type.i)
  
  Protected Result.i
  Protected *buffer
  Protected *ts.TrackSectorStructure
  Protected *rde.RawDirEntryStructure
  Protected offset.i
  
  *ts = next_ts_in_chain(*di, *di\bam)
  While *ts\track
    *buffer = get_ts_addr(*di, *ts)
    
    For offset = 0 To 255 Step 32
   
      *rde = *buffer + offset

      If (*rde\type & ~$40) = (type | $80)
   
        If match_pattern(*rawpattern, *rde\rawname)
          Result = *rde
          Break 2
        EndIf
      EndIf
    Next offset
    *ts = next_ts_in_chain(*di, *ts)
  Wend
  
  ProcedureReturn Result
  
EndProcedure
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by Marty2PB »

Super and big thanks fo the Help :D

Image

The Disk Track, Sector, Map is right but it doesn't show the correct filenames.

Progress:

Code: Select all

DeclareModule CBMDiskImage
    
    ; Init Procedures
    Declare.l di_load_image(DiskImageFile$)                         ; Load image INTO ram 
    Declare.l di_open(*di, *rawname, type.i, Mode.s)                 ; Open directory for reading
    Declare.i di_title(*di)                                         ; Get image Title
    Declare.i di_name_from_rawname(*name, *rawname )                 ; Convert title to ascii, in combinaion with "di_title(*di)"
    Declare.i di_read(*imgfile, *buffer, len)                       ; Read first block INTO buffer
    Declare.i di_read_directory_blocks(*imgfile)
    
    ; Tools Procdures
    Declare.i vDSK_Get_FreeBlocks(*di)                              ; Return Free Blocks From Image                    
    Declare.s vDSK_Get_TitleHead(*di)                               ; Convert Title to ascii and return the Title Header
    Declare.s vDSK_Get_Title_ID(*di)                                ; Convert ID To ascii and return the ID String
    Declare.s vDSK_Get_Filename(*di, Fullpath = #False)             ; Return the Image Filename (Fullpath = #true: Return the Fullpath)
    Declare.s vDSK_Get_ImageFormat(*di)                             ; Return the Image Format as string
    Declare.i vDSK_Close_Image(*imgfile)
    Declare.i vDSK_Test_BAM(*di)
    
    ; Source Taken and Converted from DiskImagery64 
    ; http://lallafa.de/blog/c64-projects/diskimagery64/
    ; https://sourceforge.net/p/diskimagery64/code/HEAD/tree/
    
EndDeclareModule

Module CBMDiskImage
    
    Structure TrackSector
        track.c
        sector.c
    EndStructure  
    
    Structure Rawname
        c.a[17]
    EndStructure
    
    Structure Unused
        c.a[4]
    EndStructure 
    
    Structure Image
        b.b
    EndStructure
    
    Structure Diskimage
        filename.s
        filepath.s
        size.i
        Type.s{3}       
        *image      
        bam.TrackSector
        bam2.TrackSector
        dir.TrackSector
        openfiles.i
        blocksfree.i
        modified.i
        status.i
        statusts.TrackSector  
    EndStructure
    
    Structure  Rawdirentry 
        nextts.TrackSector
        type.c
        startts.TrackSector
        *rawname.Rawname
        relsidets.TrackSector
        relrecsize.c
        *unused.Unused
        replacetemp.TrackSector
        sizelo.c
        sizehi.c
    EndStructure 
    
    Structure  ImageFile
        *diskimage.Diskimage
        *rawdirentry.Rawdirentry          
        mode.s
        position.i
        ts.TrackSector 
        nextts.TrackSector         
        *buffer.CharBuffer
        bufptr.i
        buflen.i
    EndStructure  
    
    Structure UnsignedChar
        b.b[0]
        c.c[0]
    EndStructure  
    
    Structure char
        c.a[17]
    EndStructure
    
    Structure ptoa
        c.a[17]
    EndStructure 
    
    Structure rawpattern
        c.a[17]
    EndStructure   
    
    Structure CharBuffer
        c.a[254]
    EndStructure
    
    
    Macro LoadDiskImage(diFileName, diFileSize)
        
        *di\image = AllocateMemory(diFileSize)
        
        Define DiskImage = OpenFile( #PB_Any, diFileName )
        If DiskImage
            While Not Eof( DiskImage )              
                ReadData(DiskImage, *di\image, diFileSize)
            Wend
            CloseFile(DiskImage)
        EndIf
    EndMacro
    Procedure.s Filetype_Get(type)
        
        Select type
            Case 0:ProcedureReturn "del"
            Case 1:ProcedureReturn "seq"
            Case 2:ProcedureReturn "prg"
            Case 3:ProcedureReturn "usr"                                
            Case 4:ProcedureReturn "rel"
            Case 5:ProcedureReturn "cbm"                                  
            Case 6:ProcedureReturn "dir"                                                               
            Default 
                ProcedureReturn "???"
        EndSelect        
    EndProcedure       
    
    Procedure.i Filetype(type)
        
        Select type
            Case 0:ProcedureReturn 0; ftype = "del"
            Case 1:ProcedureReturn 1; ftype = "seq"
            Case 2:ProcedureReturn 2; ftype = "prg"
            Case 3:ProcedureReturn 3; ftype = "usr"                                
            Case 4:ProcedureReturn 4; ftype = "rel"
            Case 5:ProcedureReturn 5; ftype = "cbm"                                  
            Case 6:ProcedureReturn 6; ftype = "dir"                                                               
        EndSelect
        
    EndProcedure       
;---------------------------------------------------------------------------------------------------------
; /* convert Pet to Ascii */
;---------------------------------------------------------------------------------------------------------       
    Procedure pettoascii(*s.char, *c.ptoa)
        
        For i = 0 To 15
            *c\c[i] = *s\c[i]
            *c\c[i] & $7f;
            
            If (*c\c[i] >= 'A' And *c\c[i] <= 'Z' )
                *c\c[i] + 32
            ElseIf   (*c\c[i] >= 'a' And *c\c[i] <= 'z' )
                *c\c[i] - 32
            ElseIf (*c\c[i] = $7f)
                *c\c[i] = $3f                            
            EndIf                   
        Next i   
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
; /* convert to rawname */
;---------------------------------------------------------------------------------------------------------       
    
    Procedure.i di_rawname_from_name(*rawname.Rawname, *name.char)               
        FillMemory( *rawname, 16, $a0)            
        For i = 0 To 15
            *rawname\c[i] = *name\c[i]
        Next     
        
        ProcedureReturn i        
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
; /* convert from rawname */
;---------------------------------------------------------------------------------------------------------   
    Procedure.i di_name_from_rawname(*name.char, *rawname.Rawname)
        
        Protected TitleLenght.i, s.s
        
        For TitleLenght = 0 To 15
            If *rawname\c[TitleLenght] = $a0
                Break
            EndIf
            *name\c[TitleLenght] = *rawname\c[TitleLenght]               
            
            ;Debug s.s + Chr(*name\c[TitleLenght])
            
        Next TitleLenght
        *name\c[TitleLenght] = 0        
        
        ProcedureReturn TitleLenght        

    EndProcedure
;---------------------------------------------------------------------------------------------------------
; /* return number of tracks for image type *
;---------------------------------------------------------------------------------------------------------
    Procedure.i set_status(*di.DiskImage, status.i, track.i, sector.i)        
        *di\status          = status
        *di\statusts\track  = track     
        *di\statusts\sector = sector
        ProcedureReturn status        
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
; /* return write interleave */
;---------------------------------------------------------------------------------------------------------
    Procedure.i interleave(Type.s)        
        Select Type
            Case "D64": ProcedureReturn 10
            Case "D71": ProcedureReturn 6
            Case "D81": ProcedureReturn 1
            Default
        EndSelect       
    EndProcedure  
        
;---------------------------------------------------------------------------------------------------------
; /* return number of tracks for image type *
;---------------------------------------------------------------------------------------------------------  
    Procedure.i di_tracks(*di.DiskImage)        
        Select *di\Type
            Case "D64": ProcedureReturn 35
            Case "D71": ProcedureReturn 70
            Case "D81": ProcedureReturn 80
                Default:ProcedureReturn 0
        EndSelect                
    EndProcedure  
;---------------------------------------------------------------------------------------------------------
; /* return disk geometry for track */
;---------------------------------------------------------------------------------------------------------
    Procedure.i di_sectors_per_track(*di.DiskImage, track.i)
        
        Select *di\Type
            Case "D64"
                If (track < 18)     :ProcedureReturn 21
                ElseIf (track < 25) :ProcedureReturn 19
                ElseIf (track < 31) :ProcedureReturn 18
                Else
                    ProcedureReturn 17
                EndIf
                
            Case "D71"
                If (track > 35)
                    track - 35
                EndIf
                
            Case "D81": ProcedureReturn 40
                
            Default
                ; No Supportet
                ProcedureReturn 0
        EndSelect
        
    EndProcedure
;---------------------------------------------------------------------------------------------------------
    ; /* convert track, sector to blocknum */
;---------------------------------------------------------------------------------------------------------    
    Procedure.i di_get_block_num(*di.DiskImage, *ts.TrackSector)
        
        Protected block.i
        
        Select *di\Type
            Case "D64":
                If (*ts\track < 18)
                   block.i = (*ts\track - 1) * 21
                ElseIf (*ts\track < 25)
                    block.i = (*ts\track - 18) * 19 + 17 * 21
                ElseIf (*ts\track < 31)
                    block.i = (*ts\track - 25) * 18 + 17 * 21 + 7 * 19
                Else 
                    block.i = (*ts\track - 31) * 17 + 17 * 21 + 7 * 19 + 6 * 18
                EndIf   
                ;Debug "Block: " + Str(block + *ts\sector)
                ProcedureReturn  (block + *ts\sector)  
                
             Case "D71":
                If (*ts\track > 35)
                    block = 683;
                    *ts\track - 35
                Else
                    block = 0
                EndIf
                
                If (*ts\track < 18)
                    block + (*ts\track - 1) * 21
                ElseIf (*ts\track < 25)
                    block + (*ts\track - 18) * 19 + 17 * 21
                ElseIf (*ts\track < 31)
                    block + (*ts\track - 25) * 18 + 17 * 21 + 7 * 19
                Else
                    block + (*ts\track - 31) * 17 + 17 * 21 + 7 * 19 + 6 * 18
                EndIf  
                ProcedureReturn (block + *ts\sector)
                
            Case "D81":
                ProcedureReturn ( (*ts\track - 1) * 40 + *ts\sector)
            Default:
                ProcedureReturn 0
        EndSelect   
        
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
    ; /* get a pointer to block data */
;---------------------------------------------------------------------------------------------------------     
    Procedure.i get_ts_addr(*di.DiskImage,  *ts.TrackSector)               
        ProcedureReturn ( *di\Image + di_get_block_num(*di, *ts) * 256 )
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
    ; /* return a pointer to the next block in the chain */
;---------------------------------------------------------------------------------------------------------
    Procedure.i next_ts_in_chain(*di.DiskImage,  *ts.TrackSector)
  
        Define *p.UnsignedChar
        
        Static newts.TrackSector

        *p = get_ts_addr(*di, *ts)
        newts\track  = *p\b[0]
        newts\sector = *p\b[1]
        
        If ( *p\b[0] > di_tracks(*di) )
            newts\track     = 0
            newts\sector    = 0
        ElseIf ( *p\b[1] > di_sectors_per_track(*di, *p\b[0] ) )
            newts\track     = 0
            newts\sector    = 0
        EndIf
       ProcedureReturn @newts
        
    EndProcedure
;---------------------------------------------------------------------------------------------------------
    ; /* return a pointer to the disk title */
;---------------------------------------------------------------------------------------------------------   
    Procedure di_title(*di.DiskImage)
        Select (*di\Type)
            Case "D64": ProcedureReturn (get_ts_addr( *di, *di\dir ) + 144)
            Case "D71": ProcedureReturn (get_ts_addr( *di, *di\dir ) + 144)
            Case "D81": ProcedureReturn (get_ts_addr( *di, *di\dir ) + 4)
            Default:
                ; Not Support
                ProcedureReturn 0
        EndSelect
     EndProcedure
;---------------------------------------------------------------------------------------------------------
    ; /* return number of free blocks in track */
;---------------------------------------------------------------------------------------------------------   
    Procedure.l di_track_blocks_free(*di.DiskImage, track.i)
                
        Define *bam.UnsignedChar
        
        Select *di\Type
            Case "D64":
                *bam = get_ts_addr(*di, *di\bam)
                
            Case "D71":
                *bam = get_ts_addr(*di, *di\bam)
                If (track >= 36)
                   ProcedureReturn ( *bam\b [track + 185] )
               EndIf  
               
            Case "D81":
                If (track <= 40)
                    *bam = get_ts_addr(*di, *di\bam);
                Else
                    *bam = get_ts_addr(*di, *di\bam2);
                    track - 40                       ;
                EndIf
                ProcedureReturn ( *bam\b[track * 6 + 10]);                
            Default
        EndSelect        
        
        ProcedureReturn ( *bam\b [track * 4]  )        
    EndProcedure    
        
;---------------------------------------------------------------------------------------------------------
    ; count number of free blocks
;---------------------------------------------------------------------------------------------------------   
    Procedure.i blocks_free(*di.DiskImage)        
        Protected Track.i, Blocks.i = 0
        
        For Track = 1 To di_tracks(*di.DiskImage)            
            If ( Track <> *di\dir\track )
                Blocks + di_track_blocks_free(*di, Track)
            EndIf
        Next
        ProcedureReturn Blocks
    EndProcedure
    
;---------------------------------------------------------------------------------------------------------
; /* check If track, sector is free IN BAM */
;---------------------------------------------------------------------------------------------------------
    Procedure.i di_is_ts_free( *di.DiskImage, *ts.TrackSector)
        
        Protected mask.l
        Define *bam.UnsignedChar
        
        Select *di\Type
            Case "D64"                
                *bam = get_ts_addr(*di, *di\bam)
                
                If ( *bam\b[ *ts\track * 4 ] )
                    mask = 1 << ( *ts\sector & 7)
                    If ( mask )
                        ProcedureReturn (*bam\b[*ts\track * 4 + *ts\sector / 8 + 1] & mask)
                    Else
                        ProcedureReturn (*bam\b[*ts\track * 4 + *ts\sector / 8 + 1])
                    EndIf    
                Else
                    ProcedureReturn 0
                EndIf
      
            Case "D71"
            Case "D81"
            Default
                ; NOT SUPPORT
                ProcedureReturn 0
         EndSelect       
        
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
    ; /* Load image into ram */
;---------------------------------------------------------------------------------------------------------
    Procedure.l di_load_image(DiskImageFile$)
                
        *di.DiskImage = AllocateMemory(SizeOf(DiskImage))
        InitializeStructure(*di, DiskImage)
        
        Protected ImageFileSize.i
        
        ImageFileSize = FileSize( DiskImageFile$ )
        Select ImageFileSize
            Case 174848         ; // standard D64
                *di\Type       = "D64"
                *di\bam\track  = 18
                *di\bam\sector = 0
                *di\dir        = *di\bam                
            Case 175531         ; // D64 With error info (which we just ignore)   
                *di\Type       = "D64"
                *di\bam\track  = 18
                *di\bam\sector = 0
                *di\dir        = *di\bam
            Case 349696    
                *di\Type       = "D71"
                *di\bam\track  = 18
                *di\bam\sector = 0
                *di\bam2\track = 53
                *di\bam2\sector= 0
                *di\dir        = *di\bam
            Case 819200
                *di\Type       = "D81"
                *di\bam\track  = 40
                *di\bam\sector = 1
                *di\bam2\track = 40
                *di\bam2\sector= 2
                *di\dir\track  = 40
                *di\dir\sector = 0
            Case 533248   
                *di\Type       = "D80: Not Supportet"                
                ProcedureReturn 0                
            Case 278234
                *di\Type       = "G64: Not Supportet"
                ProcedureReturn 0
            Case 667476
                *di\Type       = "G71: Not Supportet"                
                ProcedureReturn 0   
            Case 174912
                *di\Type       = "X64: Not Supportet"                
                ProcedureReturn 0
            Case 1066496
                *di\Type       = "D82: Not Supportet"                
                ProcedureReturn 0                                
            Case 0
                *di\Type = "Images has 0 Bytes"
                ProcedureReturn 0
            Case -1
                *di\Type = "Image " + DiskImageFile$ + "Not Found"
                ProcedureReturn -1
            Case -2    
                *di\Type = "Mismatch Error"                
                ProcedureReturn -2                
            Default
                *di\Type = GetExtensionPart(DiskImageFile$) + " Not Supportet"                
                ProcedureReturn 0
        EndSelect
                        
        LoadDiskImage(DiskImageFile$, ImageFileSize)
        
        ;Debug ShowMemoryViewer(*di\image, ImageFileSize)
        
        *di\filename    = GetFilePart(DiskImageFile$)
        *di\filepath    = GetPathPart(DiskImageFile$)
        *di\openfiles   = 0
        *di\blocksfree  = blocks_free(*di);
        *di\modified    = 0               ;
        set_status(*di, 254, 0, 0);
        
        ProcedureReturn *di.DiskImage
        
    EndProcedure    
    
;---------------------------------------------------------------------------------------------------------
; NOT FINISHED
;---------------------------------------------------------------------------------------------------------
    Procedure.l alloc_next_ts(*di.DiskImage, *prevts.TrackSector)
        
        Protected spt.i, s1.i, s2.i, t1.i, t2.i, bpt.i, boff.i, res1.i, res2.i, tsTrack.i        
        Define *bam.UnsignedChar                
        Static *ts.TrackSector
                
        Select *di\Type
            Case "D64"
                s1      =  1
                t1      = 35
                s2      =  1
                t2      = 35
                res1    = 18
                res2    =  0
                bpt     =  4
                boff    =  0
            Case "D71"
                s1      =  1
                t1      = 35
                s2      = 36
                t2      = 70
                res1    = 18
                res2    = 53
                bpt     =  4
                boff    =  0
            Case "D81"
                s1      =  1
                t1      = 40
                s2      = 41
                t2      = 80
                res1    = 40
                res2    =  0
                bpt     =  6
                boff    = 10                
            Default
                ; Not Support
        EndSelect
        
        *bam = get_ts_addr(*di, *di\bam)
        
        tsTrack = *ts\track
        For tsTrack = s1 To t1            
            If (tsTrack ! res1)               
                If  (*bam\b [ tsTrack * bpt + boff ] )                    
                    *ts\track   = tsTrack
                    spt         = di_sectors_per_track(*di, *ts\track)
                    *ts\sector  = (*prevts\sector + interleave ( *di\type) ) % spt                                                            
                EndIf                    
            EndIf                
        Next tsTrack        
        
        *ts\track   = 0
        *ts\sector  = 0        
        ProcedureReturn *ts.TrackSector     
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
; 
;--------------------------------------------------------------------------------------------------------- 
    Procedure.i match_pattern(*rawpattern.rawpattern, *rawname.char)        
    Protected i.i      
        For i = 0 To 15                       
            If *rawpattern\c[i] = '*'                 
                 ProcedureReturn 1                
             EndIf                        
             If (*rawname\c[i] = $a0 )
                If (*rawpattern\c[i] = $a0)
                     ProcedureReturn 1
                 Else
                     ProcedureReturn  0
                 EndIf
             Else
                 If (*rawpattern\c[i] = '?' ) Or ( *rawpattern\c[i] = *rawname\c[i] ) 
                 Else
                     ProcedureReturn 0
                 EndIf
             EndIf
             ProcedureReturn 1  
       Next i        
    EndProcedure
;---------------------------------------------------------------------------------------------------------
    ; 
;---------------------------------------------------------------------------------------------------------   
    Procedure.l find_file_entry(*di.DiskImage, *rawpattern, type.i) 
        
        Protected offset.i
        
        Define *p.UnsignedChar, *buffer.UnsignedChar                
        Static *rde.RawDirEntry, ts.TrackSector       
        
        *p = next_ts_in_chain(*di, *di\bam);
        ts\track  = *p\b[0]
        ts\sector = *p\b[1]
        
        While (ts\track)            
            *buffer = get_ts_addr(*di, @ts);
            
            For offset = 0 To 255 Step 32
   
                *rde = *buffer + offset
                                
                If (*rde\type & ~$40) = (Filetype(type) | $80)
                    
	                If ( match_pattern(*rawpattern, *rde\rawname) )
	                    ProcedureReturn *rde
	                EndIf

	            EndIf  
	            
                *p = next_ts_in_chain(*di, @ts);
                ts\track  = *p\b[0]
                ts\sector = *p\b[1]   	            
            Next                                   
        Wend
        ProcedureReturn 0
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
; Not yet finished
;---------------------------------------------------------------------------------------------------------     
    Procedure.l alloc_file_entry(*di.DiskImage, *rawname.char, type.i)
        
        type = Filetype(type)
        
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
    ; /* open a file */
;---------------------------------------------------------------------------------------------------------       
    Procedure.l di_open(*di.DiskImage, *rawname.char, type.i, Mode.s)
        
        If ( *di = 0 )
            ProcedureReturn 0
        ElseIf  ( *di = -1 )
            ProcedureReturn -1
        ElseIf  ( *di = -2 )            
            ProcedureReturn -2
        EndIf    
            
        *imgfile.ImageFile = AllocateMemory( SizeOf(ImageFile)  )
        InitializeStructure(*imgfile, ImageFile)
        
        *rde.RawDirEntry   = AllocateMemory( SizeOf(RawDirEntry))
        InitializeStructure(*rde, RawDirEntry)
        
        type = Filetype(type)
        
        Define *p.UnsignedChar
        
        set_status(*di, 255, 0, 0);
        
        Select Mode
            Case "rb"
                
                If ( *rawname = '$' )
                    *imgfile\mode = "r"
                    *imgfile\ts   = *di\dir
                    
                    *p = get_ts_addr(*di, *di\dir)
                    *imgfile\buffer = *p + 2;
                    
                    Select *di\type
                        Case "D64"
                            *imgfile\nextts\track = 18  ; // 1541/71 ignores bam t/s link
                            *imgfile\nextts\sector = 1  ;
                        Case "D71"
                            *imgfile\nextts\track = 18  ; // 1541/71 ignores bam t/s link
                            *imgfile\nextts\sector = 1  ;                            
                        Case "D81"
                            *imgfile\nextts\track = *p\c[0]
                            *imgfile\nextts\sector =*p\c[1]                            
                        Default
                            ; No Supportet and NULL
                    EndSelect
                    *imgfile\buflen = 254;                    
                    *rde = 0                               
                Else
                    
                    *rde = find_file_entry(*di, *rawname, Filetype(type))
                    If ( *rde = 0 )
                        set_status(*di, 62, 0, 0);
                        FreeMemory(*imgfile)   
                        ProcedureReturn 0
                    EndIf
                   
                    
                    *imgfile\mode = "r"
                    *imgfile\ts = *rde\startts
                
                    If (*imgfile\ts\track > di_tracks(*di))
                        ProcedureReturn 0
                    EndIf    
                    
                    *p = get_ts_addr(*di, *rde\startts)
                    
                    *imgfile\buffer        = *p + 2
                    
                    *imgfile\nextts\track  = *p\c[0]
                    *imgfile\nextts\sector = *p\c[1]
                    
                    
                    If (*imgfile\nextts\track = 0)
                        *imgfile\buflen = *imgfile\nextts\sector - 1
                    Else
                        *imgfile\buflen = 254
                    EndIf                      
                                        
                EndIf         
            Case "wb"    
            Default
        EndSelect

        *imgfile\diskimage      = *di
        *imgfile\rawdirentry    = *rde
        *imgfile\position       = 0
        *imgfile\bufptr         = 0
        
        *di\openfiles           + 1
        
        set_status(*di, 0, 0, 0)
        
        ProcedureReturn *imgfile
    EndProcedure  
;---------------------------------------------------------------------------------------------------------
; ;   /* Read first block INTO buffer */
;---------------------------------------------------------------------------------------------------------        
    Procedure.i di_read(*imgfile.ImageFile, *buffer.CharBuffer, len.i)
        
        Define *p.UnsignedChar , bytesleft.i ,  counter.i = 0
        Static *tts.TrackSector
        
        While len.i
            bytesleft.i = *imgfile\buflen - *imgfile\bufptr
            
            If (bytesleft.i = 0)
                
                If (*imgfile\nextts\track = 0)
                    ProcedureReturn counter
                EndIf
                
                If ( *imgfile\diskimage\Type = "D64") Or  ( *imgfile\diskimage\Type = "D71") And  ( *imgfile\ts\track = 18) And (*imgfile\ts\sector = 0)
                    *imgfile\ts\track  = 18
                    *imgfile\ts\sector = 1
                Else 			
                    *tts = next_ts_in_chain(*imgfile\diskimage, *imgfile\ts)
                    *imgfile\ts\sector = *tts\sector
                    *imgfile\ts\track  = *tts\track
                EndIf
                
                If (*imgfile\ts\track = 0)
                    ProcedureReturn counter
                EndIf
                
                *p = get_ts_addr(*imgfile\diskimage,  *imgfile\ts);
                *imgfile\buffer        = *p + 2
                *imgfile\nextts\track  = *p\c[0]
                *imgfile\nextts\sector = *p\c[1]
                
                If (*imgfile\nextts\track = 0)
                    *imgfile\buflen = *imgfile\nextts\sector - 1
                Else
                    *imgfile\buflen = 254
                EndIf
                
                *imgfile\bufptr        = 0
							    
            Else
                If (len.i >= bytesleft.i)
                    While bytesleft.i
                        *buffer + 1
                        *buffer = *imgfile\buffer\c[ *imgfile\bufptr +1 ]
                        len         - 1
                        bytesleft   - 1
                        counter     + 1
                        *imgfile\position + 1
                    Wend                                                                
                Else    
                    While len.i
                        *buffer + 1
                        *buffer = *imgfile\buffer\c[ *imgfile\bufptr +1 ]
                        len         - 1
                        bytesleft   - 1
                        counter     + 1
                        *imgfile\position + 1
                    Wend 
                EndIf    
            EndIf
        Wend
        
        ProcedureReturn counter
        
    EndProcedure  
    
;---------------------------------------------------------------------------------------------------------
    ; /* Openfile */
;--------------------------------------------------------------------------------------------------------- 
    Procedure.i cbmfile_read(*imgfile.ImageFile, *name.char, FileType.i)   
        
        *imgfile = di_open(*imgfile\diskimage, @*buffer, ftype ,"rb")
        
        C64FileLenght.i = di_rawname_from_name(@rawname.Rawname, *name)
        
        
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
    ; /* Read directory blocks */
;---------------------------------------------------------------------------------------------------------     
   Procedure.i di_read_directory_blocks(*imgfile.ImageFile)
               
        Protected offset.i, type.i, closed.i, locked.i, size.i, C64FileLen.i, C64File.s, ftype.s
        
        Structure BufferChar
            c.a[254]
        EndStructure
        
        Define *buffer.BufferChar
        
        If ( di_read(*imgfile, @*buffer, 254) ! 254)            
            Debug "BAM Read failed"
            ProcedureReturn 0
        EndIf        
        ;/* Read directory blocks */
            While ( di_read(*imgfile, @*buffer, 254) = 254)                
                *buffer =  @*buffer                   
                For offset = -2 To 254 Step 32                
                                        
                    ; If file type != 0                     
                    If (*buffer\c[ offset+2 ]! 0)
                        C64FileLen = di_name_from_rawname(@name.char, *buffer +  offset + 5)
 
                        type    = *buffer\c[ offset +2] & $7
                        ftype   = Filetype_Get(type)
                        
                        ;cbmfile_read(*imgfile,@name.char, type)
                                                                            
                        closed  = *buffer\c[ offset +2 ] & $80    ; // closed/locked file?
                        locked  = *buffer\c[ offset +2 ] & $40    ; // closed/locked file?
                        size    = *buffer\c[ offset + 31 ] << $8 | *buffer\c[ offset + 30 ]; // blocks size

                        If ( closed ) : ftype = "*"+ftype: Else: ftype = " "+ftype: EndIf                        
                        If ( locked ) : ftype + "<"      : Else: ftype + " "      : EndIf     
                                                        
                        ; /* Convert To ascii  */                        
                        pettoascii(@name,@ptoa.ptoa)
                        C64File.s = PeekS(@ptoa, C64FileLen -1, #PB_Ascii )                        
                        Debug C64File + ftype
                    EndIf    
                    
                    Debug offset
                Next offset                                
            Wend                    
    EndProcedure    
;---------------------------------------------------------------------------------------------------------
; 
;---------------------------------------------------------------------------------------------------------
    Procedure di_close(*imgfile.ImageFile)
        
        Define *p.UnsignedChar
        Static *tts.TrackSector
        
        Select *imgfile\mode
            Case "w"
                
                If (*imgfile\bufptr) 
                    
                    If (*imgfile\diskimage\blocksfree)
                                                                        
                        *tts = alloc_next_ts(*imgfile\diskimage, *imgfile\ts)
                        
                        *imgfile\nextts\sector = *tts\sector
                        *imgfile\nextts\track = *tts\track
                        
                        If (*imgfile\ts\track = 0)
                            *imgfile\rawdirentry\startts = *imgfile\nextts
                        Else
                            *p = get_ts_addr(*imgfile\diskimage, *imgfile\ts)
                            *p\c[0] = *imgfile\nextts\track
                            *p\c[1] = *imgfile\nextts\sector
                        EndIf
                        
                        *imgfile\ts = *imgfile\nextts
                        
                        *p = get_ts_addr(*imgfile\diskimage, *imgfile\ts)
                        *p\c[0] = 0
                        *p\c[1] = $ff
                        
                        CopyMemory(*imgfile\buffer , *p + 2, 254) 
                        
                        *imgfile\bufptr = 0
                        
                        If ( (*imgfile\rawdirentry\sizelo + 1) = 0 )                            
                             *imgfile\rawdirentry\sizehi + 1
                        EndIf
                        
                        *imgfile\diskimage\blocksfree - 1
                        *imgfile\rawdirentry\type | $80                                             
                    EndIf
                 Else
                     *imgfile\rawdirentry\type | $80                                                               
                 EndIf
                 
                 FreeMemory(*imgfile\buffer)
         EndSelect
         
         *imgfile\diskimage\openfiles - 1
         FreeMemory(*imgfile)                         
     EndProcedure
     
;---------------------------------------------------------------------------------------------------------
; /* Close file */
;---------------------------------------------------------------------------------------------------------         
     Procedure.i vDSK_Close_Image(*imgfile.ImageFile)
         di_close(*imgfile)
         
     EndProcedure
;---------------------------------------------------------------------------------------------------------
; Return Disk Image Format
;---------------------------------------------------------------------------------------------------------         
    Procedure.s vDSK_Get_ImageFormat(*di.DiskImage)
        
        If ( *di = 0 ) Or ( *di = -1 ) Or ( *di = -2 )
            ProcedureReturn ""
        EndIf
        
        ProcedureReturn *di\Type
         
    EndProcedure     
;---------------------------------------------------------------------------------------------------------
; Return Disk Filename
;---------------------------------------------------------------------------------------------------------         
    Procedure.s vDSK_Get_Filename(*di.DiskImage, Fullpath.i = #False)
        
        If ( *di = 0 ) Or ( *di = -1 ) Or ( *di = -2 )
            ProcedureReturn ""
        EndIf
        
        Select Fullpath
            Case #False
                ProcedureReturn *di\filename
            Case #True
                ProcedureReturn *di\filepath + *di\filename
        EndSelect           
    EndProcedure          
;---------------------------------------------------------------------------------------------------------
; Return Free Blocks Of the C64 Disk Image
;---------------------------------------------------------------------------------------------------------         
    Procedure.i vDSK_Get_FreeBlocks(*di.DiskImage)
        
        If ( *di = 0 )
            ProcedureReturn 0
        ElseIf  ( *di = -1 )
            ProcedureReturn -1
        ElseIf  ( *di = -2 )            
            ProcedureReturn -2
        EndIf  
        
        ProcedureReturn *di\blocksfree
    EndProcedure          
;---------------------------------------------------------------------------------------------------------
; Get C64 Disk Image Title
;---------------------------------------------------------------------------------------------------------        
    Procedure.s vDSK_Get_TitleHead(*di.DiskImage)
        
        Protected TitleLenght.i = 0, Title.s = ""
        
        If ( *di = 0 ) Or ( *di = -1 ) Or ( *di = -2 )
            ProcedureReturn ""
        EndIf
        
         ;Convert title To ascii
        TitleLenght.i = di_name_from_rawname(@name.char, CBMDiskImage::di_title(*di) )
        
        pettoascii(@name,@ptoa.ptoa)
        
        Title.s = PeekS(@ptoa, TitleLenght +1,#PB_Ascii )
        Title.s = LSet( Title.s, 16, Chr(32) )

        ProcedureReturn Title.s
    EndProcedure  
;---------------------------------------------------------------------------------------------------------
; Get C64 Disk Image ID
;---------------------------------------------------------------------------------------------------------        
    Procedure.s vDSK_Get_Title_ID(*di.DiskImage)
        
        Protected TitleLenght.i = 0, ident.s = ""
        
        If ( *di = 0 ) Or ( *di = -1 ) Or ( *di = -2 )
            ProcedureReturn ""
        EndIf
        
        CopyMemory(di_title(*di) +18 , @id.char, 5)    ; Convert ID To ascii
        
        pettoascii(@id,@ptoa.ptoa)
        
        ident.s = PeekS(@ptoa, 4 +1,#PB_Ascii )
        
        ProcedureReturn ident.s        
    EndProcedure     
;---------------------------------------------------------------------------------------------------------
; Test BAM
;---------------------------------------------------------------------------------------------------------    
    Procedure vDSK_Test_BAM(*di.DiskImage)
        
        Protected FreeSector.i
        Debug "Track" +#TAB$+ "Free"+#TAB$+"Map"
        
        Static ts.TrackSector
        
        CurrenTrack = ts\track
        CurrenSectr = ts\sector
        
        For CurrenTrack = 1 To di_tracks( *di )           
            
            free.i =  di_track_blocks_free(*di, CurrenTrack)
            sect.i =  di_sectors_per_track(*di, CurrenTrack)            
            
            Free$ = ""
            For CurrenSectr = 0 To di_sectors_per_track(*di, CurrenTrack) -1
                ts\track   = CurrenTrack
                ts\sector  = CurrenSectr
                FreeSector = di_is_ts_free(*di, @ts)
                
                Select FreeSector
                    Case 0
                        Free$ + "*"
                    Default
                        Free$ + "-"                       
                EndSelect                        
            Next
            Debug " "+Str(CurrenTrack) + ":  "+#TAB$+ Str(free)+"/"+Str(sect) +#TAB$+ Free$
        Next       
        Debug ""
        Debug Str( *di\blocksfree ) + " blocks free"
        
        
    EndProcedure  
EndModule
;
; Beispiel 1

    ;   
    ;                               /* Load image INTO ram */
    ;
*di = CBMDiskImage::di_load_image("B:\daten 2 - Kopie.d64")

    ;                       /* Open directory For reading */
    ;
*imgfile = CBMDiskImage::di_open(*di, '$', 2 ,"rb")
If ( *imgfile = 0 )
    Debug "Couldn't open directory"
    End
EndIf


    ;
    ;                   
    ;                      /* Convert title To ascii */
        Debug "| Disk   :" + CBMDiskImage::vDSK_Get_Filename(*di) 
        Debug "| Format :" + CBMDiskImage::vDSK_Get_ImageFormat(*di)
        Debug "| --------------------------------| Disk ID |" 
        Debug "| Disk Name  :  0 " + Chr(34) + CBMDiskImage::vDSK_Get_TitleHead(*di) + Chr(34)  + " "+CBMDiskImage::vDSK_Get_Title_ID(*di)     
        Debug "| Free Blocks: " + Str( CBMDiskImage::vDsk_Get_FreeBlocks(*di) )  
        Debug "| Test Bam   : " + #CRLF$
        CBMDiskImage::vDSK_Test_BAM(*di)
        CBMDiskImage::di_read_directory_blocks(*imgfile)        
        Debug "| ---------------------------------------|" +#CRLF$+#CRLF$             
        
        
        
        
;
; Beispiel 2
        
        *di = CBMDiskImage::di_load_image("B:\NEWIMAGE.d64")
        *imgfile = CBMDiskImage::di_open(*di, '$', 2 ,"rb")
        Debug "| Disk   :" + CBMDiskImage::vDSK_Get_Filename(*di) 
        Debug "| Format :" + CBMDiskImage::vDSK_Get_ImageFormat(*di)        
        Debug "| --------------------------------| Disk ID |" 
        Debug "| Disk Name  :  0 " + Chr(34) + CBMDiskImage::vDSK_Get_TitleHead(*di) + Chr(34)  + " "+CBMDiskImage::vDSK_Get_Title_ID(*di)     
        Debug "| Free Blocks: " + Str( CBMDiskImage::vDsk_Get_FreeBlocks(*di) ) 
        Debug "| Test Bam   : " + #CRLF$
        CBMDiskImage::vDSK_Test_BAM(*di)        
        ;CBMDiskImage::di_read_directory_blocks(*imgfile) 
        Debug "| ---------------------------------------|" +#CRLF$+#CRLF$
        
;
; Beispiel 3        
        *di = CBMDiskImage::di_load_image("B:\FUR DIE SCHULE,DiskID-2A  1.d64")
        *imgfile = CBMDiskImage::di_open(*di, '$', 2 ,"rb")
        Debug "| Disk   :" + CBMDiskImage::vDSK_Get_Filename(*di) 
        Debug "| Format :" + CBMDiskImage::vDSK_Get_ImageFormat(*di)        
        Debug "| --------------------------------| Disk ID |" 
        Debug "| Disk Name  :  0 " + Chr(34) + CBMDiskImage::vDSK_Get_TitleHead(*di) + Chr(34)  + " "+CBMDiskImage::vDSK_Get_Title_ID(*di)     
        Debug "| Free Blocks: " + Str( CBMDiskImage::vDsk_Get_FreeBlocks(*di) )  
        Debug "| Test Bam   : " + #CRLF$
        CBMDiskImage::vDSK_Test_BAM(*di)            
        Debug "| ---------------------------------------|" +#CRLF$+#CRLF$
;         
; ;
; ; Beispiel 4        
        *di = CBMDiskImage::di_load_image("B:\      NEWI  MAGE.D64")
        *imgfile = CBMDiskImage::di_open(*di, '$', 2 ,"rb")
        Debug "| Disk   :" + CBMDiskImage::vDSK_Get_Filename(*di) 
        Debug "| Format :" + CBMDiskImage::vDSK_Get_ImageFormat(*di)        
        Debug "| --------------------------------| Disk ID |" 
        Debug "| Disk Name  :  0 " + Chr(34) + CBMDiskImage::vDSK_Get_TitleHead(*di) + Chr(34)  + " "+CBMDiskImage::vDSK_Get_Title_ID(*di)     
        Debug "| Free Blocks: " + Str( CBMDiskImage::vDsk_Get_FreeBlocks(*di) )
        Debug "| Test Bam   : " + #CRLF$
        CBMDiskImage::vDSK_Test_BAM(*di)            
        Debug "| ---------------------------------------|" +#CRLF$+#CRLF$
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by infratec »

Code: Select all

DeclareModule CBMDiskImage
  
  ; Init Procedures
  Declare.l di_load_image(DiskImageFile$)                         ; Load image INTO ram
  Declare.l di_open(*di, *rawname, type.i, Mode.s)                ; Open directory for reading
  Declare.i di_title(*di)                                         ; Get image Title
  Declare.i di_name_from_rawname(*name, *rawname )                ; Convert title to ascii, in combinaion with "di_title(*di)"
  Declare.i di_read(*imgfile, *buffer, len)                       ; Read first block INTO buffer
  Declare.i di_read_directory_blocks(*imgfile)
  
  ; Tools Procdures
  Declare.i vDSK_Get_FreeBlocks(*di)                              ; Return Free Blocks From Image                   
  Declare.s vDSK_Get_TitleHead(*di)                               ; Convert Title to ascii and return the Title Header
  Declare.s vDSK_Get_Title_ID(*di)                                ; Convert ID To ascii and return the ID String
  Declare.s vDSK_Get_Filename(*di, Fullpath = #False)             ; Return the Image Filename (Fullpath = #true: Return the Fullpath)
  Declare.s vDSK_Get_ImageFormat(*di)                             ; Return the Image Format as string
  Declare.i vDSK_Close_Image(*imgfile)
  Declare.i vDSK_Test_BAM(*di)
  
  ; Source Taken and Converted from DiskImagery64
  ; http://lallafa.de/blog/c64-projects/diskimagery64/
  ; https://sourceforge.net/p/diskimagery64/code/HEAD/tree/
  
EndDeclareModule

Module CBMDiskImage
  
  Structure TrackSector
    track.c
    sector.c
  EndStructure 
  
  Structure Rawname
    c.a[17]
  EndStructure
  
  Structure Unused
    c.a[4]
  EndStructure
  
  Structure Image
    b.b
  EndStructure
  
  Structure Diskimage
    filename.s
    filepath.s
    size.i
    Type.s{3}       
    *image     
    bam.TrackSector
    bam2.TrackSector
    dir.TrackSector
    openfiles.i
    blocksfree.i
    modified.i
    status.i
    statusts.TrackSector 
  EndStructure
  
  Structure  Rawdirentry
    nextts.TrackSector
    type.c
    startts.TrackSector
    *rawname.Rawname
    relsidets.TrackSector
    relrecsize.c
    *unused.Unused
    replacetemp.TrackSector
    sizelo.c
    sizehi.c
  EndStructure
  
  Structure  ImageFile
    *diskimage.Diskimage
    *rawdirentry.Rawdirentry         
    mode.s
    position.i
    ts.TrackSector
    nextts.TrackSector         
    *buffer.CharBuffer
    bufptr.i
    buflen.i
  EndStructure 
  
  Structure UnsignedChar
    b.b[0]
    c.c[0]
  EndStructure 
  
  Structure char
    c.a[17]
  EndStructure
  
  Structure ptoa
    c.a[17]
  EndStructure
  
  Structure rawpattern
    c.a[17]
  EndStructure   
  
  Structure CharBuffer
    c.a[254]
  EndStructure
  
  
  Macro LoadDiskImage(diFileName, diFileSize)
    
    *di\image = AllocateMemory(diFileSize)
    
    Define DiskImage = OpenFile( #PB_Any, diFileName )
    If DiskImage
      While Not Eof( DiskImage )             
        ReadData(DiskImage, *di\image, diFileSize)
      Wend
      CloseFile(DiskImage)
    EndIf
  EndMacro
  
  Procedure.s Filetype_Get(type)
    
    Select type
      Case 0:ProcedureReturn "del"
      Case 1:ProcedureReturn "seq"
      Case 2:ProcedureReturn "prg"
      Case 3:ProcedureReturn "usr"                               
      Case 4:ProcedureReturn "rel"
      Case 5:ProcedureReturn "cbm"                                 
      Case 6:ProcedureReturn "dir"                                                               
      Default
        ProcedureReturn "???"
    EndSelect       
  EndProcedure       
  
  Procedure.i Filetype(type)
    
    Select type
      Case 0:ProcedureReturn 0; ftype = "del"
      Case 1:ProcedureReturn 1; ftype = "seq"
      Case 2:ProcedureReturn 2; ftype = "prg"
      Case 3:ProcedureReturn 3; ftype = "usr"                               
      Case 4:ProcedureReturn 4; ftype = "rel"
      Case 5:ProcedureReturn 5; ftype = "cbm"                                 
      Case 6:ProcedureReturn 6; ftype = "dir"                                                               
    EndSelect
    
  EndProcedure       
  ;---------------------------------------------------------------------------------------------------------
  ; /* convert Pet to Ascii */
  ;---------------------------------------------------------------------------------------------------------       
  Procedure ptoa(*c.char)
    
    Protected c.a
    
    For i = 0 To 15
      c = *c\c[i]
      If c = 0
        Break
      EndIf
      
      c & $7f
      
      If c >= 'A' And c <= 'Z'
        c + 32
      ElseIf c >= 'a' And c <= 'z'
        c - 32
      ElseIf c = $7f
        c = $3f                           
      EndIf
      *c\c[i] = c
    Next i   
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ; /* convert to rawname */
  ;---------------------------------------------------------------------------------------------------------       
  
  Procedure.i di_rawname_from_name(*rawname.Rawname, *name.char)               
    FillMemory( *rawname, 16, $a0)           
    For i = 0 To 15
      *rawname\c[i] = *name\c[i]
    Next     
    
    ProcedureReturn i       
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ; /* convert from rawname */
  ;---------------------------------------------------------------------------------------------------------   
  Procedure.i di_name_from_rawname(*name.char, *rawname.Rawname)
    
    Protected TitleLenght.i, s.s
    
    For TitleLenght = 0 To 15
      If *rawname\c[TitleLenght] = $a0
        Break
      EndIf
      *name\c[TitleLenght] = *rawname\c[TitleLenght]               
      
      ;Debug s.s + Chr(*name\c[TitleLenght])
      
    Next TitleLenght
    *name\c[TitleLenght] = 0       
    
    ProcedureReturn TitleLenght       
    
  EndProcedure
  ;---------------------------------------------------------------------------------------------------------
  ; /* return number of tracks for image type *
  ;---------------------------------------------------------------------------------------------------------
  Procedure.i set_status(*di.DiskImage, status.i, track.i, sector.i)       
    *di\status          = status
    *di\statusts\track  = track     
    *di\statusts\sector = sector
    ProcedureReturn status       
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ; /* return write interleave */
  ;---------------------------------------------------------------------------------------------------------
  Procedure.i interleave(Type.s)       
    Select Type
      Case "D64": ProcedureReturn 10
      Case "D71": ProcedureReturn 6
      Case "D81": ProcedureReturn 1
      Default
    EndSelect       
  EndProcedure 
  
  ;---------------------------------------------------------------------------------------------------------
  ; /* return number of tracks for image type *
  ;--------------------------------------------------------------------------------------------------------- 
  Procedure.i di_tracks(*di.DiskImage)       
    Select *di\Type
      Case "D64": ProcedureReturn 35
      Case "D71": ProcedureReturn 70
      Case "D81": ProcedureReturn 80
      Default:ProcedureReturn 0
    EndSelect               
  EndProcedure 
  ;---------------------------------------------------------------------------------------------------------
  ; /* return disk geometry for track */
  ;---------------------------------------------------------------------------------------------------------
  Procedure.i di_sectors_per_track(*di.DiskImage, track.i)
    
    Select *di\Type
      Case "D64"
        If (track < 18)     :ProcedureReturn 21
        ElseIf (track < 25) :ProcedureReturn 19
        ElseIf (track < 31) :ProcedureReturn 18
        Else
          ProcedureReturn 17
        EndIf
        
      Case "D71"
        If (track > 35)
          track - 35
        EndIf
        
      Case "D81": ProcedureReturn 40
        
      Default
        ; No Supportet
        ProcedureReturn 0
    EndSelect
    
  EndProcedure
  ;---------------------------------------------------------------------------------------------------------
  ; /* convert track, sector to blocknum */
  ;---------------------------------------------------------------------------------------------------------   
  Procedure.i di_get_block_num(*di.DiskImage, *ts.TrackSector)
    
    Protected block.i
    
    Select *di\Type
      Case "D64":
        If (*ts\track < 18)
          block.i = (*ts\track - 1) * 21
        ElseIf (*ts\track < 25)
          block.i = (*ts\track - 18) * 19 + 17 * 21
        ElseIf (*ts\track < 31)
          block.i = (*ts\track - 25) * 18 + 17 * 21 + 7 * 19
        Else
          block.i = (*ts\track - 31) * 17 + 17 * 21 + 7 * 19 + 6 * 18
        EndIf   
        ;Debug "Block: " + Str(block + *ts\sector)
        ProcedureReturn  (block + *ts\sector) 
        
      Case "D71":
        If (*ts\track > 35)
          block = 683;
          *ts\track - 35
        Else
          block = 0
        EndIf
        
        If (*ts\track < 18)
          block + (*ts\track - 1) * 21
        ElseIf (*ts\track < 25)
          block + (*ts\track - 18) * 19 + 17 * 21
        ElseIf (*ts\track < 31)
          block + (*ts\track - 25) * 18 + 17 * 21 + 7 * 19
        Else
          block + (*ts\track - 31) * 17 + 17 * 21 + 7 * 19 + 6 * 18
        EndIf 
        ProcedureReturn (block + *ts\sector)
        
      Case "D81":
        ProcedureReturn ( (*ts\track - 1) * 40 + *ts\sector)
      Default:
        ProcedureReturn 0
    EndSelect   
    
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ; /* get a pointer to block data */
  ;---------------------------------------------------------------------------------------------------------     
  Procedure.i get_ts_addr(*di.DiskImage,  *ts.TrackSector)               
    ProcedureReturn ( *di\Image + di_get_block_num(*di, *ts) * 256 )
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ; /* return a pointer to the next block in the chain */
  ;---------------------------------------------------------------------------------------------------------
  Procedure.i next_ts_in_chain(*di.DiskImage,  *ts.TrackSector)
    
    Define *p.UnsignedChar
    
    Static newts.TrackSector
    
    *p = get_ts_addr(*di, *ts)
    newts\track  = *p\b[0]
    newts\sector = *p\b[1]
    
    If ( *p\b[0] > di_tracks(*di) )
      newts\track     = 0
      newts\sector    = 0
    ElseIf ( *p\b[1] > di_sectors_per_track(*di, *p\b[0] ) )
      newts\track     = 0
      newts\sector    = 0
    EndIf
    ProcedureReturn @newts
    
  EndProcedure
  ;---------------------------------------------------------------------------------------------------------
  ; /* return a pointer to the disk title */
  ;---------------------------------------------------------------------------------------------------------   
  Procedure di_title(*di.DiskImage)
    Select (*di\Type)
      Case "D64": ProcedureReturn (get_ts_addr( *di, *di\dir ) + 144)
      Case "D71": ProcedureReturn (get_ts_addr( *di, *di\dir ) + 144)
      Case "D81": ProcedureReturn (get_ts_addr( *di, *di\dir ) + 4)
      Default:
        ; Not Support
        ProcedureReturn 0
    EndSelect
  EndProcedure
  ;---------------------------------------------------------------------------------------------------------
  ; /* return number of free blocks in track */
  ;---------------------------------------------------------------------------------------------------------   
  Procedure.l di_track_blocks_free(*di.DiskImage, track.i)
    
    Define *bam.UnsignedChar
    
    Select *di\Type
      Case "D64":
        *bam = get_ts_addr(*di, *di\bam)
        
      Case "D71":
        *bam = get_ts_addr(*di, *di\bam)
        If (track >= 36)
          ProcedureReturn ( *bam\b [track + 185] )
        EndIf 
        
      Case "D81":
        If (track <= 40)
          *bam = get_ts_addr(*di, *di\bam);
        Else
          *bam = get_ts_addr(*di, *di\bam2);
          track - 40                       ;
        EndIf
        ProcedureReturn ( *bam\b[track * 6 + 10]);               
      Default
    EndSelect       
    
    ProcedureReturn ( *bam\b [track * 4]  )       
  EndProcedure   
  
  ;---------------------------------------------------------------------------------------------------------
  ; count number of free blocks
  ;---------------------------------------------------------------------------------------------------------   
  Procedure.i blocks_free(*di.DiskImage)       
    Protected Track.i, Blocks.i = 0
    
    For Track = 1 To di_tracks(*di.DiskImage)           
      If ( Track <> *di\dir\track )
        Blocks + di_track_blocks_free(*di, Track)
      EndIf
    Next
    ProcedureReturn Blocks
  EndProcedure
  
  ;---------------------------------------------------------------------------------------------------------
  ; /* check If track, sector is free IN BAM */
  ;---------------------------------------------------------------------------------------------------------
  Procedure.i di_is_ts_free( *di.DiskImage, *ts.TrackSector)
    
    Protected mask.l
    Define *bam.UnsignedChar
    
    Select *di\Type
      Case "D64"               
        *bam = get_ts_addr(*di, *di\bam)
        
        If ( *bam\b[ *ts\track * 4 ] )
          mask = 1 << ( *ts\sector & 7)
          If ( mask )
            ProcedureReturn (*bam\b[*ts\track * 4 + *ts\sector / 8 + 1] & mask)
          Else
            ProcedureReturn (*bam\b[*ts\track * 4 + *ts\sector / 8 + 1])
          EndIf   
        Else
          ProcedureReturn 0
        EndIf
        
      Case "D71"
      Case "D81"
      Default
        ; NOT SUPPORT
        ProcedureReturn 0
    EndSelect       
    
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ; /* Load image into ram */
  ;---------------------------------------------------------------------------------------------------------
  Procedure.l di_load_image(DiskImageFile$)
    
    *di.DiskImage = AllocateMemory(SizeOf(DiskImage))
    InitializeStructure(*di, DiskImage)
    
    Protected ImageFileSize.i
    
    ImageFileSize = FileSize( DiskImageFile$ )
    Select ImageFileSize
      Case 174848         ; // standard D64
        *di\Type       = "D64"
        *di\bam\track  = 18
        *di\bam\sector = 0
        *di\dir        = *di\bam               
      Case 175531         ; // D64 With error info (which we just ignore)   
        *di\Type       = "D64"
        *di\bam\track  = 18
        *di\bam\sector = 0
        *di\dir        = *di\bam
      Case 349696   
        *di\Type       = "D71"
        *di\bam\track  = 18
        *di\bam\sector = 0
        *di\bam2\track = 53
        *di\bam2\sector= 0
        *di\dir        = *di\bam
      Case 819200
        *di\Type       = "D81"
        *di\bam\track  = 40
        *di\bam\sector = 1
        *di\bam2\track = 40
        *di\bam2\sector= 2
        *di\dir\track  = 40
        *di\dir\sector = 0
      Case 533248   
        *di\Type       = "D80: Not Supportet"               
        ProcedureReturn 0               
      Case 278234
        *di\Type       = "G64: Not Supportet"
        ProcedureReturn 0
      Case 667476
        *di\Type       = "G71: Not Supportet"               
        ProcedureReturn 0   
      Case 174912
        *di\Type       = "X64: Not Supportet"               
        ProcedureReturn 0
      Case 1066496
        *di\Type       = "D82: Not Supportet"               
        ProcedureReturn 0                               
      Case 0
        *di\Type = "Images has 0 Bytes"
        ProcedureReturn 0
      Case -1
        *di\Type = "Image " + DiskImageFile$ + "Not Found"
        ProcedureReturn -1
      Case -2   
        *di\Type = "Mismatch Error"               
        ProcedureReturn -2               
      Default
        *di\Type = GetExtensionPart(DiskImageFile$) + " Not Supportet"               
        ProcedureReturn 0
    EndSelect
    
    LoadDiskImage(DiskImageFile$, ImageFileSize)
    
    ;Debug ShowMemoryViewer(*di\image, ImageFileSize)
    
    *di\filename    = GetFilePart(DiskImageFile$)
    *di\filepath    = GetPathPart(DiskImageFile$)
    *di\openfiles   = 0
    *di\blocksfree  = blocks_free(*di);
    *di\modified    = 0               ;
    set_status(*di, 254, 0, 0)        ;
    
    ProcedureReturn *di.DiskImage
    
  EndProcedure   
  
  ;---------------------------------------------------------------------------------------------------------
  ; NOT FINISHED
  ;---------------------------------------------------------------------------------------------------------
  Procedure.l alloc_next_ts(*di.DiskImage, *prevts.TrackSector)
    
    Protected spt.i, s1.i, s2.i, t1.i, t2.i, bpt.i, boff.i, res1.i, res2.i, tsTrack.i       
    Define *bam.UnsignedChar               
    Static *ts.TrackSector
    
    Select *di\Type
      Case "D64"
        s1      =  1
        t1      = 35
        s2      =  1
        t2      = 35
        res1    = 18
        res2    =  0
        bpt     =  4
        boff    =  0
      Case "D71"
        s1      =  1
        t1      = 35
        s2      = 36
        t2      = 70
        res1    = 18
        res2    = 53
        bpt     =  4
        boff    =  0
      Case "D81"
        s1      =  1
        t1      = 40
        s2      = 41
        t2      = 80
        res1    = 40
        res2    =  0
        bpt     =  6
        boff    = 10               
      Default
        ; Not Support
    EndSelect
    
    *bam = get_ts_addr(*di, *di\bam)
    
    tsTrack = *ts\track
    For tsTrack = s1 To t1           
      If tsTrack <> res1
        If  *bam\b [ tsTrack * bpt + boff ]
          *ts\track   = tsTrack
          spt         = di_sectors_per_track(*di, *ts\track)
          *ts\sector  = (*prevts\sector + interleave ( *di\type) ) % spt                                                           
        EndIf                   
      EndIf               
    Next tsTrack       
    
    *ts\track   = 0
    *ts\sector  = 0       
    ProcedureReturn *ts.TrackSector     
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ;
  ;---------------------------------------------------------------------------------------------------------
  Procedure.i match_pattern(*rawpattern.rawpattern, *rawname.char)       
    Protected i.i     
    For i = 0 To 15                       
      If *rawpattern\c[i] = '*'                 
        ProcedureReturn 1               
      EndIf                       
      If (*rawname\c[i] = $a0 )
        If (*rawpattern\c[i] = $a0)
          ProcedureReturn 1
        Else
          ProcedureReturn  0
        EndIf
      Else
        If (*rawpattern\c[i] = '?' ) Or ( *rawpattern\c[i] = *rawname\c[i] )
        Else
          ProcedureReturn 0
        EndIf
      EndIf
      ProcedureReturn 1 
    Next i       
  EndProcedure
  ;---------------------------------------------------------------------------------------------------------
  ;
  ;---------------------------------------------------------------------------------------------------------   
  Procedure.l find_file_entry(*di.DiskImage, *rawpattern, type.i)
    
    Protected offset.i
    
    Define *p.UnsignedChar, *buffer.UnsignedChar               
    Static *rde.RawDirEntry, ts.TrackSector       
    
    *p = next_ts_in_chain(*di, *di\bam);
    ts\track  = *p\b[0]
    ts\sector = *p\b[1]
    
    While (ts\track)           
      *buffer = get_ts_addr(*di, @ts);
      
      For offset = 0 To 255 Step 32
        
        *rde = *buffer + offset
        
        If (*rde\type & ~$40) = (Filetype(type) | $80)
          
          If ( match_pattern(*rawpattern, *rde\rawname) )
            ProcedureReturn *rde
          EndIf
          
        EndIf 
        
        *p = next_ts_in_chain(*di, @ts);
        ts\track  = *p\b[0]
        ts\sector = *p\b[1]                 
      Next                                   
    Wend
    ProcedureReturn 0
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ; Not yet finished
  ;---------------------------------------------------------------------------------------------------------     
  Procedure.l alloc_file_entry(*di.DiskImage, *rawname.char, type.i)
    
    type = Filetype(type)
    
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ; /* open a file */
  ;---------------------------------------------------------------------------------------------------------       
  Procedure.l di_open(*di.DiskImage, *rawname.char, type.i, Mode.s)
    
    If ( *di = 0 )
      ProcedureReturn 0
    ElseIf  ( *di = -1 )
      ProcedureReturn -1
    ElseIf  ( *di = -2 )           
      ProcedureReturn -2
    EndIf   
    
    *imgfile.ImageFile = AllocateMemory( SizeOf(ImageFile)  )
    InitializeStructure(*imgfile, ImageFile)
    
    *rde.RawDirEntry   = AllocateMemory( SizeOf(RawDirEntry))
    InitializeStructure(*rde, RawDirEntry)
    
    type = Filetype(type)
    
    Define *p.UnsignedChar
    
    set_status(*di, 255, 0, 0);
    
    Select Mode
      Case "rb"
        
        If ( *rawname = '$' )
          *imgfile\mode = "r"
          *imgfile\ts   = *di\dir
          
          *p = get_ts_addr(*di, *di\dir)
          *imgfile\buffer = *p + 2;
          
          Select *di\type
            Case "D64"
              *imgfile\nextts\track = 18  ; // 1541/71 ignores bam t/s link
              *imgfile\nextts\sector = 1  ;
            Case "D71"
              *imgfile\nextts\track = 18  ; // 1541/71 ignores bam t/s link
              *imgfile\nextts\sector = 1  ;                           
            Case "D81"
              *imgfile\nextts\track = *p\c[0]
              *imgfile\nextts\sector =*p\c[1]                           
            Default
              ; No Supportet and NULL
          EndSelect
          *imgfile\buflen = 254;                   
          *rde = 0                               
        Else
          
          *rde = find_file_entry(*di, *rawname, Filetype(type))
          If ( *rde = 0 )
            set_status(*di, 62, 0, 0);
            FreeMemory(*imgfile)   
            ProcedureReturn 0
          EndIf
          
          
          *imgfile\mode = "r"
          *imgfile\ts = *rde\startts
          
          If (*imgfile\ts\track > di_tracks(*di))
            ProcedureReturn 0
          EndIf   
          
          *p = get_ts_addr(*di, *rde\startts)
          
          *imgfile\buffer        = *p + 2
          
          *imgfile\nextts\track  = *p\c[0]
          *imgfile\nextts\sector = *p\c[1]
          
          
          If (*imgfile\nextts\track = 0)
            *imgfile\buflen = *imgfile\nextts\sector - 1
          Else
            *imgfile\buflen = 254
          EndIf                     
          
        EndIf         
      Case "wb"   
      Default
    EndSelect
    
    *imgfile\diskimage      = *di
    *imgfile\rawdirentry    = *rde
    *imgfile\position       = 0
    *imgfile\bufptr         = 0
    
    *di\openfiles           + 1
    
    set_status(*di, 0, 0, 0)
    
    ProcedureReturn *imgfile
  EndProcedure 
  ;---------------------------------------------------------------------------------------------------------
  ; ;   /* Read first block INTO buffer */
  ;---------------------------------------------------------------------------------------------------------       
  Procedure.i di_read(*imgfile.ImageFile, *buffer.CharBuffer, len.i)
    
    Protected *p.UnsignedChar , bytesleft.i ,  counter.i
    Protected *tts.TrackSector
    
    While len
      bytesleft = *imgfile\buflen - *imgfile\bufptr
      
      If bytesleft = 0
        
        If *imgfile\nextts\track = 0
          ProcedureReturn counter
        EndIf
        
        If (*imgfile\diskimage\Type = "D64" Or *imgfile\diskimage\Type = "D71") And *imgfile\ts\track = 18 And *imgfile\ts\sector = 0
          *imgfile\ts\track  = 18
          *imgfile\ts\sector = 1
        Else          
          *tts = next_ts_in_chain(*imgfile\diskimage, *imgfile\ts)
          *imgfile\ts\sector = *tts\sector
          *imgfile\ts\track  = *tts\track
        EndIf
        
        If (*imgfile\ts\track = 0)
          ProcedureReturn counter
        EndIf
        
        *p = get_ts_addr(*imgfile\diskimage, *imgfile\ts)
        *imgfile\buffer        = *p + 2
        *imgfile\nextts\track  = *p\c[0]
        *imgfile\nextts\sector = *p\c[1]
        
        If (*imgfile\nextts\track = 0)
          *imgfile\buflen = *imgfile\nextts\sector - 1
        Else
          *imgfile\buflen = 254
        EndIf
        
        *imgfile\bufptr = 0
        
      Else
        If len >= bytesleft
          While bytesleft
            ;*buffer + 1
            *buffer\c[counter] = *imgfile\buffer\c[*imgfile\bufptr]
            *imgfile\bufptr + 1
            len         - 1
            bytesleft   - 1
            counter     + 1
            *imgfile\position + 1
          Wend                                                               
        Else   
          While len
            ;*buffer + 1
            *buffer\c[counter] = *imgfile\buffer\c[*imgfile\bufptr]
            *imgfile\bufptr + 1
            len         - 1
            bytesleft   - 1
            counter     + 1
            *imgfile\position + 1
          Wend
        EndIf
      EndIf
    Wend
    
    ProcedureReturn counter
    
  EndProcedure 
  
  ;---------------------------------------------------------------------------------------------------------
  ; /* Openfile */
  ;---------------------------------------------------------------------------------------------------------
  Procedure.i cbmfile_read(*imgfile.ImageFile, *name.char, FileType.i)   
    
    *imgfile = di_open(*imgfile\diskimage, @*buffer, ftype ,"rb")
    
    C64FileLenght.i = di_rawname_from_name(@rawname.Rawname, *name)
    
    
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ; /* Read directory blocks */
  ;---------------------------------------------------------------------------------------------------------     
  Procedure.i di_read_directory_blocks(*imgfile.ImageFile)
    
    Structure ByteArrayStructure
      c.a[0]
    EndStructure
    
    Protected *buffer.ByteArrayStructure
    
    Protected offset.i, type.i, closed.i, locked.i, size.i, C64FileLen.i, C64File.s, ftype.s
    
    Protected *name.char
    Protected ptoasc.ptoa
    
    *buffer = AllocateMemory(254)
    *name = AllocateMemory(17)
    
    
    If di_read(*imgfile, *buffer, 254) <> 254
      Debug "BAM Read failed"
      ProcedureReturn 0
    EndIf       
    ;/* Read directory blocks */
    While di_read(*imgfile, *buffer, 254) = 254
      
      ShowMemoryViewer(*buffer, 254)
      
      For offset = -2 To 253 Step 32               
        
        ; If file type != 0                     
        If *buffer\c[ offset+2 ]
          C64FileLen = di_name_from_rawname(*name, *buffer +  offset + 5)
          
          type    = *buffer\c[ offset + 2] & 7
          ftype   = Filetype_Get(type)
          
          ;cbmfile_read(*imgfile,@name.char, type)
          
          closed  = *buffer\c[offset + 2] & $80    ; // closed/locked file?
          locked  = *buffer\c[offset + 2] & $40    ; // closed/locked file?
          size    = *buffer\c[offset + 31] << 8 | *buffer\c[offset + 30]; // blocks size
          
          If closed : ftype = "*"+ftype: Else: ftype = " "+ftype: EndIf                       
          If locked : ftype + "<"      : Else: ftype + " "      : EndIf     
          
          ; /* Convert To ascii  */                       
          ptoa(*name)
          C64File.s = PeekS(*name, C64FileLen, #PB_Ascii )                       
          Debug C64File + ftype
        EndIf   
        
        ;Debug offset
      Next offset                               
    Wend                   
  EndProcedure   
  ;---------------------------------------------------------------------------------------------------------
  ;
  ;---------------------------------------------------------------------------------------------------------
  Procedure di_close(*imgfile.ImageFile)
    
    Define *p.UnsignedChar
    Static *tts.TrackSector
    
    Select *imgfile\mode
      Case "w"
        
        If (*imgfile\bufptr)
          
          If (*imgfile\diskimage\blocksfree)
            
            *tts = alloc_next_ts(*imgfile\diskimage, *imgfile\ts)
            
            *imgfile\nextts\sector = *tts\sector
            *imgfile\nextts\track = *tts\track
            
            If (*imgfile\ts\track = 0)
              *imgfile\rawdirentry\startts = *imgfile\nextts
            Else
              *p = get_ts_addr(*imgfile\diskimage, *imgfile\ts)
              *p\c[0] = *imgfile\nextts\track
              *p\c[1] = *imgfile\nextts\sector
            EndIf
            
            *imgfile\ts = *imgfile\nextts
            
            *p = get_ts_addr(*imgfile\diskimage, *imgfile\ts)
            *p\c[0] = 0
            *p\c[1] = $ff
            
            CopyMemory(*imgfile\buffer , *p + 2, 254)
            
            *imgfile\bufptr = 0
            
            If ( (*imgfile\rawdirentry\sizelo + 1) = 0 )                           
              *imgfile\rawdirentry\sizehi + 1
            EndIf
            
            *imgfile\diskimage\blocksfree - 1
            *imgfile\rawdirentry\type | $80                                             
          EndIf
        Else
          *imgfile\rawdirentry\type | $80                                                               
        EndIf
        
        FreeMemory(*imgfile\buffer)
    EndSelect
    
    *imgfile\diskimage\openfiles - 1
    FreeMemory(*imgfile)                         
  EndProcedure
  
  ;---------------------------------------------------------------------------------------------------------
  ; /* Close file */
  ;---------------------------------------------------------------------------------------------------------         
  Procedure.i vDSK_Close_Image(*imgfile.ImageFile)
    di_close(*imgfile)
    
  EndProcedure
  ;---------------------------------------------------------------------------------------------------------
  ; Return Disk Image Format
  ;---------------------------------------------------------------------------------------------------------         
  Procedure.s vDSK_Get_ImageFormat(*di.DiskImage)
    
    If ( *di = 0 ) Or ( *di = -1 ) Or ( *di = -2 )
      ProcedureReturn ""
    EndIf
    
    ProcedureReturn *di\Type
    
  EndProcedure     
  ;---------------------------------------------------------------------------------------------------------
  ; Return Disk Filename
  ;---------------------------------------------------------------------------------------------------------         
  Procedure.s vDSK_Get_Filename(*di.DiskImage, Fullpath.i = #False)
    
    If ( *di = 0 ) Or ( *di = -1 ) Or ( *di = -2 )
      ProcedureReturn ""
    EndIf
    
    Select Fullpath
      Case #False
        ProcedureReturn *di\filename
      Case #True
        ProcedureReturn *di\filepath + *di\filename
    EndSelect           
  EndProcedure         
  ;---------------------------------------------------------------------------------------------------------
  ; Return Free Blocks Of the C64 Disk Image
  ;---------------------------------------------------------------------------------------------------------         
  Procedure.i vDSK_Get_FreeBlocks(*di.DiskImage)
    
    If ( *di = 0 )
      ProcedureReturn 0
    ElseIf  ( *di = -1 )
      ProcedureReturn -1
    ElseIf  ( *di = -2 )           
      ProcedureReturn -2
    EndIf 
    
    ProcedureReturn *di\blocksfree
  EndProcedure         
  ;---------------------------------------------------------------------------------------------------------
  ; Get C64 Disk Image Title
  ;---------------------------------------------------------------------------------------------------------       
  Procedure.s vDSK_Get_TitleHead(*di.DiskImage)
    
    Protected TitleLenght.i = 0, Title.s = ""
    
    If ( *di = 0 ) Or ( *di = -1 ) Or ( *di = -2 )
      ProcedureReturn ""
    EndIf
    
    ;Convert title To ascii
    TitleLenght.i = di_name_from_rawname(@name.char, CBMDiskImage::di_title(*di) )
    
    ptoa(@name)
    
    Title.s = PeekS(@name, TitleLenght +1,#PB_Ascii )
    Title.s = LSet( Title.s, 16, Chr(32) )
    
    ProcedureReturn Title.s
  EndProcedure 
  ;---------------------------------------------------------------------------------------------------------
  ; Get C64 Disk Image ID
  ;---------------------------------------------------------------------------------------------------------       
  Procedure.s vDSK_Get_Title_ID(*di.DiskImage)
    
    Protected TitleLenght.i = 0, ident.s = ""
    
    If ( *di = 0 ) Or ( *di = -1 ) Or ( *di = -2 )
      ProcedureReturn ""
    EndIf
    
    CopyMemory(di_title(*di) +18 , @id.char, 5)    ; Convert ID To ascii
    
    ptoa(@id)
    
    ident.s = PeekS(@id, 4 +1,#PB_Ascii )
    
    ProcedureReturn ident.s       
  EndProcedure     
  ;---------------------------------------------------------------------------------------------------------
  ; Test BAM
  ;---------------------------------------------------------------------------------------------------------   
  Procedure vDSK_Test_BAM(*di.DiskImage)
    
    Protected FreeSector.i
    Debug "Track" +#TAB$+ "Free"+#TAB$+"Map"
    
    Static ts.TrackSector
    
    CurrenTrack = ts\track
    CurrenSectr = ts\sector
    
    For CurrenTrack = 1 To di_tracks( *di )           
      
      free.i =  di_track_blocks_free(*di, CurrenTrack)
      sect.i =  di_sectors_per_track(*di, CurrenTrack)           
      
      Free$ = ""
      For CurrenSectr = 0 To di_sectors_per_track(*di, CurrenTrack) -1
        ts\track   = CurrenTrack
        ts\sector  = CurrenSectr
        FreeSector = di_is_ts_free(*di, @ts)
        
        Select FreeSector
          Case 0
            Free$ + "*"
          Default
            Free$ + "-"                       
        EndSelect                       
      Next
      Debug " "+Str(CurrenTrack) + ":  "+#TAB$+ Str(free)+"/"+Str(sect) +#TAB$+ Free$
    Next       
    Debug ""
    Debug Str( *di\blocksfree ) + " blocks free"
    
    
  EndProcedure 
EndModule
;
; Beispiel 1

;   
; Load image INTO ram
;
*di = CBMDiskImage::di_load_image("B:\daten 2 - Kopie.d64")
;*di = CBMDiskImage::di_load_image("d:\Bernd\Extras\tmp\PureBasic\C64\V-1541.D64")

; Open directory For reading
;
*imgfile = CBMDiskImage::di_open(*di, '$', 2 ,"rb")
If ( *imgfile = 0 )
  Debug "Couldn't open directory"
  End
EndIf


;
;                   
; Convert title To ascii
Debug "| Disk   :" + CBMDiskImage::vDSK_Get_Filename(*di)
Debug "| Format :" + CBMDiskImage::vDSK_Get_ImageFormat(*di)
Debug "| --------------------------------| Disk ID |"
Debug "| Disk Name  :  0 " + Chr(34) + CBMDiskImage::vDSK_Get_TitleHead(*di) + Chr(34)  + " "+CBMDiskImage::vDSK_Get_Title_ID(*di)     
Debug "| Free Blocks: " + Str( CBMDiskImage::vDsk_Get_FreeBlocks(*di) ) 
Debug "| Test Bam   : " + #CRLF$
CBMDiskImage::vDSK_Test_BAM(*di)
CBMDiskImage::di_read_directory_blocks(*imgfile)       
Debug "| ---------------------------------------|" +#CRLF$+#CRLF$             




;
; Beispiel 2

*di = CBMDiskImage::di_load_image("B:\NEWIMAGE.d64")
*imgfile = CBMDiskImage::di_open(*di, '$', 2 ,"rb")
Debug "| Disk   :" + CBMDiskImage::vDSK_Get_Filename(*di)
Debug "| Format :" + CBMDiskImage::vDSK_Get_ImageFormat(*di)       
Debug "| --------------------------------| Disk ID |"
Debug "| Disk Name  :  0 " + Chr(34) + CBMDiskImage::vDSK_Get_TitleHead(*di) + Chr(34)  + " "+CBMDiskImage::vDSK_Get_Title_ID(*di)     
Debug "| Free Blocks: " + Str( CBMDiskImage::vDsk_Get_FreeBlocks(*di) )
Debug "| Test Bam   : " + #CRLF$
CBMDiskImage::vDSK_Test_BAM(*di)       
;CBMDiskImage::di_read_directory_blocks(*imgfile)
Debug "| ---------------------------------------|" +#CRLF$+#CRLF$

;
; Beispiel 3       
*di = CBMDiskImage::di_load_image("B:\FUR DIE SCHULE,DiskID-2A  1.d64")
*imgfile = CBMDiskImage::di_open(*di, '$', 2 ,"rb")
Debug "| Disk   :" + CBMDiskImage::vDSK_Get_Filename(*di)
Debug "| Format :" + CBMDiskImage::vDSK_Get_ImageFormat(*di)       
Debug "| --------------------------------| Disk ID |"
Debug "| Disk Name  :  0 " + Chr(34) + CBMDiskImage::vDSK_Get_TitleHead(*di) + Chr(34)  + " "+CBMDiskImage::vDSK_Get_Title_ID(*di)     
Debug "| Free Blocks: " + Str( CBMDiskImage::vDsk_Get_FreeBlocks(*di) ) 
Debug "| Test Bam   : " + #CRLF$
CBMDiskImage::vDSK_Test_BAM(*di)           
Debug "| ---------------------------------------|" +#CRLF$+#CRLF$
;         
; ;
; ; Beispiel 4       
*di = CBMDiskImage::di_load_image("B:\      NEWI  MAGE.D64")
*imgfile = CBMDiskImage::di_open(*di, '$', 2 ,"rb")
Debug "| Disk   :" + CBMDiskImage::vDSK_Get_Filename(*di)
Debug "| Format :" + CBMDiskImage::vDSK_Get_ImageFormat(*di)       
Debug "| --------------------------------| Disk ID |"
Debug "| Disk Name  :  0 " + Chr(34) + CBMDiskImage::vDSK_Get_TitleHead(*di) + Chr(34)  + " "+CBMDiskImage::vDSK_Get_Title_ID(*di)     
Debug "| Free Blocks: " + Str( CBMDiskImage::vDsk_Get_FreeBlocks(*di) )
Debug "| Test Bam   : " + #CRLF$
CBMDiskImage::vDSK_Test_BAM(*di)           
Debug "| ---------------------------------------|" +#CRLF$+#CRLF$
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by Marty2PB »

:oops: Thanks infratec :D

PS: Great, I'm watching over the source. Man, I did some things wrong. Many thanks for the help. Listing works.
Marty2PB
User
User
Posts: 47
Joined: Thu Mar 13, 2014 4:31 pm

Re: Language C to PB, Trying adapt D64,D71,D80 DiskImage Sou

Post by Marty2PB »

:mrgreen:

Image

I use a Font *.fon, converted from my Amiga 4000, "Fixplain 7.fnt" and Modified for CBM PetAscii

I Adding now Copy, Write and Format
Post Reply