Page 1 of 4
Macro help?
Posted: Mon Jan 16, 2017 3:44 pm
by floobydust
I'm looking at the CBM 1581 Source code. There's a Macro used that precedes every access to the WD1772 Status register. It's a simple entry but without knowing what all of the characters mean, I'm having difficulty deciphering how it works. In use, it may or may not insert a NOP before accessing the WD1772. I've tried using it with the WDC Tools package... no error is produced but it doesn't function either, so I'm missing some golden rule for whatever package was originally used to assembler the 1581 source code.
Code: Select all
messg "mfmmacro"
subttl "mfmmacro"
page
WDTEST macro
if <*!.$03>
nop
endif
endm
Any ideas on this would be appreciated.
Re: Macro help?
Posted: Mon Jan 16, 2017 4:07 pm
by BigDumbDinosaur
Code: Select all
messg "mfmmacro"
subttl "mfmmacro"
page
WDTEST macro
if <*!.$03>
nop
endif
endm
That appears to be part of the macro language of Commodore's DEVPAK 128 assembler. While I used DEVPAK a lot in the latter 1980s and early 1990s, I have not looked at it since c. 1993 and no longer recall the details. I do recall that a notation such as
$03 referred to a local label in the source code and
* referred to the program counter. As for
!., dunno if that is symbology for "not equal to" or what.
—————————————————————————
EDIT: Shows you how much I've forgotten about DEVPAK.

