ClipPlus BOOTLOADER DONT FIT!

REMOVED FROM ALL NATIVE BOOTLOADERS:
finish removing the text scrolling
pare down printf to a minimal subset (%c %s %l %d %u and %x(%p))
remove diacritic and rtl language support

GOAL 134000

START 135305

CURRENT 133700

SUCCESS! (ASSUMING IT WORKS -- UNESTED)

Change-Id: Ic3f6ac1dc260578f581ee53458b3e5bb47d313ec
This commit is contained in:
William Wilgus 2020-10-23 00:40:52 -04:00
parent a8aa8403ad
commit d78a37676e
7 changed files with 529 additions and 3 deletions

View file

@ -1,4 +1,6 @@
common.c
format.c
snprintf.c
#if defined(IPOD_NANO2G)
ipodnano2g.c

324
bootloader/format.c Normal file
View file

@ -0,0 +1,324 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Gary Czvitkovicz
* Copyright (C) 2017 by William Wilgus
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include <stdarg.h>
#include <stdbool.h>
#include <limits.h>
#include <string.h>
#include "file.h"
#include "format.h"
static const char hexdigit[] = "0123456789ABCDEF";
/* smaller compressed binary without inline but 18% slower */
#define FMT_DECL static inline
FMT_DECL int fmt_width_precision(int *ch, const char **fmt, char **str, va_list *ap)
{
int value = 0;
(void) str;
(void) ap;
while (*ch >= '0' && *ch <= '9')
{
value = 10 * value + (*ch - '0');
*ch = *(*fmt)++;
}
return value;
}
FMT_DECL int fmt_integer_signed(int *ch, const char **fmt, char **str, va_list *ap)
{
int val, rem, sign;
(void) ch;
(void) fmt;
val = sign = va_arg(*ap, int);
if (val < 0)
val = -val;
do {
rem = val % 10;
val /= 10;
*--(*str) = rem + '0';
} while (val > 0);
if (sign < 0)
*--(*str) = '-';
return 0;
}
FMT_DECL int fmt_integer_unsigned(int *ch, const char **fmt, char **str, va_list *ap)
{
unsigned int uval, urem;
(void) ch;
(void) fmt;
uval = va_arg(*ap, unsigned int);
do {
urem = uval % 10;
uval /= 10;
*--(*str) = urem + '0';
} while (uval > 0);
return 0;
}
FMT_DECL int fmt_long(int *ch, const char **fmt, char **str, va_list *ap)
{
int pad = 0;
long lval, lrem, lsign = 0;
unsigned long ulval, ulrem;
char ch_l = *ch;
*ch = *(*fmt)++;
if (*ch == 'd') {
lval = lsign = va_arg(*ap, long);
if (lval < 0)
lval = -lval;
do {
lrem = lval % 10;
lval /= 10;
*--(*str) = lrem + '0';
} while (lval > 0);
if (lsign < 0)
*--(*str) = '-';
}
else if (*ch == 'u') {
ulval = va_arg(*ap, unsigned long);
do {
ulrem = ulval % 10;
ulval /= 10;
*--(*str) = ulrem + '0';
} while (ulval > 0);
}
else if (*ch == 'x' || *ch == 'X') {
pad++;
ulval = va_arg(*ap, long);
do {
*--(*str) = hexdigit[ulval & 0xf];
ulval >>= 4;
} while (ulval > 0);
}
else {
*--(*str) = ch_l;
*--(*str) = *ch;
}
return pad;
}
FMT_DECL int fmt_character(int *ch, const char **fmt, char **str, va_list *ap)
{
(void) ch;
(void) fmt;
*--(*str) = va_arg(*ap, int);
return 0;
}
FMT_DECL int fmt_string(int *ch, const char **fmt, char **str, va_list *ap)
{
(void) ch;
(void) fmt;
*str = va_arg (*ap, char*);
return 0;
}
FMT_DECL int fmt_hex_unsigned(int *ch, const char **fmt, char **str, va_list *ap)
{
unsigned int uval;
(void) ch;
(void) fmt;
uval = va_arg(*ap, int);
do {
*--(*str) = hexdigit[uval & 0xf];
uval >>= 4;
} while (uval > 0);
return 1;
}
FMT_DECL int fmt_pointer(int *ch, const char **fmt, char **str, va_list *ap)
{
int pad = fmt_hex_unsigned(ch, fmt, str, ap);
/* for pointers prepend 0x and act like 'X' */
*--(*str) = 'x';
*--(*str) = '0';
return pad;
}
FMT_DECL int fmt_sizet(int *ch, const char **fmt, char **str, va_list *ap)
{
size_t uszval, uszrem;
ssize_t szval, szrem, szsign;
char ch_z = *ch;
*ch = *(*fmt)++;
if (*ch == 'd') {
szval = szsign = va_arg(*ap, ssize_t);
if (szval < 0)
szval = -szval;
do {
szrem = szval % 10;
szval /= 10;
*--(*str) = szrem + '0';
} while (szval > 0);
if (szsign < 0)
*--(*str) = '-';
}
else if (*ch == 'u') {
uszval = va_arg(*ap, size_t);
do {
uszrem = uszval % 10;
uszval /= 10;
*--(*str) = uszrem + '0';
} while (uszval > 0);
}
else {
*--(*str) = ch_z;
*--(*str) = *ch;
}
return 0;
}
static inline int fmt_next_char(int *ch, const char **fmt, char **str, va_list *ap)
{
(void) fmt;
(void) ap;
*--(*str) = *ch;
return 0;
}
void format(
/* call 'push()' for each output letter */
int (*push)(void *userp, unsigned char data),
void *userp,
const char *fmt,
va_list ap)
{
bool ok = true;
char *str;
char tmpbuf[12], pad;
int ch, width, precision, padded;
ch = *fmt++;
tmpbuf[sizeof tmpbuf - 1] = '\0';
do
{
if (ch == '%')
{
str = tmpbuf + sizeof tmpbuf - 1;
ch = *fmt++;
padded = (ch == '0' ? 1 : 0);
width = fmt_width_precision(&ch, &fmt, &str, &ap);
precision = INT_MAX;
if(ch == '.')
{
ch = *fmt++;
precision = fmt_width_precision(&ch, &fmt, &str, &ap);
}
if (ch == 'd')
fmt_integer_signed(&ch, &fmt, &str, &ap);
else if (ch == 'u')
fmt_integer_unsigned(&ch, &fmt, &str, &ap);
else if (ch == 'l')
padded += fmt_long(&ch, &fmt, &str, &ap);
else if (ch == 'c')
fmt_character(&ch, &fmt, &str, &ap);
else if (ch == 's')
fmt_string(&ch, &fmt, &str, &ap);
else if (ch == 'x' || ch == 'X')
padded += fmt_hex_unsigned(&ch, &fmt, &str, &ap);
else if (ch == 'p' || ch == 'P')
padded += fmt_pointer(&ch, &fmt, &str, &ap);
#if 0
else if (ch == 'z')
fmt_sizet(&ch, &fmt, &str, &ap);
#endif
else
fmt_next_char(&ch, &fmt, &str, &ap);
width -= strlen (str);
if (width > 0)
{
pad = (padded ? '0' : ' ');
while (width-- > 0 && ok)
ok=push(userp, pad);
}
while(*str != '\0' && ok && precision--)
ok=push(userp, *str++);
}
else
ok=push(userp, ch);
} while ((ch = *fmt++) != '\0' && ok);
}
struct for_fprintf {
int fd; /* where to store it */
int bytes; /* amount stored */
};
static int fprfunc(void *pr, unsigned char letter)
{
struct for_fprintf *fpr = (struct for_fprintf *)pr;
int rc = write(fpr->fd, &letter, 1);
if(rc > 0) {
fpr->bytes++; /* count them */
return true; /* we are ok */
}
return false; /* failure */
}
int fdprintf(int fd, const char *fmt, ...)
{
va_list ap;
struct for_fprintf fpr;
fpr.fd=fd;
fpr.bytes=0;
va_start(ap, fmt);
format(fprfunc, &fpr, fmt, ap);
va_end(ap);
return fpr.bytes; /* return 0 on error */
}
void vuprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap)
{
format(push, userp, fmt, ap);
}

