Page 1 of 2

C--

Unread postPosted: 14 Oct 2019, 17:12
by parisse
Il me semble que programmer la Numworks est difficile, en tout cas pour moi qui n'aime pas les hierarchies de classe du C++ et qui ai l'habitude de travailler avec emacs et des gros fichiers sans arborescence et pas avec un gros IDE.
Je poste ici quelques routines que j'ai eu beaucoup de mal a rassembler, qui j'espere faciliteront le travail a d'autres. Tout cela est base sur le firmware 11.
Le 1er point a resoudre est avoir un point d'entree depuis l'OS. Je pense que la frappe de la touche Home depuis Home est un bon point d'entree. Pour cela ajouter dans apps/home/controler.cpp
Code: Select all
bool Controller::handleEvent(Ion::Events::Event event) {
  if (event==Ion::Events::Home){
    caseval("+"); // appeler ici votre programme
    AppsContainer::sharedAppsContainer()->m_window.redraw(true);
    return true;
  }
...
}


J'ai ajoute des fonctions dans python/port.cpp pour attendre une touche (getKey) et gerer la ligne d'etat.
Il faudra un peu les modifier pour un autre usage que dans KhiCAS.
Code: Select all
void statuslinemsg(const char * msg){
  AppsContainer::sharedAppsContainer()->reloadTitleBarView();
  auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment();
  if (ptr)
    ptr->displaySandbox();
  auto ctx=KDIonContext::sharedContext();
  KDRect save=ctx->m_clippingRect;
  KDPoint o=ctx->m_origin;
  ctx->setClippingRect(KDRect(0,0,280,18));
  ctx->setOrigin(KDPoint(0,0));
  KDRect rect(0,0,280,18);
  KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/);
  if (strlen(msg)>25)
    ctx->drawString(msg, KDPoint(0,0), KDFont::SmallFont, 0, 64934);
  else
    ctx->drawString(msg, KDPoint(0,0), KDFont::LargeFont, 0, 64934);
  ctx->setClippingRect(save);
  ctx->setOrigin(o);
}

void statusline(int mode){
  AppsContainer::sharedAppsContainer()->reloadTitleBarView();
  auto ctx=KDIonContext::sharedContext();
  KDRect save=ctx->m_clippingRect;
  KDPoint o=ctx->m_origin;
  ctx->setClippingRect(KDRect(0,0,320,18));
  ctx->setOrigin(KDPoint(0,0));
  KDRect rect(0,0,mode==1?320:280,18);
  KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/);
  const char * text=0;
  Poincare::Preferences * preferences = Poincare::Preferences::sharedPreferences();
  if (preferences->angleUnit() == Poincare::Preferences::AngleUnit::Radian)
    text="rad";
  else
    text="deg";
  // ctx->drawString(text, KDPoint(5,1), KDFont::SmallFont, 0, 63488 /* Palette::Red*/);
  ctx->drawString(text, KDPoint(5,1), KDFont::SmallFont, 0, 64934);
  if (khicas_eval)
    text="KHICAS";
  else
    text="PYTHON";
  ctx->drawString(text, KDPoint(100,1), KDFont::SmallFont, 0, 64934);
  text="     ";
  if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::Shift)
    text="shift ";
  else {
    if (Ion::Events::isAlphaActive()){
      if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::AlphaLock)
   text="alphal";
      if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::ShiftAlphaLock)
   text="ALPHAL";
      if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::Alpha)
   text="1alpha";
      if (Ion::Events::shiftAlphaStatus()==Ion::Events::ShiftAlphaStatus::ShiftAlpha)
   text="1ALPHA";
    }
  }
  ctx->drawString(text, KDPoint(248,1), KDFont::SmallFont, 0, 64934 /* Palette::YellowDark*/);
  if (mode==1){
    if (Ion::USB::isPlugged())
      text="charge";
    else {
      auto c=Ion::Battery::level();
      if (c==Ion::Battery::Charge::EMPTY)
   text="empty";
      if (c==Ion::Battery::Charge::LOW)
   text="low";
      if (c==Ion::Battery::Charge::FULL)
   text="full";
    }
    ctx->drawString(text, KDPoint(280,1), KDFont::SmallFont, 0, 64934 /* Palette::YellowDark*/);
  }
  ctx->setClippingRect(save);
  ctx->setOrigin(o);
}

