Author |
Topic: RISC OS Sprite reader (Read 1301 times) |
|
Richard Russell
Administrator
member is offline


Posts: 803
|
 |
Re: RISC OS Sprite reader
« Reply #15 on: Jun 23rd, 2017, 1:19pm » |
|
on Jun 23rd, 2017, 08:46am, hellomike wrote:| Wouldn't know how to compile to DLL and I'm very bad in using Project and/or make files. |
|
It was trivial in this case, and I'm not a C programmer. I just added __attribute__ (dllexport) to the functions I wanted to be exported, and compiled it with the -shared switch, and it just worked: no warnings, no issues of any kind. I hadn't expected it to be that simple but fortunately the gods were kind to me on this occasion.
I wouldn't be surprised if the calling conventions (ABI) are not what you would normally expect for a DLL - I didn't add any stdcall directives - but BB4W is pretty tolerant and will call either stdcall or cdecl functions equally well.
Quote:| What did you compile it with Richard, GCC? |
|
Yes. The librosprite stuff looked to be primarily intended for use in Linux so that seemed to be the best bet, and so it proved.
You didn't react to my offer of adapting the program to convert the Acorn sprite to BMP files, but I've done it anyway! I thought it would be easier to do it whilst it's on my mind; my dreadful short-term memory means I might have had to start from scratch if I had waited. Here it is:
Code: REM Example code for loading an Acorn sprite using 'rosprite.dll' REM Richard Russell, http://www.rtrussell.co.uk/, 23rd June 2017 REM Based on 'example.c' Copyright 2008 James Shaw <js102@zepler.net> REM Constants: ROSPRITE_OK = 0 ROSPRITE_RGB = 0 ROSPRITE_CMYK = 1 BI_BITFIELDS = 3 REM Load rosprite.dll: SYS "LoadLibrary", "rosprite" TO rosprite% SYS "GetProcAddress", rosprite%, "rosprite_create_file_context" TO `rosprite_create_file_context` SYS "GetProcAddress", rosprite%, "rosprite_destroy_file_context" TO `rosprite_destroy_file_context` SYS "GetProcAddress", rosprite%, "rosprite_create_mem_context" TO `rosprite_create_mem_context` SYS "GetProcAddress", rosprite%, "rosprite_destroy_mem_context" TO `rosprite_destroy_mem_context` SYS "GetProcAddress", rosprite%, "rosprite_file_reader" TO `rosprite_file_reader` SYS "GetProcAddress", rosprite%, "rosprite_mem_reader" TO `rosprite_mem_reader` SYS "GetProcAddress", rosprite%, "rosprite_load" TO `rosprite_load` SYS "GetProcAddress", rosprite%, "rosprite_destroy_sprite_area" TO `rosprite_destroy_sprite_area` SYS "GetProcAddress", rosprite%, "rosprite_load_palette" TO `rosprite_load_palette` SYS "GetProcAddress", rosprite%, "rosprite_destroy_palette" TO `rosprite_destroy_palette` REM Define structures: DIM rosprite_area{extension_size%, extension_words%, sprite_count%, sprites%} DIM rosprite_mode{colorbpp%, maskbpp%, mask_width%, xdpi%, ydpi%, color_model%} DIM rosprite_palette{size%, palette%} DIM rosprite{name&(12), pad1&(2), mode{}=rosprite_mode{}, has_mask&, has_palette&, \ \ pad2&(1), palette{}=rosprite_palette{}, width%, height%, image%} DIM BMPfile{bfType{l&,h&}, bfSize%, bfReserved%, bfOffBits%, \ BITMAPFILEHEADER \ biSize%, biWidth%, biHeight%, biPlanes{l&,h&}, biBitCount{l&,h&}, \ \ biCompression%, biSizeImage%, biXPelsPerMeter%, biYPelsPerMeter%, \ \ biClrUsed%, biClrImportant%, dsBitfields%(2)} REM Sprite filename: sprite$ = @dir$ + "sample.ff9" PRINT "Loading "; sprite$ REM Load Acorn sprite file into memory: sprite% = OPENIN(sprite$) IF sprite% = 0 ERROR 100, "Couldn't open sprite file " + sprite$ size% = EXT#sprite% CLOSE #sprite% DIM memory% size% OSCLI "LOAD """ + sprite$ + """ " + STR$~memory% REM Get a memory context for the sprite file: SYS `rosprite_create_mem_context`, memory%, size%, ^ctx% REM Load the sprite file: SYS `rosprite_load`, `rosprite_mem_reader`, ctx%, ^sprite_area% TO res% IF res% <> ROSPRITE_OK ERROR 100, "Error loading spritefile" REM Print information about the sprite file: !(^rosprite_area{}+4) = sprite_area% PRINT "sprite_count = "; rosprite_area.sprite_count% PRINT "extension_size = "; rosprite_area.extension_size% REM Print information about and display each image: FOR I% = 0 TO rosprite_area.sprite_count%-1 PRINT '"Press a key to continue... " : IF GET CLS PRINT "Sprite "; I% ;":" !(^rosprite{}+4) = rosprite_area.sprites%!(I%*4) PRINT " name = "; rosprite.name&() CASE rosprite.mode.color_model% OF WHEN ROSPRITE_RGB: PRINT " color_model = RGB" WHEN ROSPRITE_CMYK: PRINT " color_model = CMYK" ENDCASE PRINT " colorbpp = "; ~rosprite.mode.colorbpp% PRINT " xdpi = "; rosprite.mode.xdpi% PRINT " ydpi = "; rosprite.mode.ydpi% PRINT " width = "; rosprite.width% PRINT " height = "; rosprite.height% PRINT " hasPalette = "; rosprite.has_palette& IF rosprite.has_palette& PRINT " palettesize = "; rosprite.palette.size% PRINT " hasMask = "; rosprite.has_mask& IF rosprite.has_mask& PRINT " mask_width = "; rosprite.mode.mask_width% IF rosprite.has_mask& PRINT " mask_bpp = "; rosprite.mode.maskbpp% REM Convert to BMP format and save: BMPfile.bfType.l& = ASC"B" BMPfile.bfType.h& = ASC"M" BMPfile.bfSize% = DIM(BMPfile{}) + 4 * rosprite.height% * rosprite.width% BMPfile.bfOffBits% = DIM(BMPfile{}) BMPfile.biSize% = 40 BMPfile.biWidth% = rosprite.width% BMPfile.biHeight% = rosprite.height% BMPfile.biPlanes.l& = 1 BMPfile.biBitCount.l& = 32 BMPfile.biCompression% = BI_BITFIELDS BMPfile.biSizeImage% = 4 * rosprite.height% * rosprite.width% BMPfile.biXPelsPerMeter% = rosprite.mode.xdpi% * 1000 / 25.4 + 0.5 BMPfile.biYPelsPerMeter% = rosprite.mode.ydpi% * 1000 / 25.4 + 0.5 BMPfile.dsBitfields%(0) = &FF000000 BMPfile.dsBitfields%(1) = &00FF0000 BMPfile.dsBitfields%(2) = &0000FF00 bmpfile$ = @tmp$ + rosprite.name&() + ".bmp" bmpfile% = OPENOUT(bmpfile$) SYS "WriteFile", @hfile%(bmpfile%), BMPfile{}, DIM(BMPfile{}), ^temp%, 0 span% = rosprite.width% * 4 FOR Y% = rosprite.height%-1 TO 0 STEP -1 SYS "WriteFile", @hfile%(bmpfile%), rosprite.image% + span% * Y%, span%, ^temp%, 0 NEXT CLOSE #bmpfile% OSCLI "DISPLAY """ + bmpfile$ + """" OSCLI "DISPLAY """ + bmpfile$ + """ 800,0," + STR$(rosprite.width% * 8) + \ \ "," + STR$(rosprite.height% * 8) NEXT I% REM Clean up: SYS `rosprite_destroy_mem_context`, ctx% SYS `rosprite_destroy_sprite_area`, sprite_area% END As discussed, BMPs don't support a mask (the 'alpha' values are present in the generated file, in the LS bytes of the 32-bit pixels, but no standard BMP reading software will take any notice of them).
Strictly speaking the sprite file should probably be converted not to a set of .BMPs but to a .ICO (which can hold multiple images and supports masks) but unfortunately the RGBA format in which librosprite returns the images is not at all convenient for that.
Richard.
|
|
|
|
hellomike
Junior Member
member is offline


