Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
bccada197b | |||
8c78aab32e | |||
1c7ab48330 | |||
a6698e3ead |
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,4 +1,5 @@
|
|||||||
*.tap
|
*.tap
|
||||||
*bin
|
*.block
|
||||||
*bincs
|
body
|
||||||
ac
|
header
|
||||||
|
ttttt
|
||||||
|
41
Makefile
41
Makefile
@ -1,33 +1,28 @@
|
|||||||
program.tap: program.asm headerbincs body.tap
|
program.tap: header.block body.block
|
||||||
pasmo program.asm program.tap
|
cat header.block body.block > program.tap
|
||||||
|
|
||||||
headerbincs: headerbin ac
|
header.block: header ttttt
|
||||||
cp headerbin headerbincs
|
./ttttt header header
|
||||||
./ac headerbincs
|
|
||||||
|
|
||||||
headerbin: header.tap
|
header: header.asm body.block
|
||||||
dd if=header.tap of=headerbin bs=1 count=18
|
pasmo header.asm headerlong
|
||||||
|
dd if=headerlong of=header bs=17 count=1
|
||||||
|
rm -f headerlong
|
||||||
|
|
||||||
header.tap: header.asm body.tap
|
body.block: body ttttt
|
||||||
pasmo header.asm header.tap
|
./ttttt body data
|
||||||
|
|
||||||
body.tap: body.asm bodybincs
|
body: remload.asm code.asm
|
||||||
pasmo body.asm body.tap
|
pasmo remload.asm body
|
||||||
|
|
||||||
bodybincs: bodybin ac
|
ttttt: ttttt.c
|
||||||
cp bodybin bodybincs
|
cc ttttt.c -o ttttt
|
||||||
./ac bodybincs
|
|
||||||
|
|
||||||
bodybin: remload.asm code.asm
|
|
||||||
pasmo remload.asm bodybin
|
|
||||||
|
|
||||||
ac: append_checksum.c
|
|
||||||
cc append_checksum.c -o ac
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.tap
|
rm -f *.tap
|
||||||
rm -f *bin
|
rm -f *.block
|
||||||
rm -f *bincs
|
rm -f body
|
||||||
rm -f ac
|
rm -f header
|
||||||
|
rm -f ttttt
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
@ -4,7 +4,7 @@ Sometimes it would be useful to run machine code directly from ZX BASIC without
|
|||||||
|
|
||||||
This Makefile will generate a ZX BASIC .tap file with a REM statement containing the machine code, and will automatically run it. Simply amend the code in `code.asm` and run `make`. The file `program.tap` will be created which can be loaded in an emulator or real Spectrum.
|
This Makefile will generate a ZX BASIC .tap file with a REM statement containing the machine code, and will automatically run it. Simply amend the code in `code.asm` and run `make`. The file `program.tap` will be created which can be loaded in an emulator or real Spectrum.
|
||||||
|
|
||||||
The included BASIC routine will CLEAR 59999 and set BORDER and PAPER to black and INK to white. Amend the `remload.asm` routine if this is not desired.
|
The included BASIC routine will CLEAR 32767 and set BORDER and PAPER to black and INK to white. Amend the `remload.asm` routine if this is not desired.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
unsigned char tally = 0;
|
|
||||||
unsigned char next = 0;
|
|
||||||
if (argc!=2) return -1;
|
|
||||||
|
|
||||||
fd = open(argv[1], O_RDWR|O_APPEND);
|
|
||||||
if (fd<0) return -2;
|
|
||||||
|
|
||||||
while (read(fd, &next, 1)) {
|
|
||||||
//printf("Tally: %X, next byte: %X\n", tally, next);
|
|
||||||
tally ^= next;
|
|
||||||
};
|
|
||||||
|
|
||||||
printf("Final tally: %X\n", tally);
|
|
||||||
|
|
||||||
write(fd, &tally, 1);
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
7
body.asm
7
body.asm
@ -1,7 +0,0 @@
|
|||||||
bodylength:
|
|
||||||
dw bodyend - bodycontent
|
|
||||||
|
|
||||||
bodycontent:
|
|
||||||
INCBIN bodybincs
|
|
||||||
|
|
||||||
bodyend:
|
|
10
code.asm
10
code.asm
@ -1,2 +1,12 @@
|
|||||||
|
; This is the main file you will edit to add your machine code to the REM statement.
|
||||||
|
; You _must_ include the "entry_point" tag to point to the address which will called by the BASIC "PRINT USR" statement.
|
||||||
|
; The default code below is for illustration only, and can be deleted.
|
||||||
|
; But REMEMBER TO ADD THE entry_point TAG TO YOUR OWN CODE!
|
||||||
|
|
||||||
|
|
||||||
|
data_start: ;if your routine starts here, move the entry_point tag here too
|
||||||
ld bc, 42
|
ld bc, 42
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
entry_point: ;move this tag to the start point of your code
|
||||||
|
jr data_start
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
headerflag:
|
|
||||||
db 0
|
|
||||||
|
|
||||||
blocktype:
|
blocktype:
|
||||||
db 0 ;basic program
|
db 0 ;basic program
|
||||||
|
|
||||||
@ -20,5 +17,5 @@ checksum:
|
|||||||
db 0
|
db 0
|
||||||
|
|
||||||
bodytap:
|
bodytap:
|
||||||
INCBIN body.tap
|
INCBIN body.block
|
||||||
endbodytap:
|
endbodytap:
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
headlength:
|
|
||||||
dw 19
|
|
||||||
|
|
||||||
INCBIN headerbincs
|
|
||||||
INCBIN body.tap
|
|
10
remload.asm
10
remload.asm
@ -1,7 +1,5 @@
|
|||||||
org #5cca
|
org #5ccb
|
||||||
|
|
||||||
bodyformat:
|
|
||||||
db #ff
|
|
||||||
linenumber:
|
linenumber:
|
||||||
db #00 ;MSB
|
db #00 ;MSB
|
||||||
db #00 ;LSB
|
db #00 ;LSB
|
||||||
@ -33,10 +31,10 @@ ink:
|
|||||||
db ':'
|
db ':'
|
||||||
|
|
||||||
clear:
|
clear:
|
||||||
db #fd, "59999" ;CLEAR 59999 - presumably code will be loaded somewhere?
|
db #fd, "32767" ;CLEAR 32767 - presumably code will be loaded somewhere?
|
||||||
db #0e
|
db #0e
|
||||||
db 0,0
|
db 0,0
|
||||||
dw 59999
|
dw 32767
|
||||||
db 0
|
db 0
|
||||||
db ':'
|
db ':'
|
||||||
|
|
||||||
@ -45,7 +43,7 @@ printusr:
|
|||||||
db "0" ;don't know if actual value is important
|
db "0" ;don't know if actual value is important
|
||||||
db #0e
|
db #0e
|
||||||
db 0,0
|
db 0,0
|
||||||
dw code ;actual call to REM statement code
|
dw entry_point ;actual call to REM statement code
|
||||||
db 0
|
db 0
|
||||||
db ':'
|
db ':'
|
||||||
|
|
||||||
|
95
ttttt.c
Normal file
95
ttttt.c
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/* McPhail's Tip-Top TAP Top-Tailer
|
||||||
|
* Takes a raw code file as input
|
||||||
|
* Prepends data length and appends xor checksum
|
||||||
|
* Outputs to new file with .block suffix */
|
||||||
|
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <linux/limits.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fdin, fdout;
|
||||||
|
char outfilename[PATH_MAX];
|
||||||
|
unsigned int count = 0;
|
||||||
|
unsigned char flagopt = 0;
|
||||||
|
unsigned char tally = 0;
|
||||||
|
unsigned char next = 0;
|
||||||
|
if ((argc<2) || (argc>3)) {
|
||||||
|
printf("Please specify file to read.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (3==argc) {
|
||||||
|
if (!strcmp(argv[2], "header")) flagopt = 1;
|
||||||
|
if (!strcmp(argv[2], "data")) flagopt = 2;
|
||||||
|
if (!flagopt) {
|
||||||
|
printf("Optional flags are \"header\" or \"data\"\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! flagopt) {
|
||||||
|
printf("*** WARNING ***\n");
|
||||||
|
printf("*** ttttt is running in RAW mode.\n");
|
||||||
|
printf("*** Have you manually included the format flag as the first byte of the block?\n");
|
||||||
|
printf("*** If not, run again passing 'header' or 'data' as the second parameter.\n");
|
||||||
|
printf("*** WARNING ***\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
fdin = open(argv[1], O_RDONLY);
|
||||||
|
if (fdin<0) {
|
||||||
|
printf("Couldn't open %s. for reading\n", argv[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(outfilename, PATH_MAX, "%s.block", argv[1]);
|
||||||
|
outfilename[PATH_MAX - 1] = '\0';
|
||||||
|
if (! strcmp(argv[1], outfilename)) {
|
||||||
|
printf("Filename too long - would clobber existing.\n");
|
||||||
|
close(fdin);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fdout = open(outfilename, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
|
||||||
|
if (fdout<0) {
|
||||||
|
printf("Couldn't open %s for writing.\n", outfilename);
|
||||||
|
close(fdin);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (read(fdin, &next, 1)) {
|
||||||
|
tally ^= next;
|
||||||
|
count ++;
|
||||||
|
};
|
||||||
|
lseek(fdin, 0, SEEK_SET);
|
||||||
|
|
||||||
|
if (flagopt) count++;
|
||||||
|
|
||||||
|
char lsb = (count+1)&255;
|
||||||
|
char msb = ((count+1)>>8)&255;
|
||||||
|
write(fdout, &lsb, 1);
|
||||||
|
write(fdout, &msb, 1);
|
||||||
|
next = 0;
|
||||||
|
if (flagopt == 2) next = 255;
|
||||||
|
if (flagopt) {
|
||||||
|
write(fdout, &next, 1);
|
||||||
|
tally ^= next;
|
||||||
|
}
|
||||||
|
while (read(fdin, &next, 1)) {
|
||||||
|
write(fdout, &next, 1);
|
||||||
|
}
|
||||||
|
write(fdout, &tally, 1);
|
||||||
|
|
||||||
|
close(fdout);
|
||||||
|
close(fdin);
|
||||||
|
|
||||||
|
printf("File %s written.\n", outfilename);
|
||||||
|
count--;
|
||||||
|
printf("Code length is %d (0x%.4X).\n", count, count);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user