bool isalphaactive(){
  return Ion::Events::isAlphaActive();
}

void lock_alpha(){
  Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::AlphaLock);
  statusline(0);
}

void reset_kbd(){
  Ion::Events::setShiftAlphaStatus(Ion::Events::ShiftAlphaStatus::Default);
  statusline(0);
}

void os_redraw(){
  AppsContainer::sharedAppsContainer()->m_window.redraw(true);
}

bool alphawasactive=false;

int getkey_raw(bool allow_suspend){
  int key=-1;
  for (;;){
    int timeout=10000;
    alphawasactive=Ion::Events::isAlphaActive();
    Ion::Events::Event event=Ion::Events::getEvent(&timeout);
    auto ctx=KDIonContext::sharedContext();
    KDRect save=ctx->m_clippingRect;
    KDPoint o=ctx->m_origin;
    ctx->setClippingRect(KDRect(0,0,320,240));
    ctx->setOrigin(KDPoint(0,0));
    KDRect rect(0,0,320,240);
    if (event == Ion::Events::USBPlug) {
      KDIonContext::sharedContext()->pushRectUniform(rect,33333);
      if (Ion::USB::isPlugged()) {
   if (GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate) {
     Ion::LED::setColor(KDColorBlack);
     Ion::LED::updateColorWithPlugAndCharge();
     GlobalPreferences::sharedGlobalPreferences()->setExamMode(GlobalPreferences::ExamMode::Deactivate);
     // displayExamModePopUp(false);
   } else {
     Ion::USB::enable();
   }
   Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel());
      } else {
   Ion::USB::disable();
      }
    }
    if (event == Ion::Events::USBEnumeration || event == Ion::Events::USBPlug || event == Ion::Events::BatteryCharging) {
      Ion::LED::updateColorWithPlugAndCharge();
    }
    if (event == Ion::Events::USBEnumeration
   ) {
      KDIonContext::sharedContext()->pushRectUniform(rect,64934 /* Palette::YellowDark*/);
      if (Ion::USB::isPlugged()) {
   /* Just after a software update, the battery timer does not have time to
    * fire before the calculator enters DFU mode. As the DFU mode blocks the
    * event loop, we update the battery state "manually" here.
    * We do it before switching to USB application to redraw the battery
    * pictogram. */
   // updateBatteryState();
   KDIonContext::sharedContext()->pushRectUniform(rect,65535);
   Ion::USB::DFU();
   KDIonContext::sharedContext()->pushRectUniform(rect,22222);
   // Update LED when exiting DFU mode
   Ion::LED::updateColorWithPlugAndCharge();
      } else {
   /* Sometimes, the device gets an ENUMDNE interrupts when being unplugged
    * from a non-USB communicating host (e.g. a USB charger). The interrupt
    * must me cleared: if not the next enumeration attempts will not be
    * detected. */
   Ion::USB::clearEnumerationInterrupt();
      }
    }
    if (event.isKeyboardEvent()) {
      // m_backlightDimmingTimer.reset();
      // m_suspendTimer.reset();
      Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel());
    }
    ctx->setClippingRect(save);
    ctx->setOrigin(o);
   
    if (event==Ion::Events::Shift || event==Ion::Events::Alpha){
      statusline();
      continue;
    }
    if (event.isKeyboardEvent()){
      key=event.id();
      if (allow_suspend && (key==7 || key==8) ){ // power
   Ion::Power::suspend(true);
   Ion::Backlight::setBrightness(GlobalPreferences::sharedGlobalPreferences()->brightnessLevel());
   AppsContainer::sharedAppsContainer()->reloadTitleBarView();
   //AppsContainer::sharedAppsContainer()->redrawWindow();
   statusline(1);
   //continue;
      }
      else
   statusline();
      break;
    }
  }
  return key;
}

