Last active
March 1, 2022 14:49
-
-
Save definev/0235fc17860496b3e304894b67ddea70 to your computer and use it in GitHub Desktop.
Intel hex display written in C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
: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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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