Kalmalyzer / kalms-c2p

Kalms C2P routine collection
37 stars 7 forks source link

Instructions on how to build, please? #1

Closed TheFakeMontyOnTheRun closed 4 years ago

TheFakeMontyOnTheRun commented 4 years ago

Hello - thank you for making this available! I'm trying to build c2p1x1_8_c5_030.s, just like your provided example, using vasmm68k, but can't get to build it.

What tool did you use? Thanks

Kalmalyzer commented 4 years ago

Back when I wrote these I used Devpac. I expect these to be possible to build using vasmm68k as well. Do you have an example commandline that fails? Do you have an example vasmm68k output?

TheFakeMontyOnTheRun commented 4 years ago

To be more precise, it builds, but I have trouble linking. Thankfully, the cool folks at the Amiga Discord helped me thru some of the troubles (like adding an underscore before the labels and setting the output format to Amiga Hunk) - so much so that calling c2p1x1_2_c5_gen_init seems to works - but when I try to call c2p1x1_2_c5_gen, I get some weird linking error: code reloc for _c2p1x1_2_c5_gen is out of range: 00000000

Maybe I'm somewhat out of my league, but it's the kind of thing you probably have for breakfast and could sove in a pinch - with the benefit of others not stumbling upon the same roadblocks :P

TheFakeMontyOnTheRun commented 4 years ago

BTW, I have this 320x200 framebuffer than I would draw with WriteChunkyPixels(my_window->RPort, 0, 0, 319, 199, &framebuffer[0], 320);. I expect that I should replace it with c2p1x1_2_c5_gen_init(0, 0, 0, 0, 320, 320);and then c2p1x1_2_c5_gen(&framebuffer[0], my_window->RPort);, right?

TheFakeMontyOnTheRun commented 4 years ago

Ah, it's probably worth posting my flags as well:

CFLAGS = -DAMIGA -Ibase3d/include -Imenu/include -c -m68020 -s -fno-keep-inline-functions -fexpensive-optimizations -fno-keep-inline-functions -fomit-frame-pointer -ffast-math -O3 -DAGA8BPP
LDFLAGS =  -msmall-code -fexpensive-optimizations -O3 -s -fomit-frame-pointer -noixemul
ASFLAGS = -phxass -Fhunk -m68020 -chklabels -no-fpu -wfail
spec-chum commented 4 years ago

Could you try putting your vasm code in section .text ?

TheFakeMontyOnTheRun commented 4 years ago

Oh, hey! changing from to .text is not allowed by vasm, but changing it to simply "text" works, but produces the same results.

TheFakeMontyOnTheRun commented 4 years ago

The slightly modified ASM code: https://gist.github.com/TheFakeMontyOnTheRun/203350467f23bff5ace80710d493026e

Kalmalyzer commented 4 years ago

Ok, so here's how you make C and assembly code work together, generally speaking:

Exporting symbols in assembly code

Either blah or blah: in the 1st column declares a symbol. This symbol can be used either as a function entry point or as the location of a global variable.

The symbol will not be listed among the exported symbols in the object file. It is effectively behaving like a static variable/function in C (whose visibility is the current compilation unit).

You can tell the assembler to export the symbol in the object file. You do so by including an <tab>XDEF blah in the same assembly file. XDEF stands for eXternal DEFinition.

Exporting symbols in C code

Declare your functions and variables without the static keyword. The corresponding symbols will then be listed in the object file.

Using external symbols in assembly code

Place a <tab>XREF blah in the assembly file from which you are referencing blah. XREF stands for eXternal REFerence. Some assemblers require you to have that XREF statement. Others automatically assume that any symbols that you reference, which aren't declared in the same assembly unit, are externally-referenced.

Using external symbols in C code

For functions, place a forward declaration before first usage: void blah(void);

For variables, place an external declaration before first usage: extern int blah;

Calling assembly code from C code

C compilers will typically perform symbol name mangling for functions: they prepend a _ to any function names. Some compilers will do different name mangling depending on which calling conventions (which register usage) the compiler is configured to use. This is to avoid the user accidentally linking together object files which contain C code that has different calling conventions (if the symbols matched, things would mismatch at runtime -- now the user gets a linker error instead).

