Crap 0.1 first assembly project

Show us what you're working on, (preferably with screenshots).
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: 736
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: 736
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: 736
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: 736
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.
User avatar
Seven.FFF
Manic Miner
Posts: 736
Joined: Sat Nov 25, 2017 10:50 pm
Location: USA

Re: Crap 0.1 first assembly project

Post by Seven.FFF »

Works for me Jason, but it does need a proc/endp inside the rept/endm, despite what the doumentation says. It that respect it works the same way as Zeus.

Code: Select all

org 32768

Test:
	rept 4
          proc
_A:  
	    jp _A
          endp
        endm
 	ret

end 32768

Code: Select all

C:\Users\robin\Documents\Visual Studio 2015\Projects\ZalaXa\src>pasmo --tapbas --alocal test.asm test.tap test.txt

C:\Users\robin\Documents\Visual Studio 2015\Projects\ZalaXa\src>

Code: Select all

00000000	EQU 08000H
00000001	EQU 08003H
00000002	EQU 08006H
00000003	EQU 08009H
Test		EQU 08000H
Without --alocal, fail:

Code: Select all

C:\Users\robin\Documents\Visual Studio 2015\Projects\ZalaXa\src>pasmo --tapbas test.asm test.tap test.txt
ERROR on line 6 of file test.asm
ERROR: Invalid definition, previously defined as EQU or label
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 »

Day 12: 353 days left..

With the anykey subroutine doing a good job of not crashing the program. It was time to get a little more precise/discerning with the keyboard input. Debugging the fallout from the following code will probably take up a lot of the project time today. But without it there is no real interaction beyond anykey on the menus (and later the main game). So it pays to get this right as soon as possible.

The code is from Chuntey blog. https://chuntey.wordpress.com/2012/12/1 ... chapter-2/ I adapted it to call the various menus instead of up,down.left,right. Now me at 3am in the morning probably was more potato than me fully refreshed so lets hope I can see the obvious errors that were hanging the program and making it unresponsive.

First the code.

this is the main.asm for crapchess

Code: Select all

org 50000

include "changebordercolour.asm"
include "changeinkpaper.asm"
include "mainmenu.asm"
include "keyboard.asm"
include "clearscreen.asm"
include "splashscreen.asm"
include "soundfx.asm"
include "random.asm"

Main:
	call randomChuntey
	and 7
	call rndSoundFXGen
	call changeBorderColour
	call randomChuntey
	and 255
	call changeInkPaper
	call clearScreenRom
	call splashScreen
	call keyboardAnyKPress
	call wiggy
	call blp1
	call randomChuntey
	and 7
	call changeBorderColour
	call randomChuntey
	and 255
	call changeInkPaper
	call clearScreenRom
	call mainMenuScreen
	; call keyboardAnyKPress
	call wiggy
	call rndSoundFXGen
	call randomChuntey
	and 7
	call changeBorderColour
	call randomChuntey
	and 255
	call changeInkPaper
	call clearScreenRom
	call gameMenuScreen
	call keyboardAnyKPress
	call rndSoundFXGen
	call randomChuntey
	and 7
	call changeBorderColour
	call randomChuntey
	and 255
	call changeInkPaper
	call clearScreenRom
	call aboutMenuScreen
	call keyboardAnyKPress
	call wiggy
	call rndSoundFXGen
	call randomChuntey
	and 7
	call changeBorderColour
	call randomChuntey
	and 255
	call changeInkPaper
	call clearScreenRom
	call soundMenuScreen
	call keyboardAnyKPress
	call wiggy
	call rndSoundFXGen
	call randomChuntey
	and 7
	call changeBorderColour
	call randomChuntey
	and 255
	call changeInkPaper
	call clearScreenRom
	call controlsMenuScreen
	call keyboardAnyKPress
	call rndSoundFXGen
	call randomChuntey
	and 7
	call changeBorderColour
	call randomChuntey
	and 255
	call changeInkPaper
	call clearScreenRom
	call helpMenuScreen
	call keyboardAnyKPress
	call wiggy
	call rndSoundFXGen
	call randomChuntey
	and 7
	call changeBorderColour
	call randomChuntey
	and 255
	call changeInkPaper
	call clearScreenRom
	call attractScreen
	call keyboardAnyKPress
	call wiggy
	call rndSoundFXGen
	call randomChuntey
	and 7
	call changeBorderColour
	call clearScreenRom
	call quitMenuScreen
	call keyboardAnyKPress
	call rndSoundFXGen
	call randomChuntey
	and 7
	call changeBorderColour
	call clearScreenRom
	call highScoreMenu	
	ld (51000),a
	jp Main
	ret
end Main
this is the mainmenu.asm - where the information about the main menu screen lives

Code: Select all

include "test.asm"
include "helpmenu.asm"
include "controlsmenu.asm"
include "gamemenu.asm"
include "soundmenu.asm"
include "aboutmenu.asm"
include "quitmenu.asm"
include "highscoremenu.asm"
	
mainMenuScreen:
	ld a, 2
	call 5633
	ld de, mainMenuString
	ld bc, eostr2-mainMenuString
	call 8252
	call keyboardTest1234
	ret

mainMenuString: defb 22,2,8,"Main Menu screen."
		defb 13,"1:MENU 1"
		defb 13,"2:MENU 2"
		defb 13,"3:MENU 3"
		defb 13,"4:MENU 4"
		defb 13,"5:MENU 5"
		defb 13,"6:MENU 6"
		defb 13,"7:MENU 7"
eostr2: equ $
this is the keyboard.asm file. Where all the keyboard input subroutines live.
as a sanity check I did a direct copy paste from the blog, and just replace the subroutine jumps to my program menus. (keyboardTest1234)..

Code: Select all

