It is currently Sun Aug 18, 2019 8:33 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 29 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Neo Geo Pocket emulation
PostPosted: Fri Mar 08, 2019 6:17 pm 
Offline

Joined: Mon Mar 27, 2006 5:23 pm
Posts: 1518
I'm still trying to create a Neo Geo Pocket emulator; figured I could pool the information here in case anyone else ever wants to try emulating this system.

Current questions:

I can get to this part of the NGPC BIOS:

Code:
   00FF1E8A : 0606          : EI 6
   00FF1E8C : E961          : INC 1,XBC
   00FF1E8E : E9CFFFFF0200  : CP XBC,0x0002FFFF
   00FF1E94 : 6611          : JR Z,0x00FF1EA7         ====> Done
   00FF1E96 : F1896FCF      : BIT 7,(0x006F89)
   00FF1E9A : 6EF0          : JR NZ,0x00FF1E8C         ===> Loop
   00FF1E9C : F1616C0000    : LD (0x006C61),0x00
   00FF1EA1 : 59            : POP XBC
   00FF1EA2 : 48            : POP WA
   00FF1EA3 : 0607          : DI
   00FF1EA5 : 03            : POP SR
   00FF1EA6 : 0E            : RET

   ===>

   00FF1EA7 : F1806F020000  : LDW (0x006F80),0x0000
   00FF1EAD : F1616C0000    : LD (0x006C61),0x00
   00FF1EB2 : 59            : POP XBC
   00FF1EB3 : 48            : POP WA
   00FF1EB4 : 0607          : DI
   00FF1EB6 : 03            : POP SR
   00FF1EB7 : 0E            : RET


My code ends up taking the branch to FF1EA7, whereas MAME returns at FF1E9C.

The BIOS runs in a deadloop polling 6F89.d7, which is an undocumented system RAM variable.

The only interrupt that modifies this variable to bypass this loop is at FFFF70, which is INTAD, or apparently some kind of analog to digital conversion interrupt? What is this interrupt, and what causes it to fire?

...

Reading through MAME, I see how the Z80 can trigger TLCS900H interrupts, but for the TLCS900H to trigger Z80 interrupts, it apparently happens on writes to "porta". What are these ports? The MAME core has ports 1,2,5,6,7,8,9,a,b,c,d,e.

On the topic of the Z80 ... is the port at 0xBC just a single byte that both the TLCS900H and Z80 can read and write to? Or is it more like the SNES where each side gets its own port values? MAME's code makes it look like the former.

Is the shared Z80 RAM truly shared (with some kind of bus conflict handler or access cycle interleaving in place), or is it the case where only one CPU can access it at any given moment? If the latter, it would seem you'd have to stop and restart the CPU in order to share RAM, since the Z80 only has the little 4K RAM block and that's it to execute code out of ...

...

Hblank IRQs are said to share the TIO interrupt, which is timer 0 ... but which interrupt is that from 0xffffxx in the BIOS? Eg Vblank / INT4 is FFFF2C. The APU->CPU interrupt is INT5 / FFFF30.

...

The TMP95C061 manual states that on power-on, the CPU reads the reset vector from FFFF00, but this does not point at FF1800. Yet MAME starts execution at FF1800 anyway (from its debugger), even though tlcs900.c does read from FFFF00. Not sure which is more correct as a result.

...

Still at a total loss as to how micro DMA is supposed to work. For starters, does this DMA run in parallel with the CPU, or does it take precedence over executing CPU instructions (eg blocks the CPU until the DMA transfer has completed.)

...

On the whole, MAME's emulation of the TLCS900H is *terrifyingly* low-level, beyond anything I've seen in a CPU core before. It's filled with around 100+ internal registers that do all kinds of bit-twiddling all over the core.

Are these things documented somewhere? The values like this:

Code:
#define TMP95C061_P7FC        0x17
#define TMP95C061_P8          0x18
#define TMP95C061_P9          0x19
#define TMP95C061_P8CR        0x1a
#define TMP95C061_P8FC        0x1b
#define TMP95C061_PA          0x1e
#define TMP95C061_PB          0x1f
#define TMP95C061_TRUN        0x20
#define TMP95C061_TREG0       0x22
#define TMP95C061_TREG1       0x23
#define TMP95C061_T01MOD      0x24
#define TMP95C061_TFFCR       0x25
#define TMP95C061_TREG2       0x26
#define TMP95C061_TREG3       0x27
#define TMP95C061_T23MOD      0x28
#define TMP95C061_TRDC        0x29
#define TMP95C061_PACR        0x2c
#define TMP95C061_PAFC 0x2d


