Download here
Edit two: Another minor release see the changelog.
Edit sorry to release a new version so soon but I just noticed that in certain instances Libpng would output a harmless warning however this is annoying as it overlaps the image so I fixed the cause of the warning.
The source code can be found here
From the readme:


                             Casio Prizm PNG viewer
This  is a PNG viewer for the Casio Prizm. It uses Libpng (which is paired with
zlib)  to  decompress a PNG file. When you load a png file it is  resampled  to
fill the screen but aspect ratio is preserved. As of now a simple bilinear fil-
tering is used but if there is interest I may replace it with something better.

The version you downloaded is version 1.003. Note that there is always the pos-
sibility  for a new version, so if you noticed that I posted in the PNG  viewer
thread see what I posted, there may be an update.

                           How to use the PNG viewer
You will see a file browser on startup use the arrow pad to select a file. Then
press either F1 or EXE to select the PNG file. Press any key except menu (which
actually takes you to the menu) to go back to the file browser.

                                 Notes and tips
Since  the  Casio  Prizm  does  not  have  lots  of  flash memory run Pngout or
pngwolf-zopfli on the images before putting them on your calculator.

I  have  included  instructions  on  how  to  compile  Libpng  and  Zlib  here:
Following  these  instructions gets you a libraries (Libpng and Zlib) that  you
could link against your add-in.

If  you want to use a PNG in an add-in a good option would be to make a 16bit 1
channel  image containing RGB565 data. Doing so introduces additional  overhead
with  no benefit so instead it would be better to use Zlib directly with a sim-
pler  image  format. For example uint32_t width,uint32_t height,  deflate  com-
pressed sequential RGB565 data created by zlib's deflate() function. But if you
feel  comfortable with PNG that is an option. Also you can store the PNGs as  a
const array so that it does not need to be a file. Note that LZMA works well on
the  Casio Prizm and gets a better compression ratio. Try that in favor of Zlib

The  purpose of this program is simply to show off how capable the Casio  Prizm
is. The PNG image format is well known and I think some people wrongly perceive
it  as a very ram intensive thing to decode. Libpng can output a row at a  time
or N amount of rows. When width!=384 or if height>=216 then the image is scaled
Only enough  ram to hold 2 rows are needed which is 6*width bytes of ram. I use
bilinear scaling that is why two rows are needed to be read. After the code in-
terpolates  the  pixels the resulting pixel is converted to RGB565 and sent  to
VRAM.  When the width==384 and height<=216 a buffer is created and the image is
read all at once then simply converted to RGB565 and send to VRAM
That is a pretty sweet program! It's at times like this where I wished I owned a Prizm. Sad On the other hand, great job in fitting this functionality into a calculator!
Well even though you don't own a prizm you still can use the emulator but regardless this may seem like a big accomplishment but the reality is that all I did was download the source code for both zlib and libpng and compile it for the prizm. I did modify libfxcg a bit to make it work. However it took very little time to get this all working. In fact part of my motivation of doing this is to show people how easy prizm development is and the fact that you can get many standard libraries working on the prizm with little effort.
Great job ! I'll give it a try today, it seems very interesting. I didn't think it was possible to properly decode PNG images on the Prizm, but you show me it was ! Very Happy
I also appreciate the "why you're doing that" because I'm still hoping that Prizm dev won't die, and I think such programs with such explanations will help him living ! Very Happy
What are the limits on the images this can decode?
Also, note that zlib on the Prizm has always been perceived as possible - the OS uses it for g3p files. What I didn't know is that one could make PNG decoding fit in the (buggy) 128 KB heap...
Using the OS's zlib would be really interesting, but apparently there are no exposed syscalls for it. And reverse-engineering of that part more or less stopped when people started objecting that we should not mess with the g3p file format, etc. etc.
Nemhardy I am glad that you liked my program.
gbl08ma I have tried some large images and it works. The reason I can decode large images is because I am not trying to fit the whole image on the heap. Zlib and libpng do not allocate much memory using malloc() and I use alloca for allocating memory to hold the decoded image or part of the decoded image.
Edit: Just as a testomony to that fact that my program handles large images I loaded up a 7680x4320 png file that is 8mb and it worked just fine.
New version. This one uses the full 396x244 screen.

I used to maintain this in several archives. Doing so does not make sense because it is easier just to have it on github.

Also I tried replacing zlib with miniz, but I got an error when running the image viewer. It reduced the filesize by 12384 bytes. However I got an error message which said "libpng error: Not enough image data". I am not that interested in that right now.
I like that you added the higher resolution to this.

Are you planning to keep on developing it further? After reading your statements regarding ease of libraries porting to prizm I wonder what you think of porting a pdf viewer?

I only tested you update on the new OS so far - and similarly to my message add-in's function buttons area not being cleared your viewer leaves artefacts of the last image in the outer frame area when you getout into browser screen. I have not looked at the code yet or tested it on older OS but drawing white or default colour frame when back in file browser should fix it I imagine.

Your updates motivate me to update my public add-ins too. I have not fixed my message add-in problem with function buttons area but it seems to only appear in the new OS and I suspect one of the clearvram calls behaves differently in new OS now.

I will let you know if i find any other issues.

Kind regards
I have updated this program. It now has untested support for the CG-50. I also linked against the latest releases of Libpng and Zlib. I also compiled it using the latest GCC 7.2.

Please download it only from here:

and let me know if it works for you.

