\ RCM2300 eFORTH \ HEXLOAD loads INTEL HEX 16 file \ assumes position independent (relocatable) code so \ file address is added to load address \ Each record starts with a colon ":" and \ ends with an ASCII carriage return (13D) and linefeed (10D). \ \ NN number of data bytes \ AAAA address WORD of the first data byte in record \ TT the Record Type, where: \ 00 represents data \ 01 represents end of file \ 02 represents segment address \ DD Data BYTE \ CC 8 bit binary checksum where: \ CC = -{NN+12+34+56+78+TT+DD+..+DD} & 0FFH \ \ INTEL16 \ \ :NN0000TT4000CC \ :NN5678TTDDDDDDDDDDDDDDDDDDDDDDDDDDDDCC \ :NN5678TTCC \ \ :020000024000F8 \ :0E56780048657861646563696D616C210D0A97 \ :0056780131 DECIMAL VARIABLE ADDR \ file address VARIABLE CNT CREATE LINEBUF 160 ALLOT CREATE TMPSTR 40 ALLOT VARIABLE LTYPE VARIABLE CHECKSUM VARIABLE DONE VARIABLE I VARIABLE LOADADDR \ base address. where to load. \ EXPECT puts actual char count read in var SPAN : GETLINE LINEBUF 80 EXPECT ; : LINE2NUM ( a n -- d ) \ a buffer addr; n # chars to convert TMPSTR PACK$ NUMBER? DROP ; HEX ( IF LINE < 4 CHARS, WE'RE DONE ) : PROCLINE SPAN @ 4 < NOT IF LINEBUF C@ 3A = NOT IF 1 DONE ! THEN ( GET ':' ) LINEBUF 1 + 2 LINE2NUM CNT ! ( GET COUNT ) LINEBUF 3 + 4 LINE2NUM ADDR ! ( GET ADDRESS ) LINEBUF 7 + 2 LINE2NUM LTYPE ! ( GET LINE TYPE ) LTYPE @ 0 = IF ( NOW GET DATA FIELD... ) CNT @ 0 = IF 1 DONE ! ELSE \ CNT != 0 CNT @ 1 - \ FOR is ZERO based FOR LINEBUF 9 + \ data offset into LINEBUF ( a -- ) CNT @ R@ - 1 - 2 * ( a i -- ) + 2 LINE2NUM LOADADDR @ ADDR @ + ! ( STORE BYTE AT ADDRESS ) ADDR @ 1 + ADDR ! ( INC ADDRESS ) NEXT ( GET CHECKSUM... ) LINEBUF CNT @ 2 * + 9 + 2 LINE2NUM CHECKSUM ! THEN THEN \ LTYPE = 0 ELSE 1 DONE ! THEN ; : HEXLOAD ( a -- ) \ base load address LOADADDR ! 0 DONE ! CR BEGIN GETLINE PROCLINE CR 2E EMIT \ file line flow control '.' NOT normally in file DONE @ UNTIL ; HEX HAND 2E EMIT