They seem to be related to the CPU memory map addresses 00-7f.

You end up with code like this:
Code:
m_reg[TMP95C061_PACR] = 0x0c; // HACK ngpc needs this but should be zero
m_reg[TMP95C061_PAFC] = 0x0c; // HACK ngpc needs this but should be zero

void tmp95c061_device::update_porta()
{
   int fc = (m_to1 << 2) | (m_to3 << 3);

   m_porta_write(0, ((fc & m_reg[TMP95C061_PAFC]) | (m_reg[TMP95C061_PA] & ~m_reg[TMP95C061_PAFC])) & m_reg[TMP95C061_PACR], 0xff);
}


And ... oh boy >_>


Top
 Profile  
 
PostPosted: Sat Mar 09, 2019 2:34 am 
Offline

Joined: Sat Mar 09, 2019 1:54 am
Posts: 4
byuu wrote:
It's filled with around 100+ internal registers that do all kinds of bit-twiddling all over the core. Are these things documented somewhere?

When going through datasheets for the TLCS900H, I found that the addresses of the CPU's internal registers were inconsistent between different datasheets. (I can't recall if the names or bits were also different in some cases.)
A datasheet that seemed to match MAME can be found at http://pdf.datasheetcatalog.com/datashe ... 1434_1.pdf

byuu wrote:
The only interrupt that modifies this variable to bypass this loop is at FFFF70, which is INTAD, or apparently some kind of analog to digital conversion interrupt? What is this interrupt, and what causes it to fire?

Information about the A/D converter is on page 148 of the PDF I linked above. I think it can fire either 160 or 320 states (adjustable by bit 3 of 0x6D) after A/D conversion is started (by setting bit 2 of 0x6D).
The SNK "SYSTEM PROGRAM REFERENCE MANUAL" states that an A/D channel is used for power management. The battery voltage is available at 0x6F80, and it appears that this is what it is sampling:
Code:
FF2DDC : D06020           : ld WA,(0x60)      ;0x60 ADREG0L - "AD Result Reg 0 low" (0x61 is ADREG0H - "AD Result Reg 0 high")
FF2DDF : D8EF06           : srl 0x06,WA
FF2DE2 : F1806F50         : ld (0x6F80),WA


byuu wrote:
The TMP95C061 manual states that on power-on, the CPU reads the reset vector from FFFF00, but this does not point at FF1800. Yet MAME starts execution at FF1800 anyway (from its debugger), even though tlcs900.c does read from FFFF00. Not sure which is more correct as a result.

When starting the NGPC in MAME for the first time (or without the NVRAM file), it will use the reset vector. Once there is an NVRAM file, MAME will ignore the vector and start execution at FF1800 (see ngp_state::machine_reset()).