const short int translated_keys[]=
  {
   // non shifted
   KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT,
   KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11,
   KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_XTT,KEY_CTRL_VARS,KEY_CTRL_CATALOG,KEY_CTRL_DEL,
   KEY_CHAR_EXP,KEY_CHAR_LN,KEY_CHAR_LOG,KEY_CHAR_IMGNRY,',',KEY_CHAR_POW,
   KEY_CHAR_SIN,KEY_CHAR_COS,KEY_CHAR_TAN,KEY_CHAR_PI,KEY_CHAR_ROOT,KEY_CHAR_SQUARE,
   '7','8','9','(',')',-1,
   '4','5','6','*','/',-1,
   '1','2','3','+','-',-1,
   '0','.',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1,
   // shifted
   KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT,
   KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11,
   KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,KEY_CTRL_CUT,KEY_CTRL_CLIP,KEY_CTRL_PASTE,KEY_CTRL_DEL,
   KEY_CHAR_LBRCKT,KEY_CHAR_RBRCKT,KEY_CHAR_LBRACE,KEY_CHAR_RBRACE,'_',KEY_CHAR_STORE,
   KEY_CHAR_ASIN,KEY_CHAR_ACOS,KEY_CHAR_ATAN,'=','<','>',
   '7','8','9','(',')',-1,
   '4','5','6',KEY_CHAR_FACTOR,'%',-1,
   '1','2','3',KEY_CHAR_NORMAL,'\\',-1,
   '0','.',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1,
   // alpha
   KEY_CTRL_LEFT,KEY_CTRL_UP,KEY_CTRL_DOWN,KEY_CTRL_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT,
   KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11,
   KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','"',KEY_CTRL_DEL,
   'a','b','c','d','e','f',
   'g','h','i','j','k','l',
   'm','n','o','p','q',-1,
   'r','s','t','u','v',-1,
   'w','x','y','z',' ',-1,
   '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1,
   // alpha shifted
   KEY_SHIFT_LEFT,KEY_CTRL_PAGEUP,KEY_CTRL_PAGEDOWN,KEY_SHIFT_RIGHT,KEY_CTRL_OK,KEY_CTRL_EXIT,
   KEY_CTRL_MENU,KEY_PRGM_ACON,KEY_PRGM_ACON,9,10,11,
   KEY_CTRL_SHIFT,KEY_CTRL_ALPHA,':',';','\'','%',
   'A','B','C','D','E','F',
   'G','H','I','J','K','L',
   'M','N','O','P','Q',-1,
   'R','S','T','U','V',-1,
   'W','X','Y','Z',' ',-1,
   '?','!',KEY_CHAR_EXPN10,KEY_CHAR_ANS,KEY_CTRL_EXE,-1,
  };

int getkey(bool allow_suspend){
  int k=getkey_raw(allow_suspend);
  // translate
  return translated_keys[k];
}

// Casio prototype
void GetKey(int * key){
  *key=getkey(true);
}

void numworks_wait_1ms(int ms){
  for (int i=0;i<ms/128;++i){
#ifdef SIMULATOR
    Fl::wait(0.00001);
#endif
    Ion::Keyboard::State scan = Ion::Keyboard::scan();
      // if (scan!=16) std::cerr << scan << '\n';
    Ion::Keyboard::Key interruptKey = static_cast<Ion::Keyboard::Key>(Ion::Keyboard::Key::Back);
    if (scan.keyDown(interruptKey))
      return;
    Ion::Timing::msleep(128);
  }
  Ion::Timing::msleep(ms % 128); 
}


Pour les traces, j'ai ajoute dans modkandinsky.cpp

Code: Select all
#define LCD_WIDTH_PX 320
#define LCD_HEIGHT_PX 222