37
bootloader/format.h Normal file
View file

@ -0,0 +1,37 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Felix Arends
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __FORMAT_H__
#define __FORMAT_H__
void format(
/* call 'push()' for each output letter */
int (*push)(void *userp, unsigned char data),
void *userp,
const char *fmt,
va_list ap);
/* callback function is called for every output character (byte) with userp and
* should return 0 when ch is a char other than '\0' that should stop printing */
void vuprintf(int (*push)(void *userp, unsigned char data),
void *userp, const char *fmt, va_list ap);
#endif /* __FORMAT_H__ */

80
bootloader/snprintf.c Normal file
View file

@ -0,0 +1,80 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2002 by Gary Czvitkovicz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
/*
* Minimal printf and snprintf formatting functions
*
* These support %c %s %l %d %u and %x(%p)
* Field width and zero-padding flag only
*/
#include <stdio.h>
#include <stdarg.h>
#include <stdbool.h>
#include <limits.h>
#include "format.h"
struct for_snprintf {
unsigned char *ptr; /* where to store it */
size_t bytes; /* amount already stored */
size_t max; /* max amount to store */
};
static int sprfunc(void *ptr, unsigned char letter)
{
struct for_snprintf *pr = (struct for_snprintf *)ptr;
if(pr->bytes < pr->max) {
*pr->ptr = letter;
pr->ptr++;
pr->bytes++;
return true;
}
return false; /* filled buffer */
}
int snprintf(char *buf, size_t size, const char *fmt, ...)
{
int len;
va_list ap;
va_start(ap, fmt);
len = vsnprintf(buf, size, fmt, ap);
va_end(ap);
return len;
}
int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
{
struct for_snprintf pr;
pr.ptr = (unsigned char *)buf;
pr.bytes = 0;
pr.max = size;
format(sprfunc, &pr, fmt, ap);
/* make sure it ends with a trailing zero */
pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
return pr.bytes;
}

