Logo Search packages:      
Sourcecode: cbmlink version File versions  Download package

int ext ( const struct comm comm,
const struct hostinfo hostinfo,
const unsigned char *  code,
unsigned  length,
unsigned  device,
unsigned  secondary 
)

install a server extension

Parameters:
comm the communication primitives
hostinfo information on the remote host
code the extension code to be loaded
length length of the code in bytes
device device number
secondary secondary address
Returns:
zero on success, nonzero on error

work area for receiving a jump table

work area for patching the code

Definition at line 56 of file ext.c.

References B128, B256, bank, hostinfo::driver, hostinfo::host, JMP, JSR, jump(), LDA, LDX, LDY, load(), P500, and save().

Referenced by disk_install(), qdisk_install(), rdfile_install(), and wrfile_install().

{
  /** work area for receiving a jump table */
  unsigned char jmptab[24];
  /** work area for patching the code */
  unsigned char* buf;
  unsigned addr, i, bank, start;

  if (hostinfo->host == P500 ||
      hostinfo->host == B128 ||
      hostinfo->host == B256)
    bank = 15, start = 0x0600;
  else
    bank = 0, start = 0x1800;

  /* copy the jump table from the server */
  if (save (comm, bank, hostinfo->driver,
          hostinfo->driver + sizeof jmptab, jmptab))
    return 1;

  /* Check the consistency of the jump table */
  for (i = 0; i < sizeof jmptab && jmptab[i] == JMP; i += 3);

  /* All but the last entry must be jumps */
  if (i < (sizeof jmptab) - 3)
    return 2;

  if (i == (sizeof jmptab) - 3) {
    /* The last jump table entry is not a jump; change it to one */
    jmptab[i++] = JMP;
    addr = hostinfo->driver + ((sizeof jmptab) - 3);
    jmptab[i++] = addr;
    jmptab[i] = addr >> 8;
  }

  if (!(buf = malloc (length)))
    return 3; /* out of memory */
  
  /* copy the code in order to patch it */
  memcpy (buf, code, length);

  /* patch the jumps to the jump table */
  for (i = 0; i < length - 2; i++) {
    if ((buf[i] == JSR || buf[i] == JMP) && !buf[i + 2]) {
      addr = buf[i + 1];
      if (addr >= sizeof jmptab || (addr % 3))
      continue;
      buf[++i] = jmptab[addr + 1];
      buf[++i] = jmptab[addr + 2];
    }
  }

  /* find first lda#xx:ldx#xx:ldy#xx and patch it */
  for (i = 0; i < length - 6; i++) {
    if (buf[i] != LDA || buf[i + 2] != LDX || buf[i + 4] != LDY)
      continue;
    if (buf[i + 1] == buf[i + 3] && buf[i + 1] == buf[i + 5])
      buf[i + 3] = device, buf[i + 5] = secondary;
    break;
  }

  /* load the extension */
  if (load (comm, bank, start, start + length, buf)) {
    free (buf);
    return 4; /* load error */
  }

  free (buf);
  /* start the extension */
  if (jump (comm, bank, start))
    return 5;
  return 0;
}


Generated by  Doxygen 1.6.0   Back to index