void numworks_giac_set_pixel(int x, int y, int color) {
  auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment();
  if (ptr) ptr->displaySandbox();
  KDColor c(color);
#if 1
  if (x<0 || x>=LCD_WIDTH_PX || y<0 || y>=LCD_HEIGHT_PX)
    return;
  KDPoint point(x,y+18);
  KDIonContext::sharedContext()->pushRect(KDRect(point, 1, 1), &c);
#else
  KDPoint point(x,y);
  KDIonContext::sharedContext()->setPixel(point,c);
#endif
}

void numworks_giac_fill_rect(int x,int y,int w,int h,int c){
  KDColor color = c;
  auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment();
  if (ptr) ptr->displaySandbox();
#if 1
  if (x<0){
    w += x;
    x=0;
  }
  if (y<0){
    h += y;
    y=0;
  }
  if (h+y>=LCD_HEIGHT_PX)
    h=LCD_HEIGHT_PX-y;
  if (x+w>=LCD_WIDTH_PX)
    w=LCD_WIDTH_PX-x;
  if (h<=0 || w<=0)
    return;
  KDRect rect(x,y+18,w,h);
  KDIonContext::sharedContext()->pushRectUniform(rect,color);
#else
  KDRect rect(x,y,w,h);
  KDIonContext::sharedContext()->fillRect(rect, color);
#endif
}

int numworks_giac_get_pixel(int x, int y) {
  KDPoint point(x,y);
  KDColor c = KDIonContext::sharedContext()->getPixel(point);
  return c;
}

// renvoie la position horizontale en fin de trace
// si fake est true on n'ecrit rien, on calcule juste la longueur de l'affichage
int numworks_giac_draw_string(int x,int y,int c,int bg,const char * text,bool fake){
  auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment();
  KDPoint point(x,y);
  if (ptr)
    ptr->displaySandbox();
  auto ctx=KDIonContext::sharedContext();
  KDRect save=ctx->m_clippingRect;
  KDPoint o=ctx->m_origin;
  ctx->setClippingRect(KDRect(0,18,320,fake?0:222));
  ctx->setOrigin(KDPoint(0,18));
  point=KDIonContext::sharedContext()->drawString(text, point, KDFont::LargeFont, c, bg);
  ctx->setClippingRect(save);
  ctx->setOrigin(o);
  return point.x();
}

int numworks_giac_draw_string_small(int x,int y,int c,int bg,const char * text,bool fake){
  auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment();
  KDPoint point(x,y);
  if (ptr)
    ptr->displaySandbox();
  auto ctx=KDIonContext::sharedContext();
  KDRect save=ctx->m_clippingRect;
  KDPoint o=ctx->m_origin;
  ctx->setClippingRect(KDRect(0,18,320,fake?0:222));
  ctx->setOrigin(KDPoint(0,18));
  point=ctx->drawString(text, point, KDFont::SmallFont, c, bg);
  ctx->setClippingRect(save);
  ctx->setOrigin(o);
  return point.x();
}


void numworks_giac_hide_graph(){
  auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment();
  if (ptr)
    ptr->hideSandbox();
}

void numworks_giac_show_graph(){
  auto ptr=MicroPython::ExecutionEnvironment::currentExecutionEnvironment();
  if (ptr)
    ptr->displaySandbox();
}

Le fichier kdisplay.h de giac-1.5.0 contient les declarations correspondantes, celle des touches (tres inspire du clavier Casio), ainsi que des fonctions d'UI, en particulier des menus a choix et un widget editeur de programmes, tout ca etant accessible sur le firmware delta+giac-1.5.0.

Re: C--

Unread postPosted: 14 Oct 2019, 18:21
by jean-baptiste boric
Le code d'epsilon est effectivement assez touffu. Son architecture n'est pas également propice à l'intégration de code en mode "free-style" (je continue de m'arracher les cheveux à essayer de trouver un moyen pas trop pourri de faire des apps third-party...).

