Corrected BCD management
This commit is contained in:
parent
ec87751909
commit
1d7c99d3df
|
@ -36,19 +36,25 @@ extern "C" {
|
|||
* This is the "unzipped" BCD format. There are several, this is the one libg1m
|
||||
* will always convert to.
|
||||
*
|
||||
* `neg` is whether the number is negative or not.
|
||||
* `flags` is the flags (negative, special, precision) of the BCD.
|
||||
* `exp` is the 10-exponent, between -99 and 99.
|
||||
* `digits` is the number of significant digits in the mantissa.
|
||||
* `spe` is the special bit.
|
||||
* `mant` is the mantissa: unpacked BCD digits (one digit per byte).
|
||||
*
|
||||
* It is advised to use the macros, as some of these could change. */
|
||||
* To interact the flags, it is advised to use the g1m_bcd_* macros, as some
|
||||
* of them could change. */
|
||||
|
||||
# define g1m_bcdflag_neg 0x80
|
||||
# define g1m_bcdflag_spe 0x40
|
||||
# define g1m_bcdmask_pre 0x3F
|
||||
|
||||
# define g1m_bcd_has_special(B) ((B)->flags & g1m_bcdflag_spe)
|
||||
# define g1m_bcd_is_negative(B) ((B)->flags & g1m_bcdflag_neg)
|
||||
# define g1m_bcd_precision(B) ((B)->flags & g1m_bcdmask_pre)
|
||||
# define g1m_make_bcdflags(SPE, NEG, PREC) \
|
||||
(((SPE) << 7) | ((NEG) << 6) | (PREC))
|
||||
|
||||
# define g1m_bcd_has_special(B) ((B)->spe)
|
||||
# define g1m_bcd_is_negative(B) ((B)->neg)
|
||||
typedef struct g1m_bcd_s {
|
||||
int exp, digits;
|
||||
int neg, spe; /* use the macros for these! */
|
||||
unsigned char flags; char exp;
|
||||
char mant[G1M_BCD_MANTISSA_SIZE];
|
||||
} g1m_bcd_t;
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ int g1m_bcd_fromcas(const cas_bcd_t *raw, g1m_bcd_t *bcd)
|
|||
const unsigned char *bytes = raw->mantissa;
|
||||
|
||||
/* get the exponent and sign */
|
||||
bcd->digits = 15;
|
||||
bcd->exp = (raw->exponent >> 4) * 10 + (raw->exponent & 0x0F);
|
||||
if (raw->signinfo & g1m_casbcd_pow_neg)
|
||||
bcd->exp = -bcd->exp;
|
||||
|
@ -57,9 +56,9 @@ int g1m_bcd_fromcas(const cas_bcd_t *raw, g1m_bcd_t *bcd)
|
|||
bcd->mant[14] = lwr(7);
|
||||
|
||||
/* set the special things and return */
|
||||
bcd->neg = raw->signinfo & g1m_casbcd_negative;
|
||||
bcd->spe = raw->signinfo & g1m_casbcd_special;
|
||||
return (bcd->spe);
|
||||
bcd->flags = g1m_make_bcdflags(!!(raw->signinfo & g1m_casbcd_special),
|
||||
(raw->signinfo & g1m_casbcd_negative) == g1m_casbcd_negative, 15);
|
||||
return (g1m_bcd_has_special(bcd));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -88,7 +87,10 @@ void g1m_bcd_tocas(const g1m_bcd_t *bcd, cas_bcd_t *raw)
|
|||
|
||||
/* put the flags */
|
||||
raw->signinfo = 0;
|
||||
if (bcd->exp < 0) raw->signinfo |= g1m_casbcd_pow_neg;
|
||||
if (bcd->neg) raw->signinfo |= g1m_casbcd_negative;
|
||||
if (bcd->spe) raw->signinfo |= g1m_casbcd_special;
|
||||
if (bcd->exp < 0)
|
||||
raw->signinfo |= g1m_casbcd_pow_neg;
|
||||
if (g1m_bcd_is_negative(bcd))
|
||||
raw->signinfo |= g1m_casbcd_negative;
|
||||
if (g1m_bcd_has_special(bcd))
|
||||
raw->signinfo |= g1m_casbcd_special;
|
||||
}
|
||||
|
|
|
@ -33,15 +33,13 @@ int g1m_bcd_frommcs(const mcs_bcd_t *raw, g1m_bcd_t *bcd)
|
|||
{
|
||||
const unsigned char *bytes = raw->BCDval;
|
||||
|
||||
/* get the 10-exponent */
|
||||
bcd->digits = 15;
|
||||
bcd->spe = upr(0) & 0x8;
|
||||
bcd->exp = (upr(0) & 7) * 100 + lwr(0) * 10 + upr(1);
|
||||
/* get the exponent and correct it */
|
||||
int exp = (upr(0) & 7) * 100 + lwr(0) * 10 + upr(1), neg = 0;
|
||||
if (exp >= 500) exp -= 500, neg = 1;
|
||||
bcd->exp = (char)(exp - 99);
|
||||
|
||||
/* check the negative number, correct the exponent */
|
||||
bcd->neg = 0;
|
||||
if (bcd->exp >= 500) bcd->exp -= 500, bcd->neg = 1;
|
||||
bcd->exp -= 99;
|
||||
/* set the flags */
|
||||
bcd->flags = g1m_make_bcdflags(bytes[0] & 0x80 >> 7, neg, 15);
|
||||
|
||||
/* get the mantissa */
|
||||
bcd->mant[0] = lwr(1);
|
||||
|
@ -61,7 +59,7 @@ int g1m_bcd_frommcs(const mcs_bcd_t *raw, g1m_bcd_t *bcd)
|
|||
bcd->mant[14] = lwr(8);
|
||||
|
||||
/* return the special bit */
|
||||
return (bcd->spe);
|
||||
return (g1m_bcd_has_special(bcd));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,12 +73,12 @@ int g1m_bcd_frommcs(const mcs_bcd_t *raw, g1m_bcd_t *bcd)
|
|||
void g1m_bcd_tomcs(const g1m_bcd_t *bcd, mcs_bcd_t *raw)
|
||||
{
|
||||
int exp = bcd->exp + 99;
|
||||
if (bcd->neg) exp += 500;
|
||||
if (g1m_bcd_is_negative(bcd)) exp += 500;
|
||||
|
||||
/* put the exponent (and first digit of the mantissa) */
|
||||
div_t c = div(exp, 100);
|
||||
div_t d = div(c.rem, 10);
|
||||
raw->BCDval[0] = (c.quot << 4) | d.quot | (!!bcd->spe << 7);
|
||||
raw->BCDval[0] = (c.quot << 4) | d.quot | (!!g1m_bcd_has_special(bcd) << 7);
|
||||
raw->BCDval[1] = (d.rem << 4) | bcd->mant[0];
|
||||
|
||||
/* put the mantissa */
|
||||
|
|
|
@ -84,7 +84,7 @@ int g1m_decode_mcs_matrix(g1m_mcsfile_t *handle, g1m_buffer_t *buffer,
|
|||
for (uint_fast32_t y = 0; y < h; y++)
|
||||
for (uint_fast32_t x = 0; x < w; x++) {
|
||||
GDREAD(rawbcd, bcd)
|
||||
if (tab[y][x].real.spe) {
|
||||
if (g1m_bcd_has_special(&tab[y][x].real)) {
|
||||
g1m_bcd_frommcs(&rawbcd, &bcd);
|
||||
tab[y][x].imgn = bcd;
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ struct group_corresp {
|
|||
/* Correspondances */
|
||||
/* ************************************************************************** */
|
||||
/* All correspondances. Some remarks:
|
||||
* - I think files with "PROGRAM" group are splitted because it was originally
|
||||
* - I think files with "PROGRAM" group are split because it was originally
|
||||
* planned they would be in groups like 'PROGRAM <name>', like for captures
|
||||
* or lists, but they abandoned that. Why they made such groups, I have no
|
||||
* idea yet.
|
||||
|
|
Reference in New Issue