Oops. Yea. I guess you will not be changing that bit.
Do you know how to debug with 2 symbol sets? (ofcourse you do)
Oops. Yea. I guess you will not be changing that bit.
Do you know how to debug with 2 symbol sets? (ofcourse you do)
In the command line GDB I use:
add-symbol-file "path/to/second/file.elf" address
Good. Debugging a loader is a bit trickier than just one application.
I also used command-line GDB for developing the loader, although I figured out how to do it in EmBitz also
Indeed. Having to copy builds to the SD each time is getting pretty annoying.
Know how when you do a lot of work on a project you get this urge to share screenshots to show how things are moving along?
Heh. Yeahā¦
Oh well, hereās whatās going on under the hood:
I keep saying āin RAMā a lot to emphasize that the flash has remained untouched, so far. I gave up on the idea of having a rigid memory layout: processes can freely occupy up to 29kb of RAM in 1kb pages. If two processes try to occupy the same page, the oldest gets killed.
The cooperative multitasking and IPC should allow us to have a plain progress bar or simple minigames while the loader is copying to flash without significantly slowing things down.
The screen mode got moved out of the kernel and into the applications. I did this so that we could have different screen modes, depending on the needs of each app:
Because of this flexibility, we can have minigames/apps that get executed entirely in memory. Might make for some interesting demos, screensavers and utilities.
Good progress!
It would be much faster to have loaders in ram than to flash them to rom.
Co-op. MT sounds awesome! I can imagine loaders having own progress bars, like mario running for coins
Maybe they could have, if supported by the loader. Like a python loader would search icons & screenshots from the āpy-iconsā folder.
Not a slightest idea what the heck youāre talking about. Donāt look at my raycasting thread BTW
Wow, I made myself skim through the thread and seriously hats off @FManga. A freaking microkernel kind of operating system on Pokitto. Itās potentially becoming more than a simple gaming system. If I have some time, Iāll try to create some skin mockups (warning: may include images of wildbeasts and penguins )
Yes, please post mockups, otherwise youāll be seeing more of my programmer art.
Speaking of programmer art, hereās the completed (for now) desktop:
The desktop application scans the ā/loader/desktopā folder and streams the icons from the pop files into a scrollable list that can be up to 65535 items longā¦ but ideally should only contain about 5 or so. Since itās supposed to be a short list, I used big (36x36 @ 16colors) icons.
The icons on the desktop use this palette.
Next:
Once you select an item, the desktop application will close and that item will be loaded. The first item to implement will be the bin/pop loader. It will have a different interface* and support directory navigation so you can organize your games.
To-do: For version 2 Iād like to use the desktop as a list of āfavoritesā. If you like something, you can copy it to the desktop folder and it will open with the associated loader. This is for later, though. For now, the desktop supports POP files only.
Looks very good :-)I like the big icons. Adding favourites is a fine idea also.
It looks a bit like NIntendo 3DS menu. Maybe Pico-8 palette would be nice.
I like itā¦ almost reminds me Emulation Stationā¦ Could just add how many games are under each section and itās almost the same
Good idea !
I chose this one because itās harder for me to make something terribly hideous with the limited amount of colors.
Hmmā¦ Iāll have to think about this a bit.
Pokitto Mint:
I basically redrew what I see on my desktop. CC0.
Would be cool if you could create plugin āāāappsā"" for the bottom bar.
I implemented support for desktop plugins.
The desktop looks in āloader/desktopwidgetsā and runs all the pops inside. Widgets can customize the desktop app by loading a background wallpaper, changing the palette, printing the time/battery level, etc.
A boring/trivial āhello worldā example:
The counter on the bottom left increments each time I press left/right. The compiled widget is just 340 bytes (352 in pop format). Hereās what the code looks like:
#include "../kernel/kapi.h"
namespace DESKTOP {
#include "../desktop/api.h"
}
DESKTOP::API *desktop;
int c, pressed;
void setup( DESKTOP::API *dtapi ){
desktop = dtapi;
}
void loop( KAPI *kernel ){
if( isPressedLeft() || isPressedRight() ) c += pressed?0:++pressed;
else pressed = 0;
desktop->setCursor( 0, DESKTOP::height-5 );
*desktop->drawcolor = c&0xF;
desktop->printf("%d", c);
}
Can dtapi
and kernel
be nullptr
?
If not, references would be better than pointers.
Also why setup
and loop
?
Seems a bit odd in a non-Arduino environment.
Not in this particular case, but there are enough situations where an api can be null that I preferred the uniformity of just using pointers. Itās not set in stone though, Iām going to have to clean up before I make a release and Iāll reconsider it.
I thought it seemed fitting/convenient considering how simple desktop widgets are supposed to be.
What would you suggest instead?
Same desktop, customized with a plugin:
#include "../kernel/kapi.h"
namespace DESKTOP {
#include "../desktop/api.h"
}
void setup( DESKTOP::API *desktop ){
desktop->itemStrideX = 0;
desktop->itemStrideY = 42;
desktop->itemOffsetX = DESKTOP::width - 38;
desktop->itemOffsetY = -8;
desktop->moveX = 0;
desktop->moveY = -40;
desktop->lblX = DESKTOP::width - 20;
desktop->lblY = 28;
desktop->lblColor = 0;
desktop->clearColor = 1;
desktop->clearX = DESKTOP::width - 40;
desktop->clearWidth = 40;
FS.init("");
FILE *f = FS.fopen("loader/wallpaper.16c", "r");
if( f ){
FS.fread( desktop->screenbuffer, 1, 55*88, f );
FS.fclose(f);
}
}
Iām OK with that.
ALSO: Impressive work so far Felipe!
If there are provable cases where it makes sense for the API to be nullptr
then it makes sense to use pointers.
But that means everyone will always have to check that the pointer isnāt nullptr
as a precaution.
If there arenāt any situations where the API can be nullptr
then references make more sense.
initialise
and update
(or init
and update
if you want to avoid the -ise vs -ize debate, though itās not hard to make initialize
an alias for initialise
).
Essentially I would expect usage more like:
#include "../kernel/kapi.h"
#include "../desktop/api.h"
using KernelApi = Kernel::API;
using DesktopApi = Desktop::API;
int c = 0;
int pressed = 0;
void initialise(DesktopApi & desktop)
{
(void)desktop;
}
void update(KernelApi & kernel, DesktopApi & desktop)
{
(void)kernel;
if(isPressedLeft() || isPressedRight())
{
if(pressed > 0)
{
++pressed;
c += pressed;
}
}
else
{
pressed = 0;
}
desktop.setCursor(0, (Desktop::height - 5));
desktop.drawcolor = (c & 0x0F);
desktop.print(c);
}
#include "../kernel/kapi.h"
#include "../desktop/api.h"
void initialise(Desktop::API & desktop)
{
(void)kernel;
// No nullptr check required
desktop.itemStrideX = 0;
desktop.itemStrideY = 42;
desktop.itemOffsetX = (Desktop::width - 38);
desktop.itemOffsetY = -8;
desktop.moveX = 0;
desktop.moveY = -40;
desktop.lblX = (Desktop::width - 20);
desktop.lblY = 28;
desktop.lblColor = 0;
desktop.clearColor = 1;
desktop.clearX = (Desktop::width - 40);
desktop.clearWidth = 40;
FileSystem::init("");
FileReader file = FileSystem::openRead("loader/wallpaper.16c");
if(file.isValid())
{
file.read(desktop->screenbuffer, 1, 55 * 88);
}
// Let file's destructor close the file, as per RAII
}
Yes, checking for nullptr
can be cumbersome, Iāll probably switch to references where it makes sense to do so later on.
Right now, simply using pointers everywhere makes things easier to write: donāt have to try to remember āwas this supposed to be a pointer or a reference?ā and I donāt have to think about all the possible future cases (will I ever want to change this to point to something else?).
Later on Iāll go over it all and make it easier to read.
I like init
and update
.
The names can be changed freely by the widgetās boilerplate without impact to anything else, so one widget can use init
and update
while another uses Widget::Widget(DesktopAPI &, KernelAPI &)
and void Widget::update()
or something else. All the kernel wants is function pointers.
Iāll make some template widgets that use different API styles so that others can just duplicate the one they want to start off with.
A class-based FILE wrapper with RAII is in my to-do list. Just havenāt had the chance to get to it yet.