mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
@@ -50,6 +50,7 @@ apps_src += $(addprefix apps/,\
|
||||
exam_mode_configuration_official.cpp:+official \
|
||||
exam_mode_configuration_non_official.cpp:-official \
|
||||
global_preferences.cpp \
|
||||
host_filemanager.cpp \
|
||||
i18n.py \
|
||||
lock_view.cpp \
|
||||
main.cpp \
|
||||
|
||||
@@ -7,6 +7,39 @@
|
||||
#include "../exam_mode_configuration.h"
|
||||
#include <assert.h>
|
||||
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <apps/shared/global_context.h>
|
||||
|
||||
static KDCoordinate dummyHeight(::Calculation::Calculation * c, bool expanded) {
|
||||
bool b;
|
||||
Poincare::Layout l = c->createExactOutputLayout(&b);
|
||||
if (!b) {
|
||||
l=c->createInputLayout();
|
||||
}
|
||||
KDSize s = l.layoutSize();
|
||||
const int bordersize = 10;
|
||||
int h = s.height() + bordersize;
|
||||
const int maxheight = 64;
|
||||
if (h > maxheight) {
|
||||
return maxheight;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
extern void * last_calculation_history;
|
||||
void * last_calculation_history = 0;
|
||||
const char * retrieve_calc_history();
|
||||
|
||||
#endif
|
||||
|
||||
using namespace Poincare;
|
||||
using namespace Shared;
|
||||
|
||||
@@ -21,10 +54,39 @@ CalculationStore::CalculationStore(char * buffer, int size) :
|
||||
{
|
||||
assert(m_buffer != nullptr);
|
||||
assert(m_bufferSize > 0);
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
if (last_calculation_history == 0){
|
||||
// Restore from scriptstore
|
||||
const char * buf=retrieve_calc_history();
|
||||
if (buf) {
|
||||
Shared::GlobalContext globalContext;
|
||||
char * ptr=(char *)buf;
|
||||
for (;*ptr;) {
|
||||
for (;*ptr;++ptr) {
|
||||
if (*ptr=='\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
char c = *ptr;
|
||||
*ptr=0;
|
||||
if (ptr > buf) {
|
||||
push(buf,&globalContext, dummyHeight);
|
||||
}
|
||||
*ptr = c;
|
||||
++ptr;
|
||||
buf = ptr;
|
||||
}
|
||||
}
|
||||
last_calculation_history = (void *) this;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Returns an expiring pointer to the calculation of index i, and ignore the trash
|
||||
ExpiringPointer<Calculation> CalculationStore::calculationAtIndex(int i) {
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
last_calculation_history = (void *) this;
|
||||
#endif
|
||||
if (m_trashIndex == -1 || i < m_trashIndex) {
|
||||
return realCalculationAtIndex(i);
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,12 @@
|
||||
#include <ion/unicode/utf8_helper.h>
|
||||
#include <apps/apps_container.h>
|
||||
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
extern "C" int calculator;
|
||||
extern "C" const int prizm_heap_size;
|
||||
extern "C" char prizm_heap[];
|
||||
#endif
|
||||
|
||||
namespace Code {
|
||||
|
||||
I18n::Message App::Descriptor::name() {
|
||||
@@ -150,7 +156,17 @@ bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::E
|
||||
|
||||
void App::initPythonWithUser(const void * pythonUser) {
|
||||
if (!m_pythonUser) {
|
||||
MicroPython::init(m_pythonHeap, m_pythonHeap + k_pythonHeapSize);
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
if (calculator == 1) { // fxcg50
|
||||
MicroPython::init( (void *) 0x8c200000, (void *)(0x8c200000+ 0x2e0000));
|
||||
} else if (calculator >= 1 && calculator <=4 ) {
|
||||
MicroPython::init( prizm_heap, prizm_heap+prizm_heap_size);
|
||||
} else {
|
||||
#endif
|
||||
MicroPython::init(m_pythonHeap, m_pythonHeap + k_pythonHeapSize);
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
}
|
||||
#endif
|
||||
}
|
||||
m_pythonUser = pythonUser;
|
||||
}
|
||||
|
||||
9
apps/external/app/sample.c
vendored
9
apps/external/app/sample.c
vendored
@@ -1,6 +1,15 @@
|
||||
#include <extapp_api.h>
|
||||
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
// On the port, we use the Built-in file manager to import files.
|
||||
void host_filemanager();
|
||||
void extapp_main() {
|
||||
host_filemanager();
|
||||
}
|
||||
#else
|
||||
// Elsewhere, just draw a rectangle to test the extapp API.
|
||||
void extapp_main() {
|
||||
extapp_pushRectUniform(10, 10, LCD_WIDTH-20, LCD_HEIGHT-20, 0);
|
||||
extapp_msleep(1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
859
apps/host_filemanager.cpp
Normal file
859
apps/host_filemanager.cpp
Normal file
@@ -0,0 +1,859 @@
|
||||
// #include <apps/home/apps_layout.h>
|
||||
// // #include "../apps_container.h"
|
||||
// #include "stddef.h"
|
||||
// #include "string.h"
|
||||
// #include "math.h"
|
||||
// #include "app.h"
|
||||
#include <apps/home/apps_layout.h>
|
||||
#include "../apps_container.h"
|
||||
#include "../global_preferences.h"
|
||||
#include "../exam_mode_configuration.h"
|
||||
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
}
|
||||
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
const char * storage_name="/documents/nwstore.nws.tns";
|
||||
#else
|
||||
const char * storage_name="nwstore.nws";
|
||||
#endif
|
||||
|
||||
const char * calc_storage_name="nwcalc.txt";
|
||||
void * storage_address(); // ion/src/simulator/shared/platform_info.cpp
|
||||
const char * retrieve_calc_history();
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
bool save_calc_history();
|
||||
void display_host_help();
|
||||
int load_state(const char * fname);
|
||||
#endif
|
||||
|
||||
// Additional code by B. Parisse for host file system support and persistence
|
||||
// on Casio Graph 90/FXCG50 and TI Nspire
|
||||
void erase_record(const char * name){
|
||||
unsigned char * ptr=(unsigned char *)storage_address();
|
||||
for (ptr+=4;;){ // skip header
|
||||
size_t L=ptr[1]*256+ptr[0];
|
||||
if (L==0) return;
|
||||
if (strcmp((const char *)ptr+2,name)==0){
|
||||
unsigned char * newptr=ptr;
|
||||
int S=0,erased=L;
|
||||
ptr+=L;
|
||||
for (;;){
|
||||
L=ptr[1]*256+ptr[0];
|
||||
if (L==0){
|
||||
for (int i=0;i<erased;++i)
|
||||
newptr[S+i]=0;
|
||||
break;
|
||||
}
|
||||
// if (ptr>newptr+S)
|
||||
memmove(newptr+S,ptr,L);
|
||||
S+=L;
|
||||
ptr+=L;
|
||||
}
|
||||
return;
|
||||
}
|
||||
ptr+=L;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// record filtering on read
|
||||
void filter(unsigned char * ptr){
|
||||
unsigned char * newptr=ptr;
|
||||
int S; ptr+=4;
|
||||
for (S=4;;){
|
||||
size_t L=ptr[1]*256+ptr[0];
|
||||
if (L==0) break;
|
||||
int l=strlen((const char *)ptr+2);
|
||||
// filter py records
|
||||
if (l>3 && strncmp((const char *)ptr+2+l-3,".py",3)==0){
|
||||
// if (ptr>newptr+S)
|
||||
memmove(newptr+S,ptr,L);
|
||||
S+=L;
|
||||
}
|
||||
#if 0 // def STRING_STORAGE
|
||||
if (l>5 && strncmp((const char *)ptr+2+l-5,".func",5)==0){
|
||||
int shift=l+4+13;
|
||||
Ion::Storage::Record * record=(Ion::Storage::Record *)malloc(1024);
|
||||
memcpy(record,ptr,L);
|
||||
//ExpressionModelHandle
|
||||
Poincare::Expression e=Poincare::Expression::Parse((const char *)ptr+shift,NULL);
|
||||
//ExpressionModel::setContent(Ion::Storage::Record * record, const char * c, Context * context, CodePoint symbol);
|
||||
Shared::ExpressionModel md;
|
||||
Ion::Storage::Record::ErrorStatus err=md.setExpressionContent(record, e);
|
||||
if (1){
|
||||
// if (ptr>newptr+S)
|
||||
int newL=record->value().size;
|
||||
memmove(newptr+S,record,newL);
|
||||
S+=newL;
|
||||
}
|
||||
free(record);
|
||||
}
|
||||
#endif
|
||||
ptr+=L;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
#include "../../ion/src/simulator/fxcg/platform.h"
|
||||
#include "../../ion/src/simulator/fxcg/menuHandler.h"
|
||||
#include <ion/storage.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <ion.h>
|
||||
#include <ion/events.h>
|
||||
#include "../../ion/src/simulator/nspire/k_csdk.h"
|
||||
#include "../calculation/calculation_store.h"
|
||||
|
||||
#define C_WHITE SDK_WHITE
|
||||
#define C_BLACK SDK_BLACK
|
||||
#define C_RED (31<<11)
|
||||
|
||||
int do_getkey(){
|
||||
os_wait_1ms(50);
|
||||
return getkey(0);
|
||||
}
|
||||
|
||||
void dtext(int x,int y,int fg,const char * s){
|
||||
os_draw_string_medium(x,y,fg,SDK_WHITE,s);
|
||||
}
|
||||
|
||||
void dclear(int c){
|
||||
os_fill_rect(0,0,LCD_WIDTH_PX,LCD_HEIGHT_PX,c);
|
||||
}
|
||||
|
||||
void dupdate(){
|
||||
sync_screen();
|
||||
}
|
||||
|
||||
const int storage_length=60000; // 60000 in Upsilon, 32768 in Epsilon
|
||||
// k_storageSize = 60000; in ion/include/ion/internal_storage.h
|
||||
extern void * last_calculation_history;
|
||||
|
||||
int load_state(const char * fname){
|
||||
FILE * f=fopen(fname,"rb");
|
||||
if (f){
|
||||
unsigned char * ptr=(unsigned char *)storage_address();
|
||||
fread(ptr,1,storage_length,f);
|
||||
fclose(f);
|
||||
#ifdef FILTER_STORE
|
||||
filter(ptr);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int save_state(const char * fname){
|
||||
save_calc_history();
|
||||
if (1 || Ion::Storage::sharedStorage()->numberOfRecords()){
|
||||
const unsigned char * ptr=(const unsigned char *)storage_address();
|
||||
// find store size
|
||||
int S=4;
|
||||
for (ptr+=4;;){ // skip header
|
||||
size_t L=ptr[1]*256+ptr[0];
|
||||
ptr+=L;
|
||||
S+=L;
|
||||
if (L==0) break;
|
||||
}
|
||||
S = ((S+1023)/1024)*1024;
|
||||
#ifdef FILTER_STORE
|
||||
// keep only python scripts
|
||||
unsigned char * newptr=(unsigned char *) malloc(S);
|
||||
bzero(newptr,S);
|
||||
ptr=(const unsigned char *) storage_address();
|
||||
memcpy(newptr,ptr,4); ptr+=4;
|
||||
for (S=4;;){
|
||||
size_t L=ptr[1]*256+ptr[0];
|
||||
if (L==0) break;
|
||||
int l=strlen((const char *)ptr+2);
|
||||
if (l>3 && strncmp((const char *)ptr+2+l-3,".py",3)==0){
|
||||
memcpy(newptr+S,ptr,L);
|
||||
S+=L;
|
||||
}
|
||||
ptr+=L;
|
||||
}
|
||||
S = ((S+1023)/1024)*1024;
|
||||
FILE * f;
|
||||
f=fopen(fname,"wb");
|
||||
if (f){
|
||||
fwrite(newptr,S,1,f);
|
||||
//fwrite(ptr+4,1,S-4,f);
|
||||
fclose(f);
|
||||
free(newptr);
|
||||
return S;
|
||||
}
|
||||
free(newptr);
|
||||
return 0;
|
||||
#else
|
||||
ptr=(const unsigned char *)storage_address();
|
||||
FILE * f;
|
||||
f=fopen(fname,"wb");
|
||||
if (f){
|
||||
fwrite(ptr,S,1,f);
|
||||
//fwrite(ptr+4,1,S-4,f);
|
||||
fclose(f);
|
||||
return S;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
#endif // NSPIRE_NEWLIB
|
||||
|
||||
#ifdef _FXCG
|
||||
#include "../../ion/src/simulator/fxcg/platform.h"
|
||||
#include "../../ion/src/simulator/fxcg/menuHandler.h"
|
||||
#include "../calculation/calculation_store.h"
|
||||
#include <ion/storage.h>
|
||||
|
||||
#include <gint/bfile.h>
|
||||
#include <gint/display-cg.h>
|
||||
#include <gint/gint.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <ion.h>
|
||||
#include <ion/events.h>
|
||||
#define KEY_CTRL_OK KEY_EXE
|
||||
int do_getkey(){
|
||||
return getkey().key;
|
||||
}
|
||||
|
||||
const int storage_length=60000; // 60000 in Upsilon, 32768 in Epsilon
|
||||
// k_storageSize = 60000; in ion/include/ion/internal_storage.h
|
||||
extern void * last_calculation_history;
|
||||
|
||||
int load_state(const char * fname){
|
||||
FILE * f=fopen(fname,"rb");
|
||||
if (f){
|
||||
unsigned char * ptr=(unsigned char *)storage_address();
|
||||
ptr[3]=fgetc(f);
|
||||
ptr[2]=fgetc(f);
|
||||
ptr[1]=fgetc(f);
|
||||
ptr[0]=fgetc(f);
|
||||
fread(ptr+4,1,storage_length-4,f);
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int save_state(const char * fname){
|
||||
save_calc_history();
|
||||
if (Ion::Storage::sharedStorage()->numberOfRecords()){
|
||||
#if 0
|
||||
unsigned short pFile[512];
|
||||
convert(fname,pFile);
|
||||
int hf = BFile_Open(pFile, BFile_WriteOnly); // Get handle
|
||||
// cout << hf << endl << "f:" << filename << endl; Console_Disp();
|
||||
if (hf<0){
|
||||
int l=storage_length;
|
||||
BFile_Create(pFile,0,&l);
|
||||
hf = BFile_Open(pFile, BFile_WriteOnly);
|
||||
}
|
||||
if (hf < 0)
|
||||
return 0;
|
||||
int l=BFile_Write(hf,storage_address(),storage_length);
|
||||
BFile_Close(hf);
|
||||
if (l==storage_length)
|
||||
return 1;
|
||||
return -1;
|
||||
#else
|
||||
const unsigned char * ptr=(const unsigned char *)storage_address();
|
||||
// find store size
|
||||
int S=4;
|
||||
for (ptr+=4;;){ // skip header
|
||||
size_t L=ptr[1]*256+ptr[0];
|
||||
ptr+=L;
|
||||
S+=L;
|
||||
if (L==0) break;
|
||||
}
|
||||
S = ((S+1023)/1024)*1024;
|
||||
FILE * f=fopen(fname,"wb");
|
||||
if (f){
|
||||
ptr=(const unsigned char *) storage_address();
|
||||
fputc(ptr[3],f);
|
||||
fputc(ptr[2],f);
|
||||
fputc(ptr[1],f);
|
||||
fputc(ptr[0],f);
|
||||
//fwrite(ptr+4,1,S-4,f);
|
||||
fwrite(ptr+4,S-4,1,f);
|
||||
fclose(f);
|
||||
return S;
|
||||
}
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
#endif // _FXCG
|
||||
|
||||
const char * retrieve_calc_history(){
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
static bool firstrun=true;
|
||||
if (firstrun){
|
||||
#ifdef _FXCG
|
||||
int l=gint_world_switch(GINT_CALL(load_state,storage_name));
|
||||
#else
|
||||
int l=load_state(storage_name);
|
||||
#endif
|
||||
if (l==0){
|
||||
display_host_help();
|
||||
// ((App*)m_app)->redraw();
|
||||
}
|
||||
firstrun=false;
|
||||
}
|
||||
#endif
|
||||
unsigned char * ptr=(unsigned char *)storage_address();
|
||||
for (ptr+=4;;){ // skip header
|
||||
size_t L=ptr[1]*256+ptr[0];
|
||||
if (L==0) return 0;
|
||||
if (strcmp((const char *)ptr+2,calc_storage_name)==0){
|
||||
const char * buf=(const char *)ptr+2+strlen(calc_storage_name)+1;
|
||||
return buf;
|
||||
}
|
||||
ptr += L;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
bool save_calc_history(){
|
||||
if (!last_calculation_history)
|
||||
return false;
|
||||
erase_record(calc_storage_name);
|
||||
std::string s;
|
||||
Calculation::CalculationStore * store=(Calculation::CalculationStore *) last_calculation_history;
|
||||
int N=store->numberOfCalculations();
|
||||
for (int i=N-1;i>=0;--i){
|
||||
s += store->calculationAtIndex(i)->inputText();
|
||||
s += '\n';
|
||||
}
|
||||
if (s.empty())
|
||||
return false;
|
||||
Ion::Storage::Record::ErrorStatus res= Ion::Storage::sharedStorage()->createRecordWithFullName(calc_storage_name,&s[0],s.size());
|
||||
if (res==Ion::Storage::Record::ErrorStatus::NotEnoughSpaceAvailable)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void confirm_load_state(const char * buf){
|
||||
dclear(C_WHITE);
|
||||
dtext(1,1, C_BLACK, "Loading from state file");
|
||||
dtext(1,17,C_BLACK,buf);
|
||||
dtext(1,33,C_BLACK,"Current context will be lost!");
|
||||
dtext(1,49,C_BLACK,"Press EXE to confirm");
|
||||
dupdate();
|
||||
int k=do_getkey();
|
||||
if (k==KEY_EXE || k==KEY_CTRL_OK){
|
||||
#ifdef _FXCG
|
||||
int l=gint_world_switch(GINT_CALL(load_state,buf));
|
||||
#else
|
||||
int l=load_state(buf);
|
||||
#endif
|
||||
char buf2[]="0";
|
||||
buf2[0] += l;
|
||||
if (l==0)
|
||||
dtext(1,65,C_BLACK,"Error reading state");
|
||||
if (l==1)
|
||||
dtext(1,65,C_BLACK,"Success reading state");
|
||||
dtext(1,81,C_BLACK,buf2);
|
||||
dtext(1,97,C_BLACK,"Press any key");
|
||||
dupdate();
|
||||
do_getkey();
|
||||
}
|
||||
}
|
||||
|
||||
static void convert(const char * fname,unsigned short * pFile){
|
||||
for ( ;*fname;++fname,++pFile)
|
||||
*pFile=*fname;
|
||||
*pFile=0;
|
||||
}
|
||||
|
||||
struct file {
|
||||
std::string s;
|
||||
int length;
|
||||
bool isdir;
|
||||
};
|
||||
|
||||
void host_scripts(std::vector<file> & v,const char * dirname,const char * extension){
|
||||
v.clear();
|
||||
file f={".._parent_dir",0,true};
|
||||
if (strlen(dirname)>1)
|
||||
v.push_back(f);
|
||||
DIR *dp;
|
||||
struct dirent *ep;
|
||||
dp = opendir (dirname);
|
||||
int l=extension?strlen(extension):0;
|
||||
if (dp != NULL){
|
||||
int t;
|
||||
while ( (ep = readdir (dp)) ){
|
||||
if (strlen(ep->d_name)>=1 && ep->d_name[0]=='.')
|
||||
continue;
|
||||
f.s=ep->d_name;
|
||||
if (f.s=="@MainMem")
|
||||
continue;
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
DIR * chk=opendir((dirname+f.s).c_str());
|
||||
f.isdir=true;
|
||||
if (chk)
|
||||
closedir(chk);
|
||||
else
|
||||
f.isdir=false;
|
||||
#else
|
||||
f.isdir=ep->d_type==DT_DIR;
|
||||
#endif
|
||||
#if 1
|
||||
if (f.isdir)
|
||||
f.length=0;
|
||||
else {
|
||||
struct stat st;
|
||||
stat((dirname+f.s).c_str(), &st);
|
||||
f.length = st.st_size;
|
||||
if (f.length>=32768)
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
f.length=f.isdir?0:-1;
|
||||
#endif
|
||||
if (f.isdir || !extension)
|
||||
v.push_back(f);
|
||||
else {
|
||||
t=strlen(ep->d_name);
|
||||
if (t>l && strncmp(ep->d_name+t-l,extension,l)==0)
|
||||
v.push_back(f);
|
||||
}
|
||||
}
|
||||
closedir (dp);
|
||||
}
|
||||
}
|
||||
|
||||
void nw_scripts(std::vector<file> & v,const char * extension){
|
||||
v.clear();
|
||||
#if 0
|
||||
int n=Ion::Storage::sharedStorage()->numberOfRecords();
|
||||
for (int i=0;i<n;++i){
|
||||
v.push_back(Ion::Storage::sharedStorage()->recordAtIndex(i).fullName());
|
||||
}
|
||||
#else
|
||||
const unsigned char * ptr=(const unsigned char *)storage_address();
|
||||
int l=extension?strlen(extension):0;
|
||||
for (ptr+=4;;){ // skip header
|
||||
size_t L=ptr[1]*256+ptr[0];
|
||||
ptr+=2;
|
||||
if (L==0) break;
|
||||
L-=2;
|
||||
file f={(const char *)ptr,(int)L,false};
|
||||
if (!extension)
|
||||
v.push_back(f);
|
||||
else {
|
||||
int namesize=strlen((const char *)ptr);
|
||||
if (namesize>l && strncmp((const char *)ptr+namesize-l,extension,l)==0)
|
||||
v.push_back(f);
|
||||
}
|
||||
ptr+=L;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int copy_nw_to_host(const char * nwname,const char * hostname){
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
int s=strlen(hostname);
|
||||
if (s<4 || strncmp(hostname+s-4,".tns",4)){
|
||||
std::string S(hostname);
|
||||
S+=".tns";
|
||||
return copy_nw_to_host(nwname,S.c_str());
|
||||
}
|
||||
#endif
|
||||
const unsigned char * ptr=(const unsigned char *)storage_address();
|
||||
for (ptr+=4;;){ // skip header
|
||||
size_t L=ptr[1]*256+ptr[0];
|
||||
if (L==0) return 3; // not found
|
||||
//dclear(C_WHITE);
|
||||
//dtext(1,1,C_BLACK,ptr+2);
|
||||
//dtext(1,17,C_BLACK,nwname);
|
||||
//dupdate();
|
||||
//getkey();
|
||||
if (strcmp((const char *)ptr+2,nwname)){
|
||||
ptr += L;
|
||||
continue;
|
||||
}
|
||||
ptr+=2;
|
||||
L-=2;
|
||||
int l=strlen((const char *)ptr);
|
||||
ptr += l+2;
|
||||
L -= l;
|
||||
L = 2*((L+1)/2);
|
||||
FILE * f=fopen(hostname,"wb");
|
||||
if (!f)
|
||||
return 2;
|
||||
fwrite(ptr,1,L,f);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int copy_host_to_nw(const char * hostname,const char * nwname,int autoexec){
|
||||
FILE * f=fopen(hostname,"rb");
|
||||
if (!f)
|
||||
return -1;
|
||||
std::vector<unsigned char> v(1,autoexec?1:0);
|
||||
for (;;){
|
||||
unsigned char c=fgetc(f);
|
||||
if (feof(f)){
|
||||
if (c>=' ' && c<=0x7e)
|
||||
v.push_back(c);
|
||||
break;
|
||||
}
|
||||
if (c==0xa && !v.empty() && v.back()==0xd)
|
||||
v.back()=0xa;
|
||||
else
|
||||
v.push_back(c);
|
||||
}
|
||||
if (!v.empty() && v.back()!=0xa)
|
||||
v.push_back(0xa);
|
||||
v.push_back(0);
|
||||
fclose(f);
|
||||
if (Ion::Storage::sharedStorage()->hasRecord(Ion::Storage::sharedStorage()->recordNamed(nwname)))
|
||||
Ion::Storage::sharedStorage()-> destroyRecord(Ion::Storage::sharedStorage()->recordNamed(nwname));
|
||||
Ion::Storage::Record::ErrorStatus res= Ion::Storage::sharedStorage()->createRecordWithFullName(nwname,&v.front(),v.size());
|
||||
if (res==Ion::Storage::Record::ErrorStatus::NotEnoughSpaceAvailable)
|
||||
return -2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool filesort(const file & a,const file & b){
|
||||
if (a.isdir!=b.isdir)
|
||||
return a.isdir;
|
||||
return a.s<b.s;
|
||||
}
|
||||
|
||||
void display_host_help();
|
||||
void display_host_help(){
|
||||
dclear(C_WHITE);
|
||||
dtext(1,2, C_BLACK,"You can save up to 9 Upsilon calculator states:");
|
||||
dtext(1,38,C_BLACK,"You can manage and exchange Upsilon records");
|
||||
dtext(1,56,C_BLACK,"or restore states: from home, type VARS");
|
||||
#ifdef _FXCG
|
||||
dtext(1,20,C_BLACK,"From home, type STO (above AC/ON) then 1 to 9");
|
||||
dtext(1,74,C_BLACK,"You can reset Upsilon state from Casio MENU");
|
||||
dtext(1,92,C_BLACK,"Select Memory, type F2, then erase nwstore.nws");
|
||||
dtext(1,110,C_RED, "From home, type MENU or DEL to leave Upsilon");
|
||||
#else
|
||||
dtext(1,20,C_BLACK,"From home, type STO (ctrl VAR) then 1 to 9");
|
||||
dtext(1,74,C_BLACK,"You can reset Upsilon state from Home 2");
|
||||
dtext(1,92,C_BLACK,"Erase nwstore.nws in My documents");
|
||||
dtext(1,110,C_RED ,"Type Ctrl K to shutdown screen, ON to restore");
|
||||
dtext(1,128,C_RED ,"From home, type ON or doc to leave Upsilon");
|
||||
os_wait_1ms(100);
|
||||
#endif
|
||||
dtext(1,150,C_BLACK,"Upsilon: a fork of Epsilon (c) Numworks");
|
||||
dtext(1,168,C_BLACK,"https://getupsilon.web.app/");
|
||||
dtext(1,186,C_BLACK,"creativecommons.org license CC BY-NC-SA 4.0");
|
||||
dtext(1,204,C_BLACK,"Persistance and host filesystem (c) B. Parisse");
|
||||
dupdate();
|
||||
do_getkey();
|
||||
}
|
||||
|
||||
extern "C" void host_filemanager();
|
||||
void host_filemanager(){
|
||||
int posnw=0,startnw=0,poshost=0,starthost=0;
|
||||
bool nw=true,reload=true;
|
||||
std::vector<file> v,w;
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
std::string hostdir="/documents/";
|
||||
#else
|
||||
std::string hostdir="/";
|
||||
#endif
|
||||
bool onlypy=true;
|
||||
for (;;){
|
||||
if (reload){
|
||||
nw_scripts(v,onlypy?".py":0);
|
||||
sort(v.begin(),v.end(),filesort);
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
host_scripts(w,hostdir.c_str(),onlypy?".py.tns":0);
|
||||
#else
|
||||
host_scripts(w,hostdir.c_str(),onlypy?".py":0);
|
||||
#endif
|
||||
sort(w.begin(),w.end(),filesort);
|
||||
reload=false;
|
||||
}
|
||||
dclear(C_WHITE);
|
||||
dtext(1,1, C_BLACK,"EXIT: leave; key 1 to 9: load state from file");
|
||||
#ifdef _FXCG
|
||||
dtext(1,17,C_BLACK,"Cursor keys: move, /: rootdir, OPTN: all/py files");
|
||||
#else
|
||||
dtext(1,17,C_BLACK,"Cursor keys: move, /: rootdir");
|
||||
#endif
|
||||
dtext(1,33,C_BLACK,"EXE or STO key: copy selection from/to host");
|
||||
dtext(1,49,C_BLACK,("Upsilon records Host "+hostdir).c_str());
|
||||
int nitems=9;
|
||||
if (posnw<0)
|
||||
posnw=v.size()-1;
|
||||
if (posnw>=int(v.size()))
|
||||
posnw=0;
|
||||
if (posnw<startnw || posnw>startnw+nitems)
|
||||
startnw=posnw-4;
|
||||
if (startnw>=int(v.size())-nitems)
|
||||
startnw=v.size()-nitems;
|
||||
if (startnw<0)
|
||||
startnw=0;
|
||||
if (v.empty())
|
||||
nw=false;
|
||||
for (int i=0;i<=nitems;++i){
|
||||
int I=i+startnw;
|
||||
if (I>=int(v.size()))
|
||||
break;
|
||||
dtext(1,65+16*i,(nw && I==posnw)?C_RED:C_BLACK,v[I].s.c_str());
|
||||
char buf[256];
|
||||
sprintf(buf,"%i",v[I].length);
|
||||
dtext(90,65+16*i,(nw && I==posnw)?C_RED:C_BLACK,buf);
|
||||
}
|
||||
if (w.empty())
|
||||
nw=true;
|
||||
if (poshost<0)
|
||||
poshost=w.size()-1;
|
||||
if (poshost>=int(w.size()))
|
||||
poshost=0;
|
||||
if (poshost<starthost || poshost>starthost+nitems)
|
||||
starthost=poshost-4;
|
||||
if (starthost>=int(w.size())-nitems)
|
||||
starthost=w.size()-nitems;
|
||||
if (starthost<0)
|
||||
starthost=0;
|
||||
for (int i=0;i<=nitems;++i){
|
||||
int I=i+starthost;
|
||||
if (I>=int(w.size()))
|
||||
break;
|
||||
std::string fname=w[I].s;
|
||||
if (fname.size()>16)
|
||||
fname=fname.substr(0,16)+"...";
|
||||
dtext(192,65+16*i,(!nw && I==poshost)?C_RED:C_BLACK,fname.c_str());
|
||||
if (w[I].isdir)
|
||||
dtext(154,65+16*i,(!nw && I==poshost)?C_RED:C_BLACK,"<dir>");
|
||||
else {
|
||||
char buf[256];
|
||||
sprintf(buf,"%i",w[I].length);
|
||||
#ifdef _FXCG
|
||||
dtext(340,65+16*i,(!nw && I==poshost)?C_RED:C_BLACK,buf);
|
||||
#else
|
||||
dtext(285,65+16*i,(!nw && I==poshost)?C_RED:C_BLACK,buf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
dupdate();
|
||||
int key=do_getkey();
|
||||
if (key==KEY_EXIT || key==KEY_MENU)
|
||||
break;
|
||||
if (key==KEY_OPTN || key=='\t'){
|
||||
onlypy=!onlypy;
|
||||
reload=true;
|
||||
continue;
|
||||
}
|
||||
if (key==KEY_DIV){
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
hostdir="/documents/";
|
||||
#else
|
||||
hostdir="/";
|
||||
#endif
|
||||
reload=true;
|
||||
continue;
|
||||
}
|
||||
if (key==KEY_DEL){
|
||||
if (!nw && w[poshost].isdir) // can not remove directory
|
||||
continue;
|
||||
dclear(C_WHITE);
|
||||
dtext(1,17,C_BLACK,nw?"About to suppress Upsilon record:":"About to suppress Host file:");
|
||||
dtext(1,33,C_BLACK,(nw?v[posnw].s:w[poshost].s).c_str());
|
||||
dtext(1,49,C_BLACK,"Press EXE or OK to confirm");
|
||||
dupdate();
|
||||
int ev=do_getkey();
|
||||
if (ev!=KEY_EXE && ev!=KEY_CTRL_OK)
|
||||
continue;
|
||||
if (nw){
|
||||
#if 1
|
||||
erase_record(v[posnw].s.c_str());
|
||||
#else
|
||||
char buf[256];
|
||||
strcpy(buf,v[posnw].s.c_str());
|
||||
int l=strlen(buf)-4;
|
||||
buf[l]=0;
|
||||
Ion::Storage::sharedStorage()-> destroyRecordWithBaseNameAndExtension(buf,buf+l+1);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
remove((hostdir+w[poshost].s).c_str());
|
||||
reload=true;
|
||||
}
|
||||
if (key==KEY_LEFT){
|
||||
nw=true;
|
||||
continue;
|
||||
}
|
||||
if (key==KEY_RIGHT){
|
||||
nw=false;
|
||||
continue;
|
||||
}
|
||||
if (key==KEY_PLUS){
|
||||
if (nw)
|
||||
posnw+=5;
|
||||
else
|
||||
poshost+=5;
|
||||
continue;
|
||||
}
|
||||
if (key==KEY_MINUS){
|
||||
if (nw)
|
||||
posnw-=5;
|
||||
else
|
||||
poshost-=5;
|
||||
continue;
|
||||
}
|
||||
if (key==KEY_DOWN){
|
||||
if (nw)
|
||||
++posnw;
|
||||
else
|
||||
++poshost;
|
||||
continue;
|
||||
}
|
||||
if (key==KEY_UP){
|
||||
if (nw)
|
||||
--posnw;
|
||||
else
|
||||
--poshost;
|
||||
continue;
|
||||
}
|
||||
int autoexec = key==KEY_EXE || key==KEY_CTRL_OK;
|
||||
if (key==KEY_STORE || autoexec){
|
||||
if (nw && posnw>=0 && posnw<int(v.size())){
|
||||
size_t i=0;
|
||||
for (;i<w.size();++i){
|
||||
if (v[posnw].s==w[i].s)
|
||||
break;
|
||||
}
|
||||
if (i<w.size()){
|
||||
dclear(C_WHITE);
|
||||
if (w[i].isdir){
|
||||
dtext(1,33,C_BLACK,"Can not overwrite a Host directory!");
|
||||
dupdate();
|
||||
do_getkey();
|
||||
continue;
|
||||
}
|
||||
dtext(1,33,C_BLACK,"Script exists in Host directory!");
|
||||
dtext(1,49,C_BLACK,"Press EXE to confirm overwrite");
|
||||
dupdate();
|
||||
int k=do_getkey();
|
||||
if (k!=KEY_EXE && k!=KEY_CTRL_OK)
|
||||
continue;
|
||||
}
|
||||
#ifdef _FXCG
|
||||
int l=gint_world_switch(GINT_CALL(copy_nw_to_host,v[posnw].s.c_str(),(hostdir+v[posnw].s).c_str()));
|
||||
#else
|
||||
int l=copy_nw_to_host(v[posnw].s.c_str(),(hostdir+v[posnw].s).c_str());
|
||||
#endif
|
||||
char buf2[]="0";
|
||||
buf2[0] = '0'+l;
|
||||
dclear(C_WHITE);
|
||||
dtext(1,65,C_BLACK,(hostdir+v[posnw].s).c_str());
|
||||
dtext(1,81,C_BLACK,buf2);
|
||||
dupdate();
|
||||
if (l!=0)
|
||||
do_getkey();
|
||||
reload=true;
|
||||
}
|
||||
else if (!nw && poshost>=0 && poshost<int(w.size())){
|
||||
if (w[poshost].s==".._parent_dir"){
|
||||
// one level up
|
||||
for (int j=hostdir.size()-2;j>=0;--j){
|
||||
if (hostdir[j]=='/'){
|
||||
hostdir=hostdir.substr(0,j+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
reload=true;
|
||||
continue;
|
||||
}
|
||||
// lookup if poshost is in directories
|
||||
if (w[poshost].isdir){
|
||||
hostdir += w[poshost].s;
|
||||
hostdir += "/";
|
||||
reload=true;
|
||||
continue;
|
||||
}
|
||||
size_t i;
|
||||
std::string fname=w[poshost].s;
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
if (fname.size()>4 && fname.substr(fname.size()-4,4)==".tns")
|
||||
fname=fname.substr(0,fname.size()-4);
|
||||
#endif
|
||||
for (i=0;i<v.size();++i){
|
||||
if (fname==v[i].s)
|
||||
break;
|
||||
}
|
||||
if (i<v.size()){
|
||||
dclear(C_WHITE);
|
||||
dtext(1,33,C_BLACK,"Script exists in Upsilon!");
|
||||
dtext(1,49,C_BLACK,"Press EXE to confirm overwrite");
|
||||
dupdate();
|
||||
int k=do_getkey();
|
||||
if (k!=KEY_EXE && k!=KEY_CTRL_OK)
|
||||
continue;
|
||||
}
|
||||
std::string nwname=fname;
|
||||
if (fname.size()>12){
|
||||
dclear(C_WHITE);
|
||||
dtext(1,33,C_BLACK,"Host filename too long");
|
||||
dtext(1,49,C_BLACK,fname.c_str());
|
||||
dupdate();
|
||||
do_getkey();
|
||||
continue;
|
||||
}
|
||||
if (fname.size()>4 && fname.substr(fname.size()-4,4)==".nws")
|
||||
confirm_load_state((hostdir+fname).c_str());
|
||||
else {
|
||||
#ifdef _FXCG
|
||||
gint_world_switch(GINT_CALL(copy_host_to_nw,(hostdir+fname).c_str(),nwname.c_str(),autoexec));
|
||||
#else
|
||||
copy_host_to_nw((hostdir+w[poshost].s).c_str(),nwname.c_str(),autoexec);
|
||||
#endif
|
||||
}
|
||||
reload=true;
|
||||
}
|
||||
}
|
||||
if (key>=KEY_1 && key<=KEY_9){
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
char buf[]="nwstate0.nws.tns";
|
||||
#else
|
||||
char buf[]="nwstate0.nws";
|
||||
#endif
|
||||
buf[7]='1'+(key-KEY_1);
|
||||
confirm_load_state(buf);
|
||||
reload=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // FXCG || NSPIRE
|
||||
@@ -72,7 +72,7 @@ Expression ExpressionModel::expressionReduced(const Storage::Record * record, Po
|
||||
if (isCircularlyDefined(record, context)) {
|
||||
m_expression = Undefined::Builder();
|
||||
} else {
|
||||
m_expression = Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record));
|
||||
m_expression = Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record), record);
|
||||
/* 'Simplify' routine might need to call expressionReduced on the very
|
||||
* same function. So we need to keep a valid m_expression while executing
|
||||
* 'Simplify'. Thus, we use a temporary expression. */
|
||||
@@ -90,7 +90,7 @@ Expression ExpressionModel::expressionReduced(const Storage::Record * record, Po
|
||||
Expression ExpressionModel::expressionClone(const Storage::Record * record) const {
|
||||
assert(record->fullName() != nullptr);
|
||||
/* A new Expression has to be created at each call (because it might be tempered with after calling) */
|
||||
return Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record));
|
||||
return Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record), record);
|
||||
/* TODO
|
||||
* The substitution of UCodePointUnknown back and forth is done in the
|
||||
* methods text, setContent (through BuildExpressionFromText), layout and
|
||||
@@ -125,6 +125,39 @@ Ion::Storage::Record::ErrorStatus ExpressionModel::setExpressionContent(Ion::Sto
|
||||
Ion::Storage::Record::Data newData = record->value();
|
||||
size_t previousExpressionSize = expressionSize(record);
|
||||
size_t newExpressionSize = newExpression.isUninitialized() ? 0 : newExpression.size();
|
||||
#ifdef STRING_STORAGE
|
||||
size_t stringsize = 0;
|
||||
char buf[1024] = {0};
|
||||
char repl = 0;
|
||||
buf[0] = '"';
|
||||
if (!newExpression.isUninitialized()) {
|
||||
size_t l = newExpression.serialize(buf+1,sizeof(buf)-2);
|
||||
if (l >= sizeof(buf) - 3) {
|
||||
newExpressionSize = 0;
|
||||
} else {
|
||||
buf[l + 1] = '"';
|
||||
// replace 0x1 by x for func or n for seq
|
||||
const char * name = record->fullName();
|
||||
int namel = strlen(name);
|
||||
if (namel > 4 && strncmp(name + namel - 4, ".seq", 4) == 0) {
|
||||
repl = 'n';
|
||||
} else if (namel > 5 && strncmp(name + namel - 5, ".func", 5) == 0) {
|
||||
repl = 'x';
|
||||
}
|
||||
if (repl) {
|
||||
for (char * ptr = buf; *ptr; ++ptr) {
|
||||
if (*ptr == 1) {
|
||||
*ptr = repl;
|
||||
}
|
||||
}
|
||||
}
|
||||
stringsize= l + 3; // 2 quotes and 0 at end
|
||||
if (newExpressionSize < stringsize) {
|
||||
newExpressionSize = stringsize;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
size_t previousDataSize = newData.size;
|
||||
size_t newDataSize = previousDataSize - previousExpressionSize + newExpressionSize;
|
||||
void * expAddress = expressionAddress(record);
|
||||
@@ -140,6 +173,12 @@ Ion::Storage::Record::ErrorStatus ExpressionModel::setExpressionContent(Ion::Sto
|
||||
* (as it is sometimes computed from metadata). Thus, the expression address
|
||||
* is given as a parameter to updateNewDataWithExpression. */
|
||||
updateNewDataWithExpression(record, newExpression, expAddress, newExpressionSize, previousExpressionSize);
|
||||
#ifdef STRING_STORAGE
|
||||
if (stringsize && stringsize<newExpressionSize) {
|
||||
// print size is smaller than expression size
|
||||
strncpy((char *)expAddress, buf, stringsize);
|
||||
}
|
||||
#endif
|
||||
// Set the data with the right size
|
||||
newData.size = newDataSize;
|
||||
error = record->setValue(newData);
|
||||
|
||||
11
build/platform.simulator.nspire.mak
Normal file
11
build/platform.simulator.nspire.mak
Normal file
@@ -0,0 +1,11 @@
|
||||
TOOLCHAIN = nspire-gcc
|
||||
EXE = elf
|
||||
|
||||
EPSILON_TELEMETRY ?= 0
|
||||
|
||||
HANDY_TARGETS_EXTENSIONS = tns
|
||||
|
||||
USE_LIBA = 0
|
||||
POINCARE_TREE_LOG = 0
|
||||
|
||||
SFLAGS := $(filter-out -fPIE, $(SFLAGS))
|
||||
6
build/targets.simulator.nspire.mak
Normal file
6
build/targets.simulator.nspire.mak
Normal file
@@ -0,0 +1,6 @@
|
||||
$(BUILD_DIR)/%.tns: $(BUILD_DIR)/%.elf
|
||||
# comment one of these lines. For B&W old nspire, do not use the compress option
|
||||
genzehn --compress --input $(BUILD_DIR)/epsilon.elf --output upsilon.tns --name "upsilon" --uses-lcd-blit true
|
||||
# genzehn --input $(BUILD_DIR)/epsilon.elf --output upsilon.tns --name "upsilon" --uses-lcd-blit true
|
||||
genzehn --info --input upsilon.tns
|
||||
firebird-send upsilon.tns /ndless
|
||||
9
build/toolchain.nspire-gcc.mak
Normal file
9
build/toolchain.nspire-gcc.mak
Normal file
@@ -0,0 +1,9 @@
|
||||
CC = nspire-gcc
|
||||
CXX = nspire-g++
|
||||
LD = nspire-g++
|
||||
GDB = gdb
|
||||
OBJCOPY = nspire-objcopy
|
||||
SIZE = nspire-size
|
||||
AS = nspire-as
|
||||
|
||||
SFLAGS += -DNSPIRE_NEWLIB -DSTRING_STORAGE
|
||||
@@ -7,4 +7,4 @@ SIZE = sh-elf-size
|
||||
AS = sh-elf-as
|
||||
FXGXA = fxgxa
|
||||
|
||||
SFLAGS += -D_FXCG -D_BIG_ENDIAN
|
||||
SFLAGS += -D_FXCG -D_BIG_ENDIAN -DSTRING_STORAGE
|
||||
|
||||
@@ -22,8 +22,11 @@ public:
|
||||
static constexpr char expExtension[] = "exp";
|
||||
static constexpr char funcExtension[] = "func";
|
||||
static constexpr char seqExtension[] = "seq";
|
||||
|
||||
#ifdef _FXCG
|
||||
constexpr static size_t k_storageSize = 65500;
|
||||
#else
|
||||
constexpr static size_t k_storageSize = 60000;
|
||||
#endif
|
||||
static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough");
|
||||
|
||||
constexpr static char k_dotChar = '.';
|
||||
@@ -195,7 +198,7 @@ public:
|
||||
class StorageHelper {
|
||||
public:
|
||||
static uint16_t unalignedShort(char * address) {
|
||||
#if (defined __EMSCRIPTEN__) || (defined _FXCG)
|
||||
#if (defined __EMSCRIPTEN__) || (defined _FXCG) || defined NSPIRE_NEWLIB
|
||||
uint8_t f1 = *(address);
|
||||
uint8_t f2 = *(address+1);
|
||||
uint16_t f = (uint16_t)f1 + (((uint16_t)f2)<<8);
|
||||
@@ -205,7 +208,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
static void writeUnalignedShort(uint16_t value, char * address) {
|
||||
#if (defined __EMSCRIPTEN__) || (defined _FXCG)
|
||||
#if (defined __EMSCRIPTEN__) || (defined _FXCG) || defined NSPIRE_NEWLIB
|
||||
*((uint8_t *)address) = (uint8_t)(value & ((1 << 8) - 1));
|
||||
*((uint8_t *)address+1) = (uint8_t)(value >> 8);
|
||||
#else
|
||||
|
||||
2
ion/src/simulator/external/config.nspire.mak
vendored
Normal file
2
ion/src/simulator/external/config.nspire.mak
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
undefine sdl_src
|
||||
undefine ion_simulator_sdl_src
|
||||
@@ -221,11 +221,11 @@ State scan() {
|
||||
if (menuHeldFor > 30) {
|
||||
Simulator::FXCGMenuHandler::openMenu();
|
||||
dupdate();
|
||||
// Wait until EXE is released
|
||||
// Wait until EXE and MENU are released
|
||||
do {
|
||||
sleep_ms(10);
|
||||
clearevents();
|
||||
} while (keydown(KEY_EXE));
|
||||
} while (keydown(KEY_EXE) || keydown(KEY_MENU));
|
||||
}
|
||||
} else {
|
||||
menuHeldFor = 0;
|
||||
@@ -259,4 +259,4 @@ namespace Keyboard {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <gint/display-cg.h>
|
||||
#include <gint/gint.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
@@ -13,15 +15,60 @@
|
||||
|
||||
#include <ion.h>
|
||||
#include <ion/events.h>
|
||||
#include "menuHandler.h"
|
||||
|
||||
using namespace Ion::Simulator::Main;
|
||||
|
||||
constexpr static const char * storage_name="nwstore.nws";
|
||||
|
||||
int save_state(const char * fname); // apps/home/controller.cpp
|
||||
|
||||
extern "C" {
|
||||
int main() {
|
||||
Ion::Simulator::Main::init();
|
||||
ion_main(0, NULL);
|
||||
Ion::Simulator::Main::quit();
|
||||
extern const int prizm_heap_size;
|
||||
const int prizm_heap_size = 192 * 1024;
|
||||
__attribute__((aligned(4))) char prizm_heap[prizm_heap_size];
|
||||
|
||||
return 0;
|
||||
}
|
||||
CalculatorType calculator = CalculatorType::Unchecked;
|
||||
|
||||
int main() {
|
||||
/* Allow the user to use memory past the 2 MB line on tested OS versions */
|
||||
char const * os_version = (char const *)0x80020020;
|
||||
if (!strncmp(os_version, "03.", 3) && os_version[3] <= '8'){ // 3.80 or earlier
|
||||
char buf[256];
|
||||
strncpy(buf,os_version,8);
|
||||
buf[8]=0;
|
||||
} else {
|
||||
char buf1[10], buf[256];
|
||||
// sprintf(buf,"%i",availram);
|
||||
strncpy(buf1,os_version,8);
|
||||
buf1[8]=0;
|
||||
sprintf(buf,"OS %s not checked",buf1);
|
||||
calculator = CalculatorType::Unchecked;
|
||||
dclear(C_WHITE);
|
||||
dtext(1,10,C_BLACK,buf);
|
||||
dtext(1,27,C_BLACK,"F6: continue anyway");
|
||||
dupdate();
|
||||
int key = getkey().key;
|
||||
if (key != KEY_F6){
|
||||
Ion::Simulator::FXCGMenuHandler::openMenu();
|
||||
}
|
||||
}
|
||||
bool is_emulator = *(volatile uint32_t *)0xff000044 == 0x00000000;
|
||||
uint32_t stack;
|
||||
__asm__("mov r15, %0" : "=r"(stack));
|
||||
// Check if the calculator is a Prizm or an emulator
|
||||
if (stack < 0x8c000000) {
|
||||
calculator = is_emulator ? CalculatorType::Emulator : CalculatorType::Other;
|
||||
} else {
|
||||
calculator = CalculatorType::Physical; // 0x8c200000, size 0x300000 is free
|
||||
}
|
||||
|
||||
Ion::Simulator::Main::init();
|
||||
ion_main(0, nullptr);
|
||||
Ion::Simulator::Main::quit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
@@ -53,7 +100,7 @@ void quit() {
|
||||
Ion::Simulator::Display::quit();
|
||||
}
|
||||
|
||||
void EnableStatusArea(int opt) {
|
||||
void EnableStatusArea(int /*opt*/) {
|
||||
__asm__ __volatile__ (
|
||||
".align 2 \n\t"
|
||||
"mov.l 2f, r2 \n\t"
|
||||
@@ -106,6 +153,9 @@ void worldSwitchHandler(void (*worldSwitchFunction)(), bool prepareVRAM) {
|
||||
}
|
||||
|
||||
void runPowerOffSafe(void (*powerOffSafeFunction)(), bool prepareVRAM) {
|
||||
|
||||
gint_world_switch(GINT_CALL(save_state,storage_name));
|
||||
|
||||
gint_world_switch(GINT_CALL(worldSwitchHandler, powerOffSafeFunction, prepareVRAM));
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#ifndef ION_SIMULATOR_MAIN_H
|
||||
#define ION_SIMULATOR_MAIN_H
|
||||
#include <stdint.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
@@ -13,6 +14,14 @@ void refresh();
|
||||
|
||||
void runPowerOffSafe(void (*powerOffSafeFunction)(), bool prepareVRAM);
|
||||
|
||||
enum class CalculatorType : uint8_t {
|
||||
Unchecked = (uint8_t)-1,
|
||||
Unknown = 0,
|
||||
Physical = 1,
|
||||
Emulator = 2,
|
||||
Other = 3
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
ion/src/simulator/nspire/Makefile
Normal file
53
ion/src/simulator/nspire/Makefile
Normal file
@@ -0,0 +1,53 @@
|
||||
|
||||
ion_src += $(addprefix ion/src/simulator/nspire/, \
|
||||
main.cpp \
|
||||
clipboard.cpp \
|
||||
display.cpp \
|
||||
framebuffer.cpp \
|
||||
telemetry_init.cpp \
|
||||
keyboard.cpp \
|
||||
events_keyboard.cpp \
|
||||
events.cpp \
|
||||
timing.cpp \
|
||||
console.cpp \
|
||||
backlight.cpp \
|
||||
power.cpp \
|
||||
k_csdk.c \
|
||||
)
|
||||
|
||||
liba_src += $(addprefix liba/src/, \
|
||||
strlcat.c \
|
||||
strlcpy.c \
|
||||
)
|
||||
|
||||
ion_src += ion/src/shared/collect_registers.cpp
|
||||
|
||||
sdl_simu_needs_to_be_removed += $(addprefix ion/src/simulator/shared/, \
|
||||
main.cpp \
|
||||
clipboard.cpp \
|
||||
display.cpp \
|
||||
framebuffer.cpp \
|
||||
keyboard.cpp \
|
||||
events_keyboard.cpp \
|
||||
events_platform.cpp \
|
||||
events.cpp \
|
||||
layout.cpp \
|
||||
actions.cpp \
|
||||
window.cpp \
|
||||
timing.cpp \
|
||||
console.cpp \
|
||||
)
|
||||
|
||||
sdl_simu_needs_to_be_removed += $(addprefix ion/src/shared/dummy/, \
|
||||
backlight.cpp \
|
||||
power.cpp \
|
||||
)
|
||||
|
||||
# Remove the dummy diaplay (re-implemented) and the SDL simulator stuff.
|
||||
ion_src := $(filter-out $(sdl_simu_needs_to_be_removed),$(ion_src))
|
||||
|
||||
SFLAGS := $(filter-out -Iion/src/simulator/external/sdl/include,$(SFLAGS))
|
||||
|
||||
SFLAGS += -marm -DNSPIRE_NEWLIB -I/Users/parisse/Ndless-r2015/ndless-sdk/ndless/include -I/Users/parisse/Ndless-r2015/ndless-sdk/toolchain/install/include -fno-strict-aliasing -I. -I.. -fno-exceptions -ffreestanding -nostdlib -fstrict-volatile-bitfields -g -Os
|
||||
LDFLAGS += -Wl,--nspireio,--gc-sections -L/Users/parisse/Ndless-r2015/ndless-sdk/lib -L/Users/parisse/Ndless-r2015/ndless-sdk/toolchain/install/lib -nostdlib -lc -lm -lstdc++ -lgcc
|
||||
|
||||
BIN
ion/src/simulator/nspire/assets/icon-sel.png
Normal file
BIN
ion/src/simulator/nspire/assets/icon-sel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
BIN
ion/src/simulator/nspire/assets/icon-uns.png
Normal file
BIN
ion/src/simulator/nspire/assets/icon-uns.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
24
ion/src/simulator/nspire/backlight.cpp
Normal file
24
ion/src/simulator/nspire/backlight.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <ion/backlight.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Backlight {
|
||||
|
||||
uint8_t brightness() {
|
||||
return 128;
|
||||
}
|
||||
|
||||
void setBrightness(uint8_t b) {
|
||||
}
|
||||
|
||||
void init() {
|
||||
}
|
||||
|
||||
bool isInitialized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
15
ion/src/simulator/nspire/clipboard.cpp
Normal file
15
ion/src/simulator/nspire/clipboard.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <ion/clipboard.h>
|
||||
#include <ion.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Clipboard {
|
||||
|
||||
void write(const char * text) {}
|
||||
|
||||
const char * read() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
24
ion/src/simulator/nspire/console.cpp
Normal file
24
ion/src/simulator/nspire/console.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <ion/console.h>
|
||||
#include "main.h"
|
||||
#include <kandinsky/ion_context.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Console {
|
||||
|
||||
char readChar() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void writeChar(char c) {
|
||||
// fxlibc conflicts with this
|
||||
#undef putchar
|
||||
KDIonContext::putchar(c);
|
||||
}
|
||||
|
||||
bool transmissionDone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
47
ion/src/simulator/nspire/display.cpp
Normal file
47
ion/src/simulator/nspire/display.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "display.h"
|
||||
#include "framebuffer.h"
|
||||
#include <kandinsky/color.h>
|
||||
#include <stdint.h>
|
||||
#include <ion/display.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "k_csdk.h"
|
||||
#include <libndls.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Display {
|
||||
|
||||
void init() {
|
||||
}
|
||||
|
||||
void quit() {
|
||||
}
|
||||
|
||||
void draw() {
|
||||
// copy framebuffer
|
||||
const short unsigned int * ptr = (const short unsigned int *) Ion::Simulator::Framebuffer::address();
|
||||
Gc * gcptr = get_gc();
|
||||
for (int j = 0; j < LCD_HEIGHT_PX; ++j) {
|
||||
for (int i = 0; i < LCD_WIDTH_PX;){
|
||||
int c = *ptr;
|
||||
int k = 1;
|
||||
for (; k+i < LCD_WIDTH_PX; ++k) {
|
||||
if (ptr[k]!=c) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
gui_gc_setColor(*gcptr,c_rgb565to888(c));
|
||||
gui_gc_drawRect(*gcptr,i,j,k-1,0);
|
||||
ptr += k;
|
||||
i += k;
|
||||
}
|
||||
}
|
||||
sync_screen();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
19
ion/src/simulator/nspire/display.h
Normal file
19
ion/src/simulator/nspire/display.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef ION_SIMULATOR_DISPLAY_H
|
||||
#define ION_SIMULATOR_DISPLAY_H
|
||||
|
||||
#include <kandinsky.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Display {
|
||||
|
||||
void init();
|
||||
void quit();
|
||||
|
||||
void draw();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
23
ion/src/simulator/nspire/events.cpp
Normal file
23
ion/src/simulator/nspire/events.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "events.h"
|
||||
#include <ion/events.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Events {
|
||||
|
||||
void didPressNewKey() {
|
||||
}
|
||||
|
||||
char * sharedExternalTextBuffer() {
|
||||
static char buffer[sharedExternalTextBufferSize];
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char * Event::text() const {
|
||||
if (*this == ExternalText) {
|
||||
return const_cast<const char *>(sharedExternalTextBuffer());
|
||||
}
|
||||
return defaultText();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
24
ion/src/simulator/nspire/events.h
Normal file
24
ion/src/simulator/nspire/events.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef ION_SIMULATOR_EVENTS_H
|
||||
#define ION_SIMULATOR_EVENTS_H
|
||||
|
||||
#include <ion/events.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Events {
|
||||
|
||||
void dumpEventCount(int i);
|
||||
void logAfter(int numberOfEvents);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Events {
|
||||
|
||||
static constexpr int sharedExternalTextBufferSize = 2;
|
||||
char * sharedExternalTextBuffer();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
15
ion/src/simulator/nspire/events_keyboard.cpp
Normal file
15
ion/src/simulator/nspire/events_keyboard.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <ion/events.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Events {
|
||||
|
||||
|
||||
Event getPlatformEvent() {
|
||||
Event result = None;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
53
ion/src/simulator/nspire/framebuffer.cpp
Normal file
53
ion/src/simulator/nspire/framebuffer.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "framebuffer.h"
|
||||
#include <ion/display.h>
|
||||
#include "main.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
static KDColor sPixels[Ion::Display::Width * Ion::Display::Height];
|
||||
static_assert(sizeof(KDColor) == sizeof(uint16_t), "KDColor is not 16 bits");
|
||||
static bool sFrameBufferActive = true;
|
||||
|
||||
namespace Ion {
|
||||
namespace Display {
|
||||
|
||||
static KDFrameBuffer sFrameBuffer = KDFrameBuffer(sPixels, KDSize(Ion::Display::Width, Ion::Display::Height));
|
||||
|
||||
void pushRect(KDRect r, const KDColor * pixels) {
|
||||
if (sFrameBufferActive) {
|
||||
Simulator::Main::setNeedsRefresh();
|
||||
sFrameBuffer.pushRect(r, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
void pushRectUniform(KDRect r, KDColor c) {
|
||||
if (sFrameBufferActive) {
|
||||
Simulator::Main::setNeedsRefresh();
|
||||
sFrameBuffer.pushRectUniform(r, c);
|
||||
}
|
||||
}
|
||||
|
||||
void pullRect(KDRect r, KDColor * pixels) {
|
||||
if (sFrameBufferActive) {
|
||||
sFrameBuffer.pullRect(r, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Framebuffer {
|
||||
|
||||
const KDColor * address() {
|
||||
return sPixels;
|
||||
}
|
||||
|
||||
void setActive(bool enabled) {
|
||||
sFrameBufferActive = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
17
ion/src/simulator/nspire/framebuffer.h
Normal file
17
ion/src/simulator/nspire/framebuffer.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef ION_SIMULATOR_FRAMEBUFFER_H
|
||||
#define ION_SIMULATOR_FRAMEBUFFER_H
|
||||
|
||||
#include <kandinsky.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Framebuffer {
|
||||
|
||||
const KDColor * address();
|
||||
void setActive(bool enabled);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
61
ion/src/simulator/nspire/gint.h
Normal file
61
ion/src/simulator/nspire/gint.h
Normal file
@@ -0,0 +1,61 @@
|
||||
#ifndef GINT_H
|
||||
#define GINT_H
|
||||
#include "k_defs.h"
|
||||
#define KEY_DOWN KEY_CTRL_DOWN
|
||||
#define KEY_LEFT KEY_CTRL_LEFT
|
||||
#define KEY_RIGHT KEY_CTRL_RIGHT
|
||||
#define KEY_UP KEY_CTRL_UP
|
||||
#define KEY_EXIT KEY_CTRL_EXIT
|
||||
#define KEY_MENU KEY_CTRL_MENU
|
||||
#define KEY_SHIFT KEY_CTRL_SHIFT
|
||||
#define KEY_ALPHA KEY_CTRL_ALPHA
|
||||
#define KEY_XOT KEY_CTRL_XTT
|
||||
#define KEY_VARS KEY_CTRL_VARS
|
||||
#define KEY_OPTN KEY_CTRL_OPTN
|
||||
#define KEY_DEL KEY_CTRL_DEL
|
||||
#define KEY_OPTN KEY_CTRL_OPTN
|
||||
#define KEY_DEL KEY_CTRL_DEL
|
||||
#define KEY_LN KEY_CHAR_LN
|
||||
#define KEY_LOG KEY_CHAR_LOG
|
||||
#define KEY_0 KEY_CHAR_0
|
||||
#define KEY_COMMA KEY_CHAR_COMMA
|
||||
#define KEY_SIN KEY_CHAR_SIN
|
||||
#define KEY_COS KEY_CHAR_COS
|
||||
#define KEY_TAN KEY_CHAR_TAN
|
||||
#define KEY_EXP KEY_CHAR_EXP
|
||||
#define KEY_SQUARE KEY_CHAR_SQUARE
|
||||
#define KEY_7 KEY_CHAR_7
|
||||
#define KEY_8 KEY_CHAR_8
|
||||
#define KEY_9 KEY_CHAR_9
|
||||
#define KEY_LEFTP KEY_CHAR_LPAR
|
||||
#define KEY_RIGHTP KEY_CHAR_RPAR
|
||||
#define KEY_4 KEY_CHAR_4
|
||||
#define KEY_5 KEY_CHAR_5
|
||||
#define KEY_6 KEY_CHAR_6
|
||||
#define KEY_MUL KEY_CHAR_MULT
|
||||
#define KEY_DIV KEY_CHAR_DIV
|
||||
#define KEY_FRAC KEY_CHAR_FRAC
|
||||
#define KEY_1 KEY_CHAR_1
|
||||
#define KEY_2 KEY_CHAR_2
|
||||
#define KEY_3 KEY_CHAR_3
|
||||
#define KEY_ADD KEY_CHAR_PLUS
|
||||
#define KEY_PLUS KEY_CHAR_PLUS
|
||||
#define KEY_SUB KEY_CHAR_MINUS
|
||||
#define KEY_MINUS KEY_CHAR_MINUS
|
||||
#define KEY_NEG KEY_CHAR_PMINUS
|
||||
#define KEY_0 KEY_CHAR_0
|
||||
#define KEY_DOT KEY_CHAR_DP
|
||||
#define KEY_EXE KEY_CTRL_EXE
|
||||
#define KEY_ACON KEY_CTRL_AC
|
||||
#define KEY_POWER KEY_CHAR_POW
|
||||
#define KEY_STORE KEY_CHAR_STORE
|
||||
#define KEY_F1 KEY_CTRL_F1
|
||||
#define KEY_F2 KEY_CTRL_F2
|
||||
#define KEY_F3 KEY_CTRL_F3
|
||||
#define KEY_F4 KEY_CTRL_F4
|
||||
#define KEY_F5 KEY_CTRL_F5
|
||||
#define KEY_F6 KEY_CTRL_F6
|
||||
#define KEY_FD KEY_CTRL_FD
|
||||
#define KEY_ARROW KEY_CTRL_SD
|
||||
#define KEY_TIMES KEY_CHAR_MULT
|
||||
#endif // GINT_H
|
||||
1556
ion/src/simulator/nspire/k_csdk.c
Executable file
1556
ion/src/simulator/nspire/k_csdk.c
Executable file
File diff suppressed because it is too large
Load Diff
255
ion/src/simulator/nspire/k_csdk.h
Normal file
255
ion/src/simulator/nspire/k_csdk.h
Normal file
@@ -0,0 +1,255 @@
|
||||
/* C header for Khicas interface with calculator OS */
|
||||
#ifndef K_CSDK_H
|
||||
#define K_CSDK_H
|
||||
#include "gint.h"
|
||||
#include "k_defs.h"
|
||||
// Defaults parameters do not work if included from C
|
||||
#define SDK_BLACK 0
|
||||
#define SDK_WHITE 65535
|
||||
// C58 is the pixel y coordinate where soft keys menus legends are written
|
||||
#define C24 24
|
||||
#define C18 18
|
||||
#define C10 18
|
||||
#define C6 6
|
||||
#define COLOR_SELECTED ((15<<11)|(15<<5)|15)
|
||||
#if defined FX
|
||||
#define LCD_WIDTH_PX 128
|
||||
#define LCD_HEIGHT_PX 64
|
||||
#elseif defined FXCG
|
||||
#define LCD_WIDTH_PX 384
|
||||
#define LCD_HEIGHT_PX 128
|
||||
#else
|
||||
#define LCD_WIDTH_PX 320
|
||||
#define LCD_HEIGHT_PX 240
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "stdio.h"
|
||||
|
||||
#ifdef TICE
|
||||
#define C58 214
|
||||
#include "dbg.h"
|
||||
#define max_heap_size 60
|
||||
#define COLOR_WHITE SDK_WHITE
|
||||
#define TEXT_COLOR_WHITE SDK_WHITE
|
||||
#define COLOR_BLACK SDK_BLACK
|
||||
#define COLOR_ORANGE ((31<<11)|(7<<5)|31)
|
||||
#define COLOR_CYAN ((63<<5)|31)
|
||||
#define COLOR_GREEN (63<<5)
|
||||
#define TEXT_COLOR_GREEN (63<<5)
|
||||
#define COLOR_MAGENTA ((31<<11)|31)
|
||||
#define COLOR_RED (31<<11)
|
||||
#define TEXT_COLOR_RED (31<<11)
|
||||
#define COLOR_BLUE 31
|
||||
#define TEXT_COLOR_BLACK 0
|
||||
#define TEXT_COLOR_PURPLE ((15<<11)| 24)
|
||||
#define TEXT_COLOR_BLUE 3
|
||||
#define COLOR_BROWN ((15<<11)|(15<<5))
|
||||
#define TEXT_MODE_NORMAL 0
|
||||
#define TEXT_MODE_INVERT 1
|
||||
#define MINI_REV 4
|
||||
#define false 0
|
||||
#define true 1
|
||||
void sdk_init(void);
|
||||
void sdk_end(void);
|
||||
void clear_screen(void);
|
||||
#else //TICE
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
void sdk_init(void);
|
||||
void sdk_end(void);
|
||||
#else
|
||||
inline void sdk_init(void){}
|
||||
inline void sdk_end(void){}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern short exam_mode,nspire_exam_mode;
|
||||
// nspire_exam_mode==0 normal mode
|
||||
// ==1 led are blinking
|
||||
// ==2 OS exam mode is on but led are not blinking
|
||||
// Set the Nspire in normal exam mode at home, transfer ndless and khicas
|
||||
// activate khicas: will detect led blinking (mode ==1)
|
||||
// prepare exam mode with Khicas menu item (clear led, mode==2),
|
||||
// in that mode menu menu will not leave KhiCAS anymore but
|
||||
// will clean data and do a hardware reset (launch again exam mode and leds)
|
||||
extern unsigned exam_start;
|
||||
extern int exam_duration;
|
||||
int ext_main();
|
||||
int waitforvblank();
|
||||
int back_key_pressed() ;
|
||||
// next 3 functions may be void if not inside a window class hierarchy
|
||||
void os_show_graph(); // show graph inside Python shell (Numworks), not used
|
||||
void os_hide_graph(); // hide graph, not used anymore
|
||||
void os_redraw(); // force redraw of window class hierarchy
|
||||
#ifdef NUMWORKS
|
||||
#define max_heap_size 96
|
||||
void raisememerr();
|
||||
extern unsigned _heap_size;
|
||||
extern void * _heap_ptr;
|
||||
extern void * _heap_base;
|
||||
int inexammode();
|
||||
int extapp_restorebackup(int mode);
|
||||
void numworks_set_pixel(int x,int y,int c);
|
||||
int numworks_get_pixel(int x,int y);
|
||||
void numworks_fill_rect(int x,int y,int w,int h,int c);
|
||||
#ifdef __cplusplus
|
||||
int numworks_draw_string(int x,int y,int c,int bg,const char * s,int fake=false);
|
||||
int numworks_draw_string_small(int x,int y,int c,int bg,const char * s,int fake=0);
|
||||
#else
|
||||
int numworks_draw_string(int x,int y,int c,int bg,const char * s,int fake);
|
||||
int numworks_draw_string_small(int x,int y,int c,int bg,const char * s,int fake);
|
||||
#endif
|
||||
void numworks_show_graph();
|
||||
void numworks_hide_graph();
|
||||
void numworks_redraw();
|
||||
void numworks_wait_1ms(int ms);
|
||||
// access to Numworks OS, defined in port.cpp (or modkandinsky.cpp)
|
||||
inline void os_set_pixel(int x,int y,int c){
|
||||
numworks_set_pixel(x,y,c);
|
||||
}
|
||||
inline int os_get_pixel(int x,int y){
|
||||
return numworks_get_pixel(x,y);
|
||||
}
|
||||
inline void os_fill_rect(int x,int y,int w,int h,int c){
|
||||
numworks_fill_rect(x,y,w,h,c);
|
||||
}
|
||||
inline int os_draw_string(int x,int y,int c,int bg,const char * s,int fake){
|
||||
return numworks_draw_string(x,y,c,bg,s,fake);
|
||||
}
|
||||
inline int os_draw_string_small(int x,int y,int c,int bg,const char * s,int fake){
|
||||
return numworks_draw_string_small(x,y,c,bg,s,fake);
|
||||
}
|
||||
inline void os_shaw_graph(){ return numworks_show_graph(); }
|
||||
inline void os_hide_graph(){ return numworks_hide_graph(); }
|
||||
inline void os_redraw(){ return numworks_redraw(); }
|
||||
inline void os_wait_1ms(int ms) { numworks_wait_1ms(ms); }
|
||||
int getkey_raw(int allow_suspend); // Numworks scan code
|
||||
inline void sync_screen(){}
|
||||
#endif // NUMWORKS
|
||||
|
||||
void os_wait_1ms(int ms);
|
||||
int os_set_angle_unit(int mode);
|
||||
int os_get_angle_unit();
|
||||
double millis(); //extern int time_shift;
|
||||
void get_time(int *h,int *m);
|
||||
void set_time(int h,int m);
|
||||
|
||||
int file_exists(const char * filename);
|
||||
int erase_file(const char * filename);
|
||||
const char * read_file(const char * filename);
|
||||
#ifdef __cplusplus
|
||||
int write_file(const char * filename,const char * s,int len=0);
|
||||
#else
|
||||
int write_file(const char * filename,const char * s,int len);
|
||||
#endif
|
||||
#define MAX_NUMBER_OF_FILENAMES 255
|
||||
int os_file_browser(const char ** filenames,int maxrecords,const char * extension,int storage);
|
||||
void sync_screen();
|
||||
void os_set_pixel(int x,int y,int c);
|
||||
void os_fill_rect(int x,int y,int w,int h,int c);
|
||||
inline void drawRectangle(int x,int y,int w,int h,int c){
|
||||
if (w>=0 && h>=0)
|
||||
os_fill_rect(x,y,w,h,c);
|
||||
}
|
||||
int os_get_pixel(int x,int y);
|
||||
/* returns new x position */
|
||||
#ifdef __cplusplus
|
||||
int os_draw_string(int x,int y,int c,int bg,const char * s,int fake=0);
|
||||
#else
|
||||
int os_draw_string(int x,int y,int c,int bg,const char * s,int fake);
|
||||
#endif
|
||||
inline int os_draw_string_(int x,int y,const char * s){ return os_draw_string(x,y,SDK_BLACK,SDK_WHITE,s,0);}
|
||||
#ifdef __cplusplus
|
||||
int os_draw_string_small(int x,int y,int c,int bg,const char * s,int fake=0);
|
||||
#else
|
||||
int os_draw_string_small(int x,int y,int c,int bg,const char * s,int fake);
|
||||
#endif
|
||||
inline int os_draw_string_small_(int x,int y,const char * s){ return os_draw_string_small(x,y,SDK_BLACK,SDK_WHITE,s,0);}
|
||||
|
||||
#ifdef __cplusplus
|
||||
#ifdef NUMWORKS
|
||||
inline int os_draw_string_medium(int x,int y,int c,int bg,const char * s,int fake=0){ return os_draw_string_small(x,y,c,bg,s,fake);}
|
||||
#else
|
||||
int os_draw_string_medium(int x,int y,int c,int bg,const char * s,int fake=0);
|
||||
#endif
|
||||
#else
|
||||
#ifdef NUMWORKS
|
||||
inline int os_draw_string_medium(int x,int y,int c,int bg,const char * s,int fake){ return os_draw_string_small(x,y,c,bg,s,fake);}
|
||||
#else
|
||||
int os_draw_string_medium(int x,int y,int c,int bg,const char * s,int fake);
|
||||
#endif
|
||||
#endif
|
||||
inline int os_draw_string_medium_(int x,int y,const char * s){ return os_draw_string_medium(x,y,SDK_BLACK,SDK_WHITE,s,0);}
|
||||
|
||||
inline void Printmini(int x,int y,const char * s,int i){
|
||||
// dbg_printf("Printmini %i %i %s %i\n",x,y,s,i);
|
||||
#if defined FX || defined FXCG
|
||||
os_draw_string_small(x,y,i?0xffff:0,i?0:0xffff,s,false);
|
||||
#else
|
||||
os_draw_string_small(x,y,SDK_BLACK,i?COLOR_SELECTED:SDK_WHITE,s,false);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void Printxy(int x,int y,const char * s,int i){ os_draw_string_medium(x,y,0,i?COLOR_SELECTED:0xffff,s,false);}
|
||||
inline void PrintXY(int x,int y,const char * s,int i){ Printxy(3*x,3*y,s,i);}
|
||||
|
||||
void GetKey(int * key);
|
||||
int getkey(int allow_suspend); // transformed
|
||||
inline void ck_getkey(int *key){ GetKey(key);}
|
||||
void enable_back_interrupt();
|
||||
inline void set_abort(){ enable_back_interrupt(); }
|
||||
void disable_back_interrupt();
|
||||
inline void clear_abort(){ disable_back_interrupt(); }
|
||||
int isalphaactive();
|
||||
int alphawasactive(int * key);
|
||||
void lock_alpha();
|
||||
void reset_kbd();
|
||||
int handle_f5();
|
||||
void statuslinemsg(const char * msg);
|
||||
#ifdef __cplusplus
|
||||
void statusline(int mode=0);
|
||||
#else
|
||||
void statusline(int mode);
|
||||
#endif
|
||||
void statusflags(void);
|
||||
#ifdef NUMWORKS
|
||||
inline int iskeydown(int key){ return getkey(key | 0x80000000); }
|
||||
#else
|
||||
int iskeydown(int key);
|
||||
#endif
|
||||
|
||||
#if defined NSPIRE || defined NSPIRE_NEWLIB
|
||||
extern int nspire_shift,nspire_ctrl;
|
||||
double loopsleep(int ms);
|
||||
#include <libndls.h>
|
||||
Gc * get_gc();
|
||||
int c_rgb565to888(int c);
|
||||
int nspire_scan(int * adaptive_cursor_state);
|
||||
|
||||
#define max_heap_size 60
|
||||
extern int nspireemu;
|
||||
extern char nspire_filebuf[NSPIRE_FILEBUFFER];
|
||||
extern int on_key_enabled;
|
||||
void get_hms(int *h,int *m,int *s);
|
||||
void reset_gc();
|
||||
#endif
|
||||
|
||||
extern int (*shutdown)(); // function called after 2 hours of idle
|
||||
extern short int shutdown_state;
|
||||
inline void Bdisp_PutDisp_DD(void){ sync_screen(); }
|
||||
inline void sprint_int(char * c,int i){ sprintf(c,"%d",i);}
|
||||
inline void sprint_double(char * c,double d){ sprintf(c,"%.4g",d);}
|
||||
int GetSetupSetting(int k);
|
||||
inline int Setup_GetEntry(int k){ return GetSetupSetting(k); }
|
||||
void SetQuitHandler( void (*f)(void));
|
||||
#define RTC_GetTicks millis
|
||||
#ifndef TICE
|
||||
inline void clear_screen(void){os_fill_rect(0,0,LCD_WIDTH_PX,LCD_HEIGHT_PX,SDK_WHITE);}
|
||||
#endif
|
||||
inline void Bdisp_AllClr_VRAM(void){ clear_screen(); }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // K_CSDK_H
|
||||
211
ion/src/simulator/nspire/k_defs.h
Executable file
211
ion/src/simulator/nspire/k_defs.h
Executable file
@@ -0,0 +1,211 @@
|
||||
#ifndef K_DEFS_H
|
||||
#define K_DEFS_H
|
||||
#define NSPIRE_FILEBUFFER 512*1024
|
||||
// Character codes
|
||||
#define KEY_CHAR_0 0x30
|
||||
#define KEY_CHAR_1 0x31
|
||||
#define KEY_CHAR_2 0x32
|
||||
#define KEY_CHAR_3 0x33
|
||||
#define KEY_CHAR_4 0x34
|
||||
#define KEY_CHAR_5 0x35
|
||||
#define KEY_CHAR_6 0x36
|
||||
#define KEY_CHAR_7 0x37
|
||||
#define KEY_CHAR_8 0x38
|
||||
#define KEY_CHAR_9 0x39
|
||||
#define KEY_CHAR_DP 0x2e
|
||||
#define KEY_CHAR_EXP 0x0f
|
||||
#define KEY_CHAR_PMINUS 30200
|
||||
#define KEY_CHAR_PLUS 43
|
||||
#define KEY_CHAR_MINUS 45
|
||||
#define KEY_CHAR_MULT 42
|
||||
#define KEY_CHAR_DIV 47
|
||||
#define KEY_CHAR_FRAC 0xbb
|
||||
#define KEY_CHAR_LPAR 0x28
|
||||
#define KEY_CHAR_RPAR 0x29
|
||||
#define KEY_CHAR_COMMA 0x2c
|
||||
#define KEY_CHAR_STORE 0x0e
|
||||
#define KEY_CHAR_LOG 0x95
|
||||
#define KEY_CHAR_LN 0x85
|
||||
#define KEY_CHAR_SIN 0x81
|
||||
#define KEY_CHAR_COS 0x82
|
||||
#define KEY_CHAR_TAN 0x83
|
||||
#define KEY_CHAR_SQUARE 0x8b
|
||||
#define KEY_CHAR_POW 0xa8
|
||||
#define KEY_CHAR_IMGNRY 0x7f50
|
||||
#define KEY_CHAR_LIST 0x7f51
|
||||
#define KEY_CHAR_MAT 0x7f40
|
||||
#define KEY_CHAR_EQUAL 0x3d
|
||||
#define KEY_CHAR_PI 0xd0
|
||||
#define KEY_CHAR_ANS 0xc0
|
||||
#define KEY_SHIFT_ANS 0xc1
|
||||
#define KEY_CHAR_LBRCKT 0x5b
|
||||
#define KEY_CHAR_RBRCKT 0x5d
|
||||
#define KEY_CHAR_LBRACE 0x7b
|
||||
#define KEY_CHAR_RBRACE 0x7d
|
||||
#define KEY_CHAR_CR 0x0d
|
||||
#define KEY_CHAR_CUBEROOT 0x96
|
||||
#define KEY_CHAR_RECIP 0x9b
|
||||
#define KEY_CHAR_ANGLE 0x7f54
|
||||
#define KEY_CHAR_EXPN10 0xb5
|
||||
#define KEY_CHAR_EXPN 0xa5
|
||||
#define KEY_CHAR_ASIN 0x91
|
||||
#define KEY_CHAR_ACOS 0x92
|
||||
#define KEY_CHAR_ATAN 0x93
|
||||
#define KEY_CHAR_ROOT 0x86
|
||||
#define KEY_CHAR_POWROOT 0xb8
|
||||
#define KEY_CHAR_SPACE 0x20
|
||||
#define KEY_CHAR_DQUATE 0x22
|
||||
#define KEY_CHAR_VALR 0xcd
|
||||
#define KEY_CHAR_THETA 0xce
|
||||
#define KEY_CHAR_FACTOR 0xda
|
||||
#define KEY_CHAR_NORMAL 0xdb
|
||||
#define KEY_CHAR_SHIFTMINUS 0xdc
|
||||
#define KEY_CHAR_CROCHETS 0xdd
|
||||
#define KEY_CHAR_ACCOLADES 0xde
|
||||
#define KEY_CHAR_A 0x41
|
||||
#define KEY_CHAR_B 0x42
|
||||
#define KEY_CHAR_C 0x43
|
||||
#define KEY_CHAR_D 0x44
|
||||
#define KEY_CHAR_E 0x45
|
||||
#define KEY_CHAR_F 0x46
|
||||
#define KEY_CHAR_G 0x47
|
||||
#define KEY_CHAR_H 0x48
|
||||
#define KEY_CHAR_I 0x49
|
||||
#define KEY_CHAR_J 0x4a
|
||||
#define KEY_CHAR_K 0x4b
|
||||
#define KEY_CHAR_L 0x4c
|
||||
#define KEY_CHAR_M 0x4d
|
||||
#define KEY_CHAR_N 0x4e
|
||||
#define KEY_CHAR_O 0x4f
|
||||
#define KEY_CHAR_P 0x50
|
||||
#define KEY_CHAR_Q 0x51
|
||||
#define KEY_CHAR_R 0x52
|
||||
#define KEY_CHAR_S 0x53
|
||||
#define KEY_CHAR_T 0x54
|
||||
#define KEY_CHAR_U 0x55
|
||||
#define KEY_CHAR_V 0x56
|
||||
#define KEY_CHAR_W 0x57
|
||||
#define KEY_CHAR_X 0x58
|
||||
#define KEY_CHAR_Y 0x59
|
||||
#define KEY_CHAR_Z 0x5a
|
||||
|
||||
|
||||
// Control codes
|
||||
#define KEY_CTRL_FORMAT 30203
|
||||
#define KEY_CTRL_NOP 30202
|
||||
#define KEY_CTRL_EXE 30201
|
||||
#define KEY_CTRL_DEL 30025
|
||||
#define KEY_CTRL_AC 30070
|
||||
#define KEY_CTRL_FD 30046
|
||||
#define KEY_CTRL_UNDO 30045
|
||||
#define KEY_CTRL_XTT 30001
|
||||
#define KEY_CTRL_EXIT 5
|
||||
#define KEY_CTRL_OK 4
|
||||
#define KEY_CTRL_SHIFT 30006
|
||||
#define KEY_CTRL_ALPHA 30007
|
||||
#define KEY_CTRL_OPTN 30008
|
||||
#define KEY_CTRL_VARS 30030
|
||||
#define KEY_CTRL_UP 1
|
||||
#define KEY_CTRL_DOWN 2
|
||||
#define KEY_CTRL_LEFT 0
|
||||
#define KEY_CTRL_RIGHT 3
|
||||
#define KEY_CTRL_F1 30009
|
||||
#define KEY_CTRL_F2 30010
|
||||
#define KEY_CTRL_F3 30011
|
||||
#define KEY_CTRL_F4 30012
|
||||
#define KEY_CTRL_F5 30013
|
||||
#define KEY_CTRL_F6 30014
|
||||
#define KEY_CTRL_F7 30915
|
||||
#define KEY_CTRL_F8 30916
|
||||
#define KEY_CTRL_F9 30917
|
||||
#define KEY_CTRL_F10 30918
|
||||
#define KEY_CTRL_F11 30919
|
||||
#define KEY_CTRL_F12 30920
|
||||
#define KEY_CTRL_F13 30921
|
||||
#define KEY_CTRL_F14 30922
|
||||
#define KEY_CTRL_F15 30923
|
||||
#define KEY_CTRL_F16 30924
|
||||
#define KEY_CTRL_F17 30925
|
||||
#define KEY_CTRL_F18 30926
|
||||
#define KEY_CTRL_F19 30927
|
||||
#define KEY_CTRL_F20 30928
|
||||
#define KEY_CTRL_CATALOG 30100
|
||||
#define KEY_CTRL_CAPTURE 30055
|
||||
#define KEY_CTRL_CLIP 30050
|
||||
#define KEY_CTRL_CUT 30250
|
||||
#define KEY_CTRL_PASTE 30036
|
||||
#define KEY_CTRL_INS 30033
|
||||
#define KEY_CTRL_MIXEDFRAC 30054
|
||||
#define KEY_CTRL_FRACCNVRT 30026
|
||||
#define KEY_CTRL_QUIT 30029
|
||||
#define KEY_CTRL_PRGM 30028
|
||||
#define KEY_CTRL_SETUP 30037
|
||||
#define KEY_CTRL_PAGEUP 30052
|
||||
#define KEY_CTRL_PAGEDOWN 30053
|
||||
#define KEY_CTRL_MENU 30003
|
||||
#define KEY_SHIFT_OPTN 30059
|
||||
#define KEY_CTRL_RESERVE1 30060
|
||||
#define KEY_CTRL_RESERVE2 30061
|
||||
#define KEY_SHIFT_LEFT 30062
|
||||
#define KEY_SHIFT_RIGHT 30063
|
||||
#define KEY_UP_CTRL 31060
|
||||
#define KEY_DOWN_CTRL 31061
|
||||
#define KEY_LEFT_CTRL 31062
|
||||
#define KEY_RIGHT_CTRL 31063
|
||||
#define KEY_CALCULATOR 31064
|
||||
#define KEY_SAVE 31065
|
||||
#define KEY_LOAD 31066
|
||||
#define KEY_CTRL_A 31001
|
||||
#define KEY_CTRL_D 31004
|
||||
#define KEY_CTRL_E 31005
|
||||
#define KEY_CTRL_H 31008 // help?
|
||||
#define KEY_CTRL_M 31011 // doc menu
|
||||
#define KEY_CTRL_N 31012
|
||||
#define KEY_CTRL_R 31018
|
||||
#define KEY_CTRL_S 31019
|
||||
#define KEY_CTRL_T 31020
|
||||
#define KEY_EQW_TEMPLATE 31100
|
||||
#define KEY_AFFECT 31101
|
||||
#define KEY_FLAG 31102
|
||||
#define KEY_BOOK 31103
|
||||
//#define KEY_CTRL_APPS 31104
|
||||
#define KEY_CTRL_SYMB 31105
|
||||
//#define KEY_CTRL_NUM 31106
|
||||
//#define KEY_CTRL_PLOT 31107
|
||||
#define KEY_SELECT_LEFT 31200
|
||||
#define KEY_SELECT_UP 31201
|
||||
#define KEY_SELECT_DOWN 31202
|
||||
#define KEY_SELECT_RIGHT 31203
|
||||
#define KEY_SHUTDOWN 32109
|
||||
|
||||
#define KEY_PRGM_ACON 10
|
||||
#define KEY_PRGM_DOWN 37
|
||||
#define KEY_PRGM_EXIT 47
|
||||
#define KEY_PRGM_F1 79
|
||||
#define KEY_PRGM_F2 69
|
||||
#define KEY_PRGM_F3 59
|
||||
#define KEY_PRGM_F4 49
|
||||
#define KEY_PRGM_F5 39
|
||||
#define KEY_PRGM_F6 29
|
||||
#define KEY_PRGM_LEFT 38
|
||||
#define KEY_PRGM_NONE 0
|
||||
#define KEY_PRGM_RETURN 31
|
||||
#define KEY_PRGM_RIGHT 27
|
||||
#define KEY_PRGM_UP 28
|
||||
#define KEY_PRGM_1 72
|
||||
#define KEY_PRGM_2 62
|
||||
#define KEY_PRGM_3 52
|
||||
#define KEY_PRGM_4 73
|
||||
#define KEY_PRGM_5 63
|
||||
#define KEY_PRGM_6 53
|
||||
#define KEY_PRGM_7 74
|
||||
#define KEY_PRGM_8 64
|
||||
#define KEY_PRGM_9 54
|
||||
#define KEY_PRGM_A 76
|
||||
#define KEY_PRGM_F 26
|
||||
#define KEY_PRGM_ALPHA 77
|
||||
#define KEY_PRGM_SHIFT 78
|
||||
#define KEY_PRGM_MENU 48
|
||||
#define KEY_CTRL_SD 39990
|
||||
|
||||
#endif
|
||||
276
ion/src/simulator/nspire/keyboard.cpp
Normal file
276
ion/src/simulator/nspire/keyboard.cpp
Normal file
@@ -0,0 +1,276 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
#include <ion/keyboard.h>
|
||||
#include <ion/events.h>
|
||||
#include <ion/power.h>
|
||||
|
||||
#include "layout_keyboard.h"
|
||||
#include "main.h"
|
||||
#include "k_csdk.h"
|
||||
|
||||
|
||||
using namespace Ion::Keyboard;
|
||||
|
||||
class KeyPair {
|
||||
public:
|
||||
constexpr KeyPair(Key key, bool numworksShift, bool numworksAlpha, int gintKey, bool gintShift, bool gintAlpha, bool ignoreShiftAlpha = false) :
|
||||
m_key(key),
|
||||
m_numworksShift(numworksShift),
|
||||
m_numworksAlpha(numworksAlpha),
|
||||
m_gintKey(gintKey),
|
||||
m_gintShift(gintShift),
|
||||
m_gintAlpha(gintAlpha),
|
||||
m_ignoreShiftAlpha(ignoreShiftAlpha)
|
||||
{}
|
||||
Key key() const { return m_key; }
|
||||
bool numworksShift() const { return m_numworksShift; }
|
||||
bool numworksAlpha() const { return m_numworksAlpha; }
|
||||
int gintKey() const { return m_gintKey; }
|
||||
bool gintShift() const { return m_gintShift; }
|
||||
bool gintAlpha() const { return m_gintAlpha; }
|
||||
bool ignoreShiftAlpha() const { return m_ignoreShiftAlpha; }
|
||||
private:
|
||||
Key m_key;
|
||||
bool m_numworksShift;
|
||||
bool m_numworksAlpha;
|
||||
int m_gintKey;
|
||||
bool m_gintShift;
|
||||
bool m_gintAlpha;
|
||||
bool m_ignoreShiftAlpha;
|
||||
};
|
||||
|
||||
constexpr static KeyPair sKeyPairs[] = {
|
||||
KeyPair(Key::Down, false, false, KEY_DOWN, false, false, true),
|
||||
KeyPair(Key::Left, false, false, KEY_LEFT, false, false, true),
|
||||
KeyPair(Key::Right, false, false, KEY_RIGHT, false, false, true),
|
||||
KeyPair(Key::Up, false, false, KEY_UP, false, false, true),
|
||||
KeyPair(Key::Back, false, false, KEY_EXIT, false, false),
|
||||
KeyPair(Key::Home, false, false, KEY_MENU, false, false),
|
||||
KeyPair(Key::Shift, false, false, KEY_SHIFT, false, false, true),
|
||||
KeyPair(Key::Alpha, false, false, KEY_ALPHA, false, false, true),
|
||||
KeyPair(Key::XNT, false, false, KEY_XOT, false, false),
|
||||
KeyPair(Key::Var, false, false, KEY_VARS, false, false),
|
||||
KeyPair(Key::Toolbox, false, false, KEY_CTRL_CATALOG, false, false),
|
||||
KeyPair(Key::Backspace, false, false, KEY_DEL, false, false),
|
||||
KeyPair(Key::Exp, false, false, KEY_CHAR_EXPN, false, false),
|
||||
KeyPair(Key::Ln, false, false, KEY_LN, false, false),
|
||||
KeyPair(Key::Log, false, false, KEY_LOG, false, false),
|
||||
KeyPair(Key::Imaginary, false, false, KEY_CHAR_IMGNRY, false, false),
|
||||
KeyPair(Key::Comma, false, false, KEY_COMMA, false, false),
|
||||
KeyPair(Key::Power, false, false, '^', false, false),
|
||||
KeyPair(Key::Sine, false, false, KEY_SIN, false, false),
|
||||
KeyPair(Key::Cosine, false, false, KEY_COS, false, false),
|
||||
KeyPair(Key::Tangent, false, false, KEY_TAN, false, false),
|
||||
KeyPair(Key::Pi, false, false, KEY_CHAR_PI, false, false),
|
||||
KeyPair(Key::Sqrt, false, false, KEY_CHAR_ROOT, false, false),
|
||||
KeyPair(Key::Square, false, false, KEY_SQUARE, false, false),
|
||||
KeyPair(Key::Seven, false, false, KEY_7, false, false),
|
||||
KeyPair(Key::Eight, false, false, KEY_8, false, false),
|
||||
KeyPair(Key::Nine, false, false, KEY_9, false, false),
|
||||
KeyPair(Key::LeftParenthesis, false, false, KEY_LEFTP, false, false),
|
||||
KeyPair(Key::RightParenthesis, false, false, KEY_RIGHTP, false, false),
|
||||
KeyPair(Key::Four, false, false, KEY_4, false, false),
|
||||
KeyPair(Key::Five, false, false, KEY_5, false, false),
|
||||
KeyPair(Key::Six, false, false, KEY_6, false, false),
|
||||
KeyPair(Key::Multiplication, false, false, KEY_MUL, false, false),
|
||||
KeyPair(Key::Division, false, false, KEY_DIV, false, false),
|
||||
KeyPair(Key::Division, false, false, KEY_FRAC, false, false),
|
||||
KeyPair(Key::One, false, false, KEY_1, false, false),
|
||||
KeyPair(Key::Two, false, false, KEY_2, false, false),
|
||||
KeyPair(Key::Three, false, false, KEY_3, false, false),
|
||||
KeyPair(Key::Plus, false, false, KEY_ADD, false, false),
|
||||
KeyPair(Key::Minus, false, false, KEY_SUB, false, false),
|
||||
KeyPair(Key::Zero, false, false, KEY_0, false, false),
|
||||
KeyPair(Key::Dot, false, false, KEY_DOT, false, false),
|
||||
KeyPair(Key::EE, false, false, KEY_CHAR_EXP, false, false),
|
||||
KeyPair(Key::Ans, false, false, KEY_CHAR_ANS, true, false),
|
||||
KeyPair(Key::EXE, false, false, KEY_EXE, false, false, true),
|
||||
KeyPair(Key::OnOff, false, false, KEY_ACON, false, false),
|
||||
|
||||
// Cut
|
||||
KeyPair(Key::XNT, true, false, KEY_CTRL_CUT, false, false),
|
||||
// Copy
|
||||
KeyPair(Key::Var, true, false, KEY_CTRL_CLIP, false, false),
|
||||
// Paste
|
||||
KeyPair(Key::Toolbox, true, false, KEY_CTRL_PASTE, false, false),
|
||||
// Clear
|
||||
KeyPair(Key::Backspace, true, false, KEY_ACON, false, false),
|
||||
// [
|
||||
KeyPair(Key::Exp, true, false, KEY_CHAR_CROCHETS, false, false),
|
||||
// ]
|
||||
KeyPair(Key::Ln, true, false, KEY_CTRL_F13, false, false),
|
||||
// {
|
||||
KeyPair(Key::Log, true, false, KEY_CHAR_ACCOLADES, false, false),
|
||||
// }
|
||||
KeyPair(Key::Imaginary, true, false, KEY_CTRL_F14, false, false),
|
||||
// _
|
||||
KeyPair(Key::Comma, true, false, KEY_NEG, false, false),
|
||||
// ->
|
||||
KeyPair(Key::Power, true, false, KEY_STORE, false, true),
|
||||
// asin
|
||||
KeyPair(Key::Sine, true, false, KEY_CHAR_ASIN, true, false),
|
||||
// acos
|
||||
KeyPair(Key::Cosine, true, false, KEY_CHAR_ACOS, true, false),
|
||||
// atan
|
||||
KeyPair(Key::Tangent, true, false, KEY_CHAR_ATAN, true, false),
|
||||
// =
|
||||
KeyPair(Key::Pi, true, false, KEY_CHAR_EQUAL, false, false),
|
||||
// <
|
||||
KeyPair(Key::Sqrt, true, false, '<', false, false),
|
||||
// >
|
||||
KeyPair(Key::Square, true, false, '>', false, false),
|
||||
|
||||
// :
|
||||
KeyPair(Key::XNT, false, true, ':', false, false),
|
||||
// ;
|
||||
KeyPair(Key::Var, false, true, ';', false, false),
|
||||
// "
|
||||
KeyPair(Key::Toolbox, false, true, KEY_CHAR_DQUATE, false, true),
|
||||
// %
|
||||
KeyPair(Key::Backspace, false, true, '%', false, false),
|
||||
// A
|
||||
KeyPair(Key::Exp, false, true, 'a', false, false),
|
||||
// B
|
||||
KeyPair(Key::Ln, false, true, 'b', false, false),
|
||||
// C
|
||||
KeyPair(Key::Log, false, true, 'c', false, false),
|
||||
// D
|
||||
KeyPair(Key::Imaginary, false, true, 'd', false, false),
|
||||
// E
|
||||
KeyPair(Key::Comma, false, true, 'e', false, false),
|
||||
// F
|
||||
KeyPair(Key::Power, false, true, 'f', false, false),
|
||||
// G
|
||||
KeyPair(Key::Sine, false, true, 'g', false, false),
|
||||
// H
|
||||
KeyPair(Key::Cosine, false, true, 'h', false, false),
|
||||
// I
|
||||
KeyPair(Key::Tangent, false, true, 'i', false, false),
|
||||
// J
|
||||
KeyPair(Key::Pi, false, true, 'j', false, false),
|
||||
// K
|
||||
KeyPair(Key::Sqrt, false, true,'k', false, false),
|
||||
// L
|
||||
KeyPair(Key::Square, false, true, 'l', false, false),
|
||||
// M
|
||||
KeyPair(Key::Seven, false, true, 'm', false, false),
|
||||
// N
|
||||
KeyPair(Key::Eight, false, true, 'n', false, false),
|
||||
// O
|
||||
KeyPair(Key::Nine, false, true, 'o', false, false),
|
||||
// P
|
||||
KeyPair(Key::LeftParenthesis, false, true, 'p', false, false),
|
||||
// Q
|
||||
KeyPair(Key::RightParenthesis, false, true, 'q', false, false),
|
||||
// R
|
||||
KeyPair(Key::Four, false, true, 'r', false, false),
|
||||
// S
|
||||
KeyPair(Key::Five, false, true, 's', false, false),
|
||||
// T
|
||||
KeyPair(Key::Six, false, true, 't', false, false),
|
||||
// U
|
||||
KeyPair(Key::Multiplication, false, true, 'u', false, false),
|
||||
// V
|
||||
KeyPair(Key::Division, false, true, 'v', false, false),
|
||||
// W
|
||||
KeyPair(Key::One, false, true, 'w', false, false),
|
||||
// X
|
||||
KeyPair(Key::Two, false, true, 'x', false, false),
|
||||
// Y
|
||||
KeyPair(Key::Three, false, true, 'y', false, false),
|
||||
// Z
|
||||
KeyPair(Key::Plus, false, true, 'z', false, false),
|
||||
// Space
|
||||
KeyPair(Key::Minus, false, true, KEY_CHAR_SPACE, false, false),
|
||||
// ?
|
||||
KeyPair(Key::Zero, false, true, KEY_F6, true, false),
|
||||
// !
|
||||
KeyPair(Key::Dot, false, true, KEY_F6, false, false),
|
||||
|
||||
// Brightness control shortcut in Upsilon
|
||||
KeyPair(Key::Plus, true, false, KEY_ADD, false, true),
|
||||
KeyPair(Key::Minus, true, false, KEY_SUB, false, true),
|
||||
|
||||
|
||||
};
|
||||
|
||||
constexpr int sNumberOfKeyPairs = sizeof(sKeyPairs)/sizeof(KeyPair);
|
||||
|
||||
namespace Ion {
|
||||
namespace Keyboard {
|
||||
|
||||
int menuHeldFor = 0;
|
||||
|
||||
State scan() {
|
||||
State state = 0;
|
||||
|
||||
// Grab this opportunity to refresh the display if needed
|
||||
Simulator::Main::refresh();
|
||||
if (!any_key_pressed())
|
||||
return state;
|
||||
if (isKeyPressed(KEY_NSPIRE_HOME)){
|
||||
state.setKey(Key::Home); return state;
|
||||
}
|
||||
if (isKeyPressed(KEY_NSPIRE_ENTER)){
|
||||
state.setKey(Key::EXE);
|
||||
return state;
|
||||
}
|
||||
if (isKeyPressed(KEY_NSPIRE_LEFT)){
|
||||
state.setKey(Key::Left);
|
||||
return state;
|
||||
}
|
||||
if (isKeyPressed(KEY_NSPIRE_RIGHT)){
|
||||
state.setKey(Key::Right);
|
||||
return state;
|
||||
}
|
||||
if (isKeyPressed(KEY_NSPIRE_UP)){
|
||||
state.setKey(Key::Up);
|
||||
return state;
|
||||
}
|
||||
if (isKeyPressed(KEY_NSPIRE_DOWN)){
|
||||
state.setKey(Key::Down);
|
||||
return state;
|
||||
}
|
||||
int shiftstate;
|
||||
int scancode=nspire_scan(&shiftstate);
|
||||
if (scancode==0) {
|
||||
return state;
|
||||
}
|
||||
switch (scancode){
|
||||
case -2: case -1:
|
||||
return state;
|
||||
case KEY_CTRL_EXIT:
|
||||
state.setKey(Key::Back);
|
||||
return state;
|
||||
case KEY_CTRL_EXE:
|
||||
state.setKey(Key::EXE);
|
||||
return state;
|
||||
case KEY_CTRL_MENU:
|
||||
state.setKey(Key::Home);
|
||||
return state;
|
||||
}
|
||||
nspire_ctrl=nspire_shift=0;
|
||||
for (int i = 0; i < sNumberOfKeyPairs; i++) {
|
||||
const KeyPair & keyPair = sKeyPairs[i];
|
||||
if (scancode==keyPair.gintKey()) {
|
||||
state.setSimulatedShift(keyPair.numworksShift() ? ModSimState::ForceOn : ModSimState::ForceOff);
|
||||
state.setSimulatedAlpha(keyPair.numworksAlpha() ? ModSimState::ForceOn : ModSimState::ForceOff);
|
||||
state.setKey(keyPair.key());
|
||||
return state;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Keyboard {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
15
ion/src/simulator/nspire/keyboard.h
Normal file
15
ion/src/simulator/nspire/keyboard.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef ION_SIMULATOR_KEYBOARD_H
|
||||
#define ION_SIMULATOR_KEYBOARD_H
|
||||
|
||||
#include <ion/keyboard.h>
|
||||
// #include <libndls.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Keyboard {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
97
ion/src/simulator/nspire/main.cpp
Normal file
97
ion/src/simulator/nspire/main.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "main.h"
|
||||
#include "display.h"
|
||||
#include "platform.h"
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include <ion.h>
|
||||
#include <ion/events.h>
|
||||
#include "k_csdk.h"
|
||||
|
||||
static const char * storage_name="nwstore.nws";
|
||||
|
||||
int save_state(const char * fname); // apps/home/controller.cpp
|
||||
|
||||
extern "C" {
|
||||
extern const int prizm_heap_size;
|
||||
const int prizm_heap_size=1024*1024;
|
||||
__attribute__((aligned(4))) char prizm_heap[prizm_heap_size];
|
||||
|
||||
int calculator=4; // -1 means OS not checked, 0 unknown, 1 cg50 or 90, 2 emu 50 or 90, 3 other
|
||||
|
||||
int main() {
|
||||
sdk_init();
|
||||
Ion::Simulator::Main::init();
|
||||
ion_main(0, NULL);
|
||||
Ion::Simulator::Main::quit();
|
||||
sdk_end();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Main {
|
||||
|
||||
static bool sNeedsRefresh = false;
|
||||
|
||||
void init() {
|
||||
Ion::Simulator::Display::init();
|
||||
setNeedsRefresh();
|
||||
}
|
||||
|
||||
void setNeedsRefresh() {
|
||||
sNeedsRefresh = true;
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
if (!sNeedsRefresh) {
|
||||
return;
|
||||
}
|
||||
|
||||
Display::draw();
|
||||
|
||||
sNeedsRefresh = false;
|
||||
}
|
||||
|
||||
void quit() {
|
||||
Ion::Simulator::Display::quit();
|
||||
}
|
||||
|
||||
void runPowerOffSafe(void (*powerOffSafeFunction)(), bool prepareVRAM) {
|
||||
// somewhat OFF by setting LCD to 0
|
||||
unsigned NSPIRE_CONTRAST_ADDR=is_cx2?0x90130014:0x900f0020;
|
||||
unsigned oldval=*(volatile unsigned *)NSPIRE_CONTRAST_ADDR,oldval2;
|
||||
if (is_cx2){
|
||||
oldval2=*(volatile unsigned *) (NSPIRE_CONTRAST_ADDR+4);
|
||||
*(volatile unsigned *) (NSPIRE_CONTRAST_ADDR+4)=0xffff;
|
||||
}
|
||||
*(volatile unsigned *)NSPIRE_CONTRAST_ADDR=is_cx2?0xffff:0x100;
|
||||
static volatile uint32_t *lcd_controller = (volatile uint32_t*) 0xC0000000;
|
||||
lcd_controller[6] &= ~(0b1 << 11);
|
||||
loopsleep(20);
|
||||
lcd_controller[6] &= ~ 0b1;
|
||||
unsigned NSPIRE_RTC_ADDR=0x90090000;
|
||||
unsigned offtime=* (volatile unsigned *) NSPIRE_RTC_ADDR;
|
||||
for (int n=0;!on_key_pressed();++n){
|
||||
loopsleep(100);
|
||||
idle();
|
||||
}
|
||||
lcd_controller[6] |= 0b1;
|
||||
loopsleep(20);
|
||||
lcd_controller[6]|= 0b1 << 11;
|
||||
if (is_cx2)
|
||||
*(volatile unsigned *)(NSPIRE_CONTRAST_ADDR+4)=oldval2;
|
||||
*(volatile unsigned *)NSPIRE_CONTRAST_ADDR=oldval;
|
||||
sync_screen();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
20
ion/src/simulator/nspire/main.h
Normal file
20
ion/src/simulator/nspire/main.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef ION_SIMULATOR_MAIN_H
|
||||
#define ION_SIMULATOR_MAIN_H
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Main {
|
||||
|
||||
void init();
|
||||
void quit();
|
||||
|
||||
void setNeedsRefresh();
|
||||
void refresh();
|
||||
|
||||
void runPowerOffSafe(void (*powerOffSafeFunction)(), bool prepareVRAM);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
23
ion/src/simulator/nspire/platform.h
Normal file
23
ion/src/simulator/nspire/platform.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef ION_SIMULATOR_PLATFORM_H
|
||||
#define ION_SIMULATOR_PLATFORM_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Those functions should be implemented per-platform.
|
||||
* They are defined as C function for easier interop. */
|
||||
|
||||
const char * IonSimulatorGetLanguageCode();
|
||||
|
||||
void IonSimulatorKeyboardKeyDown(int keyNumber);
|
||||
void IonSimulatorKeyboardKeyUp(int keyNumber);
|
||||
void IonSimulatorEventsPushEvent(int eventNumber);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
23
ion/src/simulator/nspire/power.cpp
Normal file
23
ion/src/simulator/nspire/power.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include <ion/power.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
void powerOff(void){
|
||||
}
|
||||
|
||||
|
||||
namespace Ion {
|
||||
namespace Power {
|
||||
|
||||
void suspend(bool checkIfOnOffKeyReleased) {
|
||||
Simulator::Main::runPowerOffSafe(powerOff, true);
|
||||
}
|
||||
|
||||
void standby() {
|
||||
Simulator::Main::runPowerOffSafe(powerOff, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
15
ion/src/simulator/nspire/telemetry_init.cpp
Normal file
15
ion/src/simulator/nspire/telemetry_init.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "platform.h"
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Telemetry {
|
||||
|
||||
void init() {
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
21
ion/src/simulator/nspire/timing.cpp
Normal file
21
ion/src/simulator/nspire/timing.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include <ion/timing.h>
|
||||
#include <chrono>
|
||||
#include "k_csdk.h"
|
||||
|
||||
namespace Ion {
|
||||
namespace Timing {
|
||||
|
||||
uint64_t millis() {
|
||||
return ::millis();
|
||||
}
|
||||
|
||||
void usleep(uint32_t us) {
|
||||
os_wait_1ms(us/1000); // sleep_us(us);
|
||||
}
|
||||
|
||||
void msleep(uint32_t ms) {
|
||||
os_wait_1ms(ms); // sleep_us(ms * 1000);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,10 @@
|
||||
|
||||
LIBA_BEGIN_DECLS
|
||||
|
||||
#if (__GLIBC__ || __MINGW32__ || _FXCG)
|
||||
#if (__GLIBC__ || __MINGW32__ || _FXCG || NSPIRE_NEWLIB)
|
||||
size_t strlcat(char * dst, const char * src, size_t dstSize);
|
||||
size_t strlcpy(char * dst, const char * src, size_t len);
|
||||
char *strdup(const char *s);
|
||||
#endif
|
||||
|
||||
LIBA_END_DECLS
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef LIBA_STRINGS_H
|
||||
#define LIBA_STRINGS_H
|
||||
|
||||
#if (_FXCG)
|
||||
#if (_FXCG) || defined NSPIRE_NEWLIB
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -19,4 +19,4 @@ LIBA_END_DECLS
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
|
||||
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
|
||||
|
||||
#if (_FXCG)
|
||||
#if (_FXCG) || defined NSPIRE_NEWLIB
|
||||
namespace std {
|
||||
// functions
|
||||
using ::acosh;
|
||||
|
||||
@@ -135,7 +135,7 @@ public:
|
||||
Expression() : TreeHandle() {}
|
||||
Expression clone() const;
|
||||
static Expression Parse(char const * string, Context * context, bool addMissingParenthesis = true);
|
||||
static Expression ExpressionFromAddress(const void * address, size_t size);
|
||||
static Expression ExpressionFromAddress(const void * address, size_t size, const void * record=nullptr);
|
||||
|
||||
/* Circuit breaker */
|
||||
typedef bool (*CircuitBreaker)();
|
||||
|
||||
@@ -21,7 +21,7 @@ class LayoutNode;
|
||||
class Integer;
|
||||
struct IntegerDivision;
|
||||
|
||||
#if (defined _3DS) || (defined _FXCG)
|
||||
#if (defined _3DS) || (defined _FXCG) || defined NSPIRE_NEWLIB
|
||||
typedef unsigned short half_native_uint_t;
|
||||
static_assert(sizeof(half_native_uint_t) == sizeof(uint16_t));
|
||||
typedef int native_int_t;
|
||||
|
||||
@@ -38,10 +38,42 @@ Expression Expression::Parse(char const * string, Context * context, bool addPar
|
||||
return expression;
|
||||
}
|
||||
|
||||
Expression Expression::ExpressionFromAddress(const void * address, size_t size) {
|
||||
Expression Expression::ExpressionFromAddress(const void * address, size_t size, const void * record) {
|
||||
if (address == nullptr || size == 0) {
|
||||
return Expression();
|
||||
}
|
||||
#ifdef STRING_STORAGE
|
||||
// Check that expression was stored as a string in record
|
||||
size_t i;
|
||||
const char * ptr=(const char *) address;
|
||||
for (i=1;i<size && ptr[i];++i){
|
||||
if (ptr[i]=='"')
|
||||
break;
|
||||
}
|
||||
if (i < 1024 && ptr[0]=='"' && i > 0 && i < size && ptr[i] == '"') {
|
||||
((char *)ptr)[i] = 0;
|
||||
Expression e = Expression::Parse(ptr + 1, nullptr);
|
||||
((char *)ptr)[i] = '"';
|
||||
address = e.addressInPool();
|
||||
size = e.size();
|
||||
if (record) {
|
||||
const char * name = ((const Ion::Storage::Record *)record)->fullName();
|
||||
char repl = 0;
|
||||
int l = strlen(name);
|
||||
if (strncmp(name+l-4,".seq",4) == 0) {
|
||||
repl='n';
|
||||
} else if (strncmp(name+l-5,".func",5) == 0) {
|
||||
repl='x';
|
||||
}
|
||||
if (repl){
|
||||
e=e.replaceSymbolWithExpression(Symbol::Builder(repl),Symbol::Builder(UCodePointUnknown));
|
||||
address= e.addressInPool();
|
||||
size=e.size();
|
||||
}
|
||||
}
|
||||
return Expression(static_cast<ExpressionNode *>(TreePool::sharedPool()->copyTreeFromAddress(address, size))); // must be done before e is destroyed
|
||||
}
|
||||
#endif
|
||||
// Build the Expression in the Tree Pool
|
||||
return Expression(static_cast<ExpressionNode *>(TreePool::sharedPool()->copyTreeFromAddress(address, size)));
|
||||
}
|
||||
|
||||
@@ -41,6 +41,25 @@ void python_error_end() {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
#ifdef _FXCG
|
||||
#include <gint/bfile.h>
|
||||
#include <gint/display-cg.h>
|
||||
#include <gint/gint.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
/* py/parsenum.h is a C header which uses C keyword restrict.
|
||||
* It does not exist in C++ so we define it here in order to be able to include
|
||||
@@ -354,23 +373,119 @@ void nlr_jump_fail(void *val) {
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
void do_mp_lexer_new_from_file(const char * filename,mp_lexer_t ** res) {
|
||||
mp_reader_t reader;
|
||||
mp_reader_new_file(&reader, filename);
|
||||
*res=mp_lexer_new(qstr_from_str(filename), reader);
|
||||
}
|
||||
|
||||
// Code from MicroPython's reader.c
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef struct _mp_reader_posix_t {
|
||||
bool close_fd;
|
||||
int fd;
|
||||
size_t len;
|
||||
size_t pos;
|
||||
byte buf[20];
|
||||
} mp_reader_posix_t;
|
||||
|
||||
STATIC mp_uint_t mp_reader_posix_readbyte(void *data) {
|
||||
mp_reader_posix_t *reader = (mp_reader_posix_t *)data;
|
||||
if (reader->pos >= reader->len) {
|
||||
if (reader->len == 0) {
|
||||
return MP_READER_EOF;
|
||||
} else {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
int n = read(reader->fd, reader->buf, sizeof(reader->buf));
|
||||
MP_THREAD_GIL_ENTER();
|
||||
if (n <= 0) {
|
||||
reader->len = 0;
|
||||
return MP_READER_EOF;
|
||||
}
|
||||
reader->len = n;
|
||||
reader->pos = 0;
|
||||
}
|
||||
}
|
||||
return reader->buf[reader->pos++];
|
||||
}
|
||||
|
||||
STATIC void mp_reader_posix_close(void *data) {
|
||||
mp_reader_posix_t *reader = (mp_reader_posix_t *)data;
|
||||
if (reader->close_fd) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
close(reader->fd);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
}
|
||||
m_del_obj(mp_reader_posix_t, reader);
|
||||
}
|
||||
|
||||
void mp_reader_new_file_from_fd(mp_reader_t *reader, int fd, bool close_fd) {
|
||||
mp_reader_posix_t *rp = m_new_obj(mp_reader_posix_t);
|
||||
rp->close_fd = close_fd;
|
||||
rp->fd = fd;
|
||||
MP_THREAD_GIL_EXIT();
|
||||
int n = read(rp->fd, rp->buf, sizeof(rp->buf));
|
||||
if (n == -1) {
|
||||
if (close_fd) {
|
||||
close(fd);
|
||||
}
|
||||
MP_THREAD_GIL_ENTER();
|
||||
mp_raise_OSError(errno);
|
||||
}
|
||||
MP_THREAD_GIL_ENTER();
|
||||
rp->len = n;
|
||||
rp->pos = 0;
|
||||
reader->data = rp;
|
||||
reader->readbyte = mp_reader_posix_readbyte;
|
||||
reader->close = mp_reader_posix_close;
|
||||
}
|
||||
void mp_reader_new_file(mp_reader_t *reader, const char *filename) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
int fd = open(filename, O_RDONLY, 0644);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
if (fd < 0) {
|
||||
mp_raise_OSError(errno);
|
||||
}
|
||||
mp_reader_new_file_from_fd(reader, fd, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_lexer_t * mp_lexer_new_from_file(const char * filename) {
|
||||
if (sScriptProvider != nullptr) {
|
||||
const char * script = sScriptProvider->contentOfScript(filename, true);
|
||||
if (script != nullptr) {
|
||||
return mp_lexer_new_from_str_len(qstr_from_str(filename), script, strlen(script), 0 /* size_t free_len*/);
|
||||
} else {
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
} else {
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
#ifdef _FXCG
|
||||
mp_lexer_t * res=0;
|
||||
gint_world_switch(GINT_CALL(do_mp_lexer_new_from_file,filename,&res));
|
||||
return res;
|
||||
#endif
|
||||
#ifdef NSPIRE_NEWLIB
|
||||
mp_lexer_t * res=0;
|
||||
do_mp_lexer_new_from_file(filename,&res);
|
||||
return res;
|
||||
#endif
|
||||
mp_raise_OSError(MP_ENOENT);
|
||||
}
|
||||
|
||||
mp_import_stat_t mp_import_stat(const char *path) {
|
||||
if (sScriptProvider && sScriptProvider->contentOfScript(path, false)) {
|
||||
return MP_IMPORT_STAT_FILE;
|
||||
}
|
||||
#if defined _FXCG || defined NSPIRE_NEWLIB
|
||||
FILE * f=fopen(path,"rb");
|
||||
if (f) {
|
||||
fclose(f);
|
||||
return MP_IMPORT_STAT_FILE;
|
||||
}
|
||||
#endif
|
||||
return MP_IMPORT_STAT_NO_EXIST;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user