It is currently Tue Dec 11, 2018 2:14 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 20 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Mon Aug 27, 2018 10:05 am 
Offline

Joined: Tue Nov 23, 2004 9:35 pm
Posts: 713
The UMC UA6527 & UA6527P(al) seem to be fairly common chips and function very well as a 2A03 CPU clone, except for the reversed duty cycles. I understand that when a NES game wants a 50% duty cycle pulse, it writes 10xxxxxx (x=don't care) to either $4000 or $4004. Similarly, if it wants a 12.5% duty cycle pulse, it writes 00xxxxxx to the register. (I hope I don't have my endianness screwed up here). The other two options, 25% and 75%, sound the same and can be written with a 01 or 11 to the high bits of $4000 or $4004.

It seems to me that if you have a discrete chip, you can fix this using extra logic either on a custom PCB or a daughterboard that wedges in between the CPU and the socket. My idea is that when $4000 or $4004 is asserted on the address bus, the high bit of the data write is inverted. As you can see from above, only the highest bit is important here. Flipping that bit restores the agreement between what the game wants and the substitute APU wants for the identical pulse wave.

My idea is to use a pair of 74'688 8-bit comparators, a 74'08 AND gate to tie the outputs of the comparators together and finally a 74'2266 XNOR gate to ensure the bit is flipped only when the comparators are active and otherwise left untouched. The address bus is 16-bit and has to be passed through to the CPU, but bit 3 would not be connected to the comparators to allow for $4000 or $4004.
The P=Q outputs, active low, go into the AND to ensure that a 0 is output only when both outputs are low. That 0 is fed into one input of an XNOR gate and the data bit (7) is the other input. When the comparators do not equal 4000 or 4004, then their input will be a 1 and the data bit is sent through the gate the same way it entered. If the comparators equal 4000 or 4004, then the data bit will end up being the opposite of the way it came in.

I'm sure someone with more experience in digital logic design could propose a more efficient way to accomplish this task. Is my idea sound or dumb?

_________________
Nerdly Pleasures - My Vintage Video Game & Computing Blog


Top
 Profile  
 
PostPosted: Mon Aug 27, 2018 10:11 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20852
Location: NE Indiana, USA (NTSC)
There are two problems with this suggestion. First, duty cycle swapping in famiclones is actually an exchange of bits 7 and 6 in each of those two registers ($4000 and $4004), not an inversion. Second, there is no way to intercept the written data on the way from the 6502 core to the APU, which is on the same die. Only using a discrete MOS 6502 with a separate APU would allow this, and I'm not aware of any popular famiclone that does that.


Top
 Profile  
 
PostPosted: Mon Aug 27, 2018 12:31 pm 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 446
Location: Poland
Say honestly, if you haven't known about the wrong duty cycle, would you ever hear the difference?


Top
 Profile  
 
PostPosted: Mon Aug 27, 2018 12:40 pm 
Offline

Joined: Tue Nov 23, 2004 9:35 pm
Posts: 713
Okay, I misunderstood how the duty works. So the 50% is not exchanged with the 12.5% but the 25%. More complicated logic will be required to swap the bits.

However, it's all rather academic if you can't intercept a write from the CPU to the APU because they are within the same physical package. But if you could observe the state of the address bus from the pins of the 2A03, conceivably you could have an external device write the opposite bits to those addresses at the same time, and if the external device had the lower impedance, it would win the bus conflict and its values would be written instead of the CPU's.

_________________
Nerdly Pleasures - My Vintage Video Game & Computing Blog


Top
 Profile  
 
PostPosted: Mon Aug 27, 2018 12:46 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7807
Location: Seattle
Nope!

The 2A03 has an internal data bus ("_db0" through "_db7" in Visual2A03) and isolation logic between the internal and external buses. (This is how reads from $4015 work: It deliberately fails to copy the external data bus onto the internal data bus). When the 2A03 writes to one of its internal registers, the value appears on the internal bus, and then copies the value to the external bus.

Overpowering the external bus drivers won't help change the value of the internal bus.


Top
 Profile  
 
