Crap 0.1 first assembly project

Show us what you're working on, (preferably with screenshots).
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Crap 0.1 first assembly project

Post by Nomad »

Seven.FFF wrote: Wed Jan 10, 2018 2:16 pm You’re jumping straight into Wiggy, loading a, then returning immediately.

Try putting your includes after Main, or else write END Main instead of END 50000.
Weird now it shows 0..

main.asm

Code: Select all

org 50000

Main:
	include "test.asm"
	nop
	nop
	ld a,50
	call Wiggy
	;<---- shouldnt the pc return us here after wiggy is called? In that case why is a not 100?
	ld (51000),a
	ret
end Main
test.asm

Code: Select all

Wiggy:
	ld a, 100
	ret
Edit --- ok include should go before Main because I put end Main... it now works as I expected :P
Last edited by Nomad on Wed Jan 10, 2018 2:24 pm, edited 1 time in total.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Crap 0.1 first assembly project

Post by Ast A. Moore »

Where do you expect the assembler to assemble the included file to? I mean, how would it know where to insert that code?

I don’t know how your assembler works, so I can’t make any concrete suggestion, but I’d start looking into that. If I had to guess, the included file is assembled exactly where the include detective is. So when you run your code at 50000, it loads A with 100 and returns to BASIC. Since the address at 51000 is initialized to 0 after a reset, poking that location returns, well 0.

Either change the address you call to run your code from BASIC, or move the include directive after the last RET instruction in your main file.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Crap 0.1 first assembly project

Post by Ast A. Moore »

Also, young Nomad, it’s time for you to learn to use a debugger/monitor. It will answer many of your questions faster than any of us ever could.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Crap 0.1 first assembly project

Post by Seven.FFF »

As to why, think of include and incbin as being similar to macro expansion. Conceptually, the assembler replaces each include line with the contents of the file being included, until you have one giant single source file. (It probably doesn’t really do this, but the effect is the same.)

Generally it’s less crazy-making to have the entry point at a fixed address so you can always call it there without having to check your symbol list for the address. Putting includes before the entry point is unhelpful because you’ll push the entry point higher every time you add something to an included file.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Crap 0.1 first assembly project

Post by Nomad »

Ast A. Moore wrote: Wed Jan 10, 2018 2:25 pm Also, young Nomad, it’s time for you to learn to use a debugger/monitor. It will answer many of your questions faster than any of us ever could.
Yes that is true, sorry for all the questions : if I could figure out how to generate a tap with Zeus I could use that. I still use the Pasmo because its easy to generate the tap, but the problem is unlike zeus I cant see whats going on.
Seven.FFF wrote: Wed Jan 10, 2018 2:26 pm As to why, think of include and incbin as being similar to macro expansion. Conceptually, the assembler replaces each include line with the contents of the file being included, until you have one giant single source file. (It probably doesn’t really do this, but the effect is the same.)

Generally it’s less crazy-making to have the entry point at a fixed address so you can always call it there without having to check your symbol list for the address. Putting includes before the entry point is unhelpful because you’ll push the entry point higher every time you add something to an included file.
Ah I see what you mean, so every time I add a library it 'moves the goalpoasts', sorry for such a dumb question but how can I force the include file to go to a specific memory location?
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Crap 0.1 first assembly project

Post by Ast A. Moore »

Nomad wrote: Wed Jan 10, 2018 2:28 pm sorry for all the questions : if I could figure out how to generate a tap with Zeus I could use that. I still use the Pasmo because its easy to generate the tap, but the problem is unlike zeus I cant see whats going on.
No worries. I suggest you look into emulators that offer built-in debuggers and use assemblers as, well, assembler. I know Fuse and SpecEmu have debuggers built into them. Windows users might chime in with more suggestions.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Crap 0.1 first assembly project

Post by Seven.FFF »

Nomad wrote: Wed Jan 10, 2018 2:28 pm what you mean, so every time I add a library it 'moves the goalpoasts', sorry for such a dumb quehow can I force the include file to go to a specific memory location?
Yes indeed!

You can force that by having another org at the top of the included file. You can have as many org directives as you like, and they can appear anywhere in the code.

The problem with that is you end up with a sparse memory map. There will be holes between the blocks of code, and your tap file will be bigger than it needs to be, if you save the entire block including the holes.

Also, consider what happens if you hard code an org, but some code below it later grows so big it starts overrunning into the next block.

Writing tap files in Zeus is dead easy, I’ll make an example in a while.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Crap 0.1 first assembly project

Post by Nomad »

Ast A. Moore wrote: Wed Jan 10, 2018 2:33 pm
No worries. I suggest you look into emulators that offer built-in debuggers and use assemblers as, well, assembler. I know Fuse and SpecEmu have debuggers built into them. Windows users might chime in with more suggestions.
Sorry I am being a potato, I use linux and fuse, I just never took the time to look at fuse's menu options. Yea I got the debugger running now with it - thanks for the tip.
dfzx
Manic Miner
Posts: 673
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: Crap 0.1 first assembly project

Post by dfzx »

Nomad wrote: Wed Jan 10, 2018 2:42 pm Sorry I am being a potato, I use linux and fuse, I just never took the time to look at fuse's menu options. Yea I got the debugger running now with it - thanks for the tip.
OK, so, scroll the middle column (the disassembly) to address 50000 and tell us what you find there. How does the assembled (and now disassembled) code relate to your main and test ASM files?

The real question is "where does that 'ld a,100' get placed in memory"?
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
User avatar
Morkin
Bugaboo
Posts: 3251
Joined: Mon Nov 13, 2017 8:50 am
Location: Bristol, UK

Re: Crap 0.1 first assembly project

Post by Morkin »

Nomad wrote: Wed Jan 10, 2018 2:42 pm
Sorry I am being a potato, I use linux and fuse,
Have you tried using Spud?

<gets coat>
My Speccy site: thirdharmoniser.com
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Crap 0.1 first assembly project

Post by RMartins »

I believe the problem you are having, is because you do not understand how the instructions are assembled (converted into bytes) and where they go.

To explain it simply, it works like a regular text editor.
If you add something in the middle of a paragraph, the remaining part of the paragraph gets pushed forward, to give space to what you are adding.

The same happens to your code, if you insert some code in between, the reminder as to move forward.

You can force some specific position, by using the ORG directive.
But if you use more than one ORG directive in your code, you risk overlapping some code, without any warning (from PASMO at least).

Another problem that might be passing you on the side, is that while this is hapenning, you keep on jumping to your start address (hardcoded in your BASIC loader), even though your code as moved.

Try something like this to anchor the start address.

Code: Select all

org 50000
	JP	Main		; This is anchored to this exact same place by the previous ORG directive.
	
	; Place your includes here or somewhere else you want them to be
	include "test.asm"

Main:
	nop
	nop
	ld a,50
	call Wiggy
	ret
end Main
Tip it's good practice, if you intend to return to BASIC after execution, to SAVE registers, specially IY, and restore them before returning to BASIC
User avatar
Spud
Manic Miner
Posts: 372
Joined: Sun Nov 12, 2017 8:50 pm
Contact:

Re: Crap 0.1 first assembly project

Post by Spud »

Morkin wrote: Wed Jan 10, 2018 5:55 pm
Nomad wrote: Wed Jan 10, 2018 2:42 pm
Sorry I am being a potato, I use linux and fuse,
Have you tried using Spud?

<gets coat>
Hey! I resemble that comment!
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Crap 0.1 first assembly project

Post by Nomad »

Day 11: 354 days left..


ImagePotato tip:
To enable local labels in Pasmo, you use the command line option --alocal, in the code you start your local labels with the _ character. mmmm nice. This will help with readability.

Well there seems to be some light at the end of the tunnel (hopefully its not an oncoming vehicle :lol: ...)

Once I had the whole 'how does input work in Pasmo, passing values incident reasonably sorted, it opened the door to actually laying out the project in a more manageable manner. (so each file handles one part of the project..)

Besides being more tidy, it helped with testing new routines to see what was faster/slower (without having to go in with a calculator and start totting up t-states)

Also with the ability to use modular code within the project cut down significantly on the errors and enables project wide updates from one location. All good stuff.

The first thing I did was set up the menu system - well a bare bones version that I can build up. At the moment it just cycles through the different screens, each time a key is pressed you get a sound effect before being whisked to the next screen.

Simple stuff but at least it works. Nice thing about this is I can use it again for other projects.

Next is to add the Prak routine into the project, and finish the start screen/attract mode for the game. (the random value will position a graphic on the screen while the computer waits for input from the user.) Need to figure out how to play a ay ditty during this phase also but the Chuntey blogs I think have the answer to that.

In addition to that been looking at the excellent utilities for generating sound on the spectrum. While the games often get a lot of love for the spectrum the utilities are often cracking also. Had a look at soundFX and that was easy to use with the exception that I must have fluffed up the disassembly of the code somehow (see the programming section for that tale of woe.) But for a simple program its great. I think it will be useful once I get the hang of disassembling the code.update: Thanks to r-tape for the fix. This little utility will help me build a library of zaps and farts for the game :lol:

Here is the code adapted from SoundFX so I can use it as a library...
b appears to regulate the length of the sound pulse.

Code: Select all

org 50000

wiggy:
	ld d,100
	ld e,50
	ld b,60
	call soundFXGen

	ld d,90
	ld e,50
	ld b,60
	call soundFXGen

	ld d,80
	ld e,50
	ld b,60
	call soundFXGen

	ld d,70
	ld e,50
	ld b,60
	call soundFXGen

	ld d,60
	ld e,50
	ld b,60
	call soundFXGen

	ld d,50
	ld e,50
	ld b,60
	call soundFXGen

	ld d,40
	ld e,50
	ld b,60
	call soundFXGen

	ld d,30
	ld e,50
	ld b,60
	call soundFXGen

	ld d,20
	ld e,50
	ld b,60
	call soundFXGen

	ld d,10
	ld e,50
	ld b,60
	call soundFXGen

	ld d,1
	ld e,50
	ld b,60
	call soundFXGen

	ld d,255
	ld e,50
	ld b,60
	call soundFXGen

	ret

soundFXGen:
_S1:     push bc
	ld a,($5C48)		; 11T
	srl a
	srl a
	srl a
	set 4,a			; 8T
	out(254),a		; 11T
	ld b,d
_S2:	nop			; 4T
	nop			; 4T
	nop			; 4T
	djnz _S2		; 50021
	res 4,a
	out(254),a		; 11T
	ld b,e
_S3:	nop			; 4T
	nop			; 4T
	nop			; 4T
	djnz _S3		; 50031
	nop
	dec e			; 4T
	inc d			; 4T
	inc e			; 4T
	pop bc			; 10T
	djnz _S1		; 50006
	ret

end wiggy
I would actually like to disassemble the whole program, as I think a few optimisations could be made to make it more efficient. (but that is a project for later, it apparently has no protection scheme and seems a fairly compact program so..)

The other utility I recall being on a cover tape years ago was a tracker to make music on the spectrum 128, When I found out browsing the interwebs that a fellow had written an entire tutorial on this I figured it would be worth my time having a look. Thanks for Hikoki for the pdf hookup.

In other project news - been experimenting with creating a better square highlighter for the chess board. It will be much more simple (just using the flash attribute) so that will save a lot of time especially with the modular code stuff its a much smaller program.

Another routine I am messing around with is a idle timer, if there is no keyboard interaction for a certain amount of time it will switch to the attract mode. But that is just in the planning stages. I am trying to think of games that did this on the spectrum..

Probably a useless feature but little things for little minds haha. Still it might come in handy for a future project.

Stuff that is left to do - create some fancy screen backgrounds for the menus, complete the chessmen sprites (been looking at the archive for chess games on the spectrum and what graphics they used for some inspiration on what is good/crap.)

Finish reading through the Chuntey blogs. I think I could really improve the quality of the game this way.

Thanks to all that gave me comments and suggestions. It helps a lot to hear your ideas and advice. I think you guys are right in that a lot of my problems are not having a clear idea of the platform or how the assembly works. Over time with some effort on my part I think I can get better and avoid the gotcha's so much. Another thing that is obvious is I need to learn the tools much better. Really understanding how to use Fuse for development and Zeus will avoid a lot of problems. Lol while still a potato I think compared to where I started a few weeks back, progress has been made. I hope this time next year I can do lots of self directed learning - That is my main goal to be in a position where I don't need to bother y'all with my wibble haha.
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Crap 0.1 first assembly project

Post by Nomad »

Figured y'all might want to have a peek at the tap file - its just flicks through the various dummy menus loading random colours for the paper, border, ink, and also generates some random sounds.

later on will make sure that the colour combinations are visible, and that the sounds are within some parameters. But in fairness it worked out a whole lot better than I thought at first.

https://nofile.io/f/yoHEpkrbxgG/main.tap
User avatar
R-Tape
Site Admin
Posts: 6353
Joined: Thu Nov 09, 2017 11:46 am

Re: Crap 0.1 first assembly project

Post by R-Tape »

No file there.
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Crap 0.1 first assembly project

Post by Nomad »

hmm the website must be slow it says its still uploading... let me see if I can find another host..

http://s000.tinyupload.com/?file_id=248 ... 7835222099
User avatar
R-Tape
Site Admin
Posts: 6353
Joined: Thu Nov 09, 2017 11:46 am

Re: Crap 0.1 first assembly project

Post by R-Tape »

I like the twiddlediddlydiddley-plips. Not so keen on the DeeeDuuhhh.
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Crap 0.1 first assembly project

Post by Nomad »

R-Tape wrote: Thu Jan 11, 2018 11:11 am I like the twiddlediddlydiddley-plips. Not so keen on the DeeeDuuhhh.
Yea thet twiddlediddlydiddley plips were manually written. the DeeDuuuhh's are the random generated sounds. I thought perhaps it would be a cheesy way to give some variety to the game but as you say they sound pants.

I think a more tightly constrained random number generation (at the moment it returns 0-255) that is why the DeeDuuuhhs are so short in many cases. Will pad them with a 50 and see if that improves things...

this is the soundfx file from the program.

Code: Select all

;r-tapes sounds
zap:
	ld d,16		;speaker = bit 4
	ld e,0		;distance between speaker move counter
	ld b,255	;overall length counter
blp0:	ld a,d
	and 248		;keep border colour the same
	out (254),a	;move the speaker in or out depending on bit 4
	cpl		;toggle, so we alternative between speaker in and out to make sound
	ld d,a		;store it
	ld c,e		;now a pause
blp1:	dec c
	jr nz,blp1
	dec e		;change to inc e to reverse the sound, or remove to make it a note
	djnz blp0	;repeat B=255 times
	ret

wiggy:
	ld d,100
	ld e,50
	ld b,60
	call soundFXGen

	ld d,90
	ld e,50
	ld b,60
	call soundFXGen

	ld d,80
	ld e,50
	ld b,60
	call soundFXGen

	ld d,70
	ld e,50
	ld b,60
	call soundFXGen

	ld d,60
	ld e,50
	ld b,60
	call soundFXGen

	ld d,50
	ld e,50
	ld b,60
	call soundFXGen

	ld d,40
	ld e,50
	ld b,60
	call soundFXGen

	ld d,30
	ld e,50
	ld b,60
	call soundFXGen

	ld d,20
	ld e,50
	ld b,60
	call soundFXGen

	ld d,10
	ld e,50
	ld b,60
	call soundFXGen

	ld d,1
	ld e,50
	ld b,60
	call soundFXGen

	ld d,255
	ld e,50
	ld b,60
	call soundFXGen

	ret
;soundFX subroutine, corupted with the simple prandom from Chuntey blog.
;not as groovy as P Rak's random function but this is very simple subroutine

rndSoundFXGen:
	call randomChuntey
	add a,50
	and 255
	ld d,a
	call randomChuntey
	add a,50
	and 255
	ld e,a	
	call randomChuntey
	add a,50
	and 255
	ld b,a
;butchered from soundFX.
soundFXGen:
_S1:     push bc
	ld a,($5C48)		; 11T
	srl a
	srl a
	srl a
	set 4,a			; 8T
	out(254),a		; 11T
	ld b,d
_S2:	nop			; 4T
	nop			; 4T
	nop			; 4T
	djnz _S2		; 50021
	res 4,a
	out(254),a		; 11T
	ld b,e
_S3:	nop			; 4T
	nop			; 4T
	nop			; 4T
	djnz _S3		; 50031
	nop
	dec e			; 4T
	inc d			; 4T
	inc e			; 4T
	pop bc			; 10T
	djnz _S1		; 50006
	ret
User avatar
Joefish
Rick Dangerous
Posts: 2042
Joined: Tue Nov 14, 2017 10:26 am

Re: Crap 0.1 first assembly project

Post by Joefish »

Nomad wrote: Thu Jan 11, 2018 7:36 am ImagePotato tip:
To enable local labels in Pasmo, you use the command line option --alocal, in the code you start your local labels with the _ character. mmmm nice. This will help with readability.
I've never been able to get local definitions to work.
This is where the documentation is lacking. What's the syntax for using the LOCAL command?

If I've got a bit of code I want to repeat between REPT / ENDM markers, and I put a label in it, it throws up an error as the label counts as a redefinition the second time it's repeated. But every way I can think of for trying to define the label as local to the REPT macro fails.
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Crap 0.1 first assembly project

Post by Nomad »

Joefish wrote: Thu Jan 11, 2018 2:11 pm I've never been able to get local definitions to work.
This is where the documentation is lacking. What's the syntax for using the LOCAL command?

If I've got a bit of code I want to repeat between REPT / ENDM markers, and I put a label in it, it throws up an error as the label counts as a redefinition the second time it's repeated. But every way I can think of for trying to define the label as local to the REPT macro fails.
example. when I assemble crapchess, its just..

Code: Select all

pasmo --tapbas --alocal main.asm main.tap
on the command line.

in the files themselves its looks like...

Code: Select all

soundFXGen:
_S1:     push bc
	ld a,($5C48)		; 11T
	srl a
	srl a
	srl a
	set 4,a			; 8T
	out(254),a		; 11T
	ld b,d
_S2:	nop			; 4T
	nop			; 4T
	nop			; 4T
	djnz _S2		; 50021
	res 4,a
	out(254),a		; 11T
	ld b,e
_S3:	nop			; 4T
	nop			; 4T
	nop			; 4T
	djnz _S3		; 50031
	nop
	dec e			; 4T
	inc d			; 4T
	inc e			; 4T
	pop bc			; 10T
	djnz _S1		; 50006
	ret
as a sanity check I use two subroutines that use identical local labels.

Code: Select all

soundFXGen:
_S1:     push bc
	ld a,($5C48)		; 11T
	srl a
	srl a
	srl a
	set 4,a			; 8T
	out(254),a		; 11T
	ld b,d
_S2:	nop			; 4T
	nop			; 4T
	nop			; 4T
	djnz _S2		; 50021
	res 4,a
	out(254),a		; 11T
	ld b,e
_S3:	nop			; 4T
	nop			; 4T
	nop			; 4T
	djnz _S3		; 50031
	nop
	dec e			; 4T
	inc d			; 4T
	inc e			; 4T
	pop bc			; 10T
	djnz _S1		; 50006
	ret

soundFXGen2:
_S1:     push bc
	ld a,($5C48)		; 11T
	srl a
	srl a
	srl a
	set 4,a			; 8T
	out(254),a		; 11T
	ld b,d
_S2:	nop			; 4T
	nop			; 4T
	nop			; 4T
	djnz _S2		; 50021
	res 4,a
	out(254),a		; 11T
	ld b,e
_S3:	nop			; 4T
	nop			; 4T
	nop			; 4T
	djnz _S3		; 50031
	nop
	dec e			; 4T
	inc d			; 4T
	inc e			; 4T
	pop bc			; 10T
	djnz _S1		; 50006
	ret
works ok.

From the link bellow - I always thought it was impossible to use local labels in pasmo but I thought I would double check and boom in the docs..
n the autolocal mode, introduced by using the --alocal command line option, all labels that begins with a '_' are locals. His ambit ends at the next non local label or in the next PROC, LOCAL, MACRO, ENDP or ENDM directive.

Both automatic and explicit local labels are represented in the symbol table listing as 8 digit hexadecimal numbers, corresponding to the first use of the label in the source.
http://pasmo.speccy.org/pasmodoc.html#sourcelabel

I still don't understand how the macro expansion stuff works with pasmo its a bit of a mind bender. You are right about the documentation for pasmo it could be better/more extensive.

I could never get the LOCAL syntax to work either, but when I tried the --alocal way, you don't need to use LOCAL it just assumes that all labels that start with _ are local.
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Crap 0.1 first assembly project

Post by Seven.FFF »

Here's a Zeus tape generation example:

Code: Select all

; wiggymain.asm

zeusemulate             "48K"                           ; Tell the Zeus emulator to be a 48K Spectrum.
org                     50000                           ; Tell the Zeus assembler where to place the code.
Stack                   equ $FF40                       ; $FF40 is the value of SP on entry from RANDOMIZE USR on a 48K model.
Zeus_SP                 equ Stack                       ; Tell the Zeus emulator where to set the stack pointer
                                                        ;   (not needed in new versions of Zeus; older versions of
                                                        ;   Zeus reset SP to $0000 after outputting a tap or tzx).

Main:
                        nop
                        nop
                        ld a,50
                        call Wiggy
                        ld (51000),a
                        ret

                        include "test.asm"


TapStart                equ Main                        ; Start address of bytes to save in the LOAD "" CODE block after the tape's BASIC loader.
TapEnd                  equ $                           ; End address of bytes to save in the LOAD "" CODE block after the tape's BASIC loader.
TapSize                 equ TapEnd-TapStart             ; Length of bytes to save in the LOAD "" CODE block after the tape's BASIC loader.
EntryPoint              equ Main                        ; Entry point (what the BASIC loader calls with RANDOMISE USR nnnnn).
TapMode                 equ 2                           ; Mode 2 is standard TAP (not speedloader etc).

                        output_tap "wiggy.tap", "Wiggy", "Comment", TapStart, TapSize, TapMode, EntryPoint
                        output_tzx "wiggy.tzx", "Wiggy", "Comment", TapStart, TapSize, TapMode, EntryPoint
                        output_z80 "wiggy.z80", Stack, TapStart
                        //output_szx "wiggy.szx", Stack, TapStart ; Zeus generates SZX files in interrupt mode 2, which
                                                                  ;   need tweaking to get them returning to BASIC.

end                     EntryPoint                      ; Tell the Zeus emulator where to start running code at.

Code: Select all

; test.asm

Wiggy:
        ld a, 100
        ret
Make sure you right-click in the editor and choose Toggle Code. The wide left margin shows assembled bytes and the addresses they get assembled to.

Image
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Crap 0.1 first assembly project

Post by Nomad »

That is all kinds of awesome, thanks Seven_FFF now I can start tackling your tutorial soon 8-)

Being able to examine the byte code like that is very nice.

Is there a manual for zeus? I know there are many examples on the website but I couldn't find a pdf of the manual. I guess there are options for generating things like microdrive/floppy disk?
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Crap 0.1 first assembly project

Post by Seven.FFF »

joefish wrote: If I've got a bit of code I want to repeat between REPT / ENDM markers, and I put a label in it, it throws up an error as the label counts as a redefinition the second time it's repeated. But every way I can think of for trying to define the label as local to the REPT macro fails.
Zeus has rich handling and scoping of local labels. This is a deliberately baroque example to show what's possible if you were insane enough:

Code: Select all

; label-scoping.asm                                             ; This example doesn't do anything if you run it,
                                                                ; but it is instructive to see how it gets assembled!

zeusemulate             "48K"                                   ; Tell the Zeus emulator to be a 48K Spectrum.
org                     50000                                   ; Tell the Zeus assembler where to place the code.
Stack                   equ $FF40                               ; $FF40 is the value of SP on entry from RANDOMIZE USR on a 48K model.
Zeus_SP                 equ Stack                               ; Tell the Zeus emulator where to set the stack pointer
                                                                ;   (not needed in new versions of Zeus; older versions of
                                                                ;   Zeus reset SP to $0000 after outputting a tap or tzx).
Zeus_PC                 equ labelGlobalA                        ; Tell the Zeus emulator where to start running code.



labelGlobalA:           ret                                     ; Global labels can be back-referenced from later code.

Menu                    proc                                    ; Named proc. All labels defined inside (except those scoped with ::) are local to that proc.
labelNamedProcA:          nop                                   ; Labels in named procs can be back- or forward referenced.
                          for loop1 = 1 to 5                    ; Assembly-time loop.
                            proc                                ; Anonymous proc inside the loop. All labels defined inside get a separate symbol instance and value for each loop iteration.
