* did not exist. If the parent existed, and parent is not null,
* parent will be filled in with the parents inoptr. Otherwise, parent
* will be set to NULL.
+ * The last node parsed is saved in lastname and is useful to some system
+ * calls as they want a parent and to create the new node.
*
* FIXME: ENAMETOOLONG might be good to add
*/
-#ifndef CONFIG_LEVEL_0
+char lastname[31];
+uint8_t n_open_fault;
+static char *name, *nameend;
-inoptr n_open(char *uname, inoptr *parent)
+static uint8_t getcf(void)
{
- inoptr r;
- char *tb;
-
- tb = (char*)pathbuf(); /* temporary memory to hold kernel's copy of the filename */
-
- if (ugets(uname, tb, 512) == -1) {
- udata.u_error = EFAULT;
- if (parent)
- *parent = NULLINODE;
- pathfree(tb);
- return NULLINODE;
+ int16_t c;
+ c = ugetc(name);
+ if (c == -1 || name == nameend) {
+ n_open_fault = 1;
+ return 0;
}
-
-#ifdef DEBUG
- kprintf("n_open(\"%s\")\n", tb);
-#endif
-
- r = kn_open(tb, parent);
-
- pathfree(tb);
-
- return r;
+ return (uint8_t)c;
}
-#endif
-inoptr kn_open(char *namep, inoptr *parent)
+inoptr n_open(char *namep, inoptr *parent)
{
staticfast inoptr wd; /* the directory we are currently searching. */
staticfast inoptr ninode;
inoptr temp;
- staticfast char *name;
+ uint8_t c;
+ char *fp;
name = namep;
+ n_open_fault = 0;
+ nameend = namep + 512; /* For now our pathmax is 512 */
+
#ifdef DEBUG
kprintf("kn_open(\"%s\")\n", name);
#endif
- if(*name == '/')
+ if(getcf() == '/')
wd = udata.u_root;
else
wd = udata.u_cwd;
if(ninode)
ninode = srch_mt(ninode);
- while(*name == '/') /* Skip(possibly repeated) slashes */
+ while((c = getcf()) == '/') /* Skip(possibly repeated) slashes */
++name;
- if(!*name) /* No more components of path? */
+ if(!c || n_open_fault) /* No more components of path? */
break;
if(!ninode){
udata.u_error = ENOENT;
goto nodir;
}
+ fp = lastname;
+ while(c = getcf()) {
+ if (c == '/')
+ break;
+ if (fp != lastname + 30)
+ *fp++ = c;
+ ++name;
+ }
+ *fp = 0;
/* See if we are going up through a mount point */
/* FIXME: re-order for speed */
if((wd == udata.u_root || (wd->c_num == ROOTINODE && wd->c_dev != root_dev)) &&
- name[0] == '.' && name[1] == '.' &&
- (name[2] == '/' || name[2] == '\0')){
+ fp[0] == '.' && fp[1] == '.' &&
+ (fp[2] == '/' || fp[2] == '\0')){
if (wd == udata.u_root) {
/* FIXME: is this assignment ever needed */
ninode = wd;
wd = temp;
}
- ninode = srch_dir(wd, name);
-
- while(*name != '/' && *name)
- ++name;
+ ninode = srch_dir(wd, lastname);
}
+ /* If we faulted then treat it as invalid */
+ if (n_open_fault)
+ goto nodir;
if(parent)
*parent = wd;
return true; // success
}
-
-
-/* Filename is given a path name in user space, and copies
- * the final component of it to name(in system space).
- */
-
-void filename(char *userspace_upath, char *name)
-{
- char *buf;
- char *ptr;
-
- buf = tmpbuf();
- if(ugets(userspace_upath, buf, 512) == -1) {
- tmpfree(buf);
- *name = '\0';
- return; /* An access violation reading the name */
- }
- ptr = buf;
- /* Find the end of the buffer */
- while(*ptr)
- ++ptr;
- /* Special case for "...name.../". SuS requires that mkdir foo/ works
- (see the clarifications to the standard) */
- if (*--ptr == '/')
- *ptr-- = 0;
- /* Walk back until we drop off the start of the buffer or find the
- slash */
- while(*ptr != '/' && ptr-- > buf);
- /* And move past the slash, or not the string start */
- ptr++;
- memcpy(name, ptr, FILENAME_LEN);
- tmpfree(buf);
-}
-
-
/* Namecomp compares two strings to see if they are the same file name.
* It stops at FILENAME_LEN chars or a null or a slash. It returns 0 for difference.
*/
/*
- * This is actually overlaid over a blkbuf holding the actual
- * record in question, and pinned until we umount the fs.
+ * Superblock structure
*/
#define FILESYS_TABSIZE 50
typedef struct filesys { // note: exists in mem and on disk
blkno_t s_tfree;
uint16_t s_tinode;
inoptr s_mntpt; /* Mount point */
+ /* TODO: Add geometry hints and support > 512 byte blocks */
} filesys, *fsptr;
typedef struct oft {
uint16_t m_flags;
struct filesys m_fs;
};
-/* The flags are not yet fully implemented */
#define MS_RDONLY 1
-#define MS_NOSUID 2
+#define MS_NOSUID 2 /* Not yet implemented */
#define MS_REMOUNT 128
/* Process table p_status values */
/* 0 is used to mean 'check we could signal this process' */
-/* FIXME: finish signal handling */
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define ugetw(a) (*(uint8_t *)(a))
#define uputc(v, p) ((*(uint8_t*)(p) = (v)) && 0)
#define uputw(v, p) ((*(uint16_t*)(p) = (v)) && 0)
-#define ugets(a,b,c) ((int)(strlcpy(b,a,c) && 0))
#define uzero(a,b) (memset(a,0,b) && 0)
#else
extern usize_t valaddr(const char *base, usize_t size);
extern int16_t ugetc(const void *userspace_source);
extern uint16_t ugetw(const void *userspace_source);
extern uint32_t _ugetl(void *uaddr);
-extern int ugets(const void *userspace_source, void *dest, usize_t maxlen);
extern int uput (const void *source, void *userspace_dest, usize_t count);
extern int uputc(uint16_t value, void *userspace_dest); /* u16_t so we don't get wacky 8bit stack games */
extern int uputw(uint16_t value, void *userspace_dest);
/* usermem.c or usermem_std.s */
extern usize_t _uget(const uint8_t *user, uint8_t *dst, usize_t count);
extern int _uput(const uint8_t *source, uint8_t *user, usize_t count);
-extern int _ugets(const uint8_t *user, uint8_t *dest, usize_t maxlen);
extern int _uzero(uint8_t *user, usize_t count);
#if defined CONFIG_USERMEM_DIRECT
/* filesys.c */
/* open file, "name" in user address space */
-#ifndef CONFIG_LEVEL_0
+extern char lastname[31];
extern inoptr n_open(char *uname, inoptr *parent);
-#else
-#define n_open kn_open
-#endif
-/* open file, "name" in kernel address space */
-extern inoptr kn_open(char *uname, inoptr *parent);
extern inoptr i_open(uint16_t dev, uint16_t ino);
extern inoptr srch_dir(inoptr wd, char *compname);
extern inoptr srch_mt(inoptr ino);
extern bool ch_link(inoptr wd, char *oldname, char *newname, inoptr nindex);
-extern void filename(char *userspace_upath, char *name);
/* return true if n1 == n2 */
extern bool namecomp(char *n1, char *n2);
extern inoptr newfile(inoptr pino, char *name);
extern uint8_t jobcontrol_ioctl(uint8_t minor, struct tty *tty, uarg_t request);
extern int tcsetpgrp(struct tty *tty, char *data);
-/* Platform must implement according to its PATH_MAX and allocators. If
- you are using a 512 byte path limit then calling tmpbuf() and brelse()
- is sufficient */
-extern char *pathbuf(void);
-extern void pathfree(char *p);
-
/* The first half of this always gets used with a constant so using a macro
turns the whole thing into a constant 32bit comparison with a fixed
or global register memory address */
.globl sigdispatch
.globl _ugetc
.globl _ugetw
- .globl _ugets
.globl _uget
.globl _uputc
.globl _uputw
;
; D = src, 2(s) = dest, 4(s) = size
;
-_ugets:
- tsx
- xgdy ; D was src, we want it in Y
- ldd 4,x ; size
- std tmp1 ; in tmp1
- ldx 2,x ; destination in X
- clrb ; 0 = kernel
- ldaa usrbank ; user space
- jmp farzcopy ; returns error/size in D
-;
-; D = src, 2(s) = dest, 4(s) = size
-;
_uget:
tsx
xgdy ; D was src, we want it in Y
.globl __ugetc
.globl __ugetw
.globl __uget
- .globl __ugets
.globl __uputc
.globl __uputw
.globl __uput
jsr map_kernel
puls u,y,pc
-__ugets:
- pshs u,y
- ldu 6,s ; user address
- ldy 8,s ; count
- jsr map_process_always
-ugetsl:
- lda ,x+
- beq ugetse
- sta ,u+
- leay -1,y
- bne ugetsl
- jsr map_kernel
- ldx #0xffff ; unterminated - error
- lda #0
- sta -1,u ; force termination
- puls u,y,pc
-ugetse:
- sta ,u
- ldx #0
- jsr map_kernel
- puls u,y,pc
-
-
__uputc:
ldd 2,s
jsr map_process_always
}
return 0;
}
-
-#ifdef CONFIG_LEVEL_2
-
-/* We always use 512 byte paths so no special pathbuf needed */
-
-char *pathbuf(void)
-{
- return tmpbuf();
-}
-
-void pathfree(char *tb)
-{
- tmpfree(tb);
-}
-
-#endif
.globl __ugetc
.globl __ugetw
.globl __uget
- .globl __ugets
.globl __uputc
.globl __uputw
.globl __uput
ldx #0
puls u,y,cc,pc
-__ugets:
- pshs u,y,cc
- ldu 7,s ; user address
- ldy 9,s ; count
- orcc #0x10
-ugetsl:
- jsr map_process_always
- lda ,x+
- beq ugetse
- jsr map_kernel
- sta ,u+
- leay -1,y
- bne ugetsl
- ldx #0xffff ; unterminated - error
- lda #0
- sta -1,u ; force termination
- puls u,y,cc,pc
-ugetse:
- jsr map_kernel
- sta ,u
- ldx #0
- puls u,y,cc,pc
-
-
__uputc:
pshs cc
orcc #0x10
.globl __ugetc
.globl __ugetw
.globl __uget
- .globl __ugets
.globl __uputc
.globl __uputw
ldx #0
puls u,y,cc,pc
-__ugets:
- pshs u,y,cc
- ldu 7,s ; user address
- ldy 9,s ; count
- orcc #0x10
-ugetsl:
- jsr map_process_always
- lda ,x+
- beq ugetse
- jsr map_kernel
- sta ,u+
- leay -1,y
- bne ugetsl
- ldx #0xffff ; unterminated - error
- lda #0
- sta -1,u ; force termination
- puls u,y,cc,pc
-ugetse:
- jsr map_kernel
- sta ,u
- ldx #0
- puls u,y,cc,pc
-
-
__uputc:
pshs cc
orcc #0x10
.globl __ugetc
.globl __ugetw
.globl __uget
- .globl __ugets
.globl __uputc
.globl __uputw
.globl __uput
ldx #0
puls u,y,cc,pc
-__ugets:
- pshs u,y,cc
- ldu 7,s ; user address
- ldy 9,s ; count
- orcc #0x10
-ugetsl:
- SAM_USER
- lda ,x+
- beq ugetse
- SAM_KERNEL
- sta ,u+
- leay -1,y
- bne ugetsl
- ldx #0xffff ; unterminated - error
- lda #0
- sta -1,u ; force termination
- puls u,y,cc,pc
-ugetse:
- SAM_KERNEL
- sta ,u
- ldx #0
- puls u,y,cc,pc
-
-
__uputc:
pshs cc
orcc #0x10
.globl __ugetc
.globl __ugetw
.globl __uget
- .globl __ugets
.globl __uputc
.globl __uputw
.globl __uput
ldx #0
puls u,y,cc,pc
-__ugets:
- pshs u,y,cc
- ldu 7,s ; user address
- ldy 9,s ; count
- orcc #0x10
-ugetsl:
- jsr map_process_always
- lda ,x+
- beq ugetse
- jsr map_kernel
- sta ,u+
- leay -1,y
- bne ugetsl
- ldx #0xffff ; unterminated - error
- lda #0
- sta -1,u ; force termination
- puls u,y,cc,pc
-ugetse:
- jsr map_kernel
- sta ,u
- ldx #0
- puls u,y,cc,pc
-
-
__uputc:
pshs cc
orcc #0x10
; exported symbols
.globl __uget
.globl __ugetc
- .globl __ugets
.globl __ugetw
.globl __uput
jr nz, nextbyte
jr ugetputret
-__ugets:
- push ix
- ld ix, #0 ; load ix with stack pointer
- add ix, sp
- ; store interrupt state, disable interrupts
- ld a, i
- di
- push af
- ; load DE with source address (in userspace)
- ld e, 4(ix)
- ld d, 5(ix)
- call ugetputsetup
- ; load HL with destination address
- ld l, 6(ix)
- ld h, 7(ix)
- ; load DE with the byte count
- ld e, 8(ix) ; byte count
- ld d, 9(ix)
- ; read from page17, write to HL for AT MOST DE bytes or until 0 byte found
- ld bc, #MMU_PAGE17 ; also loads B=0
- jr checkzeros
-nextbytes:
- in a, (c) ; read from page17
- ld (hl), a ; write to string
- or a
- jr z, getsdone
- inc hl ; advance pointer
- dec de ; decrement remaining byte counter
-checkzeros:
- ld a, d
- or e
- jr nz, nextbytes
- ; ah - we've run out of space
- dec hl ; back it up
- ld (hl), #0 ; terminate string
- ; leave HL as nonzero
- jp ugetputret ; too far for a jr
-getsdone:
- ld hl, #0 ; indicate success
- jp ugetputret ; too far for a jr
hd_sdh = 0xA0 | (minor << 3);
hd_cmd = HDCMD_RESTORE | RATE_2MS;
} else {
- hd_sdh = 0x38 | minor << 1;
+ hd_sdh = 0x38 | ((minor - MAX_HD) << 1);
hd_cmd = HDCMD_RESTORE | RATE_6MS;
}
if (hd_waitready() & 1) {
{
return 0;
}
-
-char *pathbuf(void)
-{
- return tmpbuf();
-}
-
-void pathfree(char *p)
-{
- tmpfree(p);
-}
return 0;
}
-#ifdef CONFIG_LEVEL_2
-
-/* We always use 512 byte paths so no special pathbuf needed */
-
-char *pathbuf(void)
-{
- return tmpbuf();
-}
-
-void pathfree(char *tb)
-{
- tmpfree(tb);
-}
-
-#endif
nenvp = wargs((char *) (nargv), ebuf, NULL);
// Fill in udata.u_name with program invocation name
- ugets((void *) ugetw(nargv), udata.u_name, 8);
+ uget((void *) ugetw(nargv), udata.u_name, 8);
memcpy(udata.u_ptab->p_name, udata.u_name, 8);
tmpfree(abuf);
udata.u_error = 0;
- ino = kn_open("core", &parent);
+ /* FIXME: need to think more about the case sp is lala */
+ if (uput("core", udata.u_syscall_sp - 5, 5))
+ return 0;
+
+ ino = n_open(udata.u_syscall_sp - 5, &parent);
if (ino) {
i_deref(parent);
return 0;
inoptr ino;
inoptr pino;
int r;
- char fname[FILENAME_LEN + 1];
ino = n_open(path, &pino);
udata.u_error = ENOENT;
return (-1);
}
- filename(path, fname);
- r = unlinki(ino, pino, fname);
+ r = unlinki(ino, pino, lastname);
i_deref(pino);
i_deref(ino);
return r;
{
inoptr ino;
inoptr parent;
- char fname[FILENAME_LEN + 1];
udata.u_error = 0;
return (-1);
}
- filename(name, fname);
- ino = newfile(parent, fname);
+ ino = newfile(parent, lastname);
if(!ino)
goto nogood3; /* parent inode is derefed in newfile. SN */
staticfast inoptr ino;
int16_t perm;
staticfast inoptr parent;
- char fname[FILENAME_LEN + 1];
int trunc;
int r;
int w;
udata.u_error = ENOENT;
goto cantopen;
}
- filename(name, fname);
-
/* newfile drops parent for us */
- ino = newfile(parent, fname);
+ ino = newfile(parent, lastname);
if (!ino) {
/* on error, newfile sets udata.u_error */
goto cantopen;
inoptr ino;
inoptr ino2;
inoptr parent2;
- char fname[FILENAME_LEN + 1];
if (!(ino = n_open(name1, NULLINOPTR)))
return (-1);
goto nogood;
}
- filename(name2, fname);
-
- if (!ch_link(parent2, "", fname, ino)) {
+ if (!ch_link(parent2, "", lastname, ino)) {
i_deref(parent2);
goto nogood;
}
i_deref(srcp);
return -1;
}
+ /* Save the source name */
+ memcpy(fname, lastname, FILENAME_LEN + 1);
/* n_open will wipe u_rename if it walks that inode
so it tells us whether we are trying to create a loop */
udata.u_rename = srci;
/* Destination maybe does not exist, but parent must */
- filename(dst, fname);
dsti = n_open(dst, &dstp);
+ /* lastname now holds destination name element */
/* Same file - do nothing */
if (dsti == srci) {
ret = 0;
udata.u_error = EISDIR;
goto nogood;
}
- if (unlinki(dsti, dstp, fname) == -1)
+ if (unlinki(dsti, dstp, lastname) == -1)
goto nogood;
/* Drop the reference to the unlinked file */
i_deref(dsti);
}
/* Ok we may proceed: we set up fname earlier */
- if (!ch_link(dstp, "", fname, srci))
+ if (!ch_link(dstp, "", lastname, srci))
goto nogood2;
- filename(src, fname);
/* A fail here is bad */
if (!ch_link(srcp, fname, "", NULLINODE)) {
kputs("WARNING: rename: unlink fail\n");
goto nogood2;
}
- filename(name, fname);
-
i_ref(parent); /* We need it again in a minute */
- if (!(ino = newfile(parent, fname))) {
+ if (!(ino = newfile(parent, lastname))) {
i_deref(parent);
goto nogood2; /* parent inode is derefed in newfile. */
}
#ifndef CONFIG_LEVEL_0
inoptr ino;
inoptr parent;
- char fname[FILENAME_LEN + 1];
ino = n_open(path, &parent);
goto nogood;
/* Remove the directory entry */
- filename(path, fname);
- if (!ch_link(parent, fname, "", NULLINODE))
+ if (!ch_link(parent, lastname, "", NULLINODE))
goto nogood;
/* We are unused, parent is now one link down (removal of ..) */
/* Decrease the link count of the parent inode */
if (!(parent->c_node.i_nlink--)) {
parent->c_node.i_nlink += 2;
- kprintf("_rmdir: bad nlink\n");
+ kputs("_rmdir: bad nlink\n");
}
setftime(ino, C_TIME);
wr_inode(parent);
return _ugetw(user);
}
-/* ugets is a bit odd - we don't know the length of the passed string
- so we trim to the end of the allowed memory and if we don't find a
- \0 in time we error */
-int ugets(const void *user, void *dest, usize_t maxlen)
-{
- int ret;
- maxlen = valaddr(user, maxlen);
- if (!maxlen)
- return -1;
- ret = _ugets(user, dest, maxlen);
- if (ret == -1)
- udata.u_error = EFAULT;
- return ret;
-}
-
int uput(const void *source, void *user, usize_t count)
{
if (!valaddr(user, count))
return tmp;
}
-int _ugets(const uint8_t *user, uint8_t *dest, usize_t count)
-{
- uint8_t tmp;
- while(count--) {
- BANK_PROCESS;
- tmp = *user++;
- BANK_KERNEL;
- *dest++ = tmp;
- if (tmp == '\0')
- return 0;
- }
- /* Ensure terminated */
- dest[-1] = '\0';
- return -1;
-}
-
int _uput(const uint8_t *source, uint8_t *user, usize_t count)
{
uint8_t tmp;
return 0;
}
-int _ugets(const uint8_t *user, uint8_t *dest, usize_t count)
-{
- while(count--) {
- *dest = *user++;
- if (*dest == '\0')
- return 0;
- dest++;
- }
- /* Ensure terminated */
- dest[-1] = '\0';
- return -1;
-}
-
int _uput(const uint8_t *source, uint8_t *user, usize_t count)
{
memcpy(user, source, count);
.include "kernel02.def"
.include "platform/zeropage.inc"
- .export __uget, __ugetc, __ugetw, __ugets
+ .export __uget, __ugetc, __ugetw
.export __uput, __uputc, __uputw, __uzero
.import map_kernel, map_process_always
tax
rts
-__ugets: sta tmp2
- stx tmp2+1 ; save the count
- jsr popax ; pop the destination
- sta ptr2 ; (ptr2) is our target
- stx ptr2+1
- jsr popax ; (ptr2) is our source
- sta ptr3
- stx ptr3+1
-
- ldy #0 ; counter
-
- ldx tmp2+1 ; how many 256 byte blocks
- beq __ugets_tail ; if none skip to the tail
-
-__ugets_blk:
- jsr map_process_always ; map the user process in
- lda (ptr3), y ; get a byte of user data
- beq __ugets_end
- jsr map_kernel ; map the kernel back in
- sta (ptr2), y ; save it to the kernel buffer
- iny ; move on one
- bne __ugets_blk ; not finished a block ?
- inc ptr3+1 ; move src ptr 256 bytes on
- inc ptr2+1 ; move dst ptr the same
- dex ; one less block to do
- bne __ugets_blk ; out of blocks ?
-
-__ugets_tail: cpy tmp2 ; finished ?
- beq __ugets_bad
-
- jsr map_process_always ; map the user process
- lda (ptr3),y ; get a byte of user data
- beq __ugets_end
- jsr map_kernel ; map the kernel back in
- sta (ptr2),y ; save it to the kernel buffer
- iny ; move on
- bne __ugets_tail ; always taken (y will be non zero)
-
-__ugets_bad:
- dey
- lda #0
- sta (ptr2), y ; terminate kernel buffer
- lda #$FF ; string too large
- tax ; return $FFFF
- rts
-
-__ugets_end:
- jsr map_kernel
- lda #0
- sta (ptr2), y
- tax
- rts
-
__ugetc: sta ptr2
stx ptr2+1
__uget_ptr2:
.include "kernel816.def"
.include "platform/zeropage.inc"
- .export __uget, __ugetc, __ugetw, __ugets
+ .export __uget, __ugetc, __ugetw
.export __uput, __uputc, __uputw, __uzero
.import outxa, popax
tax
rts
-;
-; This could be done more nicely using .i16 and wants optimizing
-;
-__ugets:
- sta tmp2
- stx tmp2+1 ; save the count
- jsr popax ; pop the destination
- sta ptr2 ; (ptr2) is our target
- stx ptr2+1
- jsr popax ; (ptr2) is our source
- sta ptr3
- stx ptr3+1
-
- ldy #0 ; counter
-
- ldx tmp2+1 ; how many 256 byte blocks
- beq __ugets_tail ; if none skip to the tail
-
-__ugets_blk:
- phb
- lda U_DATA__U_PAGE ; switch to user bank read
- pha
- plb
- lda (ptr3), y ; get a byte of user data
- beq __ugets_end
- plb ; back to kernel
- sta (ptr2), y ; save it to the kernel buffer
- iny ; move on one
- bne __ugets_blk ; not finished a block ?
- inc ptr3+1 ; move src ptr 256 bytes on
- inc ptr2+1 ; move dst ptr the same
- dex ; one less block to do
- bne __ugets_blk ; out of blocks ?
-
-__ugets_tail:
- cpy tmp2 ; finished ?
- beq __ugets_bad
-
- phb
- lda U_DATA__U_PAGE
- pha
- plb
- lda (ptr3),y ; get a byte of user data
- beq __ugets_end
- plb
- sta (ptr2),y ; save it to the kernel buffer
- iny ; move on
- bne __ugets_tail ; always taken (y will be non zero)
-
-__ugets_bad:
- dey
- lda #0
- sta (ptr2), y ; terminate kernel buffer
- lda #$FF ; string too large
- tax ; return $FFFF
- rts
-
-__ugets_end:
- plb
- lda #0
- sta (ptr2), y
- tax
- rts
-
__ugetc:
sta ptr2
stx ptr2+1
; exported symbols
.globl __uget
.globl __ugetc
- .globl __ugets
.globl __ugetw
.globl outcharhex
jr nz, uget_l
jr uput_out
-__ugets:
- push ix
- ld ix, #0
- add ix, sp
- call uputget ; source in HL dest in DE, count in BC
- jr z, ugets_bad ; but count is at this point magic
-
-ugets_l:
- call map_process_save
- ld a, (hl)
- inc hl
- call map_kernel_restore
- ld (de), a
- or a
- jr z, ugets_good
- inc de
- djnz ugets_l
- dec c
- jr nz, ugets_l
- dec de
- xor a
- ld (de), a
-ugets_bad:
- ld hl, #0xFFFF ; flag an error
- jr uput_out
-ugets_good:
- ld hl,#0
- jr uput_out
-
;
__uzero:
pop iy
; exported symbols
.globl __uget
.globl __ugetc
- .globl __ugets
.globl __ugetw
.globl outcharhex
jr nz, uget_l
jr uput_out
-__ugets:
- push ix
- ld ix, #0
- add ix, sp
- call uputget ; source in HL dest in DE, count in BC
- jr z, ugets_bad ; but count is at this point magic
-
-ugets_l:
- call map_process_always
- ld a, (hl)
- inc hl
- call map_kernel
- ld (de), a
- or a
- jr z, ugets_good
- inc de
- djnz ugets_l
- dec c
- jr nz, ugets_l
- dec de
- xor a
- ld (de), a
-ugets_bad:
- ld hl, #0xFFFF ; flag an error
- jr uput_out
-ugets_good:
- ld hl,#0
- jr uput_out
-
;
__uzero:
pop de ; return