utz82 / PC1403-Music-Routines

1-bit music routines for the Sharp PC-1403 Pocket Computer
Creative Commons Zero v1.0 Universal
8 stars 2 forks source link

Padding question #1

Closed genivia-inc closed 2 years ago

genivia-inc commented 3 years ago

Thanks for publishing the source code and all the work that you put into this! Wow!

I have a question about this line in main.asm:

    ;.ds 6,0            ;padding, so drum sounds are w/in page limits

In what part of the code is the 256-byte page boundary applied to? The drumTable is not padded to align to a page boundary. The plist music data is not aligned to a page.

I am porting this to the SHARP PC-1350. I rewrote the asm files to generate binaries with the AS61860 assembler https://shop-pdp.net/ashtml/asmlnk.htm which is a bit more powerful so it's easier to retarget the code for other SHARP pocket computers, but PC-1350 and PC-1403(H) for now.

I'd like to add a .bndry check to the code to enforce this page alignment which helps to avoid trouble when retargeting.

utz82 commented 3 years ago

My apologies, I can't remember. It's been ages since I touched this code. My guess, considering the wording of that comment, would be that this isn't about alignment, but rather about the drum data being on the same page as the drum code, or at least not spread out across pages. Now why exactly this is necessary, is another question.

While we're at it, I should mention one thing. There is actually a better method for making sound on Sharp PCs, which I didn't know back then, and never got around to implement later on. The idea is to calculate the output state of a rectangle wave with a duty below ~25% for a number of channels, then OR the outputs together. This gets rid of the parasite tone introduced by the Sharp's fixed-frequency tone generator. A detailed description of an implementation of this method on ZX Spectrum is available here:

http://randomflux.info/1bit/viewtopic.php?id=57

genivia-inc commented 3 years ago

I understand that's been a while, no problem! Just curious.

