1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-26 20:28:06 +11:00

Compare commits

..

No commits in common. "d3dbeb450fe36ee754ff0555bc155c8aa8031cc7" and "f023f9bcb4f62f6bf5e20a237e1f772859fcda49" have entirely different histories.

10 changed files with 112 additions and 116 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
*.o
/kernel/user.h

View File

@ -27,25 +27,33 @@ github issue][forth-issue].
Documentation is lacking, it's not ready yet, this is a WIP branch.
## Getting started
## See it in action
Usage documentation is in-system, so access to documentation requires you to
run Collapse OS. Fortunately, doing so in an emulator is easy.
Michael Schierl has put together [a set of emulators running in the browser that
run Collapse OS in different contexts][jsemul].
Using those while following along with the [User Guide](doc/) is your quickest
path to giving Collapse OS a try.
## Documentation
Usage documentation is in-system. Run `0 LIST` for an introduction. You can
also open `blk/000` in a modern text editor.
See `/emul/README.md` for getting an emulated system running.
Then, run `0 LIST` for an introduction, follow instructions from there.
## Organisation of this repository
* `blk`: Collapse OS filesystem's content. That's actually where Collapse OS'
source code is located. Everything else is peripheral.
* `recipes`: collection of recipes that assemble Collapse OS on a specific
* `forth`: Forth is slowly taking over this project (see issue #4). It comes
from this folder.
* `recipes`: collection of recipes that assemble parts together on a specific
machine.
* `blk`: Collapse OS filesystem's content. See `000` for intro.
* `doc`: User guide for when you've successfully installed Collapse OS.
* `tools`: Tools for working with Collapse OS from "modern" environments. For
example, tools for facilitating data upload to a Collapse OS machine
through a serial port.
* `emul`: Tools for running Collapse OS in an emulated environment.
* `emul`: Emulated applications.
* `tests`: Automated test suite for the whole project.
## Status
@ -55,13 +63,13 @@ for more information.
## Discussion
For a general discussion of Collapse OS and the ecosystem of technologies and
ideas that may develop around it refer to [r/collapseos][discussion]
For a general discussion of Collapse OS and the ecosystem of technologies and ideas that may develop around it refer to [r/collapseos][discussion]
A more traditional [mailing list][listserv] and IRC (#collapseos on freenode)
channels are also maintained.
A more traditional [mailing list][listserv] and IRC (#collapseos on freenode) channels are also maintained.
[libz80]: https://github.com/ggambetta/libz80
[web]: https://collapseos.org
[jsemul]: https://schierlm.github.io/CollapseOS-Web-Emulator/
[discussion]: https://www.reddit.com/r/collapseos
[listserv]: http://lists.sonic.net/mailman/listinfo/collapseos
[forth-issue]: https://github.com/hsoft/collapseos/issues/4

51
TRICKS.txt Normal file
View File

@ -0,0 +1,51 @@
This file describe tricks and conventions that are used throughout the code and
might need explanation.
*** Quickies
or a: Equivalent to "cp 0", but results in a shorter opcode.
xor a: sets A to 0 more efficiently than ld a, 0
and 0xbf: Given a letter in the a-z range, changes it to its uppercase value
if it's already uppercased, then it stays that way.
*** Z flag for results
Z if almost always used as a success indicator for routines. Set for success,
Reset for failure. "xor a" (destroys A) and "cp a" (preserves A) are used to
ensure Z is set. To ensure that it is reset, it's a bit more complicated and
"unsetZ" routine exists for that, although that in certain circumstances,
"inc a \ dec a" or "or a" can work.
*** Little endian
z80 is little endian in its 16-bit loading operations. For example, "ld hl, (0)"
will load the contents of memory address 0 in L and memory address 1 in H. This
little-endianess is followed by Collapse OS in most situations. When it's not,
it's specified in comments.
This get a bit awkward with regards to 32-bit. There are no "native" z80 32-bit
operations, so z80 doesn't mandate an alignment. In Collapse OS, 32-bit numbers
are stored as "big endian pair of little endian 16-bit numbers". For example,
if "ld dehl, (0)" existed and if the first 4 bytes of memory were 0x01, 0x02,
0x03 and 0x04, then DE (being the "high" word) would be 0x0201 and HL would be
0x0403.
*** DAA
When it comes to dealing with decimals, the DAA instruction, which look a bit
obscur, can be very useful. It transforms the result of a previous arithmetic
operation involving two BCD (binary coded decimal, one digit in high nibble,
the other digit in low nibble. For example, 0x99 represents 99) into a valid
BCD. For example, 0x12+0x19=0x2b, but after calling DAA, it will be 0x31.
To clear misunderstanding: this does **not** transform an arbitrary value into
BCD. For example, "ld a, 0xff \ daa" isn't going to magically give you a binary
coded 255 (how could it?). This is designed to be ran after an arithmetic
operation.
A common trick to transform an arbitrary number to BCD is to loop 8 times over
your bitstream, SLA your bits out of your binary value and then run
"adc a, a \ daa" over it (with provisions for carries if you expect numbers
over 99).

View File

@ -6,7 +6,7 @@ emulator.
## Not real hardware
In the few emulated apps described below, we don't try to emulate real hardware
because the goal here is to facilitate "high level" development.
because the goal here is to facilitate userspace development.
These apps run on imaginary hardware and use many cheats to simplify I/Os.
@ -18,17 +18,44 @@ folder.
First, make sure that the `libz80` git submodule is checked out. If not, run
`git submodule init && git submodule update`.
After that, you can run `make` and it builds the `forth` interpreter.
After that, you can run `make` and it builds all applications.
Run `./forth` to get the COllapse OS prompt. Type `0 LIST` for help.
## forth
Collapse OS' Forth interpreter, which is in the process of replacing the
zasm-based project.
The Forth interpreter is entirely self-hosting, that is, it assembles its
binary with itself.
There are 3 build stages.
**Stage 0**: At this stage, all we have are our bootstrap binaries, `boot.bin`
and `z80c.bin`. We concatenate them into `forth0.bin` ans then wrap the
emulator around it which is named `stage1` (because it builds the stage 1) to
have a barebone forth interpreter.
**Stage 1**: The `stage1` binary allows us to augment `forth0.bin` with
the compiled dictionary of a full Forth interpreter. We feed it with
`$(FORTHSRCS)` and then dump the resulting compiled dict.
From there, we can create `forth1.bin`, which is wrapped by both the `forth`
and `stage2` executables. `forth` is the interpreter you'll use.
**Stage 2**: `stage2` is used to resolve the chicken-and-egg problem and use
the power of a full Forth intepreter, including an assembler, to assemble
`z80c.bin`. This is a manual step executed through `make updatebootstrap`.
Normally, running this step should yield the exact same `boot.bin` and
`z80c.bin` as before, unless of course you've changed the source.
## Problems?
If the libz80-wrapped zasm executable works badly (hangs, spew garbage, etc.),
it's probably because you've broken your bootstrap binaries. They're easy to
mistakenly break. To verify if you've done that, look at your git status. If
`forth.bin` is modified, try resetting it and then run `make clean all`. Things
should go better afterwards.
`boot.bin` or `z80c.bin` are modified, try resetting them and then run
`make clean all`. Things should go better afterwards.
If that doesn't work, there's also the nuclear option of `git reset --hard`
and `git clean -fxd`.
@ -36,5 +63,3 @@ and `git clean -fxd`.
If that still doesn't work, it might be because the current commit you're on
is broken, but that is rather rare: the repo on Github is plugged on Travis
and it checks that everything is smooth.
[libz80]: https://github.com/ggambetta/libz80

1
tools/.gitignore vendored
View File

@ -10,4 +10,3 @@
/exec
/blkpack
/blkunpack
/blkup

View File

@ -8,10 +8,9 @@ BIN2C_TGT = bin2c
EXEC_TGT = exec
BLKPACK_TGT = blkpack
BLKUNPACK_TGT = blkunpack
BLKUP_TGT = blkup
TARGETS = $(MEMDUMP_TGT) $(BLKDUMP_TGT) $(UPLOAD_TGT) $(FONTCOMPILE_TGT) \
$(TTYSAFE_TGT) $(PINGPONG_TGT) $(BIN2C_TGT) $(EXEC_TGT) $(BLKPACK_TGT) \
$(BLKUNPACK_TGT) $(BLKUP_TGT)
$(TTYSAFE_TGT) $(PINGPONG_TGT) \
$(BIN2C_TGT) $(EXEC_TGT) $(BLKPACK_TGT) $(BLKUNPACK_TGT)
OBJS = common.o
all: $(TARGETS)
@ -30,7 +29,6 @@ $(BIN2C_TGT): $(BIN2C_TGT).c
$(EXEC_TGT): $(EXEC_TGT).c
$(BLKPACK_TGT): $(BLKPACK_TGT).c
$(BLKUNPACK_TGT): $(BLKUNPACK_TGT).c
$(BLKUP_TGT): $(BLKUP_TGT).c
$(TARGETS): $(OBJS)
$(CC) $(CFLAGS) $@.c $(OBJS) -o $@

View File

@ -1,67 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "common.h"
/* Push specified file to specified device blk device, starting from blkno
* and upwards.
*/
int main(int argc, char **argv)
{
if (argc != 4) {
fprintf(stderr, "Usage: ./blkup device blkno fname\n");
return 1;
}
unsigned int blkno = strtol(argv[2], NULL, 10);
FILE *fp = fopen(argv[3], "r");
if (!fp) {
fprintf(stderr, "Can't open %s.\n", argv[3]);
return 1;
}
int fd = open(argv[1], O_RDWR|O_NOCTTY|O_SYNC);
if (fd < 0) {
fprintf(stderr, "Could not open %s\n", argv[1]);
return 1;
}
set_interface_attribs(fd, 0, 0);
set_blocking(fd, 1);
char s[0x40];
char buf[1024] = {0};
sendcmdp(fd, ": _ 1024 0 DO KEY DUP .x I BLK( + C! LOOP ;");
int returncode = 0;
while (fread(buf, 1, 1024, fp)) {
sendcmd(fd, "_");
for (int i=0; i<1024; i++) {
putchar('.');
fflush(stdout);
write(fd, &buf[i], 1);
usleep(1000); // let it breathe
mread(fd, s, 2); // read hex pair
s[2] = 0; // null terminate
unsigned char c = strtol(s, NULL, 16);
if (c != buf[i]) {
// mismatch!
fprintf(stderr, "Mismatch at bno %d (%d) %d != %d.\n", blkno, i, buf[i], c);
// we don't exit now because we need to "consume" our whole program.
returncode = 1;
}
usleep(1000); // let it breathe
}
readprompt(fd);
if (returncode) break;
memset(buf, 0, 1024);
sprintf(s, "%d BLK> ! BLK!", blkno);
sendcmdp(fd, s);
blkno++;
}
sendcmdp(fd, "FORGET _");
printf("Done!\n");
fclose(fp);
return returncode;
}

View File

@ -16,24 +16,6 @@ void mread(int fd, char *s, int count)
}
}
void mexpect(int fd, char ec)
{
char c;
mread(fd, &c, 1);
if (c != ec) {
fprintf(stderr, "Expected %d but got %d\n", ec, c);
}
}
void readprompt(int fd)
{
mexpect(fd, ' ');
mexpect(fd, 'o');
mexpect(fd, 'k');
mexpect(fd, '\r');
mexpect(fd, '\n');
}
void sendcmd(int fd, char *cmd)
{
char junk[2];
@ -46,16 +28,16 @@ void sendcmd(int fd, char *cmd)
usleep(1000);
}
write(fd, "\r", 1);
mexpect(fd, '\r');
mexpect(fd, '\n');
mread(fd, junk, 2); // sends back \r\n
usleep(1000);
}
// Send a cmd and also read the " ok" prompt
// Send a cmd and also read the "> " prompt
void sendcmdp(int fd, char *cmd)
{
char junk[2];
sendcmd(fd, cmd);
readprompt(fd);
mread(fd, junk, 2);
}
// from https://stackoverflow.com/a/6947758

View File

@ -1,7 +1,6 @@
void sendcmd(int fd, char *cmd);
void sendcmdp(int fd, char *cmd);
void mread(int fd, char *s, int count);
void readprompt(int fd);
int set_interface_attribs(int fd, int speed, int parity);
void set_blocking(int fd, int should_block);

View File

@ -67,7 +67,7 @@ int main(int argc, char **argv)
}
usleep(1000); // let it breathe
}
readprompt(fd);
mread(fd, s, 2); // "> " prompt
sendcmdp(fd, "FORGET _");
printf("Done!\n");
fclose(fp);