PostPosted: Wed Aug 29, 2018 3:52 am 
Offline
User avatar

Joined: Sat Jul 04, 2015 9:58 am
Posts: 841
Location: -29.794229 -55.795374
With my pretty limited knowledge I think it's a very difficult task!
Maybe if you can make a patch for the game to change this, but this will be per game specific and I strongly doubt it could be applied with a GameGenie.
Other option should be to build an exernal APU. But that would be pretty complex to achieve with discrete logic ICs.
I'm also not sure if an external APU is possible, but having both APUs playing at the same time would do an interesting effect.

krzysiobal wrote:
Say honestly, if you haven't known about the wrong duty cycle, would you ever hear the difference?

As a kid I have noticed that some famiclones sounded slightly different.
Some adults told me that it was some difference with the TV sets, but as a curious kid I tested different clones on the same TV and confirmed it.
I asked a musician about it and I just couldn't understand the explanation.
I'm not sure if he explained correctly too, it was something related to the "xth" note that was out of tune or something like that, I don't remember clearly. :roll: And yes, I was an annoying kid! :mrgreen:
With emulators I also noticed it was slightly different too, mostly sounded similar as this clone.
Reading the forums and the wiki I finally was able to understand why it sounded different. :-)

So Great Hierophant, good luck with your project!
I hope you can do it!! :beer:


Top
 Profile  
 
PostPosted: Wed Aug 29, 2018 11:14 am 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 446
Location: Poland
I think good approach is to watch for one of those opcodes:
sta $4000 / stx $4000 / sty $4000 / sta $4004 / stx $4004 / sty $4004

That would require snooping data bus to see if three consecutive read bytes are one of the pattern (for example sta $4000 = $44 $00 $40).
Of course there might be some false positives and also writing to APU from diffferent addressing modes will not be matched. But I doubt if any game $4000/$4004 from other that absolute mode (they might be accessed from absolute,X/Y but that probably is used just for initializing all APU registers to 0 and that does not need correcting duty cycle)

So a game-genie like devices (with slot for cartridge and connector to console) is necesary.
Code:
R/!W | address  | data bus   
  1    $xxxx     $44
  1    $xxxx+1   $00
  1    $xxxx+2   $40 <- so the next CPU cycle will be STA $4000. We eremember this CPU address
  0    $4000 (?) ?   <- and here it is (I have no iea if address bus is driven with $4000 and data bus with the value to be written,
                        but that does not matter). After this cycle, CPU will try to fetch new opcode
                  We disable the cartridge and drive data bus with STA $8000. Why? We want to know what value was
                     written to $4000. And why $8000? Chosing any address below $8000 is not safe because:
           *$0000-$1fff -> will overwrite RAM cell
           *$2000-$3fff -> will mess up PPU state
           *$4000-$401f -> will mess up CPU internal state (or joypads)
           *$5000-$5fff -> will mess up mapper registers (if there are any in that range, for example MMC5)
           *$6000-$7fff -> will overwrite WRAM cell (if it is present in th ecartridge)
           But because during the STA $8000 we pull cartridge's ROMSEL to VCC, cartridge will think it is STA $0000!
  1    $xxxx+3   $44
  1    $xxxx+4   $00
  1    $xxxx+5   $80
  0    $8000     V   <- now we can see on data bus V, which is the value written to $4000. Let V' be the value with fixed bits of duty cycle
  1    $xxxx+6   $A9 <- now we want to simulate LDA #V'
  1    $xxxx+7   V'
  1    $xxxx+8   $44 <- now we want to stimulate STA $4000
  1    $xxxx+9   $00
  1    $xxxx+10  $40
  0    $4000  (?) ? <- here is APU written again, his time with corrected duty cycle
              now we want to restore previous value from accumulator (V), so we will simulate LDA #V opcode
  1    $xxxx+11  $44
  1    $xxxx+12  V'
           and now we want to return back to the code that was executing (to address $xxxx + 3). So we simulate JMP $xxxx + 3 opcode:
  1    $xxxx+13  $4c
  1    $xxxx+14  LO($xxxx + 3)
  1    $xxxx+15  HI($xxxx + 3)
  now the program returns to execution.