I think I figured it out and corrected a problem at the same time. The page boundary is located at drumTable. The padding ensures this. This table has three offsets that are the low bytes of the address into the drum1, drum2, and drum3. Because X is loaded with this address (high byte from sdata and low byte from the drumTable, the IXL op should load the first drumX value. This op is a pre-increment load. So the drumTable entries should be decremented by one, like so:

    .rept 9             ;padding: drumTable must be aligned to a page
    .db 0
    .endm

drumTable:              ;located at page-aligned address 0xHH00

    .db 0x02,0x1c,0x65      ;low byte indices-1 into drum1/2/3 tables 0xHH03,0xHH1d,0xHH66

drum1:                  ;located at 0xHH03
    .db 1,4,3,8,6,4,9,8,8,8
    .db 16,16,16,32,32,32,32
    .db 64,64,64,64,65
    .db 128,128,128,0

drum2:                  ;located at 0xHH1d
    .db 4,3,8,6,4,9,8,8,8
    .db 16,16,16,32,32,32,32,64,64,64
    .db 16,4,15,22,11,13,22,15,7
    .db 19,12,2,11,15,3,5,7,15,18
    .db 20,19,17,9,20,11,18,15,2,3
    .db 11,9,11,15,9,12,7,15,8,16
    .db 8,14,7,4,11,15,21,15,22,7
    .db 17,17,25,20,0

drum3:                  ;located at 0xHH66
    .db 5,2,4,1,5,8,2,3,8,7
    .db 5,3,5,8,4,8,6,6,1,7
    .db 7,4,2,7,5,8,6,8,8,5
    .db 3,3,7,2,3,3,4,6,5,8
    .db 5,8,5,5,1,5,3,4,3,7
    .db 6,3,1,8,6,1,6,2,2,1
    .db 6,6,3,6,8,7,3,1,8,7
    .db 4,2,1,4,1,255,255,0

sdata:

Note that I'm using AS61860 syntax here. I've rewritten the code for this assembler, updated xm2osk.pl for the AS61860 syntax, added a target.h to retarget the ASM code to PC-1350 as well as PC-1403, streamlined the build process with a makefile, added ihx2bas (a quick bootloader with POKEs) and ihx2bin (for quick load with CLOAD M) tools in C source code, rather than requiring yet another external tool download, so it's all nicely self-contained. Only AS61860 and PocketTools are needed.

To test, I ran the player on my PC-1350 and it works. But the sound through the piezo is so-so. This means I can't be 100% sure it is OK. The looping and non-looping work, but I had to change a JP instruction to a JR because the padding would be off by one byte otherwise.

Let me know if you want the updates and additions. I will create a pull request with a new directory with the updates and additions located in osaka2/pc-1350 for your review. To build on PC-1403 just edit target.h:

.globl  BASE

; PC-1403(H)
; BASE = 0x80e8
; PC-1350 (load to 0x60e8-0x6bba)
BASE = 0x60e8

AS61860 supports many OS to build this excellent assembler and linker that supports many 8-bit CPUs, see https://shop-pdp.net/ashtml/asmlnk.htm . My ihx2bas.c and ihx2bin.c tools are very simple (and free BSD-3 open source).

genivia-inc commented 3 years ago

Wait a minute. Inspecting the code further reveals the first IXL loads the offset with a pre-increment, so the padding should be +1 after a page boundary for the drumTable and its offsets do not need to be adjusted:

    .rept 10            ;padding
    .db 0
    .endm

drumTable:              ;located at page-aligned address+1 0xHH01

    ;lobyte of address into drum1/2/3 tables, e.g. 0xHH03,0xHH1d,0xHH66
    .db 0x03,0x1d,0x66

This makes more sense. The padding 10 = 6 + 4 is then the same as before (ds 6,0) with 4 bytes of opcodes removed in the updated version.

utz82 commented 3 years ago

Excellent. I'd be more than happy to receive your pull request for this! Would be great if you could also update the readme accordingly. Feel free to add your own credits below the heading, too. If you wish, I could relicense the whole repo under BSD 3-clause, so as to not create a mess.

But the sound through the piezo is so-so.

Yes, this sound routine is meant to be used by attaching the cassette interface to an amplifier/hi-fi system. Here's how it should sound:

https://soundcloud.com/irrlicht-project/osaka-ii-test-sharp-pc-1403

I can't remember what type of speaker the Pocket PCs have. On an actual piezo this synthesis method will not work properly at all, since it relies on positioning the speaker diaphragm in an intermediate state between full expansion/retraction. On a miniaturized speaker it would work, though sound would still be somewhat questionable. The ORing method I described above on the other hand would work on a piezo. It would reduce the code size significantly as well. If only I had the time to implement it...

Btw are there any good options for emulation nowadays? Back in the day I used PockEmul, but that's closed source nowadays and the last version of the source I have doesn't even build on my system anymore. Besides, it wasn't very accurate either.

genivia-inc commented 3 years ago

Btw are there any good options for emulation nowadays? Back in the day I used PockEmul, but that's closed source nowadays and the last version of the source I have doesn't even build on my system anymore. Besides, it wasn't very accurate either.

I agree. I occasionally use PockEmul which includes a PC-1350 (for free). The latest PockEmul versions are pretty good and support more accurate "sound" (ahem, squeaks and beeps...) emulation.

Not sure if you've seen this emulated PC-1403 play music? https://pockemul.com/index.php/2020/12/23/pockemul-plays-music/#more-1426

I also wanted to install sharptool, a PC-1350 emulator that comes with several other utilities, but alas this requires X11 dev libraries for the GUI. I ran into issues installing X11 for some reason and have not gotten to the point to try to fix this. Don't know if that emulator produces accurate sound output. Rather than an emulator, I still use my expanded PC-1350 with CE-126P. I also have several other SHARP (1360,2500,1500A,1262,1440,1475,E500,E500S,G850VS).

FYI. Your project brings back some memories. I wrote some Z80 code mid 80s on a P2000T to record 1-bit sound with a simple cassette interface and play it back as 1-bit music. To my big surprise, Axel F recorded in 32KB memory sounded great on that machine.

genivia-inc commented 3 years ago

One more question. The beeper is set low with:

    lip OUTP    ;4
    anim 0      ;4
    outc

This also turns off the display (bit 0) on the PC-1350. I don't know if this is intentional?

To avoid turning off the display, keep bit 0 set:

    lip OUTP    ;4
    anim 1      ;4
    outc
utz82 commented 3 years ago

Ah, good to hear that PockEmul has sound emulation now. Sounds quite ok fwiw. I can see a bug though: In the emulation, the BUSY indicator flashes on percussion. As you can see from the hardware recording, that's incorrect: The main part of the display should flash, but not the indicators.

Regarding keeping the display bit set, I'm not entirely sure, but the most likely explanation is that I just didn't pay attention to this. In either way, I don't see how keeping the display bit on would cause any problems, so it's probably a good idea to do this.

utz82 commented 3 years ago

Also, do you still have your P2000T? Never heard of that machine before. But seeing that MAME emulates it, I might try and do a sound driver for it some day. Z80 @ 2.5MHz should be plenty to pull some nifty tricks.

genivia-inc commented 3 years ago

I'll make the anim 1 change to the code.

I have the P2000T somewhere in storage in the Netherlands with family, but not sure if it is still usable. I've not seen it for a long time. We also had an Apple 2e. Back in the 80s there was a dedicated group of P2000T users that produced software for this machine, including a Z80 assembler that had an interesting animation for the two assembly passes by scrolling the code back and forth twice. It had a decent Microsoft BASIC interpreter and for "graphics" it used a "Teletekst" chip. With that and limited sound capabilities it could not compete with the ZX Spectrum and Commodore 64. Nevertheless, I learned to write Z80 code, which I appreciated better than the simple 6502 on the Apple 2e.