Skip to content

Instantly share code, notes, and snippets.

@definev
Last active March 1, 2022 14:49
Show Gist options
  • Save definev/0235fc17860496b3e304894b67ddea70 to your computer and use it in GitHub Desktop.
Save definev/0235fc17860496b3e304894b67ddea70 to your computer and use it in GitHub Desktop.
Intel hex display written in C
:0A00000095C0FECFFDCFFCCFFBCF73
:10000A00FACFF9CFF8CFF7CFF6CFF5CFDEC0F3CFDF
:10001A00F2CFF1CFF0CFEFCFEECFEDCF000000005F
:10002A0044616E67206E6861702E2E2E000D4D6F32
:10003A0069206E686170206E6F692064756E672032
:10004A006869656E207468693A0D546F6920646145
:10005A00203332206B79207475202D20456E74650B
:10006A0072206465206869656E207468690D54653C
:10007A0078743E20000D53656E6420746F204C43E3
:10008A00442E2E2E000D4E68616E207068696D2018
:10009A0057206465206E686170206D6F692E2E2E60
:1000AA000D00544553542055534152542041565241
:1000BA00210053616E6754616F436C75622E4E6501
:1000CA0074004E68616E207068696D2057206465FF
:1000DA00206E686170206E6F692064756E672120DA
:1000EA000D0080C00D0060012A0048006D01370034
:1000FA001000B5017F001D00C5018F000800E20154
:10010A0077001000EA01AC001000FA01BC002000E0
:10011A000A02CC0003000500260002004A02EC0095
:10012A000000F894EE27ECBBF1E0FBBFEBBFE5BFA4
:10013A00F8E1F1BDE1BD8DE0A2E0BB27ED938A9520
:10014A00E9F780E094E0A0E6ED930197E9F7EEEE97
:10015A00F0E085919591009761F0A591B591059090
:10016A001590BF01F00105900D920197E1F7FB018F
:10017A00F0CFEFE5EDBFE4E0EEBFC0E6D1E08BC023
:10018A005D9BFECFE881ECB93AC174D1EA81FB816B
:10019A0042D137D11E2F00E0011750F4AA81BB814A
:1001AA00EE27A00FBE1FEC91EA93EADF0F5FF4CFB0
:1001BA0064D1249608951A9310E0103220F4E12FA6
:1001CA002DD11F5FFACF199108950A921A92FA92C5
:1001DA006A937A938A939A93AA93BA93EA93FA932D
:1001EA00EFB7EA934CB0E7E5E41519F0E7E7E41551
:1001FA0019F4E0E0E71509F00BC016D1DCDFE0E600
:10020A00F1E017D1EDE6F1E016D1E1E07E2E35C03E
:10021A00EDE0E41519F4E1E0E71509F00DC0E5EBAE
:10022A00F1E009D101D1EAE2F2E003D1E5ECF1E033
:10023A0002D17724552421C0E8E0E41519F4E1E05D
:10024A00E71509F00BC0E0E0E51510F45A9403C075
:10025A00E2EEF1E0F0D0E52DE1D00FC0E1E0E715E4
:10026A0061F4EFE1E41510F45E1608F006C0E52D1E
:10027A005394F0E0E65DFD4F4082E991EFBFF991BA
:10028A00E991B991A9919991899179916991F99095
:10029A00199009901895E8E9EAB9E6E8E0BDE7E4BB
:1002AA00E9B9E0E1EA9384D0EAEEF1E0C2D0E4EF02
:1002BA00F1E0C3D0E0E0EA93E1E0EA933BD0EAEF71
:1002CA00F1E0B7D0E8EEF3E0B8D0EAE0F2E0B3D07C
:1002DA007894FFCFFFCFE881E07111F0949A01C0C2
:1002EA009498E881E07211F0959A01C09598E88196
:1002FA00E07411F0969A01C09698E881E07811F0BE
:10030A00979A01C0979887E08A95F1F7AA9A82E1AD
:10031A008A95F1F7AA9882E18A95F1F770C0E88187
:10032A008ED0E881E295E883E88189D088EB8A95C6
:10033A00F1F765C0E881F0E0E65BFD4FE081A98155
:10034A00EA0F7FD06980988022960895E2E079D0FA
:10035A00E3E0F0E072D0ECE074D0E1E072D0E3E0E8
:10036A00F0E06BD0E0E09E2E6E2E0895A881AA30B0
:10037A0011F0681440F0E0E0EA9393949A92DADF7D
:10038A00A881AA30E1F16394A89AE8815AD0A89882
:10039A0036C01A93A981BA81ED91A983BA831E2F17
:1003AA00E03019F01A93E2DFF5CF18812396089509
:1003BA008C9A8D9A8E9A8F9AA29AA09AA19AAA98A2
:1003CA00A898A9988880E881E058E0934C02E881CF
:1003DA00E054E0934D02E4E1F0E02FD0E0E32FD0C7
:1003EA0032D031D036D0E0E22AD033D0E8E229D078
:1003FA00E4E027D0E5E825D0E6E023D0A7DF219680
:10040A000895A991B991EE27FF276D91662311F0FE
:10041A003196FBCF0895FA93EA930895F0E0E65DEA
:10042A00FD4FA0E0A083089591DFE0E0EA93EA930C
:10043A0081CFF1DFAECFEFDFA8CEEDDF0FC0EA93B9
:10044A004ACFEA936CCF84E191E00197F1F7E0E3B8
:10045A00F6CF84E191E00197F1F70895E991F991D6
:10046A00309639F08DEC9AE00197F1F7A89531971B
:10047A00C9F708951A930A9308951981088108956E
:00000001FF
//Intel HEX format: https://en.wikipedia.org/wiki/Intel_HEX
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Độ dài tối đa của 1 dòng
#define MAX_HEX_LENGTH 16
// Số dòng in ra tối đa trong 1 lần
#define MAX_HEX_LINE 25
// Con trỏ file
FILE *fp;
// Mảng các đuôi file hex hợp lệ
char *hex_ext[14] = {".hex", ".h86", ".hxl", ".hxh", ".obl", ".obh", ".mcs", ".ihex", ".ihe", ".ihx", ".a43", ".a90", ".p00", ".pff"};
// Các loại header
typedef enum
{
data,
eof,
ext_seg_address,
start_seg_address,
ext_linr_address,
start_linr_address,
} RecordType;
// Dữ liệu của header
typedef struct
{
// Số lượng dữ liệu trên 1 dòng
int byte_count;
// Địa chỉ
int address;
// Loại header
RecordType record_type;
} HeaderData;
/// Hàm kiểm tra checksum
int valid_checksum(HeaderData header, int *data, int checksum)
{
// Tính checksum của dữ liệu
int sum = 0;
// Tính sum của header
sum = sum + header.byte_count //
+ ((header.address >> 8) & 255) // Dịch 8 bit sang bên phải để lấy 2 byte đầu của địa chỉ
+ (header.address & 255) // Lấy 2 byte cuối của địa chỉ
+ header.record_type;
// Cộng tất cả các byte của dữ liệu
for (int i = 0; i < header.byte_count; i++)
{
sum += data[i];
}
// Kiểm tra checksum theo công thức
if (((checksum & 255) + (sum & 255)) & 255)
{
return 0;
}
return 1;
}
// Lấy kí tự của file
int get_char()
{
int ch = fgetc(fp);
return ch;
}
/// In địa chỉ ô nhớ đầu tiên của dòng
/// `capacity` là địa chỉ đầu tiên của dòng
void print_memmory_address(int capacity)
{
printf("%.4X", capacity - MAX_HEX_LENGTH);
}
/// In giá trị hex của chuỗi kĩ tự `raw`
void print_hex_content(int *raw)
{
for (int i = 0; i < MAX_HEX_LENGTH; i++)
{
printf(" %02X ", (unsigned int)(raw[i] & 0xFF));
}
}
/// In giá trị ascii của chuỗi kĩ tự `raw`
void print_ascii_content(int *raw)
{
for (int i = 0; i < MAX_HEX_LENGTH; i++)
{
if (raw[i] != '\0')
{
// Kiểm tra một số kí tự đặc biệt như xuống dòng, tab hay dấu cách ... hiển thị kí tự `.` thay thế
if (raw[i] == '\n' || raw[i] == '\t' || raw[i] == '\r' || raw[i] == '\0' || raw[i] == 0x0C || raw[i] == 0x0B)
{
printf("%c", '.');
}
else
{
printf("%c", raw[i]);
}
}
else
{
printf("%c", '.');
}
}
}
/// Hiển thị một dòng hex
void display(int capacity, int *ch_array)
{
print_memmory_address(capacity);
printf(" | ");
print_hex_content(ch_array);
printf(" | ");
print_ascii_content(ch_array);
printf("\n");
}
void pause_display(int *line_of_hex)
{
printf("Xem them ... (Nhan phim Enter)");
char c = getchar();
if (c == '\n')
{
// Xóa màn hình
printf("\e[1;1H\e[2J");
*line_of_hex = 0;
}
}
int read_hex(FILE *fp)
{
char ch[2];
ch[0] = get_char();
ch[1] = get_char();
return (int)strtol(ch, NULL, 16);
}
int read_address(FILE *fp)
{
char ch[4];
ch[0] = get_char();
ch[1] = get_char();
ch[2] = get_char();
ch[3] = get_char();
return (int)strtol(ch, NULL, 16);
}
// Hàm lấy thông tin của header
HeaderData parse_header()
{
HeaderData header;
// Byte đầu tiên là số lượng dữ liệu trong dòng đó
header.byte_count = read_hex(fp);
header.address = read_address(fp);
int record_type = read_hex(fp);
if (record_type > 5 || record_type < 0)
{
header.record_type = 1;
}
else
{
header.record_type = record_type;
}
return header;
}
int main(int argc, char **argv)
{
// Kiểm tra số lượng đối số
if (argc < 2)
{
printf("Missing hex file link.\n");
return 1;
}
// Lấy ra đường dẫn file
char *file_name = argv[1];
char file_format[4];
// Lấy ra đuôi file
memcpy(file_format, &file_name[strlen(file_name) - 4], 4);
file_format[4] = '\0';
printf("FILE FORMAT: %s\n", file_format);
// Kiểm tra xem có phải file hex không
int is_hex_file = 0;
for (int i = 0; i < 14; i++)
{
// So sánh 2 string
if (strcmp(file_format, hex_ext[i]) == 0)
{
// Nếu là hex file thì gán 1 vào is_hex_file
is_hex_file = 1;
break;
}
}
// Không phải file hex
if (is_hex_file == 0)
{
printf("File format is not supported.\n");
return 1;
}
// Mở file hex
fp = fopen(argv[1], "r");
// Kiểm tra xem có mở được không
if (fp == NULL)
{
printf("Error: FILENAME could not be opened.\n");
return 1;
}
char ch;
HeaderData header;
// Dung lượng tối đa của file hex là 65536 (64Kb)
int hex_data[65536];
int capacity = 0;
// Đọc dữ liệu từ file ra
while ((ch = get_char()) != EOF)
{
// Kiểm tra xem đã vượt quá dung lượng tối đa chưa
if (capacity >= 65536)
{
printf("Error: File is too large.\n");
return 1;
}
// Bắt đầu đọc header
if (ch == ':')
{
header = parse_header();
int ch_array[header.byte_count];
for (int i = 0; i < header.byte_count; i++)
{
ch_array[i] = read_hex(fp);
}
// Phải có 2 byte_count
if (header.record_type == ext_linr_address)
{
// Khác 2 là không hợp lệ, dừng chương trình
if (header.byte_count != 2)
{
printf("Error: Invalid extended linear address.\n");
return 1;
}
}
else if (header.record_type == ext_seg_address)
{
if (header.byte_count != 2)
{
printf("Error: Invalid extended segment address.\n");
return 1;
}
}
else if (header.record_type == start_linr_address)
{
if (header.record_type != 4)
{
printf("Error: Invalid start linear address.\n");
return 1;
}
}
else if (header.record_type == start_seg_address)
{
if (header.record_type != 4)
{
printf("Error: Invalid start segment address.\n");
return 1;
}
}
// Kiểm tra data trên 1 dòng có hợp lệ không
int checksum = read_hex(fp);
if (!valid_checksum(header, ch_array, checksum))
{
printf("Error: Invalid checksum.\n");
return 1;
}
memcpy(&hex_data[capacity], ch_array, (header.byte_count) * sizeof(int));
capacity = capacity + header.byte_count;
}
}
// Số dòng hiện tại
int line_of_hex = 0;
int current_byte = 0;
// In đến hết data đã đọc
while (current_byte < capacity)
{
// Mỗi khi in 25 dòng thì hỏi người dùng có muốn in tiếp không
if (line_of_hex == MAX_HEX_LINE)
{
pause_display(&line_of_hex);
}
else
{
// Tạo ra 1 biến để lưu data trên 1 dòng
int ch_array[MAX_HEX_LENGTH];
// Copy data từ hex_data vào dòng này
for (int i = 0; i < MAX_HEX_LENGTH; i++)
{
ch_array[i] = hex_data[current_byte];
current_byte++;
}
// In ra sau khi copy hết 1 dòng
display(current_byte, ch_array);
// Tăng biến đếm số dòng lên 1
line_of_hex++;
}
}
fclose(fp);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment