mirror of
https://github.com/NotImplementedLife/FSPDS.git
synced 2025-06-18 17:05:33 -04:00
reading thumbnails
This commit is contained in:
parent
1b0c72e74f
commit
f9b88b1223
@ -35,7 +35,7 @@ ASFLAGS := -g $(ARCH)
|
||||
LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,-Map,$(notdir $*).map
|
||||
|
||||
|
||||
LIBS := -lnds7
|
||||
LIBS := -lfat -lnds7
|
||||
|
||||
LIBDIRS := $(LIBNDS)
|
||||
|
||||
|
6
arm7/include/log.h
Normal file
6
arm7/include/log.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
void debug_log(const char* message, ...);
|
212
arm7/source/log.c
Normal file
212
arm7/source/log.c
Normal file
@ -0,0 +1,212 @@
|
||||
#include "log.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
// gcc translates inline asm "mov r7,r7" to "add r7, r7, #0"
|
||||
// so we have to hardcode the intended instruction
|
||||
#define MOV_R7_R7 ".BYTE 0x3f, 0x46"
|
||||
|
||||
#define MOV_R6_R6 ".BYTE 0x36, 0x46"
|
||||
|
||||
#define MOV_R5_R5 ".BYTE 0x2D, 0x46"
|
||||
|
||||
#define LOG_CODE(MOV_X_X, message) asm volatile \
|
||||
( \
|
||||
"push {r6} \r\n" \
|
||||
"mov r6, %0 \r\n" \
|
||||
MOV_X_X "\r\n" \
|
||||
"pop {r6}\r\n" \
|
||||
:: "r"(message) \
|
||||
);
|
||||
|
||||
#define LOG_BUF 8
|
||||
#define LOG_MSG 7
|
||||
#define LOG_WRN 6
|
||||
#define LOG_ERR 5
|
||||
|
||||
char* copy_str(char* dest, const char* src)
|
||||
{
|
||||
for(;*src;)
|
||||
*(dest++) = *(src++);
|
||||
*dest = '\0';
|
||||
return dest;
|
||||
}
|
||||
|
||||
__attribute__((target("thumb")))
|
||||
void _log(int role, const char* message)
|
||||
{
|
||||
switch(role)
|
||||
{
|
||||
case LOG_MSG:
|
||||
LOG_CODE(MOV_R7_R7, message); break;
|
||||
case LOG_WRN:
|
||||
LOG_CODE(MOV_R6_R6, message); break;
|
||||
case LOG_ERR:
|
||||
LOG_CODE(MOV_R5_R5, message); break;
|
||||
case LOG_BUF:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const char* hex_lower = "0123456789abcdef";
|
||||
static const char* hex_upper = "0123456789ABCDEF";
|
||||
|
||||
char result[128];
|
||||
|
||||
__attribute__((target("thumb")))
|
||||
void _logv(int role, char* dest, const char* message, va_list args)
|
||||
{
|
||||
char* built = result;
|
||||
|
||||
for(const char* msg=message; *msg;)
|
||||
{
|
||||
if(*msg=='%')
|
||||
{
|
||||
++msg;
|
||||
if(*msg==0) break;
|
||||
|
||||
switch(*msg)
|
||||
{
|
||||
case 'i':
|
||||
{
|
||||
int val = va_arg(args, int);
|
||||
|
||||
if(val==0)
|
||||
{
|
||||
*(built++)='0';
|
||||
++msg;
|
||||
break;
|
||||
}
|
||||
|
||||
if(val<0)
|
||||
*(built++)='-', val = -val;
|
||||
|
||||
int nzeros = 0;
|
||||
for(;val%10==0;val/=10) nzeros++;
|
||||
|
||||
int temp = 0;
|
||||
for(;val;val/=10) temp=temp*10 + val%10;
|
||||
for(;temp;temp/=10) *(built++)='0'+temp%10;
|
||||
|
||||
for(;nzeros--;) *(built++)='0';
|
||||
|
||||
++msg;
|
||||
break;
|
||||
}
|
||||
case 'u':
|
||||
{
|
||||
unsigned int val = va_arg(args, unsigned int);
|
||||
|
||||
if(val==0)
|
||||
{
|
||||
*(built++)='0';
|
||||
++msg;
|
||||
break;
|
||||
}
|
||||
|
||||
int nzeros = 0;
|
||||
for(;val%10==0;val/=10) nzeros++;
|
||||
|
||||
int temp = 0;
|
||||
for(;val;val/=10) temp=temp*10 + val%10;
|
||||
for(;temp;temp/=10) *(built++)='0'+temp%10;
|
||||
|
||||
for(;nzeros--;) *(built++)='0';
|
||||
|
||||
++msg;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
{
|
||||
char* val = va_arg(args, char*);
|
||||
|
||||
while(*val) *(built++)=*(val++);
|
||||
|
||||
++msg;
|
||||
break;
|
||||
}
|
||||
case 'b':
|
||||
{
|
||||
int val = va_arg(args, int);
|
||||
if(val)
|
||||
built = copy_str(built, "T");
|
||||
else
|
||||
built = copy_str(built, "F");
|
||||
|
||||
++msg;
|
||||
break;
|
||||
}
|
||||
case 'B':
|
||||
{
|
||||
int val = va_arg(args, int);
|
||||
if(val)
|
||||
built = copy_str(built, "True");
|
||||
else
|
||||
built = copy_str(built, "False");
|
||||
|
||||
++msg;
|
||||
break;
|
||||
}
|
||||
case 'x':
|
||||
{
|
||||
unsigned val = va_arg(args, unsigned);
|
||||
int num_start = 0;
|
||||
for(int i=0;i<8;i++)
|
||||
{
|
||||
int digit = (val & 0xF0000000)>>28;
|
||||
val<<=4;
|
||||
if(!num_start && digit==0)
|
||||
continue;
|
||||
num_start = 1;
|
||||
*(built++) = hex_lower[digit];
|
||||
}
|
||||
if(!num_start)
|
||||
{
|
||||
*(built++)='0';
|
||||
}
|
||||
++msg;
|
||||
break;
|
||||
}
|
||||
case 'X':
|
||||
{
|
||||
unsigned val = va_arg(args, unsigned);
|
||||
int num_start = 0;
|
||||
for(int i=0;i<8;i++)
|
||||
{
|
||||
int digit = (val & 0xF0000000)>>28;
|
||||
val<<=4;
|
||||
if(!num_start && digit==0)
|
||||
continue;
|
||||
num_start = 1;
|
||||
*(built++) = hex_upper[digit];
|
||||
}
|
||||
if(!num_start)
|
||||
{
|
||||
*(built++)='0';
|
||||
}
|
||||
++msg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*(built++)=*(msg++);
|
||||
}
|
||||
}
|
||||
*(built)='\0';
|
||||
|
||||
_log(role, result);
|
||||
if(role==LOG_BUF)
|
||||
{
|
||||
copy_str(dest, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void debug_log(const char* message, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
_logv(LOG_MSG, 0, message, args);
|
||||
va_end(args);
|
||||
}
|
@ -30,6 +30,7 @@
|
||||
/// Removed wifi
|
||||
#include <nds.h>
|
||||
#include "bottom_screen_power.h"
|
||||
#include "log.h"
|
||||
|
||||
void VblankHandler(void) { }
|
||||
|
||||
@ -47,6 +48,10 @@ void powerButtonCB()
|
||||
|
||||
int main()
|
||||
{
|
||||
/*debug_log("ARM7 EZ");
|
||||
debug_log("ARM7 EZ");
|
||||
debug_log("Hello world from ARM7 %i",47);*/
|
||||
|
||||
// clear sound registers
|
||||
dmaFillWords(0, (void*)0x04000400, 0x100);
|
||||
|
||||
|
1
arm9/assets/thumbnail_selector.asset
Normal file
1
arm9/assets/thumbnail_selector.asset
Normal file
@ -0,0 +1 @@
|
||||
-tiles -8bpp -mw8 -mh8
|
BIN
arm9/assets/thumbnail_selector.png
Normal file
BIN
arm9/assets/thumbnail_selector.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 308 B |
@ -10,6 +10,8 @@ private:
|
||||
|
||||
int getSoundHeaderOffset() const;
|
||||
public:
|
||||
static int peek_only_metadata(const char* filename, void* dest);
|
||||
|
||||
unsigned char buffer[1<<20];
|
||||
|
||||
int getAnimationDataSize() const;
|
||||
@ -50,5 +52,6 @@ public:
|
||||
inline static constexpr int ERR_NULL_ARGUMENT = -1;
|
||||
inline static constexpr int ERR_FOPEN = -2;
|
||||
inline static constexpr int ERR_SIZE_EXCEEDED = -3;
|
||||
inline static constexpr int ERR_READ_COUNT = -4;
|
||||
|
||||
};
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "back_arrow.h"
|
||||
#include "error_thumbnail.h"
|
||||
#include "thumbnail_selector.h"
|
||||
|
||||
constexpr short torgb15(int rgb24)
|
||||
{
|
||||
@ -20,6 +21,7 @@ class LocationViewerScene : public SimpleScene
|
||||
private:
|
||||
VwfEngine* vwf = new VwfEngine(Resources::Fonts::default_8x16);
|
||||
Sprite* back_arrow = nullptr;
|
||||
Sprite* thumbnail_selector = nullptr;
|
||||
|
||||
int dir_len;
|
||||
char* flipnote_path;
|
||||
@ -36,6 +38,8 @@ private:
|
||||
strcpy(file_part_path+j, ".ppm");
|
||||
}
|
||||
|
||||
char ppm_metadata[9][0x6A0];
|
||||
|
||||
public:
|
||||
void init() override
|
||||
{
|
||||
@ -51,6 +55,10 @@ public:
|
||||
back_arrow->add_frame(new ObjFrame(&ROA_back_arrow8,0,0));
|
||||
back_arrow->set_position(0, 0);
|
||||
|
||||
thumbnail_selector = create_sprite(new Sprite(SIZE_64x64, Engine::Main));
|
||||
thumbnail_selector->add_frame(new ObjFrame(&ROA_thumbnail_selector8,0,0));
|
||||
thumbnail_selector->set_position(16, 16);
|
||||
|
||||
end_sprites_init();
|
||||
|
||||
dir_len = strlen(selected_location->path);
|
||||
@ -64,19 +72,131 @@ public:
|
||||
{
|
||||
load_path(i);
|
||||
Debug::log(flipnote_path);
|
||||
}
|
||||
}
|
||||
total_pages_count = (selected_location->filenames.size()+8)/9;
|
||||
|
||||
key_down.add_event(&LocationViewerScene::on_key_down, this);
|
||||
}
|
||||
|
||||
|
||||
int crt_page=0;
|
||||
void display_page()
|
||||
void on_key_down(void*, void* _keys)
|
||||
{
|
||||
int keys = (int)_keys;
|
||||
if(keys & KEY_UP)
|
||||
{
|
||||
if(thumbnail_sel_row>0)
|
||||
thumbnail_sel_row--;
|
||||
}
|
||||
else if(keys & KEY_DOWN)
|
||||
{
|
||||
if(thumbnail_sel_row<2 && 9*crt_page+3*thumbnail_sel_row+thumbnail_sel_col+3<selected_location->filenames.size())
|
||||
thumbnail_sel_row++;
|
||||
}
|
||||
else if(keys & KEY_LEFT)
|
||||
{
|
||||
if(thumbnail_sel_col>0)
|
||||
thumbnail_sel_col--;
|
||||
else
|
||||
{
|
||||
if(crt_page>0)
|
||||
{
|
||||
crt_page--;
|
||||
thumbnail_sel_col=2;
|
||||
thumbnail_selector->hide();
|
||||
frame();
|
||||
display_page();
|
||||
thumbnail_selector->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(keys & KEY_RIGHT)
|
||||
{
|
||||
if(thumbnail_sel_col<2 && 9*crt_page+3*thumbnail_sel_row+thumbnail_sel_col+1<selected_location->filenames.size())
|
||||
thumbnail_sel_col++;
|
||||
else
|
||||
{
|
||||
if(crt_page+1<total_pages_count)
|
||||
{
|
||||
crt_page++;
|
||||
thumbnail_sel_col=0;
|
||||
while(thumbnail_sel_row>0 && 9*crt_page+3*thumbnail_sel_row+thumbnail_sel_col>=selected_location->filenames.size())
|
||||
thumbnail_sel_row--;
|
||||
thumbnail_selector->hide();
|
||||
frame();
|
||||
display_page();
|
||||
thumbnail_selector->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline static constexpr int THUMBNAIL_NONE = 0;
|
||||
inline static constexpr int THUMBNAIL_CORRUPT = 1;
|
||||
inline static constexpr int THUMBNAIL_READER = 2;
|
||||
|
||||
void display_thumbnail(int index, int mode)
|
||||
{
|
||||
unsigned short* gfx = bgGetGfxPtr(1) + 16*2 + 48*16*index;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case THUMBNAIL_NONE:
|
||||
{
|
||||
volatile short zero = 0;
|
||||
for(int i=0;i<6*8*16;i++) gfx[i]=zero;
|
||||
break;
|
||||
}
|
||||
case THUMBNAIL_CORRUPT:
|
||||
{
|
||||
ROA_error_thumbnail4.extract_gfx(gfx);
|
||||
break;
|
||||
}
|
||||
case THUMBNAIL_READER:
|
||||
{
|
||||
volatile short* src = (volatile short*)&ppm_metadata[index][0xA0];
|
||||
for(int i=0;i<6*8*16;i++) gfx[i]=*(src++);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int total_pages_count = 0;
|
||||
int crt_page=0;
|
||||
void display_page()
|
||||
{
|
||||
Debug::log("Display page");
|
||||
int index = crt_page*9;
|
||||
for(int i=0;i<9;i++)
|
||||
{
|
||||
if(index < selected_location->filenames.size())
|
||||
{
|
||||
load_path(index++);
|
||||
Debug::log(flipnote_path);
|
||||
int status = PPMReader::peek_only_metadata(flipnote_path, &ppm_metadata[i][0]);
|
||||
Debug::log("Status = %i", status);
|
||||
if(status<0)
|
||||
display_thumbnail(i, THUMBNAIL_CORRUPT);
|
||||
else
|
||||
display_thumbnail(i, THUMBNAIL_READER);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug::log("None %i", i);
|
||||
display_thumbnail(i, THUMBNAIL_NONE);
|
||||
}
|
||||
}
|
||||
vwf->clear_row(1, Pal4bit);
|
||||
vwf->set_cursor(1, 90);
|
||||
vwf->put_text(str_print(page_label, "Page %i of %i", crt_page+1, total_pages_count+1), Pal4bit, SolidColorBrush(0x1));
|
||||
}
|
||||
|
||||
char page_label[32];
|
||||
int thumbnail_sel_row = 0;
|
||||
int thumbnail_sel_col = 0;
|
||||
|
||||
void frame() override
|
||||
{
|
||||
thumbnail_selector->set_position(16+thumbnail_sel_col*80, 16+thumbnail_sel_row*56);
|
||||
SimpleScene::frame();
|
||||
}
|
||||
|
||||
@ -121,31 +241,16 @@ public:
|
||||
VwfEngine::prepare_map(*vwf, SUB_BG2, 32, 0, 0, 0x9);
|
||||
vwf->clear(Pal4bit);
|
||||
|
||||
vwf->set_cursor(6, 90);
|
||||
vwf->put_text("Please wait", Pal4bit, SolidColorBrush(0x1));
|
||||
|
||||
volatile short zero = 0;
|
||||
|
||||
for(int i=0;i<32*24;i++)
|
||||
bgGetMapPtr(1)[i]=zero;
|
||||
bgGetMapPtr(1)[i]=zero;
|
||||
|
||||
unsigned short* gfx = bgGetGfxPtr(1);
|
||||
for(int i=0;i<32*24*16;i++)
|
||||
{
|
||||
gfx[i]=zero;
|
||||
}
|
||||
|
||||
gfx+=16*2;
|
||||
volatile int xx=0x1111;
|
||||
for(int i=0;i<6*8*9*16;i++)
|
||||
{
|
||||
gfx[i]=xx;
|
||||
}
|
||||
|
||||
for(int ty=0;ty<3;ty++)
|
||||
for(int tx=0;tx<3;tx++)
|
||||
ROA_error_thumbnail4.extract_gfx(gfx+48*16*(3*ty+tx));
|
||||
|
||||
}
|
||||
|
||||
int gfxq=2;
|
||||
|
||||
@ -163,9 +268,9 @@ public:
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
display_page();
|
||||
|
||||
Hardware::MainEngine::objEnable(128, true); // set to 128
|
||||
Hardware::SubEngine::objEnable(128, true); // set to 128
|
||||
@ -176,7 +281,9 @@ public:
|
||||
|
||||
~LocationViewerScene()
|
||||
{
|
||||
key_down.remove_event(&LocationViewerScene::on_key_down, this);
|
||||
delete vwf;
|
||||
delete ppm_reader;
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -339,8 +339,8 @@ public:
|
||||
{
|
||||
soundDisable();
|
||||
delete[] buffer1;
|
||||
delete[] buffer2;
|
||||
delete ppm_reader;
|
||||
delete[] buffer2;
|
||||
delete ppm_reader;
|
||||
free(sound_buffer);
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,20 @@
|
||||
|
||||
static constexpr int frames[] = { 2, 120, 60, 30, 15, 10, 5, 3, 2 };
|
||||
|
||||
int PPMReader::peek_only_metadata(const char* filename, void* dest)
|
||||
{
|
||||
if(filename==nullptr) return ERR_NULL_ARGUMENT;
|
||||
FILE* fp=fopen(filename,"rb");
|
||||
if(fp==nullptr) return ERR_FOPEN;
|
||||
fseek(fp, 0L, SEEK_SET);
|
||||
|
||||
if(fread(dest, sizeof(char), 0x6A0, fp) != 0x6A0)
|
||||
return ERR_READ_COUNT;
|
||||
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PPMReader::read_metadata(const char* filename)
|
||||
{
|
||||
if(filename==nullptr) return ERR_NULL_ARGUMENT;
|
||||
|
Loading…
Reference in New Issue
Block a user