Local labels are written with a trailing dollars sign, like a BASIC string variable. So
$03 in the above example would be a hex value.
Re: Macro help?
Posted: Mon Jan 16, 2017 4:30 pm
by John West
The same expression appears in the source for the 1571 firmware, but this time with comments:
Code: Select all
wdtest .macro
.ife <*!.$03 ; lower two bits cannot be zero
nop ; fill address error
.endif
.endm
My guess is < takes the low byte of *, the current address. !. is used to and, and $03 has the bottom two bits set. ife assembles the nop only if that expression equals zero.
The macro is used before every access of the WD1772 registers. Why it doesn't like certain instruction alignments, I don't know.
Re: Macro help?
Posted: Mon Jan 16, 2017 5:06 pm
by Dr Jefyll
Why it doesn't like certain instruction alignments, I don't know.
I think John's on the right track. I believe the NOP is for alignment. (It's not a timing thing, for instance.) I suggest you look at the 1572 schematic and see if there are any clues.
I'm half guessing, but here's an example of the sort of thing you might find. There's a hardware trick I've used where A0 (the LS address line) is used as an output bit. You do your memory-mapped I/O, and of course the alignment of the I/O instruction (alignment which you explicitly control) determines the state of A0 when the instruction is fetched. Hardware captures A0 during the instruction fetch and uses it to control whatever. It's a rather obscure but powerful technique. And it's not limited to A0; you can control two or more of the LS address lines as long as you're willing to do the necessary alignment.
Re: Macro help?
Posted: Mon Jan 16, 2017 5:23 pm
by floobydust
Thanks to both of for the insight. It is pretty strange. The WD1772 is used in polled I/O mode apparently in the 1581 as the IRQ, DRQ lines are left un-connected, so it is gong to be timing dependent on accesses. Maybe It's a hardware anomaly in the way the designed it? Hoping I can figure out how to manage it in WDC Tools.
Re: Macro help?
Posted: Mon Jan 16, 2017 5:43 pm
by Dr Jefyll
Maybe I'm mistaken to say it's not a timing thing. Polled I/O mode implies that, before an instruction that reads or writes data, there'll be a loop that reads Status and conditionally branches back, never proceeding until the chip is ready for a transfer. You don't want that backward branch to cross a page boundary because it'll add one cycle to the wait loop.
You said the macro precedes every access to the WD1772 Status register, and that's puzzling since not all reads of Status are time-sensitive. Those before a data transfer certainly are, but those in preparation for mundane stuff like a head seek aren't.
It's worth remembering some of the clues may be misleading. Perhaps the person who put in the macros used more than were necessary. And as for page crossings, you'd expect the macro to look for an address ending in $FF, not $03 -- but the latter would still work.
Re: Macro help?
Posted: Mon Jan 16, 2017 6:08 pm
by floobydust
Thanks Jeff, missed your first post before I replied. It's still not clear what the macro is doing. I did modify the 1581 source code and got it assemble with the WDC Tools package, but had to nix the macro as it shows an unknown expression pointing to the < character. I basically inserted the NOP based on the actual ROM contents. Even looking at what the actual address is when the 1772 status register is read is not obvious (at least not to me yet). Either way, if you change the code, the NOPs might be placed incorrectly. I did some testing and if you insert a NOP before every SR read, the drive doesn't work. So there is some strange requirement for the macro to make a determination to insert the NOP or leave it out.
Re: Macro help?
Posted: Mon Jan 16, 2017 6:35 pm
by Dr Jefyll
Looks like the hardware trick I mentioned is not present. It would need to use SYNC to qualify the clock of the flipflop that captures A0, and according to the 1581 schematic I found
here SYNC is a no-connect. (And FWIW the SO\ pin attaches only to a pullup resistor.)
I did some testing and if you insert a NOP before every SR read, the drive doesn't work.
Interesting puzzle! How many SR reads are there? Can you get away with defeating the macro in cases where the SR read does NOT precede a data transfer? (Just thinking out loud. There are
lots of different experiments you may wish to try.)
Re: Macro help?
Posted: Mon Jan 16, 2017 7:59 pm
by Hobbit1972
It would be good to know the full source - is it online somewhere?
Re: Macro help?
Posted: Mon Jan 16, 2017 8:18 pm
by floobydust
Yes, I found the source at:
http://www.zimmers.net/anonftp/pub/cbm/ ... index.html
I had to make some large changes to a few files (IODEF, RAM, EQUATE) and had to do a handful of minor edits for some of the auto label bits scattered in lots of different files. Basically I have a version of the code that assembles/links with WDC tools and makes a prefect replica of the ROM image. However, trying to make any changes gets ugly fast... as the WDTEST macro is apparently required but it's logic isn't clear on how it decides when to add the NOP.
Replying to Jeff, there's about 27 uses of the WDTEST macro... all precede the loading of the status register as:
Code: Select all
WDTEST ; chk address
cmd70 lda wdstat
and #3
lsr a
bcc v1
The code above gets the status register, masks off the lower 2 bits, which are DRQ and BUSY. By shifting the first bit into the carry flag (which is the BUSY flag) it's checking to see if the 1772 is busy and branching if it is. The WDTEST macro is adding the NOP before the read of the status register. In some cases there is a command sent to the 1772 before reading the status register. The core routines that access the 1772 are in MROUT and MSUB. Here's a longer code snippet:
Code: Select all
ldx #32
WDTEST ; chk address
cmd7 lda wdstat
and #3
lsr a
v6 bcc v1
beq cmd7
lda #$4e
sta wddat ; give him the $4E data
dex
bne cmd7
main7 ldx #12
WDTEST ; chk address
cmd70 lda wdstat
and #3
lsr a
bcc v1
beq cmd70
lda #0
sta wddat
dex
bne cmd70
ldx #3
WDTEST ; chk address
cmd71 lda wdstat
and #3
lsr a
v1 bcc v2
beq cmd71
Re: Macro help?
Posted: Mon Jan 16, 2017 8:41 pm
by John West
1581 source:
ftp://www.zimmers.net/pub/cbm/firmware/ ... index.html
1581 service manual (schematics at the end of the pdf):
ftp://www.zimmers.net/pub/cbm/schematic ... index.html
1571 source with that helpful comment:
ftp://www.zimmers.net/pub/cbm/firmware/ ... index.html
WD1772 datasheet:
http://dev-docs.atariforge.org/files/WD1772.pdf
When I said that every access of the WD1772 registers was preceded with this macro, I hadn't checked all of them. And it turns out that many of them don't. For example, there are two writes to WDCMD in msub.src. One has the macro, the other doesn't.
Every access of WDSTAT uses it. It can't be for timing, as some of these reads are in loops, with the macro before the start of the loop. Confusingly WDCMD and WDSTAT are the same address. You get WDSTAT when you read, WDCMD when you write.
No access of WDTRK, WDSEC, or WDDAT uses it.
I can't see anything unusual in the schematic. Nothing that would suggest any dependence on the address of instructions.
Re: Macro help?
Posted: Mon Jan 16, 2017 10:41 pm
by floobydust
Well, I found a listing file for 1581 DOS, apparently during the initial development, as it shows 150 errors and not complete, albeit for the same code level:
ftp://ftp.zimmers.net/pub/cbm/src/drives/serlib.zip
According to the listing, it's using: "(c)1987 CBM Commodore 6502ASM B0.0" as the assembler. The macro definition is slightly changed as:
WDTEST .macro
.ife <*!.$03
nop
.endif
.endm
During assembly, it seems to test to see if the instruction is going to start on an address where either bits 0 or 1 active. If not, the test results in a zero and it adds the NOP to ensure that the start address has either or both bits active as part of the address. The burning question now is why??
I also included a snippet of the assembly listing:
Code: Select all
C428 11765+ WDTEST ; chk address
=0000 11766A .ife <*!.$03
C428 EA 11767A nop
11768A .endif
C429 AD 6000 11769 cmd7n lda wdstat
C42C 29 03 11770 and #3
C42E 4A 11771 lsr a
C42F 90 3E 11772 bcc v2
C431 F0 F6 11773 beq cmd7n
11774
C433 A9 FE 11775 lda #$fe ; id address mark
C435 8D 6003 11776 sta wddat
11777
11778
C438 11779+ WDTEST ; chk address
=0000 11780A .ife <*!.$03
C438 EA 11781A nop
11782A .endif
C439 AD 6000 11783 cmd7f lda wdstat
C43C 29 03 11784 and #3
C43E 4A 11785 lsr a
C43F 90 2E 11786 bcc v2
C441 F0 F6 11787 beq cmd7f
11788
C443 AD 6001 11789 lda wdtrk ; give him the track
C446 8D 6003 11790 sta wddat
11791
C449 11792+ WDTEST ; chk address
=0001 11793A .ife <*!.$03
11794A nop
11795A .endif
C449 AD 6000 11796 cmd7e lda wdstat
Now that the concept is known (pretty much by accident on my part), how does one use WDC Tools macro capabilities to implement it? BTW - I'm terrible at macros, yet another reason I never use them.
Re: Macro help?
Posted: Mon Jan 16, 2017 11:20 pm
by floobydust
I think I have the macro working properly now as:
Code: Select all
WDTEST .macro
.if *&$03=0
nop
.endif
.endm
I do get some odd entries in the lower status window of TIDE which I didn't get before that make no sense, basically calling out every include file in the assembly, some with garbage characters, but TIDE isn't exactly a great front end.
I'm going to try and do some additional testing with some changed code and see how it works out. Thanks to everyone for taking the time and sharing some knowledge and ideas. I still don't know the "why" of doing this however.
Re: Macro help?
Posted: Tue Jan 17, 2017 4:25 am
by floobydust
So, all seems good. I made some changes to the code:
- integrated the patch file updates into the core routines so no need to include it.
- integrated the -02 ROM updates into the core routines
- re-wrote the MSUB1 routine to use a simple loop instead of twice 256 times to move track cache to/from buffers (saves over 2KB)
- removed the page boundary equates which takes several voids in the ROM code
Code size now is at 20KB. Have done some testing and everything on the drive seems to work fine. Have run some of my ancient C64 Macro Assembler code that runs through 30+ source files and takes ~12 minutes to assemble. Drive appears to perform the same as a stock drive. Having the working Macro makes it easier to modify the code. With the -02 ROM upgrade the initial ROM checksum was disabled, but there is still a ROM test utility that should fail if run, haven't bothered to try that yet. Still, it shouldn't be difficult to get the initial ROM checksum working again.
I still need to clean up a few pieces of code... but if anyone is interested to play around with it, you're welcome to it. As the HW design is quite simple, it should be easy to build a drive up provided you can get an 8520A (or possibly a 6526) and the WD1772 chip. Everything else is readily available.
Re: Macro help?
Posted: Tue Jan 17, 2017 7:04 am
by BigDumbDinosaur
I still need to clean up a few pieces of code... but if anyone is interested to play around with it, you're welcome to it. As the HW design is quite simple, it should be easy to build a drive up provided you can get an 8520A (or possibly a 6526) and the WD1772 chip. Everything else is readily available.
The only significant architectural difference between the 6526 and the 65C22 is the former has a time-of-day clock driven by the mains frequency. The 6526 was used in the Commodore 1571 and 1581 floppy drives so CP/M files could be time-stamped. If you can live without that feature I suppose the 65C22 would be usable.