--- /dev/null
+descr
+boot.s
+pmfile
+README
+include/ack/config.h
+include/unistd.h
+libsys/pmfile
+libsys/_hol0.s
+libsys/brk.c
+libsys/close.c
+libsys/creat.c
+libsys/errno.s
+libsys/getpid.c
+libsys/isatty.c
+libsys/kill.c
+libsys/libsys.h
+libsys/lseek.c
+libsys/open.c
+libsys/read.c
+libsys/signal.c
+libsys/time.c
+libsys/write.c
+libsys/_sys_rawread.s
+libsys/_sys_rawwrite.s
--- /dev/null
+# $Source$
+# $State$
+# $Revision$
+
+
+The NES platform
+=================
+
+NES is a platform for the Nintendo Entertainment System.
+
+Example command line
+====================
+
+ack -mnes -O -o nes.img examples/paranoia.c
+
--- /dev/null
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+
+
+start2:
+ jmp _main
+
+.define __exit
+.extern __exit
+.define EXIT
+.extern EXIT
+__exit:
+EXIT:
+
+.define begtext, begdata, begbss
+.sect .data; begdata:
+.sect .rom; begrom:
+.sect .bss; begbss:
+
+! Some magic data. All EM systems need these.
+
+.define .trppc, .ignmask, _errno
+.comm .trppc, 4
+.comm .ignmask, 4
+.comm _errno, 4
--- /dev/null
+# $Source$
+# $State$
+# $Revision$
+
+var w=2
+var p=2
+var s=2
+var l=4
+var f=4
+var d=8
+var ARCH=6500
+var PLATFORM=nes
+var PLATFORMDIR={EM}/lib/{PLATFORM}
+var CPP_F=
+var ALIGN=-a0:1 -a1:1 -a2:1 -a3:1
+var MACHOPT_F=-m8
+
+# Override the setting in fe so that files compiled for linux386 can see
+# the platform-specific headers.
+
+var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/include/ansi
+
+name be
+ from .m.g
+ to .s
+ program {EM}/lib.bin/{PLATFORM}/ncg
+ args <
+ stdout
+ need .e
+end
+name as
+ from .s.so
+ to .o
+ program {EM}/lib.bin/{PLATFORM}/as
+ args - -o > <
+ prep cond
+end
+name led
+ from .o.a
+ to .out
+ program {EM}/lib.bin/em_led
+ mapflag -l* LNAME={PLATFORMDIR}/lib*
+ mapflag -i SEPID=-b1:0
+ mapflag -fp FLOATS={EM}/{ILIB}fp
+ args {ALIGN} {SEPID?} \
+ (.e:{HEAD}={PLATFORMDIR}/boot.o) \
+ ({RTS}:.ocm.b={PLATFORMDIR}/c-ansi.o) \
+ ({RTS}:.c={PLATFORMDIR}/c-ansi.o) \
+ ({RTS}:.mod={PLATFORMDIR}/modula2.o) \
+ ({RTS}:.p={PLATFORMDIR}/pascal.o) \
+ -o > < \
+ (.p:{TAIL}={PLATFORMDIR}/libpascal.a) \
+ (.b:{TAIL}={PLATFORMDIR}/libbasic.a) \
+ (.mod:{TAIL}={PLATFORMDIR}/libmodula2.a) \
+ (.ocm:{TAIL}={PLATFORMDIR}/liboccam.a) \
+ (.ocm.b.mod.c.p:{TAIL}={PLATFORMDIR}/libc.a) \
+ {FLOATS?} \
+ (.e:{TAIL}={PLATFORMDIR}/libem.a \
+ {PLATFORMDIR}/libsys.a \
+ {PLATFORMDIR}/libend.a)
+ linker
+end
+name cv
+ from .out
+ to .img
+ program {EM}/bin/aslod
+ args < >
+ outfile nes.img
+end
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#ifndef _ACK_CONFIG_H
+#define _ACK_CONFIG_H
+
+/* We're providing a time() system call rather than wanting a wrapper around
+ * gettimeofday() in the libc. */
+
+#define ACKCONF_TIME_IS_A_SYSCALL
+
+#endif
--- /dev/null
+/*
+ * unistd.h - standard system calls
+ */
+/* $Id$ */
+
+#ifndef _UNISTD_H
+#define _UNISTD_H
+
+#include <stddef.h>
+
+/* Types */
+
+typedef int pid_t;
+typedef int mode_t;
+
+/* Constants for file access (open and friends) */
+
+enum
+{
+ O_ACCMODE = 0x3,
+
+ O_RDONLY = 0,
+ O_WRONLY = 1,
+ O_RDWR = 2,
+
+ O_CREAT = 0100,
+ O_TRUNC = 01000,
+ O_APPEND = 02000,
+ O_NONBLOCK = 04000
+};
+
+/* Special variables */
+
+extern char** environ;
+
+/* Implemented system calls */
+
+extern void _exit(int);
+extern pid_t getpid(void);
+extern void* sbrk(intptr_t increment);
+extern int isatty(int d);
+extern off_t lseek(int fildes, off_t offset, int whence);
+extern int close(int d);
+extern int open(const char* path, int access, ...);
+extern int creat(const char* path, mode_t mode);
+extern int read(int fd, void* buffer, size_t count);
+extern int write(int fd, void* buffer, size_t count);
+
+/* Unimplemented system calls (these are just prototypes to let the library
+ * compile). */
+
+extern int fcntl(int fd, int op, ...);
+
+/* Signal handling */
+
+typedef int sig_atomic_t;
+
+#define SIG_ERR ((sighandler_t) -1) /* Error return. */
+#define SIG_DFL ((sighandler_t) 0) /* Default action. */
+#define SIG_IGN ((sighandler_t) 1) /* Ignore signal. */
+
+#define SIGABRT 6 /* Abort (ANSI) */
+#define SIGILL 11 /* Illegal instruction */
+
+#define _NSIG 32 /* Biggest signal number + 1
+ (not including real-time signals). */
+typedef void (*sighandler_t)(int);
+extern sighandler_t signal(int signum, sighandler_t handler);
+extern int raise(int signum);
+
+#endif
--- /dev/null
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .bss
+
+! This data block is used to store information about the current line number
+! and file.
+
+.define hol0
+.comm hol0, 8
--- /dev/null
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+
+! Reads a single byte.
+
+.define __sys_rawread
+__sys_rawread:
+ xorb ah, ah
+ int 0x16
+ xorb ah, ah
+ ret
+
\ No newline at end of file
--- /dev/null
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+.sect .text
+
+! Writes a single byte to the console.
+
+.define __sys_rawwrite
+.extern __sys_rawwrite
+
+__sys_rawwrite:
+ push bp
+ mov bp, sp
+
+ movb al, 4(bp)
+ movb ah, 0x0E
+ mov bx, 0x0007
+ int 0x10
+ jmp .cret
+
\ No newline at end of file
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#define OUT_OF_MEMORY (void*)(-1) /* sbrk returns this on failure */
+#define STACK_BUFFER 128 /* number of bytes to leave for stack */
+
+extern char _end[1];
+static char* current = _end;
+
+int brk(void* newend)
+{
+ /* This variable is used to figure out the current stack pointer,
+ * by taking its address. */
+ char dummy;
+ char* p = newend;
+
+ if ((p > (&dummy - STACK_BUFFER)) ||
+ (p < _end))
+ return -1;
+
+ current = p;
+ return 0;
+}
+
+void* sbrk(intptr_t increment)
+{
+ char* old;
+
+ if (increment == 0)
+ return current;
+
+ old = current;
+ if (brk(old + increment) < 0)
+ return OUT_OF_MEMORY;
+
+ return old;
+}
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+int close(int fd)
+{
+ errno = EBADF;
+ return -1;
+}
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include "libsys.h"
+
+int open(const char* path, int access, ...)
+{
+ errno = EACCES;
+ return -1;
+}
--- /dev/null
+#
+! $Source$
+! $State$
+! $Revision$
+
+! Declare segments (the order is important).
+
+.sect .text
+.sect .rom
+.sect .data
+.sect .bss
+
+#define D(e) .define e; e
+
+.sect .data
+
+! Define various ACK error numbers. Note that these are *not* ANSI C
+! errnos, and are used for different purposes.
+
+D(ERANGE) = 1
+D(ESET) = 2
+D(EIDIVZ) = 6
+D(EHEAP) = 17
+D(EILLINS) = 18
+D(EODDZ) = 19
+D(ECASE) = 20
+D(EBADMON) = 25
+
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+pid_t getpid(void)
+{
+ return 0;
+}
--- /dev/null
+int hello(void)
+{
+ return 42;
+}
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+int isatty(int fd)
+{
+ return 1;
+}
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+int kill(pid_t pid, int sig)
+{
+ errno = EINVAL;
+ return -1;
+}
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#ifndef LIBSYS_H
+#define LIBSYS_H
+
+extern void _sys_rawwrite(unsigned char b);
+extern unsigned char _sys_rawread(void);
+
+extern void _sys_write_tty(char c);
+
+/* extern int _sys_ttyflags; */
+
+#endif
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+off_t lseek(int fd, off_t offset, int whence)
+{
+ errno = EINVAL;
+ return -1;
+}
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include "libsys.h"
+
+int creat(const char* path, int mode)
+{
+ return open(path, O_CREAT|O_WRONLY|O_TRUNC, mode);
+}
--- /dev/null
+-- $Source$
+-- $State$
+-- $Revision$
+
+local d = ROOTDIR.."plat/nes/libsys/"
+
+libsys_nes = acklibrary {
+ ACKBUILDFLAGS = {PARENT, "-ansi"},
+ ACKINCLUDES = {"%BINDIR%include"},
+
+-- ackfile (d.."errno.s"),
+-- ackfile (d.."_hol0.s"),
+-- ackfile (d.."_sys_rawread.s"),
+-- ackfile (d.."_sys_rawwrite.s"),
+-- ackfile (d.."open.c"),
+-- ackfile (d.."creat.c"),
+-- ackfile (d.."close.c"),
+-- ackfile (d.."read.c"),
+-- ackfile (d.."write.c"),
+-- ackfile (d.."brk.c"),
+-- ackfile (d.."getpid.c"),
+-- ackfile (d.."kill.c"),
+-- ackfile (d.."isatty.c"),
+-- ackfile (d.."lseek.c"),
+-- ackfile (d.."time.c"),
+-- ackfile (d.."signal.c"),
+
+ ackfile (d.."hello.c"),
+
+ install = pm.install("%BINDIR%lib/%PLATFORM%/libsys.a"),
+}
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include "libsys.h"
+
+int read(int fd, void* buffer, size_t count)
+{
+ char i;
+
+ /* We're only allowed to read from fd 0, 1 or 2. */
+
+ if ((fd < 0) || (fd > 2))
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ /* Empty buffer? */
+
+ if (count == 0)
+ return 0;
+
+ /* Read one byte. */
+
+ i = _sys_rawread();
+#if 0
+ if ((i == '\r') && !(_sys_ttyflags & RAW))
+ i = '\n';
+ if (_sys_ttyflags & ECHO)
+ _sys_write_tty(i);
+#endif
+ if (i == '\r')
+ i = '\n';
+ _sys_write_tty(i);
+
+ *(char*)buffer = i;
+ return 1;
+}
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+#include "libsys.h"
+
+sighandler_t signal(int signum, sighandler_t handler)
+{
+ return SIG_DFL;
+}
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <time.h>
+#include "libsys.h"
+
+time_t time(time_t* t)
+{
+ if (t)
+ *t = 0;
+ return 0;
+}
--- /dev/null
+/* $Source$
+ * $State$
+ * $Revision$
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include "libsys.h"
+
+void _sys_write_tty(char c)
+{
+ _sys_rawwrite(c);
+#if 0
+ if ((c == '\n') && !(_sys_ttyflags & RAW))
+ _sys_rawwrite('\r');
+#endif
+ if (c == '\n')
+ _sys_rawwrite('\r');
+}
+
+int write(int fd, void* buffer, size_t count)
+{
+ int i;
+ char* p = buffer;
+
+ /* We're only allowed to write to fd 0, 1 or 2. */
+
+ if ((fd < 0) || (fd > 2))
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ /* Write all data. */
+
+ i = 0;
+ while (i < count)
+ {
+ _sys_write_tty(*p++);
+
+ i++;
+ }
+
+ /* No failures. */
+
+ return count;
+}
--- /dev/null
+-- $Source$
+-- $State$
+-- $Revision$
+
+local d = ROOTDIR.."plat/nes/"
+
+include (d.."libsys/pmfile")
+
+local bootsector = ackfile {
+ file (d.."boot.s"),
+ install = pm.install("%BINDIR%lib/nes/boot.o"),
+}
+
+local descr = group {
+ install = pm.install(d.."descr", "%BINDIR%%PLATIND%/%PLATFORM%/descr")
+}
+
+local headers = group {
+ install = {
+ pm.install(d.."include/ack/config.h", "%BINDIR%%PLATIND%/%PLATFORM%/include/ack/config.h"),
+ pm.install(d.."include/unistd.h", "%BINDIR%%PLATIND%/%PLATFORM%/include/unistd.h"),
+ }
+}
+
+platform_nes = group {
+ ARCH = "6500",
+ PLATFORM = "nes",
+ OPTIMISATION = "-O",
+
+ -- Ensure the descr and headers are installed first because we'll need
+ -- them to build the libraries.
+
+ descr,
+ headers,
+
+ -- Build the back-end support.
+
+ mach_6500,
+ support_6500,
+ lang_runtimes,
+ -- Build the NES library.
+
+ libsys_nes,
+ bootsector
+}