Jump to content

Photo

MADS Knowledge-Base


273 replies to this topic

#1 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • 13,670 posts
  • Location:United Kingdom

Posted Tue Mar 29, 2011 6:00 AM

MADS now being my assembler of choice, I'm keen to master some of its more advanced features. Rough English translation of the Polish docs to hand, I set about using "OPT ?+" to make labels prefixed with "?" behave as local rather than temporary labels. I assumed this would mean I could re-use "?1", "?2", etc, as loop labels without having to set up local ranges. Unfortunately, "OPT ?+" at the top of my source file had disastrous effects on all my struct and enum definitions. MADS suddenly seemed to to think they were all multiply defined, and they weren't. I'm not sure if there's a bug in that switch, or not.

I know there are some pretty good examples in the MADS distro, but all the comments are in Polish. Before I try and run them all through Google Translate, I thought some shared knowledge on MADS's more esoteric features and constructs would be pretty cool. I've posted examples of the very cool "structs" in the GUI thread, but I'm sure there are many other compiler features which would make life easier if only I knew how to use them.

Maybe we could add to this topic as we discover new stuff...

#2 JAC! OFFLINE  

JAC!

    Stargunner

  • 1,701 posts
  • Always looking for GFX and MSX for my demos
  • Location:Lebach, Germany

Posted Wed Mar 30, 2011 6:24 AM

Hi Jon,

I'd recommend not to use this generic approache to local labels. The problem with locality is that you have to speciy "how local" the label should be. The ".PROC/.ENDP" of MADS is the perfit fit to express how local something is. Everthing within this block is local. And the very cool thing: It is still globally accssible.

.PROC main

mva #1 routine.counter
jsr routine

.PROC routine
.var counter .byte

loop lda counter
sta colbk
dec counter

rts

.ENDP

.ENDPRO

#3 JAC! OFFLINE  

JAC!

    Stargunner

  • 1,701 posts
  • Always looking for GFX and MSX for my demos
  • Location:Lebach, Germany

Posted Wed Mar 30, 2011 6:24 AM

Hi Jon,

I'd recommend not to use this generic approache to local labels. The problem with locality is that you have to speciy "how local" the label should be. That is the case in many compilers. They try some heuristic approach or implicit logic ("Everything until the next XYZ statement). The ".PROC/.ENDP" of MADS is the perfect fit to express how local something is. Everthing within this block is local. Most of my procs only have one "loop" or some "loopx/loopy" labels.

And the very cool thing: It is still globally accssible from every other location in the source using qualified access.

.PROC main

loop mva #2 routine.counter
     jsr routine
     jmp loop ;Main loop


.PROC routine
.var counter .byte

loop lda counter
     sta colbk
     dec counter
     bne loop
     rts

.ENDP

.ENDP

Edited by JAC!, Wed Mar 30, 2011 6:28 AM.


#4 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • Topic Starter
  • 13,670 posts
  • Location:United Kingdom

Posted Wed Mar 30, 2011 9:33 AM

Thanks Jac! That was even better the second time. :)

Seriously, I appreciate your getting the ball rolling here.

#5 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • Topic Starter
  • 13,670 posts
  • Location:United Kingdom

Posted Wed Mar 30, 2011 11:13 AM

An elementary question:

How do you set the location counter separately from the program counter (i.e. in order to compile code which will be relocated to the shadow RAM at runtime)?

Secondly, I see several potentially useful references to relocation and built-in "virtual" and "hardware" memory bank handling. Unfortunately the Google translated docs are impenetrable to my tired eyes. :)

#6 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • Topic Starter
  • 13,670 posts
  • Location:United Kingdom

Posted Wed Mar 30, 2011 11:32 AM

OK: First one answered:

ORG adr, adr2

assembles at adr, but sets binary file header to adr2.

#7 tebe OFFLINE  

tebe

    Dragonstomper

  • 738 posts
  • Location:Poland

Posted Fri Apr 15, 2011 12:54 AM

.proc label , new_org
.endp


.local label , new_org
.endl

.proc zp_routine,$80    ; backup original ORG, switch assembles ORG to $80
 ;  code
.endp                   ; restore original ORG ADD PROC (LOCAL) LENGTH and set new assembles ORG

Edited by tebe, Fri Apr 15, 2011 12:56 AM.


#8 JAC! OFFLINE  

JAC!

    Stargunner

  • 1,701 posts
  • Always looking for GFX and MSX for my demos
  • Location:Lebach, Germany

Posted Fri Apr 15, 2011 3:00 AM

This is cool! Available as of which MADS version?

#9 JAC! OFFLINE  

JAC!

    Stargunner

  • 1,701 posts
  • Always looking for GFX and MSX for my demos
  • Location:Lebach, Germany

Posted Wed May 4, 2011 1:18 AM

This is cool! Available as of which MADS version?

#10 tebe OFFLINE  

tebe

    Dragonstomper

  • 738 posts
  • Location:Poland

Posted Thu May 5, 2011 12:56 AM

this is old feature

#11 JAC! OFFLINE  

