BitMagic

Talk about your programs in progress. Discuss how to implement features, etc.
Forum rules
This section is for testing Commander X16 programs and programs related to the CX16 for other platforms (compilers, data conversion tools, etc.)

Feel free to post works in progress, test builds, prototypes, and tech demos.

Finished works go in the Downloads category. Don't forget to add a hashtag (#) and the version number your program was meant to run on. (ie: #R41).
Post Reply
User avatar
Yazwho
Posts: 172
Joined: Fri Feb 19, 2021 2:59 pm
Contact:

BitMagic

Post by Yazwho »


Introducing BitMagic!

BitMagic is -- currently -- a macro assembler and a compiler for the X16, that utilises C# and the dotnet build chain to provide us with the ability to write macros to a much greater degree of complexity than offered by traditional assemblers. The ideal being that there will no longer be a need to write external applications to construct what we're trying to do, especially with assets.

There are a few things to do, most importantly implement any missing 65c02 opcodes, but it is nearing a usable state so it felt like the right time to at least share.

Instead of cut/pasting the text on the GitHub repository, you can read all about it here.

However, an picture is worth a thousand words, so as an example here is the code for this downloadable demo. It is assembler -- honest!


assembly "..\..\Libraries\Compression\bin\Debug\net6.0\Compression.dll";



assembly "..\..\Libraries\ImageProcessor\bin\Debug\net6.0\ImageProcessor.dll";



assembly "..\..\Libraries\Vera\bin\Debug\net6.0\Vera.dll";



using Compression;



using ImageProcessor;



using Vera;

 


    BM.X16Header(); // byte code to start execution.

 


    VideoMemory.SetCopyZpWordAddress(0x00); // define where in ZP the copy can use.



    Inflator.SetSourceZp(0x00); // define where in ZP we can use for inflating.

 


    Video.Mode(Layers.None); // disable all layers and sprites while the image inflates.

 


    Video.Scaling(Resolution.Half); // 320x240

 


    Video.LayerBitmap(ConfigLayer.Layer0, Depth.Bpp_8, BitmapWidth.Half_320, 0x1000);

 


    ; in case colour 0 is not black!



    lda #$11



    sta ADDRx_H



    lda #$fa



    sta ADDRx_M



    stz ADDRx_L



    stz DATA0



    stz DATA0

 


    ; call decompress



    Inflator.InflateToVram("compressed_data", 0x1000);

 


    var imageData = ImageAsset.LoadFullImage(@"Assets\bliss.bmp");

 


    ; copy palette to vera



    VideoMemory.Copy("palette", 0x1fa00, imageData.X16Colours.Length);

 


    Video.Mode(Layers.Layer0); // turn on layer 0 to show the image.

 


    ; infinite loop



    .loop:



        jmp loop

 


    Inflator.InflateToVramCode(); // decompressor proc code.



   



    VideoMemory.CopyProc(); // copy proc code.



 



    .palette:



    BM.Bytes(imageData.X16Colours);



   



    var compressed = Deflator.Deflate(imageData.Pixels);



    ; Source data is @(imageData.Pixels.Length) bytes.



    ; Compressed data is $@(compressed.Length.ToString("X4")) bytes.



    .compressed_data:



    BM.Bytes(compressed);

 


    ; scratch space for decompression.



    .segment Variables, $400



    Inflator.DefineScratchArea();



    .endsegment


Thanks for reading, and I hope you find it at least interesting!

User avatar
Yazwho
Posts: 172
Joined: Fri Feb 19, 2021 2:59 pm
Contact:

BitMagic

Post by Yazwho »


In an attempt to be more generic I've added the ability to target individual 'machines'. The only two so far implemented are the X16 R38 and R39, but hopefully I'll add more later. (The ability to target just a CPU is on the todo list, eg 6502 or 65c02.)

This gives us a handy feature, in that we can check the version in both libraries and the main csasm file as the Template Engine constructs the bmasm file.

For example:






        if (BM.Machine.Name == "CommanderX16")



        {



            if (BM.Machine.Version <= 38)



            {



                lda #38



            }



            else



            {



                lda #39



            }



            sta version



        }