When MAME starts without the NVRAM file, nothing gets displayed and the CPU ends up in a deadloop at 0xFF1128 (I don't know why 0xFF1128 is shown executing here):
Code:
FF110D: ld XSP,0x00006c00
FF1112: ei 0x05
FF1114: set 2,(0xb3)
FF1117: ld (0x6c7a),0xa5a5
FF111D: ld (0x6e95),0x4e50
FF1123: ld (0xb4),0x00a0
FF1127: halt
FF1128: res 7,(0x6f86)
FF1128: res 7,(0x6f86)


I imagine that setting the PC to 0xFF1800 is a hack to get around this.

byuu wrote:
Hblank IRQs are said to share the TIO interrupt, which is timer 0 ... but which interrupt is that from 0xffffxx in the BIOS? Eg Vblank / INT4 is FFFF2C. The APU->CPU interrupt is INT5 / FFFF30.

Timer 0 is at 0xFFFF40.
In case it is handy to have... (interrupt sources gleaned from MAME)
Code:
NGPC
   handlerAddress   vectorAddress   irq
   FF204A         FFFF00         Reset or [SWI0] instruction
   FF2772         FFFF04         [SW1] instruction
   FF2305         FFFF08         Illegal or [SW2] instruction
   FF2202         FFFF0C         [SW3] instruction
   FF220B         FFFF10         [SW4] instruction
   FF2214         FFFF14         [SW5] instruction
   FF221D         FFFF18         [SW6] instruction
   FF2226         FFFF1C         [SW7] instruction
   FF1898         FFFF20         NMI    : /NMI Pin (Power Button)
   FF2D98         FFFF24         INTWD  : Watchdog timer
   FF2856         FFFF28         INT0   : INT0 Pin (Alarm/RTC)
   FF2163         FFFF2C         INT4   : INT4 Pin (VBlank)
   FF2282         FFFF30         INT5   : INT5 Pin (Z80)
   FF2B25         FFFF34         INT6   : INT6 Pin
   FF2DB6         FFFF38         INT7   : INT7 Pin
   FF22A4         FFFF3C         (Reserved)
   FF22A5         FFFF40         INTT0  : 8-bit Timer 0 (HBlank)
   FF22AE         FFFF44         INTT1  : 8-bit Timer 1
   FF22B7         FFFF48         INTT2  : 8-bit Timer 2
   FF22C0         FFFF4C         INTT3  : 8-bit Timer 3
   FF22C9         FFFF50         INTTR4 : 16-bit Timer 4 (TREG4)
   FF22CA         FFFF54         INTTR5 : 16-bit Timer 4 (TREG5)
   FF22CB         FFFF58         INTTR6 : 16-bit Timer 5 (TREG6)
   FF22CC         FFFF5C         INTTR7 : 16-bit Timer 5 (TREG7)
   FF22CD         FFFF60         INTRX0 : Serial RX (Channel 0) (Serial RX)
   FF22D6         FFFF64         INTTX0 : Serial TX (Channel 0) (Serial TX)
   FF22DF         FFFF68         INTRX1 : Serial RX (Channel 1)
   FF22E0         FFFF6C         INTTX1 : Serial TX (Channel 1)
   FF2DCE         FFFF70         INTAD  : A/D Conversion End
   FF22E1         FFFF74         INTTC0 : Micro DMA End (Ch. 0)
   FF22EA         FFFF78         INTTC1 : Micro DMA End (Ch. 1)
   FF22F3         FFFF7C         INTTC2 : Micro DMA End (Ch. 2)
   FF22FC         FFFF80         INTTC3 : Micro DMA End (Ch. 3)

NGP
   handlerAddress   vectorAddress   irq
   FF1DE8         FFFF00         Reset or [SWI0] instruction
   FF2426         FFFF04         [SW1] instruction
   FF200F         FFFF08         Illegal or [SW2] instruction
   FF1F31         FFFF0C         [SW3] instruction
   FF1F3A         FFFF10         [SW4] instruction
   FF1F43         FFFF14         [SW5] instruction
   FF1F4C         FFFF18         [SW6] instruction
   FF1F55         FFFF1C         [SW7] instruction
   FF1898         FFFF20         NMI    : /NMI Pin (Power Button)
   FF29BE         FFFF24         INTWD  : Watchdog timer
   FF24E3         FFFF28         INT0   : INT0 Pin (Alarm/RTC)
   FF1E92         FFFF2C         INT4   : INT4 Pin (VBlank)
   FF1F8C         FFFF30         INT5   : INT5 Pin (Z80)
   FF274B         FFFF34         INT6   : INT6 Pin
   FF29D7         FFFF38         INT7   : INT7 Pin
   FF1FAE         FFFF3C         (Reserved)
   FF1FAF         FFFF40         INTT0  : 8-bit Timer 0 (HBlank)
   FF1FB8         FFFF44         INTT1  : 8-bit Timer 1
   FF1FC1         FFFF48         INTT2  : 8-bit Timer 2
   FF1FCA         FFFF4C         INTT3  : 8-bit Timer 3
   FF1FD3         FFFF50         INTTR4 : 16-bit Timer 4 (TREG4)
   FF1FD4         FFFF54         INTTR5 : 16-bit Timer 4 (TREG5)
   FF1FD5         FFFF58         INTTR6 : 16-bit Timer 5 (TREG6)
   FF1FD6         FFFF5C         INTTR7 : 16-bit Timer 5 (TREG7)
   FF1FD7         FFFF60         INTRX0 : Serial RX (Channel 0) (Serial RX)
   FF1FE0         FFFF64         INTTX0 : Serial TX (Channel 0) (Serial TX)
   FF1FE9         FFFF68         INTRX1 : Serial RX (Channel 1)
   FF1FEA         FFFF6C         INTTX1 : Serial TX (Channel 1)
   FF29EF         FFFF70         INTAD  : A/D Conversion End
   FF1FEB         FFFF74         INTTC0 : Micro DMA End (Ch. 0)
   FF1FF4         FFFF78         INTTC1 : Micro DMA End (Ch. 1)
   FF1FFD         FFFF7C         INTTC2 : Micro DMA End (Ch. 2)
   FF2006         FFFF80         INTTC3 : Micro DMA End (Ch. 3)


Top
 Profile  
 
PostPosted: Sat Mar 09, 2019 4:01 am 
Offline

Joined: Mon Mar 27, 2006 5:23 pm
Posts: 1518
Oh wow, thank you so much! This helps a ton.

Quote:
I found that the addresses of the CPU's internal registers were inconsistent between different datasheets. (I can't recall if the names or bits were also different in some cases.)