Gender: 
Posts: 55
|
 |
Re: RISC OS Sprite reader
« Reply #16 on: Jun 24th, 2017, 09:22am » |
|
Quote:| I wouldn't be surprised if the calling conventions (ABI) are not what you would normally expect for a DLL - I didn't add any stdcall directives - but BB4W is pretty tolerant and will call either stdcall or cdecl functions equally well. |
|
Indeed that already would be one of my concerns if 'it' would compile and link with correct calling conventions. Also I'm unaware that something like "__attribute__ (dllexport)" would make it compile as DLL.
I didn't react to the offer yet as I was still trying to grasp the new info sofar. Filling the BMPfile{} structure the correct way is interesting as well.
All in all, the above was a nice exercise. Maybe nice for a Wiki article explaining how to turn a simple C-program into a DLL so that the code can be used in BB4W via SYS.
Thanks for all the new insights.
Mike
|
|
Logged
|
|
|
|
Richard Russell
Administrator
member is offline


Posts: 803
|
 |
Re: RISC OS Sprite reader
« Reply #17 on: Jun 24th, 2017, 1:17pm » |
|
on Jun 24th, 2017, 09:22am, hellomike wrote:| compile and link with correct calling conventions. |
|
I think your concern may be misplaced. It's not really a case of 'correct' or 'incorrect' calling conventions; I've come across several DLLs that have a 'non-standard' ABI but so long as they are used in the context of a specific application (as in this case being intended for use with BB4W) I don't see that as a problem.
The BOX2DBBC DLL uses an even less standard calling convention, one that even SYS cannot call straightforwardly, but since it is intended to be used only with the BB4W BOX2D library again I don't see that as an issue.
Quote:| Also I'm unaware that something like "__attribute__ (dllexport)" would make it compile as DLL. |
|
Google is your friend. Although I'd done it several times before, I couldn't remember anything about how to make a DLL, so I just looked it up. The only thing that makes my memory-loss manageable is Google - it's interesting (and slightly disconcerning) how often my searches find a reference that I myself have posted or published, but which I've subsequently completely forgotten about!
Quote:| Maybe nice for a Wiki article explaining how to turn a simple C-program into a DLL so that the code can be used in BB4W via SYS. |
|
I'm not too sure how that is different from "how to turn a simple C program into a DLL" which is something very easily found already. The "so that the code can be used in BB4W via SYS" doesn't really impose any extra constraints, other than the ABI issue; stdcall and cdecl are both fine.
But feel free to write such a BB4W Wiki article and copy/adapt the information you can find elsewhere, so long as Copyright restrictions permit you to do so.
Richard.
|
|
Logged
|
|
|
|
|