A practical use would be switching look up tables for the YM2151.

The machine you're building can be set in both the csasm and the bmasm.

csasm:


machine CommanderX16R38;


bmasm:


.machine CommanderX16R38


As an aside; a machine for the compilation is just a set of constants, so for example the rom bank switch location would be mapped correctly to the 'RAM_BANK' constant depending on if you target R38 or R39.

User avatar
Yazwho
Posts: 172
Joined: Fri Feb 19, 2021 2:59 pm
Contact:

BitMagic

Post by Yazwho »


The assembler part now supports embedded procs, and correctly scopes them. (Scopes set with the .scope command still work in the same way.)

The end of the proc is also tagged with a constant called 'endproc' if a definition with that name doesn't exist.

One thing to note, referencing constants that are defined later in the file will always be assumed to be 16bit, so defined 8 bit ones earlier in the file. This is important for commands like lda to get the right opcode.

All of this is demonstrated below:


.machine CommanderX16R40;

 


.const a = $01

 


.proc proca

 


    .const a = $02



    lda #a          ; $02



    ;lda #procb:a   ; $03   doesn't work yet



    lda procb:b     ; $1234

 


    .proc procb



        .const a = $03



        .const b = $1234



        lda #a      ; $03



    .endproc

 


    lda #a          ; $02



    lda #procb:a    ; $03

 


.endproc

 


lda #a


With the output:




$0801:  $A9, $02              LDA       #a



$0803:* $AD, $CD, $AB   LDA       procb:b



$0806:  $A9, $03              LDA       #a



$0808:  $A9, $02              LDA       #a



$080A:  $A9, $03              LDA       #procb:a



$080C:  $A9, $01              LDA       #a



Revaluations:



$0803:  $AD, $34, $12     LDA       procb:b




and the constants:




App:Main:a = $01



App:Main:proca = $801



App:Main:proca:a = $02



App:Main:proca:procb = $806



App:Main:proca:endproc = $80C



App:Main:proca:procb:a = $03



App:Main:proca:procb:b = $1234



App:Main:proca:procb:endproc = $808




 

 

 

Edmond D
Posts: 499
Joined: Thu Aug 19, 2021 1:42 am

BitMagic

Post by Edmond D »


I'm not following the first couple lines of code; it appears the comments are incorrect: 

 


  1.  .const a = $01


  2.  .proc proca


  3.      .const a = $01


  4.     lda #a          ; $02


<snip>

    X.     lda #a          ; $02

 

where in the compilation the value is

$0801:  $A9, $01              LDA       #a

<snip>

$080C:  $A9, $01              LDA       #a

if a = $01 in line 1 & 3, plus the assembled code shows $01, how come the comment on line 4 & X is ";$02"?  

Am I missing something?

 

User avatar
Yazwho
Posts: 172
Joined: Fri Feb 19, 2021 2:59 pm
Contact:

BitMagic

Post by Yazwho »



On 4/17/2022 at 12:54 PM, Edmond D said:




Am I missing something?



Nope. I had the wrong text, thanks!

User avatar
Yazwho
Posts: 172
Joined: Fri Feb 19, 2021 2:59 pm
Contact:

BitMagic

Post by Yazwho »


I've added code to the image library to take an image and turn it into tiles. Eg, the following code takes logo.png and turns it into 1bpp tiles, and adds a full tile so we know it will be tile #1. (tile #0 is empty and is always added by setting a parameter)




public class Logo



{



    private TileData? _tileData = null;

 


    public void LoadLogo()



    {



        var image  = ImageProcessor.Processor.LoadImage(@"logo.png");

 


        // flip pixels



        for(var i = 0; i < image.Pixels.Count(); i++)



            image.Pixels = image.Pixels == 0 ? (byte)1 : (byte)0;

 


        // add a full set so we know it will be in position #1



        var toAdd = new Tile(8, 8, Depth.Bpp_1);

 


        for(var x = 0; x < 8; x++)



            for(var y = 0; y < 8; y++)



                toAdd.Pixels[x, y] = 1;

 


        _tileData = ImageProcessor.Processor.CreateTileMap(image, ImageProcessor.Depth.Bpp_1, ImageProcessor.TileSize.Size_8, ImageProcessor.TileSize.Size_8, false, true, ImageProcessor.TileExcessHandling.Error, new [] { toAdd });



    }

 


    public IEnumerable<byte> TileMapData()



    {



        foreach(var m in _tileData.Map)



        {



            yield return m.Index;



            yield return 0x01;



        }



    }

 


    public IEnumerable<byte> TileData()



    {



        foreach(var tile in _tileData.Tiles)



        {



            foreach(var b in tile.Data())



            {



                yield return b;



            }



        }



    }

 


    public int Height => _tileData.MapHeight;



    public int Width => _tileData.MapWidth;



}





 




This can then be used:




VideoMemory.Copy("tiles", 0x2000, logo.TileData().Count());




and




.tileMap:



    BM.Bytes(logo.TileMapData());



.tiles:



    BM.Bytes(logo.TileData(), 8);




 



However, I'm going to stop development on the X16 bits while I concentrate on the developing for the Amiga. I'm sure I'll pick this back up at some point, although mostly to generalise the macro compiler to other chipsets -- namely the 68000 -- and to remove the basic X16 emulator to retarget the project in a more general direction.



 



 

epsilon537
Posts: 31
Joined: Sun May 01, 2022 12:12 pm

BitMagic

Post by epsilon537 »



On 5/5/2022 at 1:22 PM, Yazwho said:




However, I'm going to stop development on the X16 bits while I concentrate on the developing for the Amiga. I'm sure I'll pick this back up at some point, although mostly to generalise the macro compiler to other chipsets -- namely the 68000 -- and to remove the basic X16 emulator to retarget the project in a more general direction.



  



 

If I may ask, where do you hang out online for Amiga development, and what's your target? UAE, an actual Amiga...?

I've been looking into the Amiga design while doing research for my BoxLambda project, and the more I look at it, the more I like it: The bitplane concept, the Copper, the Blitter are all very cool, and those are just the pieces I had a chance to look at.

User avatar
Yazwho
Posts: 172
Joined: Fri Feb 19, 2021 2:59 pm
Contact:

BitMagic

Post by Yazwho »



On 5/5/2022 at 2:10 PM, epsilon537 said:




If I may ask, where do you hang out online for Amiga development, and what's your target? UAE, an actual Amiga...?



I've been looking into the Amiga design while doing research for my BoxLambda project, and the more I look at it, the more I like it: The bitplane concept, the Copper, the Blitter are all very cool, and those are just the pieces I had a chance to look at.



I'm on the 'Official Commodore Amiga' discord, which is a good place to ask questions. ( https://discord.gg/MQ6Mfwk ) The 'English Amiga Board' is also a good resource. ( http://eab.abime.net/index.php )

I'm using VSC with the Amiga Assembly extension to compile with vasm and run (+debug) in WinUAE. I have an A500 and 1200, but no small monitor right now, when I pick one up I'll use those for final testing.

The copper and the blitter are where I started as well. Both are very interesting to code against. Didn't take long to knock up the app below. (Its animated, so looks a bit better than below!)

While the X16 doesn't need such systems, it's a shame it doesn't have them. It makes developing for the system so much more interesting.

image.png.14d5bfdb5bfcb422c23b7ef0099870a0.png

User avatar
desertfish
Posts: 1123
Joined: Tue Aug 25, 2020 8:27 pm
Location: Netherlands

BitMagic

Post by desertfish »


yay copper plasma!

epsilon537
Posts: 31
Joined: Sun May 01, 2022 12:12 pm

BitMagic

Post by epsilon537 »


Thanks for those links.

I haven't looked at the VERA design internals yet. I wonder if a VERA Copper would be feasible, or if it even makes sense given that VERA already is quite powerful. It would be fun though.

Xosera added a Copper to their VERA-like graphics controller, and I was surprised to see that the ZX Spectrum Next also has one.

 

Post Reply