This commit is contained in:
nino-porcino 2022-02-10 17:06:16 +01:00
parent 01a4618934
commit 06ed8bfc4d
8 changed files with 244 additions and 142 deletions

View File

@ -1,4 +1,7 @@
void comando_dump(char *filename, word start, word end) {
// global start_address
// global end_address
void comando_dump() {
// send command byte
send_byte_to_MCU(CMD_READ);
@ -18,8 +21,8 @@ void comando_dump(char *filename, word start, word end) {
return;
}
// get file length
word len = receive_word_from_mcu();
// get file length in tmpword
receive_word_from_mcu();
if(TIMEOUT) return;
// 1234567890123456789012345678901234567890
@ -27,11 +30,11 @@ void comando_dump(char *filename, word start, word end) {
// get file bytes
byte row = 0;
for(word t=0;t!=len;t++) {
for(word t=0;t!=tmpword;t++) {
byte data = receive_byte_from_MCU();
if(TIMEOUT) return;
if(!(t>=start && t<=end)) continue;
if(!(t>=start_address && t<=end_address)) continue;
if(row == 0) {
woz_putc('\r');

View File

@ -4,7 +4,9 @@
// PRODOS format:
// "A","1", 510 bytes low memory, basic program
void comando_load(char *filename, byte cmd) {
// global cmd
void comando_load() {
// send command byte
send_byte_to_MCU(CMD_READ);
@ -24,13 +26,13 @@ void comando_load(char *filename, byte cmd) {
return;
}
// get file length
word len = receive_word_from_mcu();
// get file length in tmpword
receive_word_from_mcu();
if(TIMEOUT) return;
// get file bytes
byte *dest = (byte *) 0;
for(word t=0;t!=len;t++) {
token_ptr = (byte *) 0;
for(word t=0;t!=tmpword;t++) {
byte data = receive_byte_from_MCU();
if(TIMEOUT) return;
@ -43,32 +45,28 @@ void comando_load(char *filename, byte cmd) {
}
else if(t<0x0100) {
// writes in the zone $4a-$ff (BASIC pointers)
*dest = data;
*token_ptr = data;
}
else if(t<0x1ff) {
// skip zone $100-$1ff (stack)
}
else if(t==0x1ff) {
// basic program chuck follows, move the pointer
dest = (byte *) ((*BASIC_LOMEM) -1); // compensate for the increment in the loop
token_ptr = *BASIC_LOMEM;
token_ptr--; // compensate for the increment in the loop
}
else {
// writes in the BASIC program zone
*dest = data;
*token_ptr = data;
}
dest++;
token_ptr++;
#ifdef LOADING_DOTS
if(((byte)t) == 0) woz_putc('.');
#endif
}
// print feedback to user
woz_putc('\r');
woz_puts(filename);
woz_puts(": LOMEM=");
woz_print_hexword(*BASIC_LOMEM);
woz_puts(" HIMEM=");
woz_print_hexword(*BASIC_HIMEM);
woz_puts("\rOK");
bas_file_info();
// executes basic program $EFEC = RUN entry point
if(cmd == CMD_RUN) {
@ -78,3 +76,19 @@ void comando_load(char *filename, byte cmd) {
}
}
}
void bas_file_info() {
// print feedback to user
woz_putc('\r');
woz_puts(filename);
woz_puts(": ");
bas_info();
woz_puts("\rOK");
}
void bas_info() {
woz_puts("LOMEM=");
woz_print_hexword((word) *BASIC_LOMEM);
woz_puts(" HIMEM=");
woz_print_hexword((word) *BASIC_HIMEM);
}

View File

@ -3,7 +3,12 @@
// MCU sends $00 + 2 bytes file length (MSB first) + file data bytes (if OK)
// MCU sends $FF + string error description (if error)
//
void comando_read(char *filename, word start) {
// global start_address
// global len
// global token_ptr
void comando_read() {
// send command byte
send_byte_to_MCU(CMD_READ);
@ -23,28 +28,34 @@ void comando_read(char *filename, word start) {
return;
}
// get file length
word len = receive_word_from_mcu();
// get file length in tmpword
receive_word_from_mcu();
if(TIMEOUT) return;
// get file bytes
byte *dest = (byte *) start;
for(word t=0;t!=len;t++) {
token_ptr = (byte *) start_address;
for(word t=0;t!=tmpword;t++) {
byte data = receive_byte_from_MCU();
if(TIMEOUT) return;
*dest++ = data;
*token_ptr++ = data;
#ifdef LOADING_DOTS
if(((byte)t) == 0) woz_putc('.');
#endif
}
// decrease by one for display result
token_ptr--;
// print feedback to user
woz_putc('\r');
woz_puts(filename);
woz_puts(": ");
woz_print_hexword(start);
woz_print_hexword(start_address);
woz_putc('.');
woz_print_hexword(start+len-1);
woz_print_hexword((word)token_ptr);
woz_puts(" (");
utoa(len, filename, 10); // use filename as string buffer
utoa(tmpword, filename, 10); // use filename as string buffer
woz_puts(filename);
woz_puts(" BYTES)\rOK");
}

View File

@ -1,4 +1,6 @@
void comando_save(char *filename) {
// global len
void comando_save() {
// send command byte
send_byte_to_MCU(CMD_WRITE);
@ -18,8 +20,21 @@ void comando_save(char *filename) {
}
// send file size
word len = ((word) *BASIC_HIMEM) - ((word)*BASIC_LOMEM) + 512;
send_word_to_mcu(len);
//tmpword = ((word) *BASIC_HIMEM) - ((word)*BASIC_LOMEM) + 512;
// in assembly:
asm {
sec
lda BASIC_HIMEM
sbc BASIC_LOMEM
sta tmpword
lda BASIC_HIMEM+1
sbc BASIC_LOMEM+1
sta tmpword+1
inc tmpword+1
inc tmpword+1
}
send_word_to_mcu();
if(TIMEOUT) return;
// send actual bytes
@ -30,16 +45,20 @@ void comando_save(char *filename) {
if(TIMEOUT) return;
// lowmem + stack chuck
for(byte *ptr=(byte *)2; ptr<=(byte *)0x1ff; ptr++) {
send_byte_to_MCU(*ptr);
for(token_ptr=(byte *)2; token_ptr<=(byte *)0x1ff; token_ptr++) {
send_byte_to_MCU(*token_ptr);
if(TIMEOUT) return;
}
// basic data
for(word ptr=*BASIC_LOMEM; ptr<*BASIC_HIMEM; ptr++) {
send_byte_to_MCU(*((byte *)ptr));
tmpword = (word) *BASIC_HIMEM;
for(token_ptr=*BASIC_LOMEM; token_ptr<(byte *)tmpword; token_ptr++) {
send_byte_to_MCU(*token_ptr);
if(TIMEOUT) return;
if(((byte)ptr) == 0) woz_putc('.');
#ifdef LOADING_DOTS
if(((byte)token_ptr) == 0) woz_putc('.');
#endif
}
// get second response
@ -51,12 +70,5 @@ void comando_save(char *filename) {
return;
}
// print feedback to user
woz_putc('\r');
woz_puts(filename);
woz_puts(": LOMEM=");
woz_print_hexword(*BASIC_LOMEM);
woz_puts(" HIMEM=");
woz_print_hexword(*BASIC_HIMEM);
woz_puts("\rOK");
bas_file_info();
}

View File

@ -1,4 +1,4 @@
void comando_type(char *filename) {
void comando_type() {
// send command byte
send_byte_to_MCU(CMD_READ);
@ -18,12 +18,12 @@ void comando_type(char *filename) {
return;
}
// get file length
word len = receive_word_from_mcu();
// get file length in tmpword
receive_word_from_mcu();
if(TIMEOUT) return;
// get file bytes
for(word t=0;t!=len;t++) {
for(word t=0;t!=tmpword;t++) {
byte data = receive_byte_from_MCU();
if(TIMEOUT) return;
woz_putc(data);

View File

@ -1,4 +1,8 @@
void comando_write(char *filename, word start, word end) {
// gloabl start_address
// global end_address
// gloabl len
void comando_write() {
// send command byte
send_byte_to_MCU(CMD_WRITE);
@ -18,16 +22,30 @@ void comando_write(char *filename, word start, word end) {
}
// send file size
word len = end-start + 1;
send_word_to_mcu(len);
//tmpword = (word) end_address - (word) start_address + 1; // KickC bug: (word) cast is needed
asm {
sec
lda end_address
sbc start_address
sta tmpword
lda end_address+1
sbc start_address+1
sta tmpword+1
}
tmpword++;
send_word_to_mcu();
if(TIMEOUT) return;
// send actual bytes
byte *ptr = (byte *) start;
for(word t=0;t<len;t++) {
send_byte_to_MCU(*ptr++);
token_ptr = (byte *) start_address;
for(word t=0;t<tmpword;t++) {
send_byte_to_MCU(*token_ptr++);
if(TIMEOUT) return;
#ifdef LOADING_DOTS
if(((byte)t) == 0) woz_putc('.');
#endif
}
// get second response
@ -43,11 +61,11 @@ void comando_write(char *filename, word start, word end) {
woz_putc('\r');
woz_puts(filename);
woz_puts(": ");
woz_print_hexword(start);
woz_print_hexword(start_address);
woz_putc('.');
woz_print_hexword(end);
woz_print_hexword(end_address);
woz_puts(" (");
utoa(len, filename, 10); // use filename as string buffer
utoa(tmpword, filename, 10); // use filename as string buffer
woz_puts(filename);
woz_puts(" BYTES)\rOK");
}

View File

@ -1,9 +1,9 @@
#include <stdlib.h>
#include <stdlib.h>
word *const BASIC_LOMEM = (word *) 0x004a; // lomem pointer used by integer BASIC
word *const BASIC_HIMEM = (word *) 0x004c; // himem pointer used by integer BASIC
byte *const KEYBUF = (byte *) 0x0200; // use the same keyboard buffer as in WOZ monitor
byte **const BASIC_LOMEM = (byte **) 0x004a; // lomem pointer used by integer BASIC
byte **const BASIC_HIMEM = (byte **) 0x004c; // himem pointer used by integer BASIC
byte *const KEYBUF = (byte *) 0x0200; // use the same keyboard buffer as in WOZ monitor
#define KEYBUFSTART (0x200)
#define KEYBUFLEN (40)
@ -18,16 +18,18 @@ byte *const hex2 = (byte *) (KEYBUFSTART+KEYBUFLEN+6+33+5); // [5] stores a
const byte ERR_RESPONSE = 0xFF;
// command constants, which are also byte commands to send to the MCU
const byte CMD_READ = 0;
const byte CMD_WRITE = 1;
const byte CMD_DIR = 2;
const byte CMD_TIME = 3;
const byte CMD_LOAD = 4;
const byte CMD_RUN = 5;
const byte CMD_SAVE = 6;
const byte CMD_TYPE = 7;
const byte CMD_DUMP = 8;
const byte CMD_EXIT = 9;
const byte CMD_READ = 0;
const byte CMD_WRITE = 1;
const byte CMD_DIR = 2;
const byte CMD_TIME = 3;
const byte CMD_LOAD = 4;
const byte CMD_RUN = 5;
const byte CMD_SAVE = 6;
const byte CMD_TYPE = 7;
const byte CMD_DUMP = 8;
const byte CMD_JMP = 9;
const byte CMD_BAS = 10;
const byte CMD_EXIT = 11;
// the list of recognized commands
byte *DOS_COMMANDS[] = {
@ -40,6 +42,8 @@ byte *DOS_COMMANDS[] = {
"SAVE",
"TYPE",
"DUMP",
"JMP",
"BAS",
"EXIT"
};
@ -48,13 +52,14 @@ byte *DOS_COMMANDS[] = {
// returns the number of character to advance the pointer
// leading and trailing spaces are ignored
// max is the (maximum) size of dest
byte get_token(byte *source, byte *dest, byte max) {
void get_token(byte *dest, byte max) {
byte i = 0;
byte j = 0;
byte first_char_found = 0;
while(1) {
byte c = source[i];
byte c = token_ptr[i];
if(c == 0) {
break;
}
@ -71,32 +76,38 @@ byte get_token(byte *source, byte *dest, byte max) {
else break;
}
dest[j] = 0;
return i+1;
token_ptr += i+1;
}
// returns the command code or 0xff if not recognized
byte find_command() {
for(byte cmd=0; cmd<sizeof(DOS_COMMANDS); cmd++) {
if(strcmp(command, DOS_COMMANDS[cmd]) == 0) return cmd;
void find_command() {
/*
for(cmd=0; cmd<sizeof(DOS_COMMANDS); cmd++) {
if(strcmp(command, DOS_COMMANDS[cmd]) == 0) return;
}
return 0xFF;
cmd = 0xFF;
*/
for(cmd=0; cmd<sizeof(DOS_COMMANDS); cmd++) {
byte *ptr = DOS_COMMANDS[cmd];
for(byte j=0;;j++) {
if(command[j] != ptr[j]) break;
else if(command[j] == 0) return;
}
}
cmd = 0xFF;
}
// converts the hexadecimal string argument to 16 bit word
byte hex_to_word_ok;
word hex_to_word(byte *str) {
void hex_to_word(byte *str) {
hex_to_word_ok = 1;
word res=0;
tmpword=0;
byte c;
byte i;
for(i=0; c=str[i]; ++i) {
res = res << 4;
if(c>='0' && c<='9') res += (c-'0');
else if(c>='A' && c<='F') res += (c-65)+0x0A;
tmpword = tmpword << 4;
if(c>='0' && c<='9') tmpword += (c-'0');
else if(c>='A' && c<='F') tmpword += (c-65)+0x0A;
else hex_to_word_ok = 0;
}
if(i>4 || i==0) hex_to_word_ok = 0;
return res;
}
#include "cmd_read.h"
@ -112,10 +123,10 @@ void console() {
VIA_init();
// 1234567890123456789012345678901234567890
woz_puts("\rREAD,WRITE,LOAD,RUN,SAVE,TYPE,DUMP,DIR\r"
"TIME,EXIT\r");
//woz_puts("\rREAD,WRITE,LOAD,RUN,SAVE,TYPE,DUMP,DIR\r"
// "TIME,JMP,EXIT\r");
woz_puts("\rSD CARD DOS 1.0\r");
woz_puts("\r\r*** SD CARD OS 1.0\r");
// main loop
while(1) {
@ -129,114 +140,133 @@ void console() {
woz_putc('\r');
// decode command
byte *ptr = KEYBUF;
ptr += get_token(ptr, command, 5);
byte cmd = find_command();
token_ptr = KEYBUF;
get_token(command, 5);
find_command(); // put command in cmd
if(cmd == CMD_READ) {
ptr += get_token(ptr, filename, 32); // parse filename
get_token(filename, 32); // parse filename
if(filename[0] == 0) {
woz_puts("?MISSING FILENAME");
continue;
}
ptr += get_token(ptr, hex1, 4); // parse hex start address
word start = hex_to_word(hex1);
get_token(hex1, 4); // parse hex start address
hex_to_word(hex1);
start_address = tmpword;
if(!hex_to_word_ok) {
woz_puts("?BAD ADDRESS");
continue;
}
comando_read(filename, start);
comando_read();
}
else if(cmd == CMD_WRITE) {
// parse filename
ptr += get_token(ptr, filename, 32);
get_token(filename, 32);
if(filename[0] == 0) {
woz_puts("?MISSING FILENAME");
continue;
}
// parse hex start address
ptr += get_token(ptr, hex1, 4);
word start = hex_to_word(hex1);
get_token(hex1, 4);
hex_to_word(hex1);
start_address = tmpword;
if(!hex_to_word_ok) {
woz_puts("?BAD ADDRESS");
continue;
}
// parse hex end address
ptr += get_token(ptr, hex2, 4);
word end = hex_to_word(hex2);
get_token(hex2, 4);
hex_to_word(hex2);
end_address = tmpword;
if(!hex_to_word_ok) {
woz_puts("?BAD ADDRESS");
continue;
}
comando_write(filename, start, end);
comando_write();
}
else if(cmd == CMD_DIR) {
comando_dir();
}
else if(cmd == CMD_TIME) {
ptr += get_token(ptr, hex1, 4); // parse hex timeout value
get_token(hex1, 4); // parse hex timeout value
if(strlen(hex1)!=0) {
TIMEOUT_MAX = hex_to_word(hex1);
hex_to_word(hex1);
if(!hex_to_word_ok) {
woz_puts("?BAD ARGUMENT");
continue;
}
TIMEOUT_MAX = tmpword;
}
woz_puts("TIMEOUT_MAX: ");
woz_print_hexword(TIMEOUT_MAX);
}
else if(cmd == CMD_LOAD || cmd == CMD_RUN) {
ptr += get_token(ptr, filename, 32); // parse filename
get_token(filename, 32); // parse filename
if(filename[0] == 0) {
woz_puts("?MISSING FILENAME");
continue;
}
comando_load(filename, cmd);
comando_load();
}
else if(cmd == CMD_SAVE) {
ptr += get_token(ptr, filename, 32); // parse filename
get_token(filename, 32); // parse filename
if(filename[0] == 0) {
woz_puts("?MISSING FILENAME");
continue;
}
comando_save(filename);
comando_save();
}
else if(cmd == CMD_TYPE) {
ptr += get_token(ptr, filename, 32); // parse filename
get_token(filename, 32); // parse filename
if(filename[0] == 0) {
woz_puts("?MISSING FILENAME");
continue;
}
comando_type(filename);
comando_type();
}
else if(cmd == CMD_DUMP) {
ptr += get_token(ptr, filename, 32); // parse filename
get_token(filename, 32); // parse filename
if(filename[0] == 0) {
woz_puts("?MISSING FILENAME");
continue;
}
// parse hex start address
ptr += get_token(ptr, hex1, 4);
word start = hex_to_word(hex1);
if(!hex_to_word_ok) {
woz_puts("?BAD ADDRESS");
continue;
}
start_address = 0;
end_address = 0xffff;
// parse hex end address
ptr += get_token(ptr, hex2, 4);
word end = hex_to_word(hex2);
// parse hex start address
get_token(hex1, 4);
hex_to_word(hex1);
if(hex_to_word_ok) {
start_address = tmpword;
// parse hex end address
get_token(hex2, 4);
hex_to_word(hex2);
if(hex_to_word_ok) end_address = tmpword;
}
comando_dump();
}
else if(cmd == CMD_JMP) {
get_token(hex1, 4); // parse hex
hex_to_word(hex1);
if(!hex_to_word_ok) {
woz_puts("?BAD ADDRESS");
woz_puts("?BAD ARGUMENT");
continue;
}
if(end<start) end = 0xFFFF;
comando_dump(filename, start, end);
asm {
jmp (tmpword)
}
}
else if(cmd == CMD_BAS) {
woz_puts("BAS ");
bas_info();
}
else if(cmd == CMD_EXIT) {
woz_puts("BYE\r");

View File

@ -1,16 +1,18 @@
// TODO warm flag form boot message
// TODO comando HELP
// TODO comando CD
// TODO comando MKDIR
// TODO comando RMDIR
// TODO comando DEL
// TODO comando REN
// TODO comando COPY
// TODO comando JMP
// TODO comando RUN a vuoto
// TODO comando RUN a vuoto?
// TODO questione del puntino che va in timeout
#define APPLE1_USE_WOZ_MONITOR 1
#pragma start_address(0x8000)
//#pragma start_address(0x0280)
#pragma zp_reserve(0x4a)
#pragma zp_reserve(0x4b)
@ -44,9 +46,17 @@ byte *const DDRA = (byte *) 0xA003; // port B data direction register
#define CPU_STROBE(v) (*PORTB = (v)) /* CPU strobe is bit 0 OUTPUT */
#define MCU_STROBE (*PORTB & 128) /* MCU strobe is bit 7 INPUT */
__address(3) byte TIMEOUT;
__address(4) word TIMEOUT_MAX = 0x1388;
__address(6) word TIMEOUT_CNT;
// global variables that are shared among the functions
__address( 3) byte TIMEOUT;
__address( 4) word TIMEOUT_MAX = 0x1388;
__address( 6) word TIMEOUT_CNT;
__address( 8) word tmpword;
__address(10) word start_address;
__address(12) word end_address;
__address(14) word len;
__address(16) byte hex_to_word_ok;
__address(17) byte cmd;
__address(18) byte *token_ptr;
void wait_mcu_strobe(byte v) {
if(TIMEOUT) return;
@ -104,21 +114,25 @@ void print_string_response() {
if(TIMEOUT) break;
if(data == 0) break; // string terminator
else woz_putc(data);
if(apple1_readkey()) {
woz_puts("*BRK*\r");
break;
}
}
}
word receive_word_from_mcu() {
word data;
*((byte *)&data) = receive_byte_from_MCU();
*((byte *)(&data+1)) = receive_byte_from_MCU();
return data;
void receive_word_from_mcu() {
*((byte *)&tmpword) = receive_byte_from_MCU();
*((byte *)(&tmpword+1)) = receive_byte_from_MCU();
}
void send_word_to_mcu(word data) {
send_byte_to_MCU( *((byte *)&data) );
send_byte_to_MCU( *((byte *)(&data+1)) );
void send_word_to_mcu() {
send_byte_to_MCU( *((byte *)&tmpword) );
send_byte_to_MCU( *((byte *)(&tmpword+1)) );
}
// #define LOADING_DOTS 0
#include "console.h"
void main() {