The only change I made was making VRAM_CopySprite use GetVRAMAddress. The part of the code which draws the PNGs uses a separate buffer.
Thanks - i will test on 50 model and report back. I wonder if you could include or share compiled libpng16.a please
I can already tell you what I posted previously would not have worked. Before testing please re-download. It was due to an incorrect linker script. See my Mandelbrot post. At this point my fix is just speculation.
just downloaded it now - file browser worked, but opening 2 png files I had 409x409 pxs each only gave clack screen with a few pixels of blue at the top and pressing any key return me back to open file menu

sorry for the bad news - I hope it still helps
Edit: I never tested this on the fx-CG-50 emulator. I don't know why I wrote that. I tested the mandelbrot explorer and that works just fine. It also works on my fx-CG-10.
It works on the fx-CG-50 emulator. It may be because of the non blocking DMA code. I wonder if any addresses have changed. If this is true the reason the menus work is because it uses GetKey to redraw the screen. This also applies to the Mandelbrot explorer.
Does it mean you are using some addresses which are hardcoded? Maybe i shall use insight to dump some address range if it helps? That’s how i was searching for menu icons in the past.
Edit: At-least the part relating to DMA below may be incorrect. Instead maybe I can't DMA from addresses that are virtually mapped. I got a similar issue on a real fx-CG-10 when the screen just became a solid color.
When I use 0x08100000 for the stack I get a solid color. It works when I use 0x88160000 I can see the PNGs.

That is correct both my MPEG2 player and the PNG viewer have hard-coded addresses. In my MPEG2 player we have


#define FLASH_START 0xA0000000

This relates to code which uses Bfile_ReadFile_OS to read a sector of the file and then it searches for it in flash memory using memcmp.

Maybe I could replace it with Bfile_FindFirst which gives the caller an address. I don't know how this will work if the file is fragmented.

We also have


// Module Stop Register 0
#define MSTPCR0   (volatile unsigned *)0xA4150030
// DMA0 operation register
#define DMA0_DMAOR   (volatile unsigned short*)0xFE008060
#define DMA0_SAR_0   (volatile unsigned *)0xFE008020
#define DMA0_DAR_0  (volatile unsigned *)0xFE008024
#define DMA0_TCR_0   (volatile unsigned *)0xFE008028
#define DMA0_CHCR_0   (volatile unsigned *)0xFE00802C

#define LCD_BASE   0xB4000000
#define SYNCO() __asm__ volatile("SYNCO\n\t":::"memory");
#define PRDR *(volatile unsigned char*)0xA405013C
#define LCDC *(volatile unsigned short*)0xB4000000

#define LCD_GRAM_X 0x200
#define LCD_GRAM_Y 0x201
#define LCD_GRAM 0x202
#define LCD_WINDOW_LEFT 0x210
#define LCD_WINDOW_RIGHT 0x211
#define LCD_WINDOW_TOP 0x212
#define LCD_WINDOW_BOTTOM 0x213

This code is also used in the PNG viewer. It allows me to send images in a buffer to the LCD screen using DMA and while the DMA transfer is running I can start working on the next frame. In PNG viewer's case it is not done for performance but rather so I can use a buffer from a different address.

I already modified all code that used the hard-coded VRAM address.
ProgrammerNerd wrote:

This relates to code which uses Bfile_ReadFile_OS to read a sector of the file and then it searches for it in flash memory using memcmp.

Maybe I could replace it with Bfile_FindFirst which gives the caller an address. I don't know how this will work if the file is fragmented.

isn't this my old hacked code to create file mapping I used in cgdoom and cgplayer? I think you cannot optimise it that way. I did not test the address returned by Bfile_FindFirst, but if the file is fragmented, it might happen, that N+1 block has lower address than block N. I think I put a comment to the code about this. It seems you ask for special case, where N=0.
That is correct, it is your old code. I, like you, am concerned about file fragmentation. My primary interest in using the address returned by Bfile_FindFirst is because I have no idea if 0xA0000000 is still valid on the fx-CG-50 for the flash start. I don't have a fx-CG-50 and I read that the emulator is still acting more like a fx-CG-20.
ProgrammerNerd wrote:
I have no idea if 0xA0000000 is still valid on the fx-CG-50 for the flash start.

I think you can use Bfile_FindFirst to have address of the zeroth block and then (if you detect fragmentation), use min(Bfile_FindFirst + processed area, 0xA0000000). I think this can be the simplest heuristics. For larger files you might consider to make bitmap, 1 bit for each already found 4K block, so you do not check them again. Also you can cache the file mapping in RAM (as a file), so second run might be faster (just verify the cache is valid). But the very correct solution would be to truly map the file to continuous address space, but I have no idea how to do it.
BTW: do you expect any SW changes between fxCG50 and fxcg20 with the latest FW?
I like the bitmap idea and agree that somehow using the MMU to map the file to a contiguous address space is the best solution.

For the Bfile_FindFirst heuristic It may be easier to just detect if it is a fx-CG-50 and use the proper flash start address. This can be done by getting the VRAM address and checking if it is 0xA8000000 and if not assume a fx-CG-50. I am guessing that the start address is the same but I don't know that it is a the same. Someone will have to confirm this.

For software changes between the fx-CG-20 and fx-CG-50 the only one that I know of is that one should no longer hard code the VRAM address and instead use the system call to get it because the VRAM address has changed. It seems like other add-in developers were able to just make that change and their program works on both models.
GCC is no longer having the LTO issues it seems, I just ran it and it worked on my calculator (CG10).

Try running it on yours and post the results.

Before running it please re-download and put the latest version on your calculator. I recompiled it using the latest version of GCC and Binutils.

Edit: this still needs work for the fx-CG50. I don't yet have DMA from a virtual address to a physical address working and I don't know if the CPU supports that.
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 2
» All times are UTC - 5 Hours
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum