nxtBasic: A New Compiler for Basic Code on the X16

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).
mgkaiser
Posts: 54
Joined: Sat Dec 02, 2023 6:49 pm

Re: nxtBasic: A New Compiler for Basic Code on the X16

Post by mgkaiser »

unartic wrote: Tue Jul 16, 2024 3:06 pm
I meant for it to be 2bpp 16x16. Since 2bpp doesn't exist I will have to rework it.
Does this come close? ;-)

Schermafbeelding 2024-07-16 170556.png
That's close, but upside down. I'm converting it from a C64 2bpp sprite. Looks like it's gonna be easier and better to just redo it from scratch.
mgkaiser
Posts: 54
Joined: Sat Dec 02, 2023 6:49 pm

Re: nxtBasic: A New Compiler for Basic Code on the X16

Post by mgkaiser »

unartic wrote: Tue Jul 16, 2024 3:06 pm
I meant for it to be 2bpp 16x16. Since 2bpp doesn't exist I will have to rework it.
Does this come close? ;-)

Schermafbeelding 2024-07-16 170556.png
I see another need. Right now AddSprite loads the sprite image into a specific sprite slot. There is no means to just load a sprite image without also taking up a sprite and no way to change the sprite image. I need to change the image to animate the sprite. For now I'm just going to use "AddSprite" to load each frame into separate sprites and use VPOKE to change the image from frame to frame. It would be nice to build that in. Even cooler would be able to pass a loop of frames, an interval at which to change them, and let an interrupt just cycle the animation until I tell it to stop.

If I add functions to "basic-functions.s" will they just "magically" become available to the compiler? If so I will take a crack at writing what I want, send it to you, and you can accept it if you like it.
unartic
Posts: 136
Joined: Sat Oct 28, 2023 3:26 pm

Re: nxtBasic: A New Compiler for Basic Code on the X16

Post by unartic »

I see another need. Right now AddSprite loads the sprite image into a specific sprite slot. There is no means to just load a sprite image without also taking up a sprite and no way to change the sprite image. I need to change the image to animate the sprite. For now I'm just going to use "AddSprite" to load each frame into separate sprites and use VPOKE to change the image from frame to frame. It would be nice to build that in. Even cooler would be able to pass a loop of frames, an interval at which to change them, and let an interrupt just cycle the animation until I tell it to stop.

If I add functions to "basic-functions.s" will they just "magically" become available to the compiler? If so I will take a crack at writing what I want, send it to you, and you can accept it if you like it.
I imagined 'changing' spriteimages would just be hiding and showing sprits, but I guess there is a marrit for changing the image data aswell. A sprite-animation-cycle routine would also be pretty nice ;-) I think I'll have a look at that one!

Yes, everything you add to basc-functions.s will become available to you on the basic-side. I'm planning to actualy add a second file (like user-def.s) in which anyone can add their own basic functions to keep them seperate from the files that are updates by new releases. I haven'd documented this part yet, but here are some things to note:

Syntax is like this:

func "BASICNAME(ARGTYPES) as RETURNTYPE":"ASMLABEL"
ASMLABEL:
;do you asm stuff here
rts
endfunc:

- BASICNAME: this is the function/statement name you'll use on the basic side
- Arg types: can be any list of variable types, seperated by a komma. Values can be: STRING INT or FLOAT (if you'll check you will see optional parameter support and support for more then one type per argument. For now I would keep away from it)
- If you want to return something you add 'AS' and then the type, like: AS STRING

Reading arguments:
- Arguments are read in reverse order.
Call jsr PopBuffer to read an argument. It will bestored in 'WorkBuffer' (1024 byte buffer)
The length will be returned in WorkBufferLen (2 bytes)
The type will be returned in WorkBufferType (1=int, 2=string, 3=float)

For returning you have to setup WorkBuffer, WorkBufferLen and WorkBufferType and call: jsr PushBuffer

So for changing the image data offset of a sprite index, it could look like this:
func "SPRITE_SET_IMG(INT,INT,INT)":"SetSpriteMemOffset" 
;SPRITE_SET_IMG index,verab-ank,vera-address
    SetSpriteMemOffset:
        ;Read vera-address and store it in temp
        jsr PopBuffer
        lda WorkBuffer
        sta temp
        lda WorkBuffer+1
        sta temp+1

        ;Read vera-bank and store it in temp2
        jsr PopBuffer
        lda WorkBuffer
        sta temp        ;always only one byte as the value is <256
        
        ;Read sprite index
        jsr PopBuffer
        lda WorkBuffer
        
        ;This subroutine will set the vera registers to the sprite
        ;attributes of the spriteindex in 'A'
        jsr SetVeraToSpriteIndex   
        
        ;to some bitshifting to compose the address part of the
        ;image data and use sta VERA_data0 to write it to the sprite
        ;lattributes
        
        
        
    
    rts
endfunc:

And be aware of the assembly language: I'm using a custom build assembler, do you'll be missing some fancy stuff the well known brands offer. Just check the existing source to see what you can use :-)
mgkaiser
Posts: 54
Joined: Sat Dec 02, 2023 6:49 pm

Re: nxtBasic: A New Compiler for Basic Code on the X16

Post by mgkaiser »

This extensibility in nxtBasic is REALLY nice. I know Assembly, I know C. BASIC is just so much easier most of the time. This makes a super simple way of writing BASIC/Assembly hybrids. Consider adding a directive similar to #INCLUDE that specifies a ".s" file to include. That way I can make it clear my extensions are part of my source, distribute them with my source, and let others have repeatable results building my code.
unartic
Posts: 136
Joined: Sat Oct 28, 2023 3:26 pm

Re: nxtBasic: A New Compiler for Basic Code on the X16

Post by unartic »

Thats also a nice idea. I was planning to keep the assembly side seperate from the basic side. But I see how this can clarify where everything is coming from and help speed up development without having to get all the directories right.

Thanks for the suggestion ;=)
unartic
Posts: 136
Joined: Sat Oct 28, 2023 3:26 pm

Re: nxtBasic: A New Compiler for Basic Code on the X16

Post by unartic »

btw, are you on Discord? Under 'basic-dev' I've created a thread where I post all 'design question' I have to obtain insights of others. Would be good to have as many voices there as possible to come up with the 'best' basic for x16.
mgkaiser
Posts: 54
Joined: Sat Dec 02, 2023 6:49 pm

Re: nxtBasic: A New Compiler for Basic Code on the X16

Post by mgkaiser »

Here's my take on it. Seems to work. (By the way, HEX$ only returns the first 2 digits of a 16 bit int)

func "SPRITE_GET_IMG_BANK(INT) as INT":"GetSpriteMemBank"
GetSpriteMemBank:

;Read sprite index
jsr PopBuffer
lda WorkBuffer

;This subroutine will set the vera registers to the sprite
;attributes of the spriteindex in 'A'
jsr SetVeraToSpriteIndex

lda VERA_data0 ; Discard the first byte
lda VERA_data0 ; Keep the 2nd byte
AND #%00001000 ; Keep only the 16th bit
clc
ROR
ROR
ROR

; Return the banks
sta WorkBuffer
stz WorkBuffer+1
lda #$02
sta WorkBufferLen
lda #$01
sta WorkBufferType
jsr PushBuffer

rts
endfunc:

func "SPRITE_GET_IMG_ADDR(INT) as INT":"GetSpriteMemAddr"
GetSpriteMemAddr:

;Read sprite index
jsr PopBuffer
lda WorkBuffer

;This subroutine will set the vera registers to the sprite
;attributes of the spriteindex in 'A'
jsr SetVeraToSpriteIndex

lda VERA_data0
sta r0
lda VERA_data0
and #%00000111
sta r0+1

; Roll it left 5
asl r0
rol r0+1
asl r0
rol r0+1
asl r0
rol r0+1
asl r0
rol r0+1
asl r0
rol r0+1

; Return the adress
lda r0
sta WorkBuffer
lda r0+1
sta WorkBuffer+1
lda #$02
sta WorkBufferLen
lda #$01
sta WorkBufferType
jsr PushBuffer
rts
endfunc:

func "SPRITE_SET_IMG(INT,INT,INT)":"SetSpriteMemOffset"
;SPRITE_SET_IMG index,verab-ank,vera-address
SetSpriteMemOffset:
;Read vera-address and store it in temp
jsr PopBuffer
lda WorkBuffer
sta temp
lda WorkBuffer+1
sta temp+1

;Read vera-bank and store it in temp2
jsr PopBuffer
lda WorkBuffer
sta temp+2 ;always only one byte as the value is <256

;Read sprite index
jsr PopBuffer
lda WorkBuffer

;This subroutine will set the vera registers to the sprite
;attributes of the spriteindex in 'A'
jsr SetVeraToSpriteIndex

;to some bitshifting to compose the address part of the
;image data and use sta VERA_data0 to write it to the sprite
;attributes

lda temp
sta r0
lda temp+1
sta r0+1

; If Bank = 1 then SEC ELSE CLC
lda temp+2
beq RolInAZero_SetSpriteImg
sec
bra Continue_SetSpriteImg
RolInAZero_SetSpriteImg:
clc
Continue_SetSpriteImg:

; Roll the 16th bit in
ror r0+1
ror r0

; Roll it into the correct place
clc
ror r0+1
ror r0
clc
ror r0+1
ror r0
clc
ror r0+1
ror r0
clc
ror r0+1
ror r0

;Back up addr
lda VERA_addr_low
sta temp
lda VERA_addr_low+1
sta temp+1
lda VERA_addr_low+2
sta temp+2

; Store the existing value of 8bpp in temp+3
lda VERA_data0
lda VERA_data0
and #%10000000
sta temp+3

; Restore addr
lda temp
sta VERA_addr_low
lda temp+1
sta VERA_addr_low+1
lda temp+2
sta VERA_addr_low+2

lda r0
sta VERA_data0 ; Byte 0 Address 12:5
lda r0+1
ORA temp+3 ; Set 8bpp if it was already set
sta VERA_data0 ; Byte 1: Mode + Address 16:13

rts
endfunc:
unartic wrote: Wed Jul 17, 2024 6:18 am
I see another need. Right now AddSprite loads the sprite image into a specific sprite slot. There is no means to just load a sprite image without also taking up a sprite and no way to change the sprite image. I need to change the image to animate the sprite. For now I'm just going to use "AddSprite" to load each frame into separate sprites and use VPOKE to change the image from frame to frame. It would be nice to build that in. Even cooler would be able to pass a loop of frames, an interval at which to change them, and let an interrupt just cycle the animation until I tell it to stop.

If I add functions to "basic-functions.s" will they just "magically" become available to the compiler? If so I will take a crack at writing what I want, send it to you, and you can accept it if you like it.
I imagined 'changing' spriteimages would just be hiding and showing sprits, but I guess there is a marrit for changing the image data aswell. A sprite-animation-cycle routine would also be pretty nice ;-) I think I'll have a look at that one!

Yes, everything you add to basc-functions.s will become available to you on the basic-side. I'm planning to actualy add a second file (like user-def.s) in which anyone can add their own basic functions to keep them seperate from the files that are updates by new releases. I haven'd documented this part yet, but here are some things to note:

Syntax is like this:

func "BASICNAME(ARGTYPES) as RETURNTYPE":"ASMLABEL"
ASMLABEL:
;do you asm stuff here
rts
endfunc:

- BASICNAME: this is the function/statement name you'll use on the basic side
- Arg types: can be any list of variable types, seperated by a komma. Values can be: STRING INT or FLOAT (if you'll check you will see optional parameter support and support for more then one type per argument. For now I would keep away from it)
- If you want to return something you add 'AS' and then the type, like: AS STRING

Reading arguments:
- Arguments are read in reverse order.
Call jsr PopBuffer to read an argument. It will bestored in 'WorkBuffer' (1024 byte buffer)
The length will be returned in WorkBufferLen (2 bytes)
The type will be returned in WorkBufferType (1=int, 2=string, 3=float)

For returning you have to setup WorkBuffer, WorkBufferLen and WorkBufferType and call: jsr PushBuffer

So for changing the image data offset of a sprite index, it could look like this:
func "SPRITE_SET_IMG(INT,INT,INT)":"SetSpriteMemOffset" 
;SPRITE_SET_IMG index,verab-ank,vera-address
    SetSpriteMemOffset:
        ;Read vera-address and store it in temp
        jsr PopBuffer
        lda WorkBuffer
        sta temp
        lda WorkBuffer+1
        sta temp+1

        ;Read vera-bank and store it in temp2
        jsr PopBuffer
        lda WorkBuffer
        sta temp        ;always only one byte as the value is <256
        
        ;Read sprite index
        jsr PopBuffer
        lda WorkBuffer
        
        ;This subroutine will set the vera registers to the sprite
        ;attributes of the spriteindex in 'A'
        jsr SetVeraToSpriteIndex   
        
        ;to some bitshifting to compose the address part of the
        ;image data and use sta VERA_data0 to write it to the sprite
        ;lattributes
        
        
        
    
    rts
endfunc:

And be aware of the assembly language: I'm using a custom build assembler, do you'll be missing some fancy stuff the well known brands offer. Just check the existing source to see what you can use :-)
unartic
Posts: 136
Joined: Sat Oct 28, 2023 3:26 pm

Re: nxtBasic: A New Compiler for Basic Code on the X16

Post by unartic »

Nice!

Hex$ should return 4 bytes if the int is >255 btw.

Will have a look at it later.
unartic
Posts: 136
Joined: Sat Oct 28, 2023 3:26 pm

Re: nxtBasic: A New Compiler for Basic Code on the X16

Post by unartic »

Nice!

I think it is best to merge SPRITE_GET_IMG_BANK and SPRITE_GET_IMG_ADDR into: SPRITEGETIMGOFFSET

You can then return the address bit in the WorkBuffer as done in your current version. For the bank there is no need to have a seperate function (slower and takes op ram).

The SYS functions alows to communicate three extra bytes with basic (like pseudo proc registers A, X and Y). You can use one of these to return the vera bank:

lda VeraBank ;(or wherever it is)
sta ProcReg

In basic the bank can then be returned with GETA()

(ProcReg+1 = GETX() and ProcReg+2 = GETY())


Maybe it is even good enough to make a CopySpriteMemOffset(indexSrc,indexDest) which copies the memory offset address from one sprite to another. That would be way quicker then communicating it back in basic and using it again.

The developer can then load 'all' sprite images from which some could be dummy's just to load the image data and then use CopySpriteMemOffset to change the address offset.

Alternativly, we could also use the pseudo processor registers each time ADDSPRITE is used to 'return' the bank and address of the image data offset. If the developer need it, it can save these after ADDSPRITE for later use. That would also be a lot better performing.
mgkaiser
Posts: 54
Joined: Sat Dec 02, 2023 6:49 pm

Re: nxtBasic: A New Compiler for Basic Code on the X16

Post by mgkaiser »

unartic wrote: Fri Jul 19, 2024 6:43 am Nice!

I think it is best to merge SPRITE_GET_IMG_BANK and SPRITE_GET_IMG_ADDR into: SPRITEGETIMGOFFSET

You can then return the address bit in the WorkBuffer as done in your current version. For the bank there is no need to have a seperate function (slower and takes op ram).

The SYS functions alows to communicate three extra bytes with basic (like pseudo proc registers A, X and Y). You can use one of these to return the vera bank:

lda VeraBank ;(or wherever it is)
sta ProcReg

In basic the bank can then be returned with GETA()

(ProcReg+1 = GETX() and ProcReg+2 = GETY())


Maybe it is even good enough to make a CopySpriteMemOffset(indexSrc,indexDest) which copies the memory offset address from one sprite to another. That would be way quicker then communicating it back in basic and using it again.

The developer can then load 'all' sprite images from which some could be dummy's just to load the image data and then use CopySpriteMemOffset to change the address offset.

Alternativly, we could also use the pseudo processor registers each time ADDSPRITE is used to 'return' the bank and address of the image data offset. If the developer need it, it can save these after ADDSPRITE for later use. That would also be a lot better performing.
I'm actually cool dropping them entirely. I needed them to prove SPRITE_SET_IMG worked. I will always know where I loaded my sprite images.
Post Reply