JAC!

    Stargunner

  • 1,701 posts
  • Always looking for GFX and MSX for my demos
  • Location:Lebach, Germany

Posted Wed Jun 15, 2011 10:23 AM

I'm trying to create an 8k ROM cardidge consisting of two 4k banks with MADS 1.9.2 build 21 (21 Jan 11).

opt h-f+

.segdef bank0 $f000 $1000 RW 0
.segdef bank1 $f000 $1000 RW 1

.segment bank0		;Main part

org $f000
.proc any
.endp
.proc chunky_zp_template, chunky_zp;  chunky_zp=$A0 <= first error
.endp
.endseg; <= second error

When I use the ",chunky_zp" addition to relocate the procedure to $A0, i get "Segment BANK0 error at $00A0".
When I remove the addition, I get "Can't fill from higher to lower memory location".

Any ideas? It's the first time I'm using segments, and I'm not sure about the documentation.

#12 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • Topic Starter
  • 13,670 posts
  • Location:United Kingdom

Posted Fri Jun 17, 2011 12:29 AM

Can't really suggest anything since I don't know what the .segdef and .segment statements do. Could you explain these? I'm building a banked cart with MADS too, and I figure I should be using them. Once I understand them, I'll have better insight into your problem. I'm struggling with the Google translated docs at the moment.




#13 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • Topic Starter
  • 13,670 posts
  • Location:United Kingdom

Posted Fri Jun 17, 2011 4:05 AM

In the meantime, here's a new translation of the MADS docs for version 1.9.2, covering .SEGDEF and other features not covered in the last translation I uploaded:

Attached File  MADS 1.9.2 English Documentation.txt   159.96KB   479 downloads

Edited by flashjazzcat, Fri Jun 17, 2011 4:07 AM.


#14 JAC! OFFLINE  

JAC!

    Stargunner

  • 1,701 posts
  • Always looking for GFX and MSX for my demos
  • Location:Lebach, Germany

Posted Fri Jun 17, 2011 5:45 AM

Compiling the example from the documentation results in an error and a warning "Memory segments overlap".
Interesting: Lost of new directies and support for illegal opcodes contained in 1.9.2!

#15 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • Topic Starter
  • 13,670 posts
  • Location:United Kingdom

Posted Fri Jun 17, 2011 9:29 AM

So - to be clear about .SEGDEF: in your code example, you're defining labels "bank0" and "bank1" as shorthand for the parameters which follow them (i.e. "$f0000 $1000 RW 0").

".PROC label, new_org" looks useful: I'd missed that before. I need an init bank to include code assembled at $2000, which is copied to the target region at runtime. This should do the job nicely.

I should really take the time to edit the translated manual and PDF it as I become more familiar with all the directives. It's a huge document, though. I'd appreciate any help from MADS experts who'd be willing to take the raw translation and tidy it up.

Edited by flashjazzcat, Fri Jun 17, 2011 9:31 AM.


#16 JAC! OFFLINE  

JAC!

    Stargunner

  • 1,701 posts
  • Always looking for GFX and MSX for my demos
  • Location:Lebach, Germany

Posted Fri Jun 17, 2011 10:21 AM

At least I found a way to create a banked ROM without ".SEGDEF" now ;-)
The trick is to disable fill mode before the next ORG statement.
This way you can have code at the same address origins.

;	Create a ROM with two 4K banks
	opt h-		;Disbale headers

	org $f000	;Set origin
	opt f+		;Enable ROM mode

	.proc bank1
	lda #2

	org $fffe	;Make sure bank is full
	.byte $12,$34
	.endp
	opt f-		;Disable ROM mode

	org $f000	;Set origin
	opt f+		;Enable ROM mode
	
	.proc bank2
	lda #2

	org $fffe	;Make sure bank is full
	.byte $56,$78
	.endp


#17 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • Topic Starter
  • 13,670 posts
  • Location:United Kingdom

Posted Fri Jun 17, 2011 10:46 AM

Heh... there seem to be many ways to break an egg here. I was using .ALIGN $C000, $FF at the end of each bank (actually, the fill will be six bytes short and have the cart header bytes at the end of each bank, similar to your example). What does ROM mode do, exactly?

Here is the inter-bank JMP/JSR mechanism as it stands:

ljsr .macro ; do a long JSR to a label in a different bank
	sta asave
	sty ysave
	stx xsave
	lda #= :1 ; get bank number of target label
	sta target_bank
?1	ldy #= ?1 ; get current bank
	lda #< :1
	ldx #> :1
	jsr :long_jump
	.endm
;

ljmp .macro ; do a long JMP to a label in a different bank
	sta asave
	sty ysave
	lda #= :1 ; get bank number of target label
	tay
	lda #$FF
	sta cart_banks,y ; switch in target bank
	lda #< :1
	sta jmp_vec
	lda #> :1
	sta jmp_vec+1
	lda asave
	ldy ysave
	jmp (jmp_vec)
	.endm

...

