Page 7 of 8

Re: Streaming PCM Audio from SD Card?

Posted: Sun Aug 27, 2023 7:26 pm
by BruceRMcF
Dacobi wrote: Sun Aug 27, 2023 7:04 pm With my lack of knowledge of 6502 assembly I didn't even consider it or maybe I thought that the flag would be '0' unless it was specifically set to '1'.

I still don't understand what causes the flag to be set only sometimes?
If the machine code compiled by the C compiler has to do any pointer arithmetic or 16 bit comparisons, both of those will often involve the Carry flag in the 65C02 processor, so the state of the carry flag can be harder to infer in an assembled routine embedded in C code than if you are writing in pure assembly code.

Re: Streaming PCM Audio from SD Card?

Posted: Sun Aug 27, 2023 7:29 pm
by Daedalus
It's a commonly used processor status flag. It's used in addition and subtraction, so it's 1, it's 0... it's all over the place, whatever it happened to be the last time it was used. In THIS particular instance, it's used as a flag to denote an input condition. In the X16's defense? It's actually documented in the github documentation for macptr. But it's the rare bird in that the OTHER calls (That were in existence in the C64 days) are not given that same treatment.

Re: Streaming PCM Audio from SD Card?

Posted: Sun Aug 27, 2023 7:35 pm
by Daedalus
I should add this for clarity:
The carry flag is also used for the "error" flag in a lot of the KERNAL calls, and then also used as an error flag in the FAT32 addition. FAT32 uses C=0 as the error, and KERNAL usually used C=1 as the error. In all cases of both of those, the flag is set to the non-error condition at the start of the called routine, so it's not normally needed to enforce it when the routine is called.

But here, it's used as an input condition, so it has to be asserted to the condition you need.

I should have caught that. Sorry.

Edited to change the error status of FAT32 and KERNAL... FAT32 calls use C=1 to indicate success. The KERNAL calls that use carry for that denote C=1 to indicate error. It's actually quite confusing. But this is what happens when you band aid a FAT32 implementation onto a 40 plus year old code monolith with the design condition of "The monolith must be intact!" Heh.

Re: Streaming PCM Audio from SD Card?

Posted: Sun Aug 27, 2023 8:20 pm
by Dacobi
I was aware of the flag being used as an input from the GitHub documentation and used it for writing to the FIFO, but like I said, I think I assumed it would be '0' unless set to '1'.
But I'm still confused as to how it would only become a problem once and only in some conditions.
With the flag being used for simple things like add and subtract I would have thought the problem to occur something like 50% of the time?

Re: Streaming PCM Audio from SD Card?

Posted: Sun Aug 27, 2023 9:29 pm
by Daedalus
To answer that, I think it's because the carry flag is USUALLY 0. It's set in an ADC instruction when a carry occurs, it's reset in a SBC instruction when a borrow occurs, and it's set by what rotates during ROR and ASL instructions... I think the "heavy lifter" to set it zero there is the ADC, when it's just set to 0 at the start.

The exception is when you do a lot of file activity, as FAT32 operations leave carry at 1.

What happens right at the beginning of a program? file activity.

It's a theory.

Re: Streaming PCM Audio from SD Card?

Posted: Sun Aug 27, 2023 11:40 pm
by DragWx
Here's my guess:
  1. The memory holding the audio buffer starts out initialized to all-zeroes, probably by the emulator.
  2. The program loads PCM data.
  3. The first part of the routine resets the FIFO, then uses MACPTR to fill it, and it works just fine (and was always going to because of the "SEC").
  4. The second part of the routine calls MACPTR with carry in an undefined state, which happened to be "clear".
  5. MACPTR fills the audio buffer with 4080 bytes just fine, completely by luck.
  6. The third part of the routine calls MACPTR with carry in an undefined sate, and unluckily is "set", which is incorrect.
  7. MACPTR writes to the 4081th byte in the buffer 16 times, leaving the last 15 bytes of the buffer untouched.
  8. The very first time PCM plays in the program, the untouched bytes are all zeroes, leading to a pop.
  9. The routine responsible for refilling the audio buffer correctly refills it (probably by chance again, make sure to add CLCs there too), so the last 15 bytes now contain valid audio data.
  10. When a new PCM file plays, this process happens again, with the same problem where the last 15 bytes in the buffer are not correctly filled, but because these last 15 bytes contain leftover audio data, there may be a subtle audio glitch, but no loud pop like before.
In 6502 assembly, the carry flag is powerful because you can set and clear it at will (SEC and CLC), your code can branch on it (BCC and BCS), and only a few math and bitwise operators actually modify the state of the carry flag, so it's possible to write routines that don't touch it all, and use it for something else.

Here's an example from some code I wrote for the NES almost a decade ago:

Code: Select all

; Fill a nametable with the tile in A, and the attribute in X [Affects Y]
; Set PPU address before calling.
; Call ppumanager_fill_attribute to fill only the attribute (set PPU address to the attribute table)
; and put attribute in A
ppumanager_fill
 ldy #$78		;Fill $78 * $8 = $3C0 bytes
 sec			;The carry bit is unaffected by all of this code, so let's use it to determine
			;which part of the loop we're in (tile filling vs. attribute filling)
ppumanager_fill_loop
 sta $2007
 sta $2007
 sta $2007
 sta $2007
 sta $2007
 sta $2007
 sta $2007
 sta $2007
 dey
 bne ppumanager_fill_loop
 bcc ppumanager_fill_end
 txa			;Get the attribute byte
ppumanager_fill_attribute
 ldy #$08		;Fill $8 * $8 = $40 bytes
 clc			;Clear the carry so the above branch succeeds next time
 bcc ppumanager_fill_loop
ppumanager_fill_end
 rts
This is pretty nice when coding only in assembly. When mixing C and assembly, you don't have any guarantee to what the C code has compiled (and optimized!) to, so it's impossible to know whether the carry flag is set or clear, even if it may sometimes look like it's usually clear. :P

Re: Streaming PCM Audio from SD Card?

Posted: Mon Aug 28, 2023 12:04 am
by Daedalus
Step 6:
"The third part of the routine calls MACPTR with carry in an undefined sate, and unluckily is "set", which is incorrect."

Except that it JUST used several of the FAT32 routines over and over to do the first block of data, so the C flag is 1 (C=1 is success)

So there probably wasn't much luck involved.

Yeah, I think your analysis is spot on.

Re: Streaming PCM Audio from SD Card?

Posted: Mon Aug 28, 2023 12:34 am
by Daedalus
Followed a hunch...
During the VSYNC interrupt every 1/60 second, ps/2 mouse scan clears the carry flag as a normal part of getting no data... So it would be normal for carry to be generally 0 after startup.

Re: Streaming PCM Audio from SD Card?

Posted: Mon Aug 28, 2023 6:49 am
by Dacobi
All this talk about 6502 assembly has made me start to warm up to the idea of re-writing at least some of the more processor expensive code in assembly. Most of my physics and collision code uses 16bit int multiplication and division.

Is it possible to create a sort of asm macro for 16bit operations?

I have written small proc's in 6502 asm, but only with 8bit math.

If I could re-write my physics and collision code in asm my hope would be that the game would run with 4 players.

Re: Streaming PCM Audio from SD Card?

Posted: Mon Aug 28, 2023 7:49 am
by Ed Minchau
There's 16 bit multiplication in the new VERA, along with some Mode 7 type graphics.