Possible problems:
* $4000 is first written with V (which has incorrect duty cycle), and then V'. We could abort doing the STA $4000 by distabling the cartridge in 3rd line and driving data bus with for example $80. That way we would change the STA $4000 to STA $8000 and we could get the value was to be written to $4000 much faster. But the problem is that if the $xxxx is not $8000-$ffff, but for example $0000-$1fff, we cannot disable it (but we can probably overcurrent the databus from the lower impedance)
* Those 15 cycle delay might cause some critical-timed code to go wrong


Top
 Profile  
 
PostPosted: Wed Aug 29, 2018 11:24 am 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7807
Location: Seattle
I bet you don't need to repeat the write to $8000: The 2A03 (and so I strongly suspect the famiclones too) drives the data bus during all writes, even ones to its internal registers. So you already know the value that was written.

I wonder if it would be practical to reimplement just the pulse waves into a cheap FPGA / CPLD. But ... do most famiclones stuff both audio channels onto one pin?


Top
 Profile  
 
PostPosted: Wed Aug 29, 2018 12:29 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20852
Location: NE Indiana, USA (NTSC)
Whether sta $4000,X (as seen in pentlysound.s line 223 and line 312) should be intercepted depends on the value of X.


Top
 Profile  
 
PostPosted: Wed Aug 29, 2018 12:38 pm 
Offline

Joined: Sun Apr 13, 2008 11:12 am
Posts: 7807
Location: Seattle
But when you're monitoring the actual address and data buses, you don't care about how the write to $4000 or $4004 happened ... 1- just that it did, and 2- what register had the "wrong" value


Top
 Profile  
 
PostPosted: Thu Aug 30, 2018 4:42 am 
Offline
User avatar

Joined: Sat Jul 04, 2015 9:58 am
Posts: 841
Location: -29.794229 -55.795374
lidnariq wrote:
do most famiclones stuff both audio channels onto one pin?

I don't know of any clone that does.
I'll take a look at the 2 NOACs I have, but I suspect both have separate audio outputs.
Since it's a small sample of the vast ammount of clones that exists I think it's non-conclusive.
Having the pulse channels on different pins could do interesting fake stereo effects in most games.


Top
 Profile  
 
PostPosted: Thu Aug 30, 2018 11:51 am 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 446
Location: Poland
Every blob or semi-blob (UM6561) famiclone has only one audio output signals .
Only DIP bases consoles output separate audio channels on 2 pins.


Top
 Profile  
 
PostPosted: Fri Aug 31, 2018 3:34 am 
Offline
User avatar

Joined: Sat Jul 04, 2015 9:58 am
Posts: 841
Location: -29.794229 -55.795374
krzysiobal wrote:
Every blob or semi-blob (UM6561) famiclone has only one audio output signals .

Interesting.
When I looked at mine's I supposed the channels were split, then I found this schematics on Farid's thread:
Image
I first tought it was Amp0 and Amp1 pins, tied together with the mistery Audio output.
Then I realised it was AmpI (input) and AmpO (output), so I was wrong afterall. :oops:
Are these pins some kind of audio amplificator like the one built inside the NES/FC with a inverter?


Top
 Profile  
 
PostPosted: Fri Aug 31, 2018 5:44 am 
Offline

Joined: Sun Jun 12, 2011 12:06 pm
Posts: 446
Location: Poland
It is an internal amplifier. In one of the famiclones that I had repairder, I needed to disable it and use external amplifier on transistor, because when the internal one wanted to drive low signal on its output, video signal was heavily disturbed.


Top
 Profile  
 
PostPosted: Sun Sep 02, 2018 4:12 am 
Offline
User avatar

Joined: Sat Jul 04, 2015 9:58 am
Posts: 841
Location: -29.794229 -55.795374
Definitely too complex to a single and even a couple of piggybacked genies.
Also, an external APU seems too complex to implement with discrete logic.
Maybe using a sound chip like SN76489 could simplify the design?
Seems that an CPLD / FPGA is the way to solve it, be it with an external APU or ROM patching.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 20 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group