Un moyen assez simple de prendre le contrôle en sélectionnant une app est de détourner App::App(Snapshot*) et de faire vivre sa propre mainloop depuis le constructeur. Pour quitter l'app, il suffit de mémoire de faire un switchTo() vers homeSnapshot() depuis sharedAppsContainer() avant de quitter le constructeur. L'inconvénient est que la mainloop de AppsContainer (qui s'occupe entre autres de l'assombrissement/suspension ainsi que de l'USB) n'est plus active, mais il devrait être possible de la rétablir en appelant Ion::Events::getEvent() et dispatchEvent() périodiquement. Cette technique est plutôt pensée pour des apps qui demandent un contrôle sur la mainloop style jeux vidéos, mais je l'ai quand même décrite au cas où elle pourrait être utile ici.

C'est clairement du bricolage, cependant ça devrait aider à s'intégrer un minimum avec epsilon sans pour autant se marier avec ce dernier. J'avoue ne pas être sûr de ce que ça va donner sur les autres plateformes que la calculatrice physique par contre...

Re: C--

Unread postPosted: 14 Oct 2019, 18:54
by parisse
jean-baptiste boric wrote:Un moyen assez simple de prendre le contrôle en sélectionnant une app est de détourner App::App(Snapshot*) et de faire vivre sa propre mainloop depuis le constructeur.

Ce qui manque pour ce type d'approche, c'est au moins un exemple Hello world.
Avec mes indications, on peut ecrire une fonction "main" (en C ou en C++), on la declare dans apps/home/controler.cpp. La fonction main peut par exemple contenir quelque chose du style
Code: Select all
int main(){
  numworks_giac_draw_string(0,0,"Hello world");
  int key=getkey(true); // true autorise OFF/ON
  return 0;
}

il faut ensuite linker tout epsilon avec en plus le fichier objet genere.
Bien entendu on peut faire une boucle avec getKey() que l'on ne quittera que si l'utilisateur a tape sur la touche Home ou Back etc. On a tout ce qu'il faut pour faire un jeu ou une appli de maths comme KhiCAS.
C'est surement moins propre que de creer une vraie app, mais ca me semble beaucoup plus simple, a la portee d'un programmeur un peu experimente en C. Et sur une calculatrice on n'a pas vraiment besoin de faire une vraie app, il n'y a qu'un seul utilisateur qui fait une seule tache, qui occupe tout l'ecran et le CPU.

Re: C--

Unread postPosted: 14 Oct 2019, 19:11
by jean-baptiste boric
Au-delà d'un Hello World, c'est un SDK, une documentation et des exemples qui manquent. Peut-être même un fork car certaines de mes idées pour rendre le tout plus hacker-friendly seront incompatibles avec l'upstream. Il faudrait que je me décide à forker un de ces jours, faire le grand écart avec l'upstream et périodiquement devoir déterrer mes modifications commence à devenir pénible...

Re: C--

Unread postPosted: 14 Oct 2019, 19:33
by Lephe
Pardonnez-moi de m'introduire dans ce fil avec des questions moins techniques... je n'ai jamais programmé la Numworks en natif, et je suis surpris de voir que ça se passe "mal". Pourquoi est-ce si difficile ? Est-ce un manque de documentation ? Est-ce que le système ne fournit pas les interfaces qu'on attend pour les applications ? D'autres raisons peut-être ? :O

Re: C--

Unread postPosted: 14 Oct 2019, 20:21
by parisse
De mon point de vue, c'est un manque de documentation (ce qui n'a rien d'anormal, les developpeurs n'ont sans doute pas specialement de temps libre pour en faire) et un OS qui me semble dans la meme philisophie que des toolkits GUI pour PC, un peu comme FLTK mais en plus complique. Pas du tout comme les syscalls de Casio. Avec des espaces de noms dans tous les sens, le tout en C++ avec des constructions du standard recent, avec pas mal de "private" ou "protected" que j'ai du enlever pour acceder a certains champs de donnees. Pour ne rien arranger, j'ai beaucoup de mal a suivre certaines parties du code au debugger sur le simulateur, peut-etre a cause des options de compilation -Og -g (mais -g tout seul ne marche pas).
Maintenant, c'est possible que mes difficultes viennent de mon style de programmation beaucoup plus basique, ca serait interessant d'avoir d'autres avis.

Re: C--

