summaryrefslogtreecommitdiff
path: root/src/s19stuff.c
diff options
context:
space:
mode:
authorDominic Radermacher <blip@mockmoon-cybernetics.ch>2017-07-19 14:08:49 +0200
committerDominic Radermacher <blip@mockmoon-cybernetics.ch>2017-07-19 14:08:49 +0200
commitc57a8a9bf49fa7a3231ce8d6e435603e8ab016eb (patch)
tree6c83a316511a185cc497a4fc2237742417d3c718 /src/s19stuff.c
initial importv0.9
Diffstat (limited to 'src/s19stuff.c')
-rw-r--r--src/s19stuff.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/src/s19stuff.c b/src/s19stuff.c
new file mode 100644
index 0000000..59b39fb
--- /dev/null
+++ b/src/s19stuff.c
@@ -0,0 +1,148 @@
+
+/* --------------------------------------------------------------------
+ Copyright (C) 2004 Dominic Radermacher <dominic.radermacher@gmail.com>
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -------------------------------------------------------------------- */
+
+#include <stdio.h>
+#include <ctype.h> /* isdigit(), tolower() */
+
+#include "s19stuff.h"
+
+static uint8_t _s19_chksum_val=0;
+
+uint8_t hex2chr(char *s)
+{
+ return( ((isdigit(s[0])?s[0]-'0':tolower(s[0])-'a'+10)<<4)
+ + (isdigit(s[1])?s[1]-'0':tolower(s[1])-'a'+10));
+}
+
+void s19_chksum_init(void)
+{
+ _s19_chksum_val=0;
+}
+
+void s19_chksum_add(uint8_t val)
+{
+ _s19_chksum_val += val;
+}
+
+uint8_t s19_chksum_get(void)
+{
+ return ~_s19_chksum_val;
+}
+
+int parse_s19_line(struct obj *bo, char *buf)
+{
+ int i, len, addr, val;
+
+ if(*buf++ != 'S') {
+ return -1;
+ }
+ s19_chksum_init();
+ val=0;
+ if(*buf == '0') {
+ printf("ignoring S0 record\n");
+ return 0;
+ } else if(*buf == '1') {
+ len=hex2chr(++buf);
+ s19_chksum_add(len);
+ buf+=2;
+ addr=hex2chr(buf);
+ s19_chksum_add(addr);
+ buf+=2;
+ addr=addr<<8;
+ val=hex2chr(buf);
+ s19_chksum_add(val);
+ addr+=val;
+ buf+=2;
+ for(i=0; i<len-3; i++) {
+ val=hex2chr(buf);
+ bo->code[addr+i]=val;
+ s19_chksum_add(val);
+ buf+=2;
+ }
+ val=hex2chr(buf);
+ if(val != s19_chksum_get()) { /* checksum does not match */
+ printf("Invalid checksum for S1 Record: len=%d bytes addr=%04x chk=%02x calc=%02x\n", len, addr, val, s19_chksum_get());
+ }
+ if(bo->start_addr > addr) {
+ bo->start_addr = addr;
+ }
+ if(bo->end_addr < (addr+len-3)) {
+ bo->end_addr = addr+len-3;
+ }
+ } else if((*buf == '2') || (*buf == '3') || (*buf == '7') || (*buf == '8')) {
+ printf("S%c records cant be loaded to the 68HC11 (16 bit adress only)\n", *buf);
+ return -1;
+ } else if(*buf == '5') {
+ printf("S5 record count ignored\n");
+ return 0;
+ } else if(*buf == '9') {
+ printf("S9 record ignored yet\n");
+ return 0;
+ }
+ if(val != s19_chksum_get()) {
+ printf("checksum error (found: %02x, expected: %02x)\n", val, s19_chksum_get());
+ }
+ return 0;
+}
+
+/* --------------------------------------------------------------------
+ Description read from file 'f' to buffer 'd' of size 'size'
+ until either the buffer is full, or \n or EOF is
+ found. return the number of read octets or -1
+ if no octets could be read (EOF)
+ -------------------------------------------------------------------- */
+
+int f_readline(FILE *f, char *buf, int size)
+{
+ int n, c;
+ char *p;
+
+ for(n=0, p=buf; n<size; ) {
+ c=fgetc(f);
+ if(c != EOF) {
+ if(c == '\n') break; /* LF -> stop and terminate */
+ *p++=c;
+ n++;
+ } else {
+ if(n != 0) break; /* line NOT empty -> terminate */
+ return -1; /* else return -1 */
+ }
+ }
+ if(n < size) { /* we have left space to terminate string */
+ *p=0;
+ }
+ return n;
+}
+
+int load_s19file(struct obj *bo, char *file)
+{
+ int i;
+ char buf[515]; /* 'S1' + len (2 chars) + 255*2 + '\0' */
+ FILE *f;
+
+ bo->start_addr=0xffff;
+ bo->end_addr=0x0000;
+ for(i=0; i<(int)sizeof(bo->code); bo->code[i++]=0);
+ if((f=fopen(file, "r")) == NULL) {
+ fprintf(stderr, "cant open file '%s'\n", file);
+ return -1;
+ }
+ while((i=f_readline(f, buf, 515)) != -1) {
+ parse_s19_line(bo, buf);
+ }
+ return 0;
+}