Thanks! I’m not sure I could pull off a comic just yet, though. I still need to practice a bit more first.


Ok, but when you are ready I am sure we could help you with generating ideas for it :stuck_out_tongue_winking_eye:


Preview of a new project type coming in the next release:


New jam opportunity? :wink:

That could be fun :slight_smile:

1 Like

Release v0.1.5

  • New Bitsy Project template
  • Updated PokittoLib
  • HTML viewer plugin (toggle Source view with Ctrl+Enter)

Known issue: The PokittoLib in this release is incompatible with MicroPython projects.


The elf file viewer is a really good feature! Saved my day yesterday. Very easy to spot problematic objects.

Another thing. There is a bug hiding somewhere in the emulator. If I am printing to a debug console in C++ (printf), the Tilemap drawing shows garbage. The normal bitmap drawing works ok. This is an old bug as I have seen it on PyInSky emulator also (with a tilemap and console printing) long time ago. I first noticed the problem after I enabled audio in the MIB game. So it might be also related to audio or low ram (I have used about 85 % of ram). The same flash image works ok on HW.

1 Like

I remember seeing this bug a few times as well, but it always happens in situations that are really hard to pinpoint. -_-

Should I try to reproduce it?

If you can find a minimal test case that shows the bug, it’d help a lot in finding the cause.

My example is pretty complicated :wink:

Quick question: Is it possible to include an assembly file in the project?

I’ve seen some flags in project.json for S files, but if I try to put a .s file with a .h for C bindings it doesn’t get compiled (or, at least, the symbols are not recognized). The file is this:

.syntax             unified
                    .cpu                cortex-m0

                    .func               unlz4
                    .global             unlz4,unlz4_len
                    .type               unlz4,%function
                    .type               unlz4_len,%function

unlz4:              ldrh                r2,[r0]             /* get length of compressed data */
                    adds                r0,r0,#2            /* advance source pointer */

unlz4_len:          push                {r4-r6,lr}          /* save r4, r5, r6 and return-address */

                    adds                r5,r2,r0            /* point r5 to end of compressed data */

getToken:           ldrb                r6,[r0]             /* get token */
                    adds                r0,r0,#1            /* advance source pointer */
                    lsrs                r4,r6,#4            /* get literal length, keep token in r6 */
                    beq                 getOffset           /* jump forward if there are no literals */
                    bl                  getLength           /* get length of literals */
                    movs                r2,r0               /* point r2 to literals */
                    bl                  copyData            /* copy literals (r2=src, r1=dst, r4=len) */
                    movs                r0,r2               /* update source pointer */
getOffset:          ldrb                r3,[r0,#0]          /* get match offset's low byte */
                    subs                r2,r1,r3            /* subtract from destination; this will become the match position */
                    ldrb                r3,[r0,#1]          /* get match offset's high byte */
                    lsls                r3,r3,#8            /* shift to high byte */
                    subs                r2,r2,r3            /* subtract from match position */
                    adds                r0,r0,#2            /* advance source pointer */
                    lsls                r4,r6,#28           /* get rid of token's high 28 bits */
                    lsrs                r4,r4,#28           /* move the 4 low bits back where they were */
                    bl                  getLength           /* get length of match data */
                    adds                r4,r4,#4            /* minimum match length is 4 bytes */
                    bl                  copyData            /* copy match data (r2=src, r1=dst, r4=len) */
                    cmp                 r0,r5               /* check if we've reached the end of the compressed data */
                    blt                 getToken            /* if not, go get the next token */
                    pop                 {r4-r6,pc}          /* restore r4, r5 and r6, then return */

getLength:          cmp                 r4,#0x0f            /* if length is 15, then more length info follows */
                    bne                 gotLength           /* jump forward if we have the complete length */
getLengthLoop:      ldrb                r3,[r0]             /* read another byte */
                    adds                r0,r0,#1            /* advance source pointer */
                    adds                r4,r4,r3            /* add byte to length */
                    cmp                 r3,#0xff            /* check if end reached */
                    beq                 getLengthLoop       /* if not, go round loop */
gotLength:          bx                  lr                  /* return */

copyData:           rsbs                r4,r4,#0            /* index = -length */
                    subs                r2,r2,r4            /* point to end of source */
                    subs                r1,r1,r4            /* point to end of destination */

copyDataLoop:       ldrb                r3,[r2,r4]          /* read byte from source_end[-index] */
                    strb                r3,[r1,r4]          /* store byte in destination_end[-index] */
                    adds                r4,r4,#1            /* increment index */
                    bne                 copyDataLoop        /* keep going until index wraps to 0 */
                    bx                  lr                  /* return */

                    .size               unlz4,.-unlz4


There’s a generic C implementation but I want to try this ARM-Cortex M0 assembly version :slight_smile:


did you use extern "C" to declare unlz4 and unlz4_len in your C++ code?
Edit: Tested here, adding extern "C" does the trick. Looks like this could be a useful addition to the library, especially if it can uncompress image/tilemap data at a good speed. I’ll do some more tests.


Yes, that works. Thanks a lot!

I’m going to make some tests too. My flag animation for Road Star is about 16KB with LZ4 vs more than 100KB with RLE :sunglasses:



My contribution to all this?

I really tried to find a good gif.


Hahahahaha. It’s more @Pharap contribution :joy:

What did I do?

Got some sense into me. I was waiting for an exquisite demoscene trick.

Edit: that’s why I was looking for an “approving, but slightly disheartened” gif

1 Like

LZ4 is also an exquisite trick,
just a premade, well-tested one rather than a ‘demoscene’ one.

Also I’m presuming @manuelsagra probably wouldn’t have bothered to go looking for LZ4 implementations it if you hadn’t suggested trying to use a more optimum technique.

(Personally I would have just left it as-is and worried about finding something better later on.
After all, laziness is a virtue.)

Not a .gif, but in future I recommend this:

In case anyone’s wondering why this is needed,
it’s because using C linkage (extern "C") disables name mangling.
C++ needs name mangling to support function overloading,
whereas C doesn’t support function overloading, so it doesn’t mangle function names.


Feature request…

  1. Option to clean & build.
  2. Ctrl + Tab for tab switching.

Thanks for your time :slight_smile:

1 Like