View file

@ -194,7 +194,7 @@ static const struct diac_range diac_ranges[] =
};
#define MRU_MAX_LEN 32
#ifndef BOOTLOADER
bool is_diacritic(const unsigned short char_code, bool *is_rtl)
{
static uint8_t mru_len = 0;
@ -248,4 +248,12 @@ Found:
return (char_code < diac->base + (info & DIAC_CNT));
}
#else /*BOOTLOADER*/
inline bool is_diacritic(const unsigned short char_code, bool *is_rtl)
{
(void)char_code;
if (is_rtl)
*is_rtl = false;
return false;
}
#endif /* ndef BOOTLOADER*/

View file

@ -118,6 +118,7 @@ void LCDFN(update_viewport_rect)(int x, int y, int width, int height)
LCDFN(update_rect)(current_vp->x + x, current_vp->y + y, width, height);
}
#ifndef BOOTLOADER
/* put a string at a given pixel position, skipping first ofs pixel columns */
static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
{
@ -257,6 +258,72 @@ static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
}
font_lock(current_vp->font, false);
}
#else /* BOOTLOADER */
/* put a string at a given pixel position, skipping first ofs pixel columns */
static void LCDFN(putsxyofs)(int x, int y, int ofs, const unsigned char *str)
{
unsigned short *ucs;
struct font* pf = font_get(current_vp->font);
int vp_flags = current_vp->flags;
const unsigned char *bits;
int width;
if ((vp_flags & VP_FLAG_ALIGNMENT_MASK) != 0)
{
int w;
LCDFN(getstringsize)(str, &w, NULL);
/* center takes precedence */
if (vp_flags & VP_FLAG_ALIGN_CENTER)
{
x = ((current_vp->width - w)/ 2) + x;
if (x < 0)
x = 0;
}
else
{
x = current_vp->width - w - x;
x += ofs;
ofs = 0;
}
}
/* allow utf but no diacritics or rtl lang */
for (ucs = bidi_l2v(str, 1); *ucs; ucs++)
{
const unsigned short next_ch = ucs[1];
if (x >= current_vp->width)
break;
/* Get proportional width and glyph bits */
width = font_get_width(pf, *ucs);
if (ofs > width)
{
ofs -= width;
continue;
}
bits = font_get_bits(pf, *ucs);
#if defined(MAIN_LCD) && defined(HAVE_LCD_COLOR)
if (pf->depth)
lcd_alpha_bitmap_part(bits, ofs, 0, width, x, y,
width - ofs, pf->height);
else
#endif
LCDFN(mono_bitmap_part)(bits, ofs, 0, width, x,
y, width - ofs, pf->height);
if (next_ch)
{
x += width - ofs;
ofs = 0;
}
}
}
#endif
/*** pixel oriented text output ***/

View file

@ -52,7 +52,6 @@ static const char scroll_tick_table[18] = {
};
static void scroll_thread(void);
static char scroll_stack[DEFAULT_STACK_SIZE*3];
static const char scroll_name[] = "scroll";
#include "drivers/lcd-scroll.c"
@ -195,8 +194,11 @@ static void scroll_thread(void)
}
#endif /* HAVE_REMOTE_LCD */
#ifndef BOOTLOADER
void scroll_init(void)
{
static char scroll_stack[DEFAULT_STACK_SIZE*3];
#ifdef HAVE_REMOTE_LCD
queue_init(&scroll_queue, true);
#endif
@ -205,3 +207,9 @@ void scroll_init(void)
IF_PRIO(, PRIORITY_USER_INTERFACE)
IF_COP(, CPU));
}
#else
void scroll_init(void)
{
/* DUMMY */
}
#endif /* ndef BOOTLOADER*/