label1A:                      nop                               ; Labels in anonymous procs can be back- or forward referenced.
                              jp Menu.labelNamedProcA           ; You can refer to labels defined in any named proc
                              jp Menu.labelNamedProcB           ;   with [proc].[label] dot notation.
                              jp ^^^^labelGlobalA               ; Each pair of ^^ jumps up one level
                              jp ^^^^labelGlobalB               ;   to resolve labels in a parent scope.
                              jp labelGlobalA                   ; Local labels in current scope need no qualification.
                              jp ::labelGlobalB                 ; You can refer to global labels with :: prefix from anywhere.
                              for loop2 = 1 to 3                ; A second assembly-time loop nested inside the first one.
                                proc                            ; Another Anonymous proc inside the inner loop.
label2A:                          nop                           ; Labels in anonymous procs can be back- or forward referenced.
                                  jp ^^label1A                  ; ^^ Scopes up one level to refer
                                  jp ^^label1B                  ;    to label inside outer anon proc.
                                  jp ^^^^labelNamedProcA        ; ^^ Scopes up two levels to refer
                                  jp ^^^^labelNamedProcB        ;    to label inside named proc proc.
                                  jp Menu.labelNamedProcA       ; Or refer to same proc proc label
                                  jp Menu.labelNamedProcB       ;    directly with dot notation.
                                  jp labelGlobalA               ; Local labels in current scope
                                  jp labelGlobalB               ;    need no qualification.
                                  jp ::labelGlobalA             ; You can refer to global labels
                                  jp ::labelGlobalB             ;    with :: prefix from anywhere.
label2B:                          nop                           ; Enclosing labels can also be forward-referenced from earlier code.
                                pend                            ; Closing inner anon proc.
                              next ; loop2                      ; Closing inner loop.
label1B:                      nop                               ; Enclosing labels can also be forward-referenced from earlier code.
                            pend                                ; Closing outer anon proc.
                          next ; loop1                          ; Closing outer loop.
labelNamedProcB:          nop                                   ; Enclosing labels can also be forward-referenced from earlier code.
                          jp labelNamedProcA                    ; Local labels in current scope need no qualification, whether back-
                          jp labelNamedProcB                    ;   or forward-referenced.
                          jp Menu.labelNamedProcA               ; Labels in named procs can be referenced with dot notation, whether back-
                          jp Menu.labelNamedProcB               ;   or forward-referenced.
                          jp labelGlobalA                       ; Global labels can be referenced without :: notation, whether back-
                          jp labelGlobalB                       ;   or forward-referenced, provided they are unambiguous.
                          jp ^^labelGlobalA                     ; Global labels can also be referenced with ^^  notation, whether back-
                          jp ^^labelGlobalB                     ;   or forward-referenced, from a first-level named or anonymous proc.
                          jp ::labelGlobalA                     ; Global labels can always be referenced with :: notation, whether back-
                          jp ::labelGlobalB                     ;   or forward-referenced.
pend
labelGlobalB:             nop                                   ; Global labels can also be forward-referenced from earlier code.
                          jp Menu_4_2.label2A                   ; Any instance-named symbol can be DIRECTLY referenced from anywhere. Use with caution!
                          		        		; Procs (both named and anonymous) and macros open up a new child scope. Other assembly-time
                          		        		; directlves (loops etc) don't. Hence why each loop here has an anon proc immediately inside.
                          		        		; Here there are three nested scopes (Main, outer anon and inner anon).
                          		        		; Nested scopes inside loops get a new scope instance for each iteration of the loop.
                          		        		; Nesting loops *and* scopes gets a new scope instance for each combination of iterations.
                          					; You can see this in the symbol naming below. FOr example in Menu_3_2.label2A, 
                          					; Global is an implicit outer scope, "Menu" is the named proc scope, "3" is the scope inside the outer
                          					; anon proc, and "2" is the scope inside the inner named proc. All this gives a unique scope name for 
                          					; that scope instance, then ".label2A" refers to the "label2A" label inside that scope instance.                      

; All this still assembles in only four passes!

; Symbol list generated by Zeus:

; labelGlobalA                    EQU $C350
; labelGlobalB                    EQU $C5B5
; loop1                           EQU $0006
; loop2                           EQU $0004
; Menu                            EQU $C351
; Menu.labelNamedProcA            EQU $C351
; Menu.labelNamedProcB            EQU $C596
; Menu_0.label1A                  EQU $C352
; Menu_0.label1B                  EQU $C3C5
; Menu_0_0.label2A                EQU $C365
; Menu_0_0.label2B                EQU $C384
; Menu_0_1.label2A                EQU $C385
; Menu_0_1.label2B                EQU $C3A4
; Menu_0_2.label2A                EQU $C3A5
; Menu_0_2.label2B                EQU $C3C4
; Menu_1.label1A                  EQU $C3C6
; Menu_1.label1B                  EQU $C439
; Menu_1_0.label2A                EQU $C3D9
; Menu_1_0.label2B                EQU $C3F8
; Menu_1_1.label2A                EQU $C3F9
; Menu_1_1.label2B                EQU $C418
; Menu_1_2.label2A                EQU $C419
; Menu_1_2.label2B                EQU $C438
; Menu_2.label1A                  EQU $C43A
; Menu_2.label1B                  EQU $C4AD
; Menu_2_0.label2A                EQU $C44D
; Menu_2_0.label2B                EQU $C46C
; Menu_2_1.label2A                EQU $C46D
; Menu_2_1.label2B                EQU $C48C
; Menu_2_2.label2A                EQU $C48D
; Menu_2_2.label2B                EQU $C4AC
; Menu_3.label1A                  EQU $C4AE
; Menu_3.label1B                  EQU $C521
; Menu_3_0.label2A                EQU $C4C1
; Menu_3_0.label2B                EQU $C4E0
; Menu_3_1.label2A                EQU $C4E1
; Menu_3_1.label2B                EQU $C500
; Menu_3_2.label2A                EQU $C501
; Menu_3_2.label2B                EQU $C520
; Menu_4.label1A                  EQU $C522
; Menu_4.label1B                  EQU $C595
; Menu_4_0.label2A                EQU $C535
; Menu_4_0.label2B                EQU $C554
; Menu_4_1.label2A                EQU $C555
; Menu_4_1.label2B                EQU $C574
; Menu_4_2.label2A                EQU $C575
; Menu_4_2.label2B                EQU $C594
; Stack                           EQU $FF40
; Zeus_PC                         EQU $C350
; Zeus_SP                         EQU $FF40
A lot of this came out of discussions with Simon about a real doubly-nested loop I was trying to write, and getting frustrated with. I was trying to conditionally jump to specific places inside the assembly-time loops, depending on run-time conditions, and it wasn't behaving as expected. The jiggling letters on the Jet Power Jack menu, I think it was.
Last edited by Seven.FFF on Thu Jan 11, 2018 5:34 pm, edited 5 times in total.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Seven.FFF
Manic Miner
Posts: 735
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Crap 0.1 first assembly project

Post by Seven.FFF »

Nomad wrote: Thu Jan 11, 2018 4:15 pm That is all kinds of awesome, thanks Seven_FFF now I can start tackling your tutorial soon 8-)

Being able to examine the byte code like that is very nice.

Is there a manual for zeus? I know there are many examples on the website but I couldn't find a pdf of the manual. I guess there are options for generating things like microdrive/floppy disk?
Nope, no PDF. Half the documentation is in the website example files, and the other half is in the History section of the About screen. The only thing really missing is an overall structure. I did mull over making a wiki, but I'm not sure I could maintain it in the longer term.

I usually download this, unzip into a directory, download the history text into the same directory, then use grep/whatever to search through the whole thing.

Simon is very amenable to questions (and making improvements arising from questions and discussions). As am I (well the questions if not the improvements!). If you're on facebook messenger, hit him or me up on there.
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel NXTP ESP Update ESP Reset CSpect Plugins
User avatar
Joefish
Rick Dangerous
Posts: 2042
Joined: Tue Nov 14, 2017 10:26 am

Re: Crap 0.1 first assembly project

Post by Joefish »

So when it comes to PASMO, nobody knows?
I'll be adding the auto locals directive to my builds in future anyway.
Post Reply