long_jump ; execute "far" subroutine (this code must reside in low RAM)
	sta jmp_vec
	stx jmp_vec+1
	tya ; push return bank on stack
	pha
	lda #> [return-1] ; push address of return routine on the stack
	pha
	lda #< [return-1]
	pha
	ldy target_bank ; get bank number
	lda #$FF
	sta cart_banks,y ; switch in the target bank
	lda asave
	ldy ysave
	ldx xsave
	jmp (jmp_vec) ; execute the routine
;

return ; handle return from banked routine
	sta asave
	sty ysave
	pla ; get return bank
	tay
	lda #$FF
	sta cart_banks,y ; switch in originating bank
	lda asave
	ldy ysave
	rts



#18 JAC! OFFLINE  

JAC!

    Stargunner

  • 1,701 posts
  • Always looking for GFX and MSX for my demos
  • Location:Lebach, Germany

Posted Sat Jun 18, 2011 4:49 AM

"OPT f+" fills all intermediate space between the first and the last byte with $FF (does not create COM segments in case of large ".ALIGN", ".DS" or "ORG" spacing) and makes sure that the ORG statements only have addresses in ascending order.

#19 snicklin OFFLINE  

snicklin

    River Patroller

  • 2,107 posts
  • Location:Australia

Posted Fri Jul 15, 2011 2:29 PM

Why don't you all post on here?

http://wiki.strotmann.de/wiki/

It may be easier to structure.

#20 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • Topic Starter
  • 13,670 posts
  • Location:United Kingdom

Posted Fri Aug 26, 2011 12:22 AM

I finally got around to putting the .PROC tags in the GUI source code last night following a massive re-write and the collapsible navigation pane in WUDSN is just astounding. Two amazing development tools.

#21 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • Topic Starter
  • 13,670 posts
  • Location:United Kingdom

Posted Tue Apr 10, 2012 1:19 PM

The .PROC wrappers don't seem to work if the source is for a relocatable SDX application. Slightly disappointing, but not a huge problem. Is this intentional?

#22 phaeron OFFLINE  

phaeron

    River Patroller

  • 2,534 posts
  • Location:USA

Posted Tue Apr 24, 2012 11:44 PM

Does anyone know how to re-enable the Source: markers in the listing file? These used to be emitted with MADS 1.9.0, but they are missing with 1.9.3 and this breaks Altirra's source-level debugging. :(

#23 JAC! OFFLINE  

JAC!

    Stargunner

  • 1,701 posts
  • Always looking for GFX and MSX for my demos
  • Location:Lebach, Germany

Posted Wed Apr 25, 2012 7:02 AM

I assume you mean the include file references. At least 1.9.2 and 1.9.3 work as expected for me:
I use "-p" in the compiler options and "OPT l+" in the source. The resulting .lst file contains:


mads 1.9.3 build 49 (31 Jul 11)
2 opt l+
3 org $2000
4
5 icl "Test-include.asm"
Source: C:\Users\D025328\Documents\Eclipse\runtime-WUDSN-IDE\Test\Test-include.asm
1 FFFF> 2000-2008> AD 0B + loop lda $d40b
2 2003 8D 1A D0 sta $d01a
3 2006 4C 00 20 jmp loop
6

#24 flashjazzcat ONLINE  

flashjazzcat

    Quadrunner

  • Topic Starter
  • 13,670 posts
  • Location:United Kingdom

Posted Wed Apr 25, 2012 12:20 PM

Here's one I just discovered after an hour trying to understand the translated manual:

ptr1  equ $80
ptr2  equ $82

addw .macro " "
.if :3 = '#'
  lda ptr1
  clc
  adc #< :4
  sta ptr1
  lda ptr1+1
  adc #> :4
  sta ptr1+1
.else
  lda ptr1
  clc
  adc :4
  sta ptr1
  lda ptr1+1
  adc :4+1
  sta ptr1+1
.endif
.endm

;
org $4000

addw ptr1 #200
addw ptr1 ptr2


The pair of double quotes after the macro name cause the parameters to be split into addressing mode and argument. So, the first call yields " ", PTR1, "#", 200, while the second yields " ", PTR1, " ", PTR2. Thus the macro can check the addressing mode and react accordingly. The first call will add 200 to PTR1, while the second will add PTR1 and PTR2 together. This is useful, because I want to make my 16 bit signed integer macros behave this way.

NOTE: I'm aware MADS has inbuilt macros for performing unsigned 16-bit arithmetic - the above is just an example.

Edited by flashjazzcat, Wed Apr 25, 2012 12:23 PM.


#25 phaeron OFFLINE  

phaeron

    River Patroller

  • 2,534 posts
  • Location:USA

Posted Wed Apr 25, 2012 11:15 PM

I assume you mean the include file references. At least 1.9.2 and 1.9.3 work as expected for me:
I use "-p" in the compiler options and "OPT l+" in the source. The resulting .lst file contains:


Figured it out -- the Source: lines disappear if MADS 1.9.3 is fed a relative path. "mads -l foo.s" and "mads -l d:\test\foo.s" generate source file indicators, but "mads -l test\foo.s" and "mads -l .\foo.s" don't. Now I just need to figure out how to derive absolute paths in NMAKE.




0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users