Yeah, these appear to be little SoC-like devices. MAME tries to support both the TMP95C061 (NGP/C) and TMP95C063 (Taito Type-Zero), but I'm guessing the latter is only barely supported since it's just an I/O controller. Probably the best real way to emulate the TLCS900(/H,/H2) is to have a each model inherit from a base TLCS900 class. Emulating MIN mode is probably not worth it since no game systems use it.

Quote:
When starting the NGPC in MAME for the first time (or without the NVRAM file), it will use the reset vector. Once there is an NVRAM file, MAME will ignore the vector and start execution at FF1800 (see ngp_state::machine_reset()).

When MAME starts without the NVRAM file, nothing gets displayed and the CPU ends up in a deadloop at 0xFF1128 (I don't know why 0xFF1128 is shown executing here):


Ah, I thought MAME wasn't working at first because all I got was a solid white screen on first run. How peculiar. It feels like MAME should force FF1800 then, or if (FFFF00) does some critical setup, then there's a bug there that it won't reach FF1800.

On my real NGPC, the CR2032 is dead, and so when I put in batteries and run it, it goes right into the setup screen like you get when MAME runs from FF1800.

Quote:
Timer 0 is at 0xFFFF40.


Ah, thank you. So Hblank IRQs share the same (FFFF40) vector as timer 0 (TIO), then? Seems a strangely conservative choice given the obscene number of IRQs this chip has available.


Top
 Profile  
 
PostPosted: Sat Mar 09, 2019 7:24 am 
Offline

Joined: Sat Mar 09, 2019 1:54 am
Posts: 4
You're welcome! I'm glad that it was helpful.
byuu wrote:
So Hblank IRQs share the same (FFFF40) vector as timer 0 (TIO), then? Seems a strangely conservative choice given the obscene number of IRQs this chip has available.

If you have the SNK "8 BIT TIMER REFERENCE MANUAL", they give an example at the end of how to set up the timer for usage as an Hblank IRQ.
What they do is set timer 0 to use an external clock (which happens to be the Hblank interrupt from the graphic controller), then set the counter to the desired number of lines between each interrupt. Timer 0 is the only timer that can use an external clock.


Top
 Profile  
 
PostPosted: Sat Mar 09, 2019 4:15 pm 
Offline

Joined: Sat Mar 09, 2019 1:54 am
Posts: 4
JamesHall7 wrote:
When MAME starts without the NVRAM file, nothing gets displayed and the CPU ends up in a deadloop at 0xFF1128

It just dawned on me why the deadloop at 0xFF1128 occurs: When the NGPC is off, the CPU seems to park there while waiting for the NMI from the power button.
Pressing the power button in MAME will make it toggle between regular operation and staying in that loop.
(also, I get a strong feeling that MAME is showing inaccurate information here -- it would make far more sense to me if it was stopped at 0xFF1127 (halt))


Top
 Profile  
 
PostPosted: Sat Mar 09, 2019 5:26 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21558
Location: NE Indiana, USA (NTSC)
If the program counter is already incremented after fetching the halt, the CPU will halt with PC pointed at the next instruction to execute.

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
PostPosted: Sat Mar 09, 2019 8:33 pm 
Offline

Joined: Mon Mar 27, 2006 5:23 pm
Posts: 1518
https://twitter.com/byuu_san/status/1104545144253034496
https://twitter.com/byuu_san/status/1104574115183190016

I got the NGP and NGPC BIOSes running. I'm ignoring sprite priorities, Hblank interrupts, timers, micro/H DMA, ports, interrupt internal register settings, CPU instruction timings, the RTC, etc, but ... oh well.

It currently hangs at the last BIOS screen, the logo keeps fading in and out. Wish I knew what was causing that ... if I can get in-game, then I can start running through Hidden Asbestos' test ROMs.

I'm still just floored that I've gotten this far with only one CPU bug so far.

...

There's some real craziness right now with sprite coordinates needing to be offset by 7 ... I must be doing something wrong.
spritePos-screenPos should get me a value from 0-7 when in range, but it seems to be backward and so I have to invert the tile flipping logic as well.

Code:
auto VPU::renderSprite() -> maybe<uint12> {
  maybe<Sprite&> p;
  for(auto& s : sprites) {
    s.x = s.hoffset;
    s.y = s.voffset;
    if(s.hchain && p) s.x += p->x;
    if(s.vchain && p) s.y += p->y;
    p = s;

    uint8 x = 7 + s.x + sprite.hscroll - io.hcounter;  //hcounter = 0-159
    if(x >= 8) continue;  //out of range?
    uint8 y = 7 + s.y + sprite.vscroll - io.vcounter;  //vcounter = 0-151
    if(y >= 8) continue;  //out of range?

    if(s.hflip == 1) x ^= 7;
    if(s.vflip == 0) y ^= 7;


Quote:
It just dawned on me why the deadloop at 0xFF1128 occurs: When the NGPC is off, the CPU seems to park there while waiting for the NMI from the power button.


Yeah. It sets (0xb3).d2 which seems to need INT0/NMI to fire (it's the only interrupt that's been configured), and then it polls the battery level and power button repeatedly.

The Neo Geo Pocket breaks even my newer, more extreme tree-based emulation core design by being a system that's technically always on, but just idling. My GUI expects to have a toggle to power the system on and off, not a button that triggers an NMI. I don't yet know how I'm going to handle this one. I would prefer the system to not be running before you power on the system in the menu.

Also, there are a ton of registers in the 0x80-0xff space that are being written to, but not emulated at all in MAME. Fun. I get it, they're all undocumented.


Top
 Profile  
 
PostPosted: Sat Mar 09, 2019 9:18 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 21558
Location: NE Indiana, USA (NTSC)
Off: make a save state and halt emulation
On: restore the save state and fire an NMI

_________________
Pin Eight | Twitter | GitHub | Patreon


Top
 Profile  
 
PostPosted: Sat Mar 09, 2019 10:16 pm 
Offline

Joined: Sat Mar 09, 2019 1:12 pm
Posts: 1
FYI, 0xFF1800 is the prescribed point of entry when using SNK's dev tools (the debugger):

Image

Also, if you're not already aware, you may want to check out this book:

http://bitsavers.trailing-edge.com/components/toshiba/_dataBook/1995_Toshiba_TLCS-900_16bit_Microcontroller.pdf

Despite it being for the TLCS-900 (not the 900/H), it's very comprehensive in its coverage of the 900 series' register set and functionality. An equivalent data book for the 900/H should exist, but I wasn't able to find it in my admittedly brief search.


Top
 Profile  
 
PostPosted: Wed Mar 13, 2019 7:41 am 
Offline

Joined: Mon Mar 27, 2006 5:23 pm
Posts: 1518
I have some games running now, but most games hang right away, and only DAC sound works.

I'm currently missing: proper TLCS900H instruction timings, micro DMA, internal I/O ports, serial communication, and some undocumented registers between 0x80 and 0xff.

The Z80 gets far enough to run instructions and do a few initializing writes to the PSG, but then nothing. It's either the missing micro DMA, or my timers are broken, or the interrupt mechanism between the CPU and Z80 cores is broken.

The timers on this system ... oh my god. Of the ~20ish systems I emulate, nothing even comes remotely close to this level of complexity. Not even a little. Four 8-bit ports that can be lined into sets of two. Or you can use programmable pulse generation mode, or pulse width modulation mode (which has its own frequency setting, and a value of 0 is undocumented.) You can clock them off of a prescaler against the main oscillator (which you can disable) at various frequencies, or off of an external pin (hblank for this system). The timer firing goes through flip-flops (which you can drive manually or choose which timers can toggle them) which can drive timer out pins that are multiplexed with interrupt and port lines. There's a double-buffering system to reload comparators on PPG/PWM events. So you can use this to acknowledge Z80 interrupts, for example.

Then there's two more 16-bit counters, this time with one pin taking in vblank. These timers work completely differently. There's two comparators and two capture registers for each timer. You can set the counters to clear on a comparator match or not. You can configure whether INT4 fires on rising or falling edges of INT1/INT6 input (which is multiplexed with TI4/TI6.) There's a manual counter capture method. Both timers have a very configurable flip-flop that can optionally trigger on either/both comparator matches or when the counters are latched into either/both of the capture registers. They both have double-buffering as well. You can end up implementing all of the functionality (PPG, PWM) of the 8-bit counters through these anyway, but in completely different ways. Plus you can implement event counters, one-shot timers, frequency measurements, pulse width measurements, time difference measurements, etc. Then finally there's PG0T/PG1T, that selects "shift triggers" based on timers 0/1 or 4 (PG0) or timers 2/3 or 5 (PG1), and a mystery T45CR.d7 bit that even this elaborate 200-page manual just says "always write zero, and it always reads as zero." so ... who knows what happens if you write 1 there.

PG0T/PG1T powers a stepping motor control / pattern generator that outputs to port 7. I haven't implemented this yet, but with gems in the manual like, (circuit diagram) "Figure 3.10 (8). Output Waveforms of 4-Phase 1-Step Excitation (Normal Rotation and Reverse Rotation)", I know I'm in for a really good time.

As for the FF1800 thing: it's basically the case that you don't turn this system off. It starts at (FFFF00) and soon goes into HALT state. The only thing that wakes it up from there is pressing down the power button to trigger an NMI. Since it's /NMI, the value in the I/O port and the NMI line value seem to be inverted. MAME's code doesn't show this is the case, but things just don't work at all if the I/O port treats the power button being pressed as 1 like the other buttons. Once the NMI fires, the system boots up. To turn the system off, you have to hold the power button for a few seconds. The last problem I'm having is that, when I set the sub-battery failure bit, it shows the warning only for a brief second and then turns the system off anyway. On my real NGPC, you have to press another button to acknowledge it, so as always, more research needed there.

An important BIOS discovery for any future emudevs: it reads back the K1GE palette colors (0x8103, etc) and doesn't mask the unmapped bits. The manual doesn't specify what those return, and being used to floating high systems, I returned 1s. This was wrong and needs to be 0s. I don't know if the general case should be 1s or 0s, but at least for these registers, d3-d7=0.

Well, I guess people who implement I/O registers as RAM blocks will neatly avoid the issue, but then there are a lot of write-only bits that always read back 1s per the dev manuals.


Top
 Profile  
 
PostPosted: Wed Mar 13, 2019 8:20 pm 
Offline

Joined: Sun Jan 26, 2014 9:31 am
Posts: 304
Just stopping by to say it's great that you're taking a serious swing at the NGP. It's about time someone took a closer, finer look at how this handheld works. I looked into it late last year out of boredom, and I share the sentiments about system complexity. Your progress looks awesome so far, so keep it up!

I did have a question for you, byuu. Any interest in emulating some of the additional hardware for the NGP? Of particular note would be the Wireless Communication Unit. It looks quite exotic, but I'm guessing it boils down to simply transmitting the correct bytes back to the game via the link port, so nothing too extreme (once you understand how the Wireless Communication Unit works, of course). General emulation of the link port and link cable would be outstanding as well, as no current NGP emulator seems to support multiplayer. If I recall correctly, however, that you're not too keen on network programming, right? So not pursuing netplay is completely understandable. I'm pretty sure the Setsuzoku Cable (NGP-to-Dreamcast Cable) is probably too much to hope for at this time, since it sounds like a lot of work (needing at least 1 or 2 people pretty familiar with NGP and/or DC emulation and willing to bridge together two emulators), but I'll mention it anyway. You know, just in case, maybe one day... :wink:

Even if you don't implement any of the above or even dream about touching them, it'd still be immensely helpful to have solid NGP emulation in Higan, should anyone want to tackle those devices on their own. I'll admit, the only reason I took an interest in the NGP was to gauge how feasible emulating its obscure hardware would be. Making sure weird and otherwise forgotten gaming hardware is preserved through emulation has become a bit of an obsession of mine, and it's already spreading beyond the Game Boy.

Anyway, good luck!


Top
 Profile  
 
PostPosted: Thu Mar 14, 2019 9:16 am 
Offline

Joined: Mon Mar 27, 2006 5:23 pm
Posts: 1518
Audio works. The callbacks trigger Z80 IRQs. There is also a separate Z80 NMI trigger, of course. But mostly IRQs are used.

I implemented the RTC, and it works, and yet ... as soon as the "set time and date" BIOS screen appears, it seems to auto-activate the default January 1st, 1999 00:00 time. I'm suspecting it's not an RTC nor an input bug, but possibly a CPU bug.

Lots of games were hanging because I missed the register fetch for ld to and from control registers, whoops.

I am now saving the CPU RAM to disk and loading it on startup, but it still goes into the BIOS setup every single time. Not sure what's wrong. MAME has the same problem, and nothing else emulates the BIOS at all.

I added ports 1, 2, A, and B. Although ports 1 (d8-d15) and 2 (a16-a23) are ... strange. They're likely emulated very wrong. I don't even understand how one can change the direction of the data bus. I'm ... suspecting that ports have their own latch values, but the manual isn't very clear on this. Also not sure how I'm going to implement most ports, like the analog input port pins into the ADC. But I can at least stop ADC from working if you reverse the port direction like it would on real hardware.

I implemented the memory and bus chip select components and their associated waitstates. This one's kind of cool. We say 200000-3fffff is cartridge flash chip 1, and 800000-9fffff is cartridge flash chip 2. But in actuality, you can configure them to appear anywhere you want on the bus, and be any size you want (well, sort of ... it's like x86 MTRR in a way.) There's also two other chip selects that aren't used by the NGPC. Then there's wait state timing for "external chip selects", which is anything not matched by /CS0-3 but ... it is unclear to me what happens when it's an internal access, eg CPU RAM, APU RAM, VRAM, I/O registers, BIOS reads, etc. If that *doesn't* use external chip select wait states, then ... what does? Unmapped addresses?

Still lots more to do.

> It's about time someone took a closer, finer look at how this handheld works.

Much appreciated. I confess I knew nothing about it before. When I saw the TLCS900/H in the past, I nope'd strongly out of it.

I'd been told MAME had really faithful emulation of it, but in actuality most games don't run at all. It was the only one that could run the BIOS, and the only one to really attempt to have a go at the internal SoC registers, but it's extremely incomplete.

Of all the systems I've emulated, this one is by far the least well emulated to date. Nothing else even comes close.

> Any interest in emulating some of the additional hardware for the NGP?

I'm always up for emulating anything and everything possible. I adore all your work on strange peripherals.

The problem is just my limited time and too many systems.

Just offering ... if you ever feel like you want to work on peripherals, but don't want to dive into the absolute insanity that is the NGPC CPU core, I'd fully welcome you to work with me on emulating this system ^-^

> Wireless Communication Unit

"Dousing" to scan radio frequencies to give you cards ... wow. Not quite fish sonar, but ... move over, Soul Dollz and Barcode Battler. Sounds cool!

> General emulation of the link port and link cable would be outstanding as well, as no current NGP emulator seems to support multiplayer.

That is currently missing from every handheld system in higan (and the SGB2.)

I'm very open to it, but I'm not sure how to go about writing the IPC necessary. higan's cores can't be instantiated, so you can't have two instances in the same process. Plus, ideally we'd want to allow it to work over LAN anyway (I understand over the internet is impractical due to them expecting super fast responses.)

I don't know that I have the time to do it, but if anyone were interested, I'd wholly welcome teaming up with them to make this happen.

> I'm pretty sure the Setsuzoku Cable (NGP-to-Dreamcast Cable) is probably too much to hope for at this time

I always wanted to be able to link up with Dolphin for GBA emulation, but my GBA core is just too slow I guess.

NGP<>Dreamcast is similarly a really cool idea. Are there ... active open source Dreamcast emulators, currently? I don't keep up with the more modern gen emulators.

It would be really fun to devise some kind of inter-community standard for all emulators to talk to other emulators for things like GBA<>GC and NGP<>DC, and perhaps even GB<>GB. How cool would it be to link higan and mGBA together?

> it'd still be immensely helpful to have solid NGP emulation in Higan

The main issue right now is my NGP core is rather demanding, about on par with the SNES accuracy core, because of the ridiculous ADC and 26-interrupts that are nested and have priorities. And the lack of clear CPU timings so the MIPS rating is probably 4-8x higher than it should be. And of course, like all my stuff, it has a pixel-based renderer.

I've always been willing to put more care into non-SNES cores, it just never worked out that way. I really thought with the WonderSwan I might get there, but my WS efforts have been pretty much ignored by the world. If NGP support ends up being popular with people like my SNES support is, I'd be willing to add in a scanline video renderer, and to break it out to a standalone GUI ala bsnes (so I guess, calling dibs on bngp now?)

> Making sure weird and otherwise forgotten gaming hardware is preserved through emulation has become a bit of an obsession of mine

You're an absolute hero for that. Thank you so much for your efforts!


Top
 Profile  
 
PostPosted: Thu Mar 14, 2019 9:32 pm 
Offline

Joined: Sun Jan 26, 2014 9:31 am
Posts: 304
I'd definitely want to help Higan emulate those peripherals. That would probably have to be one of those "eventually" kinda plans. I just have so much on my plate right now and in the short-term future, but the NGP has really caught my eye. When I saw a video of the Wireless Communication Unit in action, I just couldn't get it out of my head. Working with an existing emulator would the best path forward (least resistance), so I'm all for teaming up once the time comes. I believe you once said that getting emudevs together was like 'herding cats', and endrift recently said something to the effect that we all basically work in "silos", so it may be time to break that cycle (at least, I'm guilty of doing it myself).

Thanks for the kind words as well! I'll be watching what happens from here on out. You've already posted a lot of interesting development notes, which have been fascinating to read so far. Like I said, keep it up, this is great work!


Top
 Profile  
 
PostPosted: Fri Mar 15, 2019 5:03 am 
Offline

Joined: Mon Mar 27, 2006 5:23 pm
Posts: 1518
> it may be time to break that cycle (at least, I'm guilty of doing it myself)

Myself as well.

The temptation is really high to be in control of decisions, and for these older systems it's very possible for one person to implement the entire systems alone. It's also a great learning experience, and really rewarding.

But when groups are required to do things, you can watch the progress of Dolphin, Yuzu, Citra, RPCS3, etc and just kind of feel in awe as to the amount of great work they are doing. It makes me envious to imagine the kinds of 2D emulators we could have if we all worked together like that.

While emulating an entire 2D system alone is practical for one person, emulating every mapper variant, every obscure peripheral, every coprocessor, every new test ROM gitch, etc ... is not. Then throw on needing to have a good solid GUI on every major OS, to have a great understanding of multipass pixel shaders, audio filtering and DRC, etc. That can easily take ten years to do. There's a few people like us so the NES, SNES, Game Boy gets done. But there's just not nearly enough of us for systems like the PC Engine, Neo Geo Pocket, WonderSwan, and Virtual Boy.

In my own case, I've always had great difficulty working in teams and not getting my way on things. It's a habit I am going to try my best to work on. I think if I ever work on a 3D system, it will be as part of a team. Presuming anyone would have me, hahah ^^;


Top
 Profile  
 
PostPosted: Fri Mar 15, 2019 11:25 pm 
Offline

Joined: Mon Mar 27, 2006 5:23 pm
Posts: 1518
If (0x6c14)=0xdd, (0x6c15)=0x00, then the NGP(C) BIOSes boot without going through the setup procedures again.
They're 0xff,0xff normally with MAME and higan.

I actually found this by a fluke. I think what has to happen is you have to power off the system with the system button to trigger the NMI in order to actually write out that the setup completed? Not entirely sure yet.

Still having issues with turning the system back on after having turned it off, it doesn't seem to want to boot correctly again after that.

Not being able to set the BIOS RTC time was due to a bug in ZCF. It's not CF=ZF, it's CF=!ZF.

The ports on this CPU are truly insane. You can literally force certain address/data bus lines to certain values on a bit-by-bit basis if you want. Every single port is for a totally different, totally insane to emulate function.

The BIOS seems to read and write (0xb4) and (0xb5) internal registers, but I've no idea what they are since they're not documented.

...

Non-bump edit:

I implemented all instruction cycle timings, along with all penalties for the ALU shifter, memory addressing modes, interrupts, and HDMA. Also improved an issue that was preventing INTTCx from firing repeatedly. That gets http://jiggawatt.org/badc0de/nymp.html running, but unfortunately the audio runs about twice as fast as it should. The pitch is correct though, so anything easy like halving the interrupt firing rate or somesuch will throw off the pitch. Not sure what's going on here, and I can't really get a trace log of this running somewhere else to compare it to. Shoot.

...

Another non-bump edit:

Fixed a major CPU bug in "ld xix,(xix+)". It loads (xix), then increments xix, then stores the loaded value into xix. Pretty standard, just missed it before. That fixes corrupt graphics in Card Fighters.

Also, it turns out incw #3,r and incl #3,r will not update flags, but incw #3,(mem) will. What the hell. That fixes input in Sonic Pocket Adventure and Rockman Battle Fighters.

The sound chip in the Neo Geo Pocket is quite weird. Turns out only the volume registers are unique, and the tone/noise pitch/control registers are unique. They took the time to decouple the sharing of tone 2 pitch and noise period as well, cool. Supposedly it's a 15-bit LFSR with taps on d0 and d2, although that's apparently not 100% right either. Doesn't seem anyone knows exactly how it works. I'm not even sure how anyone was able to analyze it since the registers are write-only, and there's no digital audio output.

There's a few serious bugs here and there still, but overall things are progressing quite nicely now. I did implement the two 16-bit timers because they tie into Vblank interrupts and the BIOS configures them as such, but I don't know if I want to attempt to support the stepping motor, DRAM refresh, or using ports as outputs to control things like chip select, address/data bus bits. The serial interface is definitely not happening until I figure out how to do linking between multiple higan instances.

I couldn't find any games that use the "D" button (from the SNK manual), so I unmapped binding it as an input for now, since having it would mean that "Option" would have to be named either "C" or "C/Option", both of which are super ugly.

Nymp still doesn't sound nice. I have a feeling that it's not synchronizing the DAC value generation and the NGPC audio playback, and is instead cycle timing things perfectly. If that's the case, then being off at all would result in the two desyncing and the CPU code overwriting DAC samples before they are played. So short of some heroic third-party assistance, it looks like this one's going to sadly remain out of reach for now.


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

All times are UTC - 7 hours


Who is online

Users browsing this forum: PSI and 2 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