Unread postPosted: 14 Oct 2019, 20:47
by jean-baptiste boric
Lephe wrote:je n'ai jamais programmé la Numworks en natif, et je suis surpris de voir que ça se passe "mal". Pourquoi est-ce si difficile ? Est-ce un manque de documentation ? Est-ce que le système ne fournit pas les interfaces qu'on attend pour les applications ? D'autres raisons peut-être ? :O

Pour moi, c'est principalement à cause de:
  • Manque de documentation: elle est incomplète (escher notamment pour l'interface graphique) et n'est pas assez orientée pour les débutants (type tutoriel "Comment créer son application")
  • Architecture logicielle: epsilon est une application de calculatrice très (trop?) intégrée avec elle-même et ne dispose pas de mécanismes permettant d'ajouter facilement des applications et du code sans devoir s'intégrer intimement avec les sources et le fonctionnement du firmware (pas d'équivalent à un SDK type Casio/TI)
  • Bibliothèque C/C++: freestanding et extrêmement spartiate, ce qui rend le portage de code tiers vers epsilon compliqué
  • Débogage: sur calculatrice, rien n'est prévu à part utiliser le SWD avec un adaptateur type ST-Link V2 (pas d'écran de plantage avec un minimum d'informations pour recoller les morceaux) ce qui implique des modifications matérielles assez lourdes, sur calculatrice Bernard développe plus ou moins à l'aveuglette de son côté à cause de cela
  • Stabilité du code: epsilon évolue très rapidement et tout ce qui n'est pas dans le dépôt git officiel de NumWorks bitrotte à la vitesse grand V (cf. numworks-rpn, https://github.com/numworks/epsilon/pull/947)
  • Modifications tierces: epsilon n'est pas suffisamment architecturé pour faciliter le maintien de modifications out-of-tree (je pense notamment à Settings où ajouter des options demande pas mal de modifications qui vont inévitablement entrer en conflit si on tente de fusionner deux modifications distinctes)
  • Style de programmation: très orientée objet et MVC, on peut se perdre assez facilement dans les méandres d'epsilon en tentant de comprendre un point de fonctionnement particulier du firmware
  • Développement internes de NumWorks: les ingénieurs NumWorks développent chaque nouvelle version dans leur coin, puis quand c'est suffisamment prêt pour une beta ils dumpent d'un coup des centaines de commits sur leur dépôt officiel, les développeurs tiers comme moi manquent de visibilité sur les PR

Je connais assez bien epsilon à force de travailler dessus depuis sa sortie et je suis outillé pour faire du débogage sur calculatrice si nécessaire, mais je suis l'exception et non la règle. Les divergences fonctionnelles entre moi et NumWorks me pousse à considérer de plus en plus un fork car j'ai de plus en plus de mal à recoller toutes mes modifications dispersées que j'ai accumulé après un nouveau dump. Au vu du nombre de personnes qui attendent la venue d'un nouveau super-firmware, ça se justifierait.

Re: C--

Unread postPosted: 15 Oct 2019, 16:22
by M4x1m3
J'ai commencé à m'intéresser à la numworks en natif ce week-end. J'ai réussi à faire un hello world, qui se trouve sur mon bitbucket : https://bitbucket.org/m4x1m3/nw-hello-app/src/master/
En espérant que ça puisse aider.

Re: C--

Unread postPosted: 15 Oct 2019, 17:43
by parisse
Ca compile et ca tourne effectivement, bravo!
Mais ca me laisse perplexe pour savoir si une adaptation pourrait servir de point d'entree pour lancer la future console de Khicas.

Re: C--

Unread postPosted: 15 Oct 2019, 20:35
by parisse
Bon, j'ai reussi a m'en servir de point d'entree (un peu deroutant de nommer drawRect une fonction qui affiche le Hello world). Ca devrait permettre d'avoir une app visible pour lancer Khicas (en plus de l'appui sur Home depuis Home), n'utilisant que l'OS de Numworks, independante de l'UI de l'app Python de Numworks, et donc, quand ce sera au point, on pourra diffuser un firmware compile, sans avoir de problemes de licence. Merci!