This illustrates that you need to match up two things when calling C->assembly: the symbol names, and the calling convention. Where do the function arguments go? Into registers, onto the stack, a combination thereof? If there is a return value, where is that passed? in d0 or somewhere else? Also, which registers are guaranteed to be preserved by the assembly code? Most C compilers' calling conventions expect all registers except d0/d1/a0/a1 to be preserved by the called code. Here is the calling convention for VBCC when targetting M68k.

Sometimes you can adapt the C side to match the assembly side. For an assembly routine that expects arguments on the stack, and doesn't stomp registers outside of d0/d1/a0/a1, you just need to match up the symbol name. For an assembly routine that wants parameters directly in registers, doesn't stomp registers outside of d0/d1/a0/a1, of there are often compiler-specific ways of writing the external function declaration (see VBCC manual on register arguments) - and then you need to match up the symbol name.

Making the assembly name match up with the C side is typically done by either renaming the assembly name to _blah (remembering to also rename the corresponding XDEF) -- or having two symbols on the assembly side, both blah and _blah.

If you can't make the C compiler adapt to the assembly code, the easiest way to glue together the C and the assembly code is to create a wrapper function in assembly: a function that accepts arguments in a format which is suitable to the C side, then it preserves registers, does any necessary argument shuffling, then it calls the real assembly routine, then it restores registers, and returns back to the C side.

Debugging symbol name problems

Use the vobjdump tool to inspect the object files that vasm/vbcc produces. You should be able to see both where symbols are being defined, and where they are being referenced. Something is bound to not match up. To make this easier, move the interesting bits out to tiny assembly/C files and then inspect the resulting tiny object files.

Kalmalyzer commented 4 years ago

And, finally...

Picking the appropriate C2P routine

You are currently using WriteChunkyPixels(). That routine expects a linear stream of bytes and writes that to a rectangular 2D area within a RastPort.

The closest you will find in this collection is the generic BitMap outputting c2p routine. Other variations in the same folder do pixel doubling and write to fewer bitplanes.

The so-called normal routines are a little bit faster, but they want a base pointer to the first in a series of bitplanes that are laid out contiguous in memory, and they typically do not support any row modulo (they always write full bitplanes). You can find variations in there which consume less CPU time on <68060 systems but the pixel order within each 32-pixel group is scrambled (so some complexity is effectively moved to the rendering code).

Kalmalyzer commented 4 years ago

(I agree that it would be nice if this package included C bindings out of the box. That's something for the (distant) future...)

TheFakeMontyOnTheRun commented 4 years ago

Thank you for the nice write up! The C side of things I was pretty much aware, but not much the ASM side (I'm much more familiar with x86 and even then, when I did, was with inline __asm).

Gonna give c2p1x1_8_c5_bm.s a try - seems to be the one more likely to satisfy my needs.

I believe it's useful to document this here as well, to whoever fings this issue: bebbo's gcc require the code to be on a text section.

(edit to remove stupid thing I said)

TheFakeMontyOnTheRun commented 4 years ago

(I agree that it would be nice if this package included C bindings out of the box. That's something for the (distant) future...)

I would gladly propose an example code for bebbo's gcc + vasm, once I get this up and running

TheFakeMontyOnTheRun commented 4 years ago

...it's finally working! And it's so fast that, for 030 machines, it might a little too fast! Thank you very much! Hope you accept pull requests for examples of usage? Screenshot 2019-11-18 at 23 11 39

Kalmalyzer commented 4 years ago

Sure thing!

On Tue, Nov 19, 2019 at 12:36 AM Daniel Monteiro notifications@github.com wrote:

...it's finally working! And it's so fast that, for 030 machines, it might a little too fast! Thank you very much! Hope you accept pull requests for examples of usage? [image: Screenshot 2019-11-18 at 23 11 39] https://user-images.githubusercontent.com/2441483/69103040-2ad39600-0a5c-11ea-9cd0-01d736f9fc97.png

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Kalmalyzer/kalms-c2p/issues/1?email_source=notifications&email_token=AAJHC6237VNJSC4E6I4SYITQUMRH7A5CNFSM4JOJ4QN2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEEMJZPA#issuecomment-555261116, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJHC6YHZI2O2TL4HQQ2EMLQUMRH7ANCNFSM4JOJ4QNQ .