CPC: save autoload .SCR
with a .BAS if needed
This commit is contained in:
parent
5b5bdf54dc
commit
22b6c2439f
28
src/cpc_scr_simple_loader.h
Normal file
28
src/cpc_scr_simple_loader.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/* vim:expandtab:ts=2 sw=2:
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* author : unknown
|
||||||
|
*/
|
||||||
|
static const unsigned char cpc_scr_simple_loader[] = {
|
||||||
|
0x3a, 0xd0, 0xd7, // C7D0 LD A,(D7D0)
|
||||||
|
0xcd, 0x1c, 0xbd, // C7D3 CALL BD1C ; Set screen mode
|
||||||
|
0x21, 0xd1, 0xd7, // C7D6 LD HL,D7D1
|
||||||
|
0x46, // C7D9 LD B,(HL)
|
||||||
|
0x48, // C7DA LD C,B
|
||||||
|
0xcd, 0x38, 0xbc, // C7DB CALL BC38 ; Set border
|
||||||
|
0xaf, // C7DE XOR A
|
||||||
|
0x21, 0xd1, 0xd7, // C7DF LD HL,D7D1
|
||||||
|
0x46, // C7E2 LD B,(HL) <-------------------+
|
||||||
|
0x48, // C7E3 LD C,B |
|
||||||
|
0xf5, // C7E4 PUSH AF |
|
||||||
|
0xe5, // C7E5 PUSH HL |
|
||||||
|
0xcd, 0x32, 0xbc, // C7E6 CALL BC32 ; Set ink A to color B,C |
|
||||||
|
0xe1, // C7E9 POP HL |
|
||||||
|
0xf1, // C7EA POP AF |
|
||||||
|
0x23, // C7EB INC HL |
|
||||||
|
0x3c, // C7EC INC A |
|
||||||
|
0xfe, 0x10, // C7ED CP &10 |
|
||||||
|
0x20, 0xf1, // C7EF JZ NZ, C7E2 -------------------+
|
||||||
|
0xc3, 0x18, 0xbb // C7F1 JP BB18 ; Wait key
|
||||||
|
|
||||||
|
};
|
||||||
124
src/cpcformats.c
124
src/cpcformats.c
@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "fileformats.h"
|
#include "fileformats.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
@ -607,6 +608,9 @@ void Load_SCR(T_IO_Context * context)
|
|||||||
free(cpc_ram);
|
free(cpc_ram);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include "impdraw_loader.h"
|
||||||
|
#include "cpc_scr_simple_loader.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save Amstrad SCR file
|
* Save Amstrad SCR file
|
||||||
*
|
*
|
||||||
@ -633,32 +637,43 @@ void Save_SCR(T_IO_Context * context)
|
|||||||
unsigned char r1 = 0;
|
unsigned char r1 = 0;
|
||||||
int cpc_mode;
|
int cpc_mode;
|
||||||
FILE* file;
|
FILE* file;
|
||||||
|
int cpc_plus_pal = 0;
|
||||||
|
unsigned short load_address = 0xC000;
|
||||||
|
unsigned short exec_address = 0xC7D0;
|
||||||
|
int overscan;
|
||||||
|
byte cpc_hw_pal[16];
|
||||||
|
byte r12 = 0x0C | 0x30;
|
||||||
|
byte r13 = 0;
|
||||||
|
|
||||||
switch(context->Ratio)
|
switch(context->Ratio)
|
||||||
{
|
{
|
||||||
case PIXEL_WIDE:
|
case PIXEL_WIDE:
|
||||||
case PIXEL_WIDE2:
|
case PIXEL_WIDE2:
|
||||||
cpc_mode = 0;
|
cpc_mode = 0;
|
||||||
|
overscan = (context->Width * context->Height) > (16384 * 2);
|
||||||
break;
|
break;
|
||||||
case PIXEL_TALL:
|
case PIXEL_TALL:
|
||||||
case PIXEL_TALL2:
|
case PIXEL_TALL2:
|
||||||
case PIXEL_TALL3:
|
case PIXEL_TALL3:
|
||||||
cpc_mode = 2;
|
cpc_mode = 2;
|
||||||
|
overscan = (context->Width * context->Height) > (16384 * 8);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
cpc_mode = 1;
|
cpc_mode = 1;
|
||||||
|
overscan = (context->Width * context->Height) > (16384 * 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (overscan)
|
||||||
file = Open_file_write_with_alternate_ext(context, "pal");
|
|
||||||
if (file == NULL)
|
|
||||||
return;
|
|
||||||
if (!Write_byte(file, cpc_mode) || !Write_byte(file, 0) || !Write_byte(file, 0))
|
|
||||||
{
|
{
|
||||||
fclose(file);
|
// format iMP v2
|
||||||
return;
|
load_address = 0x170;
|
||||||
|
// picture at 0x200
|
||||||
|
r12 = 0x0C | (0x200 >> 9);
|
||||||
|
r13 = (0x200 >> 1) & 0xff;
|
||||||
|
exec_address = 0; // BASIC program !
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CPC_set_HW_palette(context->Palette + 0x40);
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
// search for the color in the HW palette (0x40-0x5F)
|
// search for the color in the HW palette (0x40-0x5F)
|
||||||
@ -669,12 +684,28 @@ void Save_SCR(T_IO_Context * context)
|
|||||||
if (index >= 0x60)
|
if (index >= 0x60)
|
||||||
{
|
{
|
||||||
GFX2_Log(GFX2_WARNING, "Save_SCR() color #%i not found in CPC HW palette.\n", i);
|
GFX2_Log(GFX2_WARNING, "Save_SCR() color #%i not found in CPC HW palette.\n", i);
|
||||||
// TODO : set CPC Plus flag
|
cpc_plus_pal = 1;
|
||||||
index = 0x54 - i; // default
|
index = 0x54 - i; // default
|
||||||
}
|
}
|
||||||
|
cpc_hw_pal[i] = index;
|
||||||
|
if (!CPC_is_CPC_old_color(context->Palette + i))
|
||||||
|
cpc_plus_pal = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
file = Open_file_write_with_alternate_ext(context, "pal");
|
||||||
|
if (file == NULL)
|
||||||
|
return;
|
||||||
|
CPC_write_AMSDOS_header(file, context->File_name, "pal", 2, 0x8809, 0x8809, 239);
|
||||||
|
if (!Write_byte(file, cpc_mode) || !Write_byte(file, 0) || !Write_byte(file, 0))
|
||||||
|
{
|
||||||
|
fclose(file);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
for (j = 0; j < 12; j++) // write the same color for the 12 frames
|
for (j = 0; j < 12; j++) // write the same color for the 12 frames
|
||||||
{
|
{
|
||||||
Write_byte(file, index);
|
Write_byte(file, cpc_hw_pal[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// border
|
// border
|
||||||
@ -694,7 +725,7 @@ void Save_SCR(T_IO_Context * context)
|
|||||||
}
|
}
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
|
||||||
output = raw2crtc(context, cpc_mode, 7, &outsize, &r1, 0x0C, 0);
|
output = raw2crtc(context, cpc_mode, 7, &outsize, &r1, r12, r13);
|
||||||
GFX2_Log(GFX2_DEBUG, "Save_SCR() output=%p outsize=%lu r1=$%02X\n", output, outsize, r1);
|
GFX2_Log(GFX2_DEBUG, "Save_SCR() output=%p outsize=%lu r1=$%02X\n", output, outsize, r1);
|
||||||
|
|
||||||
if (output == NULL)
|
if (output == NULL)
|
||||||
@ -706,9 +737,80 @@ void Save_SCR(T_IO_Context * context)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
File_error = 0;
|
File_error = 0;
|
||||||
|
CPC_write_AMSDOS_header(file, context->File_name, "SCR", overscan ? 0 : 2, load_address, exec_address, overscan ? 32400 : outsize);
|
||||||
|
if (overscan)
|
||||||
|
{
|
||||||
|
// write iMPdraw loader
|
||||||
|
byte buffer[0x90];
|
||||||
|
memcpy(buffer, impdraw_loader, 0x90);
|
||||||
|
buffer[0x184 - 0x170] = 0x0e + cpc_mode;
|
||||||
|
buffer[0x18e - 0x170] = r1;
|
||||||
|
//buffer[0x190 - 0x170] = // R2 ?
|
||||||
|
buffer[0x192 - 0x170] = context->Height / 8; // r6
|
||||||
|
//buffer[0x194 - 0x170] = // r7 ?
|
||||||
|
buffer[0x196 - 0x170] = r12;
|
||||||
|
buffer[0x198 - 0x170] = r13;
|
||||||
|
buffer[0x1ac - 0x170] = cpc_plus_pal;
|
||||||
|
if (!Write_bytes(file, buffer, 0x90))
|
||||||
|
File_error = 1;
|
||||||
|
output = realloc(output, 32400 - 0x90);
|
||||||
|
memset(output + outsize, 0, 32400 - 0x90 - outsize);
|
||||||
|
outsize = 32400 - 0x90;
|
||||||
|
memcpy(output + 0x7F00 - 0x200, cpc_hw_pal, 16);
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
output[0x601 + i*2] = (context->Palette[i].R & 0xf0) | (context->Palette[i].B >> 4);
|
||||||
|
output[0x602 + i*2] = context->Palette[i].G >> 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(output + exec_address - load_address, cpc_scr_simple_loader, sizeof(cpc_scr_simple_loader));
|
||||||
|
output[0xd7d0 - load_address] = cpc_mode;
|
||||||
|
//memcpy(output + 0xd7d1 - load_address, cpc_hw_pal, 16);
|
||||||
|
for (i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
output[0xd7d1 - load_address + i] = (context->Palette[i].G / 86) * 9 + (context->Palette[i].R / 86) * 3 + (context->Palette[i].B / 86);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!Write_bytes(file, output, outsize))
|
if (!Write_bytes(file, output, outsize))
|
||||||
File_error = 1;
|
File_error = 1;
|
||||||
fclose(file);
|
fclose(file);
|
||||||
|
if (!overscan)
|
||||||
|
{
|
||||||
|
file = Open_file_write_with_alternate_ext(context, "BAS");
|
||||||
|
if (file != NULL)
|
||||||
|
{
|
||||||
|
byte buffer[128];
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
|
buffer[2] = 10; // basic line number
|
||||||
|
buffer[4] = 0xad; // MODE
|
||||||
|
buffer[5] = ' ';
|
||||||
|
buffer[6] = 0x0e + cpc_mode;
|
||||||
|
buffer[7] = 0x01; // :
|
||||||
|
buffer[8] = 0xa8; // LOAD
|
||||||
|
buffer[9] = '"';
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (context->File_name[i] == '\0' || context->File_name[i] == '.')
|
||||||
|
break;
|
||||||
|
buffer[10+i] = (byte)toupper(context->File_name[i]);
|
||||||
|
}
|
||||||
|
memcpy(buffer + 10 + i, ".SCR\"", 5);
|
||||||
|
i += 15;
|
||||||
|
buffer[i++] = 0x01; // :
|
||||||
|
buffer[i++] = 0x83; // CALL
|
||||||
|
buffer[i++] = 0x1c; // &
|
||||||
|
buffer[i++] = 0xd0;
|
||||||
|
buffer[i++] = 0xc7;
|
||||||
|
buffer[i++] = 0x00;
|
||||||
|
buffer[0] = (byte)i; // length of line data
|
||||||
|
CPC_write_AMSDOS_header(file, context->File_name, "BAS", 0, 0x170, 0, i + 2);
|
||||||
|
if (!Write_bytes(file, buffer, 128))
|
||||||
|
File_error = 1;
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
free (output);
|
free (output);
|
||||||
}
|
}
|
||||||
|
|||||||
65
src/impdraw_loader.h
Normal file
65
src/impdraw_loader.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/* vim:expandtab:ts=2 sw=2:
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Amstrad CPC Loader for overscan picture.
|
||||||
|
* Locomotive BASIC + Z80 Code
|
||||||
|
* (c) Ast/iMP4CT
|
||||||
|
* https://amstradplus.forumforever.com/t462-iMPdraw-v2-0.htm?start=45
|
||||||
|
*/
|
||||||
|
static const unsigned char impdraw_loader[] = {
|
||||||
|
0x0e, 0x00, 0x0a, 0x00, 0x01, 0xc0, 0x20, 0x69, // starts at &0170
|
||||||
|
0x4d, 0x50, 0x20, 0x76, 0x32, 0x00, 0x0d, 0x00, // 10 ' iMP v2
|
||||||
|
0x14, 0x00, 0xad, 0x20, 0x0e, 0x01, 0x83, 0x1c, // 20 MODE 0:CALL &1ad
|
||||||
|
0xad, 0x01, 0x00, 0x00, 0x00, // &0184 : token 0x0e = 0, 0x0f = 1, 0x10 = 2
|
||||||
|
0x01, 0x30, 0x02, 0x32, 0x06, 0x22, 0x07, 0x23, // From &018d CRTC registers
|
||||||
|
0x0c, 0x0d, 0xd0, 0x00, 0x00, 0x3f,
|
||||||
|
0xff, 0x00, 0xff, 0x77, 0xb3, 0x51, 0xa8, 0xd4, // From &019b CPC Plus ASIC unlocking sequence
|
||||||
|
0x62, 0x39, 0x9c, 0x46, 0x2b, 0x15, 0x8a, 0xcd,
|
||||||
|
0xee,
|
||||||
|
0x00, // &01ac = CPC PLUS flag (0=CPC old, 1=CPC+)
|
||||||
|
0xf3, // 01ad di
|
||||||
|
0x21, 0x8d, 0x01, // 01ae ld hl,&018d
|
||||||
|
0x3e, 0x06, // 01b1 ld a,&06
|
||||||
|
0x01, 0xbe, 0xbd, // 01b3 ld bc,BDBE
|
||||||
|
0xed, 0xa3, // 01b6 outi ; first decrements b <---+
|
||||||
|
0x41, // 01b8 ld b,c |
|
||||||
|
0xed, 0xa3, // 01b9 outi |
|
||||||
|
0x3d, // 01bb dec a |
|
||||||
|
0x20, 0xf8, // 01bc jz nz,01B6 ; loop ------------+
|
||||||
|
// load colors into gate array (from 7F00 ;)
|
||||||
|
0x01, 0x00, 0x7f, // 01be ld bc,7F00 ; Gate array
|
||||||
|
0x1e, 0x10, // 01c1 ld e,10
|
||||||
|
0x0a, // 01c3 ld a,(bc) <---+
|
||||||
|
0xed, 0x49, // 01c4 out (c),c ; select ink# |
|
||||||
|
0xed, 0x79, // 01c6 out (c),a ; set ink |
|
||||||
|
0x0c, // 01c8 inc c |
|
||||||
|
0x1d, // 01c9 dec e |
|
||||||
|
0x20, 0xf7, // 01ca jz nz,01C3 ; loop ---------+
|
||||||
|
|
||||||
|
0x3a, 0xac, 0x01, // 01cc ld a,01AC ; CPC PLUS flag
|
||||||
|
0xfe, 0x01, // 01cf cp 01
|
||||||
|
0x20, 0x22, // 01d1 jz nz,01F5 ; flag != 1 => skip CPC+
|
||||||
|
// CPC Plus ASIC unlock
|
||||||
|
0x21, 0x9b, 0x01, // 01d3 ld hl,019B
|
||||||
|
0x01, 0x11, 0xbc, // 01d6 ld bc,BC11
|
||||||
|
0x7e, // 01d9 ld a,(hl) <---+
|
||||||
|
0xed, 0x79, // 01da out (c),a |
|
||||||
|
0x2c, // 01dc inc l |
|
||||||
|
0x0d, // 01dd dec c |
|
||||||
|
0x20, 0xf9, // 01de jr nz,01D9 ; loop --+
|
||||||
|
// set CPC Plus colors
|
||||||
|
0x01, 0xb8, 0x7f, // 01e0 ld bc,7FB8
|
||||||
|
0xed, 0x49, // 01e3 out (c),c ; open ASIC I/O
|
||||||
|
0x21, 0x01, 0x08, // 01e5 ld hl,0801
|
||||||
|
0x11, 0x00, 0x64, // 01e8 ld de,6400
|
||||||
|
0x01, 0x20, 0x00, // 01eb ld bc,0020
|
||||||
|
0xed, 0xb0, // 01ee ldir ; copy bc bytes from (hl) to (de)
|
||||||
|
0x01, 0xa0, 0x7f, // 01f0 ld bc,7FA0
|
||||||
|
0xed, 0x49, // 01f3 out (c),c ; close ASIC I/O
|
||||||
|
|
||||||
|
0x21, 0xf9, 0xb7, // 01f5 ld hl,B7F9 ; SCR Event Block: Set Inks
|
||||||
|
0xcd, 0xdd, 0xbc, // 01f8 call BCDD ; remove event block for CRTC IRQ
|
||||||
|
0xfb, // 01fb ei
|
||||||
|
0xc3, 0x18, 0xbb, // 01fc jp BB18 ; Wait Keypress
|
||||||
|
0x00 // 01ff
|
||||||
|
};
|
||||||
55
src/oldies.c
55
src/oldies.c
@ -27,6 +27,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "struct.h"
|
#include "struct.h"
|
||||||
#include "oldies.h"
|
#include "oldies.h"
|
||||||
@ -724,6 +725,23 @@ int CPC_compare_colors(T_Components * col1, T_Components * col2)
|
|||||||
return v1 == v2;
|
return v1 == v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CPC_is_CPC_old_color(T_Components * col)
|
||||||
|
{
|
||||||
|
if (15 < col->R && col->R < 0x60)
|
||||||
|
return 0;
|
||||||
|
if (0x82 < col->R && col->R < 0xf0)
|
||||||
|
return 0;
|
||||||
|
if (15 < col->G && col->G < 0x60)
|
||||||
|
return 0;
|
||||||
|
if (0x82 < col->G && col->G < 0xf0)
|
||||||
|
return 0;
|
||||||
|
if (15 < col->B && col->B < 0x60)
|
||||||
|
return 0;
|
||||||
|
if (0x82 < col->B && col->B < 0xf0)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void CPC_set_default_BASIC_palette(T_Components * palette)
|
void CPC_set_default_BASIC_palette(T_Components * palette)
|
||||||
{
|
{
|
||||||
static const byte basic_colors[] = {
|
static const byte basic_colors[] = {
|
||||||
@ -808,6 +826,43 @@ int CPC_check_AMSDOS(FILE * file, word * loading_address, word * exec_address, u
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int CPC_write_AMSDOS_header(FILE * file, const char * filename, const char * ext, byte type, word load_address, word exec_address, word file_length)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
word checksum = 0;
|
||||||
|
byte header[128];
|
||||||
|
|
||||||
|
memset(header, 0, sizeof(header));
|
||||||
|
memset(header + 1, ' ', 11);
|
||||||
|
for (i = 0 ; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (filename[i] == '\0' || filename[i] == '.')
|
||||||
|
break;
|
||||||
|
header[1+i] = (byte)toupper(filename[i]);
|
||||||
|
}
|
||||||
|
for (i = 0 ; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (ext[i] == '\0' || ext[i] == '.')
|
||||||
|
break;
|
||||||
|
header[9+i] = (byte)toupper(ext[i]);
|
||||||
|
}
|
||||||
|
header[18] = type;
|
||||||
|
header[21] = load_address & 0xff;
|
||||||
|
header[22] = load_address >> 8;
|
||||||
|
header[24] = file_length & 0xff;
|
||||||
|
header[25] = file_length >> 8;
|
||||||
|
header[26] = exec_address & 0xff;
|
||||||
|
header[27] = exec_address >> 8;
|
||||||
|
header[64] = file_length & 0xff;
|
||||||
|
header[65] = file_length >> 8;
|
||||||
|
for (i = 0; i < 67; i++)
|
||||||
|
checksum += (word)header[i];
|
||||||
|
header[67] = checksum & 0xff;
|
||||||
|
header[68] = checksum >> 8;
|
||||||
|
GFX2_LogHexDump(GFX2_DEBUG, "AMSDOS ", header, 0, sizeof(header));
|
||||||
|
return Write_bytes(file, header, sizeof(header));
|
||||||
|
}
|
||||||
|
|
||||||
int DECB_Check_binary_file(FILE * f)
|
int DECB_Check_binary_file(FILE * f)
|
||||||
{
|
{
|
||||||
byte code;
|
byte code;
|
||||||
|
|||||||
10
src/oldies.h
10
src/oldies.h
@ -109,6 +109,11 @@ void ZX_Spectrum_set_palette(T_Components * palette);
|
|||||||
*/
|
*/
|
||||||
void CPC_set_HW_palette(T_Components * palette);
|
void CPC_set_HW_palette(T_Components * palette);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the color is likely to be a CPC RGB tri level color
|
||||||
|
*/
|
||||||
|
int CPC_is_CPC_old_color(T_Components * col);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set 16 color default Amstrad CPC BASIC palette
|
* Set 16 color default Amstrad CPC BASIC palette
|
||||||
*
|
*
|
||||||
@ -147,6 +152,11 @@ byte CPC_Firmware_to_Hardware_color(byte fw_color);
|
|||||||
*/
|
*/
|
||||||
int CPC_check_AMSDOS(FILE * file, word * loading_address, word * exec_address, unsigned long * file_length);
|
int CPC_check_AMSDOS(FILE * file, word * loading_address, word * exec_address, unsigned long * file_length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write AMSDOS header
|
||||||
|
*/
|
||||||
|
int CPC_write_AMSDOS_header(FILE * file, const char * filename, const char * ext, byte type, word load_address, word save_address, word file_length);
|
||||||
|
|
||||||
/** @}*/
|
/** @}*/
|
||||||
|
|
||||||
/** @defgroup decb DECB binary format
|
/** @defgroup decb DECB binary format
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user