• Please review our updated Terms and Rules here

Four-voice polyphonic music on my S-100 Z80 system circa 1981-1982

Well, you can save another 4T by the following;

XOR A ; 4T - Used to hold the DAC output. Start off at 0. LD H,msb(WAVETBL) ; 7T - This table should be page aligned. LD L,D ; 4T - Voice 3 Integer byte. ADD A,(HL) ; 7T - Index wave table for Voice 3 Integer byte.

to

; XOR A ; Eliminate this line. LD H,msb(WAVETBL) ; 7T - This table should be page aligned. LD L,D ; 4T - Voice 3 Integer byte. LD A,(HL) ; 7T - Index wave table for Voice 3 Integer byte.

Since that will do the same, will clear the carry ( at the next add, not that it matters ) and will bypass any pre-existing state in A.
 
Last edited:
Done. And the spreadsheet and source updated as well.

Always good to have a fresh pair of eyes!

Dave
 
Last edited:
Done. And the spreadsheet and source updated as well.

Always good to have a fresh pair of eyes!

Dave

Also I noted you used the undocumented instruction as; LD (IX+IYH),A

Which I'd normally assume to be LD IYH,A being the extended version of LD H,A as you constructed with the macro ( and the same with L etc in other locations ).

I was curious as to the format of the instruction - Which assembler accepts (IX+IYH) as IYH?
 
Ah, that is not an undocumented instruction but a documented one!

It is the standard instruction LD (IX+n),A and I have defined a symbol IYH to be an offset from IX pointing to a byte of RAM I am using.

This was the purpose of the USEUNDOC symbol.

If set, the macros would use the undocumented Z80 opcode bytes.

If clear, the macros would only use documented instructions to 'fake' the undocumented ones (albeit with a time penelty).

If you look further down the source, you will see where I have defined IYH and IYL (also within a conditional).

I was not sure whether the asm80 emulator would actually simulate the undocumented Z80 opcodes correctly. Since I already had these macros from another job, I copied them in by default and used them in my code.

Fortunately, the asm80 emulator does work OK. I checked the documentation, but it makes absolutely no mention at all of the undocumented Z80 instructions.

I hope that clears your question up?

Dave
 
Last edited:
I have done a bit more code tidying up (no more speed optimisations have come to mind though).

I have also added the "Star Spangled Banner" tune from the Byte magazine article. Only the data bytes as of yet - no comments.

I just need to research the TEMPO value mathematics now a bit...

Dave
 
Ah, that is not an undocumented instruction but a documented one!

It is the standard instruction LD (IX+n),A and I have defined a symbol IYH to be an offset from IX pointing to a byte of RAM I am using.

This was the purpose of the USEUNDOC symbol.

If set, the macros would use the undocumented Z80 opcode bytes.

If clear, the macros would only use documented instructions to 'fake' the undocumented ones (albeit with a time penelty).

If you look further down the source, you will see where I have defined IYH and IYL (also within a conditional).

I was not sure whether the asm80 emulator would actually simulate the undocumented Z80 opcodes correctly. Since I already had these macros from another job, I copied them in by default and used them in my code.

Fortunately, the asm80 emulator does work OK. I checked the documentation, but it makes absolutely no mention at all of the undocumented Z80 instructions.

I hope that clears your question up?

Dave

Yep, that makes sense... If I had read deeper I would have understood ! :) Now I get it.

Your source was a great example to me of why conditional code *and* macro's are needed in assembly. It's convinced me to simplify how I was planning on doing it and aim at something simpler in my own assembler implementation. Which was a good idea, because as I started looking into this, I realized I needed a way to handle memory in a way that could extent beyond the TPA without rewriting my entire code base once I got to the point of storing macros in RAM and started to allow things like "nesting" meaning I need to be able to open multiple independent file handles in memory and switch DMA locations in and out without repeating the same 128 byte DMA block throughout memory. ( ASM80 doesn't support nesting, and if I combine the assembler and linker, it makes sense to support some degree of nesting to allow automatic resolution of any assembly dependencies. ).

Funny thing is I never used either when I was an assembly programmer. Even in retrospect, the need simply never manifested with the kinds of programming I was doing at the time. So I've been struggling with better understanding their use so I can implement them correctly.

Following your code has been super helpful :) Thank you.

And of course, I really want to hear the recordings you make of the music playing :)
 
Back
Top