keyboardAnyKPress:
		ld hl,23560     ; LAST K system variable.
		ld (hl),0       ; put null value there

_loop:
		ld a,(hl)       ; new value of LAST K.
		cp 0            ; is it still zero?
		jr z,_loop    ; yes, so no key pressed.
		ret             ; key was pressed.

keyboardTest1234:
       ld bc,63486         ; keyboard row 1-5/joystick port 2.
       in a,(c)            ; see what keys are pressed.
       rra                 ; outermost bit = key 1.
       push af             ; remember the value.
       call nc,aboutMenuScreen         ; it's being pressed, move left.
       pop af              ; restore accumulator.
       rra                 ; next bit along (value 2) = key 2.
       push af             ; remember the value.
       call nc,gameMenuScreen         ; being pressed, so move right.
       pop af              ; restore accumulator.
       rra                 ; next bit (value 4) = key 3.
       push af             ; remember the value.
       call nc,soundMenuScreen         ; being pressed, so move down.
       pop af              ; restore accumulator.
       rra                 ; next bit (value 8) reads key 4.
       call nc,controlsMenuScreen         ; it's being pressed, move up.
       ret
       
		
keyboardTest12345:
	ld bc,63486	; keyboard row 1-5/joystick p2
	in a,(c)	; see what keys are pressed
	rra		; outermost bit = key 1
	push af		; remember the value
	call nc,aboutMenuScreen	; its being pressed - load about menu
	pop af		; restore accumulator
	rra		; next bit along (value2) = key 2
	push af		; remember the value
	call nc,gameMenuScreen 	; its being pressed - load game menu
	pop af		; restore accumulator
	rra		; next bit along (value4) = key 3
	push af		; remember the value
	call nc,soundMenuScreen	; its being pressed - load sound menu
	pop af		; restore accumulator
	rra		; next bit along (value8) = key 4
	push af		; remember the value
	call nc,controlsMenuScreen ; its being pressed - load control main
	pop af		; restore accumulator
	rra		; next bit along (value16) = key 5
	push af		; remember the value
	call nc,helpMenuScreen ; its being pressed - load help menu
	ret

when keyboardTest12345 is called none of the keys respond...

have the menu screen set a memory location to hold the subroutines in order like.

CHOICE1, CHOICE2, CHOICE3, CHOICE4, CHOICE5

then calls the keyboard input subroutine,

the subroutine looks at memory location X, then if key 1 is pressed, call subroutine from memory location[1]

the subroutine looks at memory location X, then if key 2 is pressed, call subroutine from memory location[2]

the subroutine looks at memory location X, then if key 3 is pressed, call subroutine from memory location[3]

the subroutine looks at memory location X, then if key 4 is pressed, call subroutine from memory location[4]

the subroutine looks at memory location X, then if key 5 is pressed, call subroutine from memory location[5]

That way I could have menu key input as a subroutine, and just pass the subroutines for the calls to the memory location for each menu page. Making things a lot more tidy if you see what I mean.

I think these would be described as 'jump tables'

Another weird issue I have been having is trying to get fuse to load the outlet microdrives from the archive. There are some nice programs contained in this magazine but most of the issues are distributed as microdrive only. is there a way I can load these into fuse?

A fair question is ... why bother searching the archives for 'skillz', well using my potato logic mostly derived from Dragonlance novels: I equate the archive to being a similar situation with finding the ancient tombs + Fistandantilus spell books. But saying 'nah bro.. who needs that..' :lol:

Just browsing I notice there are routines for screen wipes, scrolls and other interesting effects that would make my projects look better. my plan was to scour the archive for every useful assembly routine/technique and compile them into a wiki. If the 'skills' were arranged in modular form it would be pretty useful and furthermore could only help me learn.

The plan was to go from this..
Image
to this...
Image

with Assembly gains :lol:
Any tips to good assembly routines in the archives would be appreciated.
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Crap 0.1 first assembly project

Post by Nomad »

As an addition to todays progress report, now the project code is starting to get quite large, and having multiple source files. Even with lots of comments and my wibble in this development log even I am starting to find it difficult to keep track of what such and such subroutine does in the program and how it fits into the overall picture.

I think the best idea is to use a diagram tool to make it more visual, Dia is pretty good for this. And anyone that did a computer science course last century will be well acquainted with flowcharts. :lol:

So to help documentation - and for future reuse this is essential for comprehension and quickly understanding if the code cam be used or not in new projects. Each subroutine is going to get its own flow chart detailing its intended use, what it calls, what it writes, what it reads, code execution.

It might slow me down a bit going back through the code but I think its going to pay dividends later on. Especially as I want to reuse as much of the code as possible in future projects.

kinda like this..

Image
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 »

Seven.FFF wrote: Thu Jan 11, 2018 11:18 pm Works for me Jason, but it does need a proc/endp inside the rept/endm, despite what the doumentation says. It that respect it works the same way as Zeus.
I was referring to the LOCAL directive, not the auto local mode.
I've still not seen any way of making it work in context.
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: Fri Jan 12, 2018 7:59 am As an addition to todays progress report, now the project code is starting to get quite large, and having multiple source files. Even with lots of comments and my wibble in this development log even I am starting to find it difficult to keep track of what such and such subroutine does in the program and how it fits into the overall picture.
To each his own, but I’ve never been partial to multi-source projects. All of mine are single-source (aside from inserting large data files such as fonts, some graphics, etc.). The only place I tend to combine multiple sources is the loader. If you use comments correctly, and your text editor has good search options, I find it much easier to keep track of things when everything is in a single file.

Versioning also becomes much easier.

Your milage may vary, obviously.
Last edited by Ast A. Moore on Fri Jan 12, 2018 10:38 am, edited 1 time in total.
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.
Post Reply