From 5a3c040056215b18feb94275080ea7cde79c71a6 Mon Sep 17 00:00:00 2001 From: Will Haldean Brown Date: Wed, 12 Feb 2014 20:18:56 -0800 Subject: [PATCH] Add some nifty shit to stdio.s. Adds print and fread functions, both of which read NUL-terminated strings. print writes them using the character output device, and fread reads them from the block device to a region of memory. --- README | 26 +++++--- main.c | 2 +- sample_programs/README | 4 +- sample_programs/diskread/gendisk.c | 5 +- sample_programs/diskread/testdisk.bin | Bin 13 -> 65310 bytes sample_programs/stdlib_test.s | 26 ++++++++ stdlib/stdio.s | 82 ++++++++++++++++++++++++-- 7 files changed, 129 insertions(+), 16 deletions(-) create mode 100644 sample_programs/stdlib_test.s diff --git a/README b/README index 0cada9a..fea7686 100644 --- a/README +++ b/README @@ -66,13 +66,13 @@ Extensions to the 6502 instruction set I/O memory map: - There are three I/O devices right now: a character input - device, a character output device and a virtual - terminal. Convenience constants and macros for the - character I/O devices are defined in `stdlib/stdio.s' - for use in user programs. Add stdlib to your include - path and then add `#include ' to your program - to use these constants. + There are four I/O devices right now: a character input + device, a character output device, a virtual terminal + and a block device. Convenience constants and macros for + the character I/O devices are defined in + `stdlib/stdio.s' for use in user programs. Add stdlib to + your include path and then add `#include ' to + your program to use these constants. I/O options are controlled by setting bits on the I/O flag byte at address 0xFF02. The current set of @@ -141,6 +141,18 @@ I/O devices: sample_programs/echo.s, and an example of a vterm application is provided in sample_programs/spam.s + A block device can be mapped in with control addresses + at 0xFF03 through 0xFF07. To use the block device, you + must specify a binary disk image to back the device + using the -d flag. To read from the block device, write + an address in the disk image to 0xFF03 and 0xFF04, with + the low byte in 0xFF03. The value at that location in + the disk image will be written to 0xFF05, which your + program can then read. To write, set the memory address + to write to using the same method, then write the + desired byte to 0xFF06. If any of these operations + return an error, the byte at 0xFF07 will be nonzero. + Reading the source x6502 was written to be easy to understand and read. A diff --git a/main.c b/main.c index 76d69e5..595d820 100644 --- a/main.c +++ b/main.c @@ -52,8 +52,8 @@ int main(int argc, char *argv[]) { return -1; } - debugf("using %s as a backing file for block device 0\n", blck0_file); if (blck0_file != NULL) { + debugf("using %s as a backing file for block device 0\n", blck0_file); FILE *blck0 = fopen(blck0_file, "r+"); if (blck0 == NULL) { fprintf(stderr, "block file %s does not exist.\n", blck0_file); diff --git a/sample_programs/README b/sample_programs/README index 9f2ad16..cf06028 100644 --- a/sample_programs/README +++ b/sample_programs/README @@ -1,6 +1,6 @@ Test 6502 assembler programs. Generate binaries with: -xa -w -bt 0x0100 -Istdlib/ sample_programs/test.s +xa -w -Istdlib/ sample_programs/test.s xa is a cross-assembler and utility suite for 65xx series processors. It's included in many package repositories as `xa65', including Homebrew on OSX in @@ -20,3 +20,5 @@ Sample programs: spam.s Writes A through Z repeatedly, filling the vterm. Demonstrates vterm output and how to do indirect addressing to address the whole vterm. + stdlib_test.s Demo program displaying the functionality of the + standard library. diff --git a/sample_programs/diskread/gendisk.c b/sample_programs/diskread/gendisk.c index 9063ddd..04a2082 100644 --- a/sample_programs/diskread/gendisk.c +++ b/sample_programs/diskread/gendisk.c @@ -8,7 +8,10 @@ int main() { printf("could not open file, err: %s", strerror(errno)); return 1; } - fprintf(f, "hello, world!"); + fprintf(f, "hello, world, from disk!\n"); + fputc(0, f); + fseek(f, 0xFF00, SEEK_SET); + fprintf(f, "hello from a seeked position.\n"); fclose(f); return 0; } diff --git a/sample_programs/diskread/testdisk.bin b/sample_programs/diskread/testdisk.bin index 30f51a3fba5274d53522d0f19748456974647b4f..1e03cbc5da14735dfe24bc1624930a06606a39d1 100644 GIT binary patch literal 65310 zcmeIu(Fubv6ac_}JH_)~x>F$$gR!q9Lf7vgy&K_<+Iw#C&C$yi`^YOwo9DVbFkrxd z0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwA zz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEj zFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r z3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@ z0|pEjFkrxd0RsjM7%*VKfB^#r3>YwAz<>b*1`HT5V8DO@0|pEjFkrxd0RsjM7%*VK tfB^#r3>YwAz<>b*1`HT5V8FnC4IH)ijD6%4ub8!-wZtc9yIa1W%MVJL6Gi|4 literal 13 Ucmc~u&B@8vQ7F$Z%1KcK03rSassI20 diff --git a/sample_programs/stdlib_test.s b/sample_programs/stdlib_test.s new file mode 100644 index 0000000..f869048 --- /dev/null +++ b/sample_programs/stdlib_test.s @@ -0,0 +1,26 @@ +#include + + lda #$02 ; set WAIT_TERMINATE flag + sta iomode + lda #str + sta $F1 + jsr print + + lda #$00 + sta blck0_addrl + sta blck0_addrh + jsr fread + jsr print + + lda #$00 + sta blck0_addrl + lda #$FF + sta blck0_addrh + jsr fread + jsr print + + ext + +str: .asc "hello, world, from .data!", $0A, $00 diff --git a/stdlib/stdio.s b/stdlib/stdio.s index 66c7a65..3d52191 100644 --- a/stdlib/stdio.s +++ b/stdlib/stdio.s @@ -1,11 +1,81 @@ -; defines useful constants for writing 6502 assembler that targets x6502 - -putc = $FF00 -getc = $FF01 -iomode = $FF02 -paint = $FEE8 +; defines useful constants and methods for writing 6502 assembler that targets x6502 #define debug .byt $FC #define ext .byt $FF #define DEBUG debug #define EXT ext + +.( +jmp prog + ++putc = $FF00 ++getc = $FF01 ++iomode = $FF02 ++paint = $FEE8 + ++blck0_addrl = $FF03 ++blck0_addrh = $FF04 ++blck0_read = $FF05 ++blck0_write = $FF06 ++blck0_err = $FF07 + +; print reads two bytes from $00F0, treats them as a memory address, then +; reads from that memory address and prints those characters to the character +; device until a NUL character is found. the printed string must be less than +; 256 characters long. ++print: +.( + pha + ldy #$00 +loop: + lda ($F0),Y + cmp #$00 + beq done + sta putc + iny + ; check that y hasn't overflowed + cpy #$00 + beq done + jmp loop +done: + pla + rts +.) + +; fread reads up to 255 bytes into a memory region that starts at the address in +; $00F0 from the current position of the block device until a null character is +; encountered. ++fread: +.( + pha + ldy #$00 + +loop: + lda blck0_read + ; TODO check read status + + sta ($F0),Y + + iny + ; check that y hasn't overflowed + cpy #$00 + beq done + + ; increment disk address, using carry addition + clc + lda #$01 + adc blck0_addrl + sta blck0_addrl + lda #$00 + adc blck0_addrh + sta blck0_addrh + + jmp loop + +done: + pla + rts +.) + +prog: +.)