Submind YouTube summaries
Thumbnail for Dumping and reverse engineering a very cheap NES phone case

Dumping and reverse engineering a very cheap NES phone case

Watch on YouTube

Video summary

The video documents an in-depth reverse engineering project centered on a very cheap NES/Famicom clone handheld purchased from AliExpress, which appears to be based on the VT369 chip and marketed as a phone case. After acquiring the device for five Swiss Franks, the creator opened it up to reveal an internal microcontroller with built-in ROM that initializes hardware and manages emulation via SPI flash storage containing titles like *Super Mario Bros.* and *Contra*. Initial attempts to dump the firmware using clip-on readers failed due to signal interference at high speeds of 90 MHz; consequently, successful extraction required desoldering the chip and soldering it into a socket. Despite physical challenges such as broken screens and poor contact points that necessitated hot glue fixes, the analysis confirmed the device runs an emulator rather than pure software on external ROMs, though full reverse engineering was hindered by inaccessible internal memory and proprietary extensions for graphics and audio handling. To overcome signal interference issues during data capture, the creator employed a unique method involving an old smartphone to record screen brightness changes while processing raw analog data with `ffmpeg` to extract individual frame values as binary signals resembling Morse code pulses. This approach initially yielded noisy results due to automatic brightness control and low resolution but was resolved by re-recording at 60 frames per second with auto-brightness disabled, resulting in a clean signal that decoded into valid machine code after manual corrections for missed transitions. Further analysis of the dumped ROM revealed startup vectors, SPI flash initialization routines, and evidence of multiple memory-mapped peripherals, including an internal boot ROM, an external EPROM likely used for configuration or copy protection, and a serial peripheral accessed via custom commands rather than standard I²C protocols. Although identifying Mapper 427 as the likely hardware mapping, the creator encountered significant hurdles when attempting to run the extracted images in emulators like Nintendoo or MAME due to incorrect register states, infinite loops from missing interrupt handlers, and mismatched hardware behavior that prevented full emulation without deeper research into Windows support. Despite failing to achieve a perfect software simulation of the device, the project successfully resulted in the extraction of all four ROM images: main flash, internal boot code, serial protection chip data, and EPROM contents. The creator concluded that while complete emulation was unlikely without further hardware investigation, they planned to upload these dumped files to community archives for others' use and intended to retrofit a working unit into a custom console in future projects not shown on camera.
Read the full video transcript
I have a new phone case which is also a NEZ. So, let's pull it apart and see what makes it tick. What this is is a cheap and nasty NEZ/Famcom clone. It's probably based around a similar NEZ on a chip device as this thing here, which I've played with here before. After Nintendo's patents in the original NEZ ran out, everyone and their pet dogs started producing NEZ implementations on a single chip that sold for very little money and were more or less compatible with the original NEZ. These things were available for almost nothing. I think this cost me five Swiss Franks from AliExpress and they are ubiquitous. If I turn it on, anyone who's played with one of these before will probably get flashbacks from the music. >> [music] >> Yeah, enough of that. If I then select English, you can see that what's on it is a million different we go. A million different ROMs. They're either straight copies, ROM hacks, ripped off public domain stuff, you know, most of them run. Some of them don't run very well. The compatibility of these things is not great. It's okay for what it is, which is a very cheap handheld games console with miserable controls. But if you want to play Mario 14, for example, this is where you go to get one of these. Now, I'm expecting this to be extremely similar. However, I learned of these from James channel, and he took the lid off one, and there's a feature inside that I am very interested in. So, let's just have a quick look at it. You can see in here that this is clearly a very different firmware package than on the sub. If I select English, here is the main menu, which again is quite different. These are all the usual collection of totally legal licensed ROMs. What I don't see are the ROM hacks, which are interesting. There are fewer of them. I think there's only 30 odd. Yeah, there's only three pages. and they are displayed in this interesting colorful title screen that I am not sure that the stock NEZ is capable of displaying which is rather interesting. The games are of course if I start one there we go the usual NEZ games and they run okay. I'm not experienced enough with the NEZ to know if this is running at the right speed or sounds right. All I know is there's a mushroom there. Sometimes I can reach the end of the first level. It's either clearly emulating the NES or it's got a Noak on board. And I suspect it's got a NOAK because that's the cheapest way to do it. If it was emulating, it would need a much more powerful microcontroller and you know that costs money. So, let's spudge this thing open. If I can figure out how to open it and see how it works inside. Maybe I should turn this off first. There we go. Huh. So, that was in fact glued together, but luckily it was really bad glue. So, what's inside our cheap Fami clone? Well, we've got the loudspeaker. We've got the USB connector providing power and only power. There's only a red and black wire coming from there. We've got a battery with a battery protection circuit, which is nice. We have a PCB and we have the screen. We also have 324 Ultra written on the board here, which could be a model name. Let's take the PCB off and see what there is to see. It's screwed together with a whole three screws. There's a hole here, but there doesn't seem to be a post underneath it for a screw. And I need to take the screen out as well. Oh, that's fun. The screen has been plastic welded into place. I wonder if I can get that off without breaking it. Someone's been pretty rough with this thing. Okay. Well, I don't want to risk breaking the screen at this point. So, let's lift up the rest of the works. Start by removing the USB thing, revealing absolutely nothing of any interest. So now we should be able to lift the speaker out of the way, which I think has actually fallen into two pieces. Is this bit glued down? Yes. I don't think that's really very good. Here's a piece of 3M tape that's just sort of Oh, it's double-sided sticky tape, but they haven't peeled the backing off. Wow, that's a choice. Okay, can we get the battery off? This is probably glued down, but I probably also don't want to puncture it. Yeah, that's easy. Okay, so now I can flip the board and see what there is. Oh, good. This is exactly what I was expecting. It's a simple PCB based around this epoxy blob. This will contain all the intelligence of the device. It'll either be a NOAC, a NEZ on a chip if this is using a NOAC, or something else. if this is using something else. These two 8pin chips, this one is bigger and there is a label on it, but I can't quite make it out from where I am. So, this is probably an SPI flash chip containing all the software. And this is something else. Power controller maybe. Here we've got all the various buttons. These things will push down on them, short out the two pads, and that's how the thing knows the button is pressed. And if you look over here, there's an unpopulated USB socket. If this PCB is close enough to the edge of the case, then they can just stick a USB socket here and not need the little daughterboard. So, if I put this down here and press The power LED comes on, the screen backlight comes on, and the speaker makes some very nasty scratchy sound. Yeah, I think that metal thing was actually part of it. Anyone who's seen my Tony games console video is probably going to guess what comes next. This is a flash chip. Let's dump it and see what's on it. Now, the first thing I'm going to try is this clip. I've never had good luck with these. What these are for is you clip them to the chip when they're on the board, like that, and then they let you read or write the chip without desoldering it. I've never been able to make these work. The problem is that when the chip reader powers the chip to read or write it, it also ends up powering the microcontroller and the microcontroller of course immediately starts talking to the chip and that interferes with all the signals. But let's give it a try and see what happens. I might be lucky and it would be really convenient if I were. Now I know that this thing is a windbond 25Q16 which Mini Pro knows about. So, I should be able to do this. And okay, well, it's reading, which is a good thing, but that's not a good thing. I think that we're getting a bad read here. It is interesting. It seemed to get the device and serial. Okay. What's in the ROM? Nothing. Yep, that hasn't worked. Fantastic. I'm going to have to remove the thing from the board. Here it is on the carrier board. So, we now uh drop it into the chip reader the right way round. And hopefully this will now work. Okay, what do we get? Right, it has correctly read the chip ID. See here it got zero. Here it got the right value. So I think we are now actually getting real data. And what do we get when we look in it? Stuff. What kind of stuff? Well, I see lots of zeros. And I see what look like jump tables or something like. So I don't think this is encrypted. Let's just run strings on it and see what comes out. Garbage. Garbage. Lots of garbage. There we go. Alpha, beta, gamma, delta, epsilon, theta, ea, theta, iota. These are this is the Greek alphabet. It is an unencrypted ROM. Excellent. The next thing to do is to run it through CPU wreck to try and recognize any machine code that happened to be in the thing. Now, since it's a NEZ, I expect it to find lots of 602 code, but it might find something else. Right. That's not impressive. It's found six bytes of 6502 code. Right. This This is garbage. So, the NEZ boots weirdly. If this is a real NEZ emulation, I would expect it to start with reset vectors, which would be somewhere up here, but there is nothing. If it's a different architecture, then CPU rag doesn't know about it. We did see plain text strings, so it doesn't seem to be encrypted. I wonder if this is hooked up by an SPI bridge. The bridge knows whether the actual CPU is reading code or data. Could it be encrypting the code reads but not the data reads? That would explain what we're seeing. That gives us like here this is a structured table 014D 014 014F etc. So that's clearly not encrypted. But the actual code part assuming this is code is all wrong. Well, I could try and figure it out by static analysis, but it'd be so much easier to just hook it up to the signal analyzer and see what it's actually doing. As you can hear, not quite right. If I reset it, it runs fine for a bit and then glitches out. So, what I think is happening here is that my wires are too long and I'm hitting various capacitance issues. That's fine. I can always shorten stuff. And it runs for a little bit. So, it's is at least getting to the bootup sequence, which is good. Let me just reassemble this so I can see the screen. Now, it's not working at all. I suspect something's shorting out here where all the wires are bunched together. Or then again, possibly not. The thing is, I shortened these wires in the hope that it would work a bit better. It doesn't. it works worse. If I try to reset it, there is a faint click from the speaker and nothing happened. So, I immediately went to my oscilloscope to see what I could see. And not only could I see things, I saw them happening at 90 MHz. That's really fast for an SPI chip. Not only is it really fast, it's really out of my comfort zone when it comes to electronics. And I don't think this horrible bundle of wires is going to cut it here. I think this is going to need short traces. So, I'm going to have to change my plan slightly. I'm going to solder this thing on, which is a ze socket attached to a soic 8 adapter. I've used these before. They've never really worked very well. Turns out the cheap PCBs don't really like have anything this size hanging off them. So, I'm going to also have to apply lots of hot glue to hold it on. I'm not going to be able to put this thing back together and I probably won't be able to make it so that I can see the screen, but I do want to actually get the thing running because this is going to need rather more serious signal analysis than I thought I was going to need. I don't even know if my signal analyzer goes up to 90 MHz. I was expecting, you know, 8 16 Well, here it is after some very fiddly soldering that I couldn't do on camera. So, we insert this thing like this. I haven't done any of the hot glue yet. I want to see if it works first. Yeah, I don't like doing that. Okay. And power. Nothing has happened yet. Now, let's try the on button, which is here. I said it's here. Okay. Have I got the power wrong somehow? Wire has fallen out on the power supply. There we go. Oh, that's interesting. That wanted to draw more than 150 milliamps. That suggests it's trying to turn the light on, which is good. Why didn't it hit that limit before? I do know that this carrier works because I managed to read the chip. So, at this point, the possibilities are I've broken it or I've broken the chip or the signaling between the chip and the board is simply not working right. I fired up the oscilloscope and that is showing something rather interesting, which is if I check the power line on the flash chip, that little bump is all that's happening on the flash chip. It's not powering up the flash chip. One thing I found which is exceptionally weird is if I do a continuity test of these two pins. This is power to the flash chip. I think I've shorted something together on the board. Either that or I fried the power controller chip. And look here. Here are two components that appear to have dripped solder on. Let's clean those up a bit. and then see if anything's changed. So, I just spread the solder around a bit and what do we get? Nothing. Okay, I think that could well have been the problem. So, I shall carefully stick the flash chip back in. This thing needs rather more force than I'm comfortable with. It's a ze socket. It's not supposed to use force. Okay, it's the right way up. 3.8 volt to the battery terminal and hit the onoff button. Oh, red light. Ah, I mean the speaker is not making any horrible sounds. Let's try reset. Nothing. Ah, maybe I should reconnect this wire. Nasty scratchy sound. And it's not glitching out. Okay, the board is running, which is nice. I haven't broken it. I really ought to start ordering two of these things. So, now I have it working. All I need to do now is figure out how to capture the SBI signals to the flash chip. So, this might be harder than it looks. Let's take a look under the scope. In QSBI mode, this pin is the clock signal, which indicates the highest resolution we need to capture. That is registering 8.5 MHz. That's not the 90 I was getting before. I wonder if this is working quite right. If I zoom in on one of these fast bits, does the signal change? Okay. Yeah. Now it's registering 90 MHz. So I think that previously like this it's seeing those big dips as the frequency it's supposed to count. So I think that each one of those dips represents a single SPI command as it's reading bytes from the chip. And you can see that it's all structured very nearly the same. So I think it's just reading a single bite at a time, which is very characteristic of an SPI bridge. So now I need something that can capture 90 MHz signals. Given that my trusty clone signal analyzer has got 24 megahertz written on the front, I don't think this is going to cut it. This setup deeply offends me. I'm going to have to build a jig. To do that, I need to take the screen out. Now, this side has already popped due to my general mishandling, so it may come out reasonably cleanly. That was a nasty noise. It's a very bad screen. Okay, that bit's come out. I think. All right. So, now at least I can place it where the screen is visible. Let's try some power and go through the rather complicated startup process. I don't think it likes having the battery repeatedly disconnected. So, it does this for a while. Doing various combinations of reset does help. There we go. And oh, good. The screen is working. So now I should be able to attach it to some kind of test jig where everything is just a little bit more, you know, more than stray component on my workbench. And here is the finished test jig. It is largely made out of wishful thinking and hot glue, but it does actually work. I discovered a bunch of stuff about things such as the fact that there's a huge inrush current when it starts up and the lithium battery could provide that, but my power supply can't. On startup, the voltage would drop just for a moment, but that would be enough to cause the battery controller chip to cut the power, thus causing it to boot loop. So, a big capacitor solved that. This thing is 3D printed and made out of some Cherry clone key switches and key caps I had lying around from another project. It's actually pretty nice to use, although Nintendo games don't tend to react well if you press both left and right or up and down at the same time, which normally can't happen because of the D-pad. But, it does all work with one minor proviso. Let's see if you can spot it. Yes, I got careless and broke the screen. More fragile than I thought. This doesn't really matter. I'm not going to use the screen for anything. All I need to know is that it works, which it does. So I can select Super Mario Brothers, start it playing and you can actually see and hear on the remaining bits of screen that it is all present and working. I'm not very good at Super Mario Brothers. I can replace the screen possibly with the one from the other Nintendo clone that I've got, which I'm also never going to actually play games on and is much less hackable than this one. The other one uses a parallel ROM rather than the serial flash chip here. Or maybe I can just order one off AliExpress. Well, I'm going to deal with that later. For now, it's working well enough for my purposes. So, all I need to do now is to turn that thing off. is to hook up a signal analyzer and capture all the traffic to the flash chip when it starts up. And as this thing runs at 90 MHz, I need to capture at least 180 million samples per second, which is a pretty tall order. So, I'm going to have to seek outside help. So, here I am in a maker space with a seriously expensive Sala A Logic Pro 16 capable of doing 500 million samples per second. One end is plugged into my device and the other end is plugged into my laptop. So, all I need to do is go over here and hit the start button like so and hit the power button like so. The light comes on and the data comes in. You'll notice the screen hasn't come on and it's not making nasty noises. That is unfortunately because the logic analyzer itself is corrupting the signal. This is like 90 megahertz. It's a pain to deal with. But I don't need that much data. So I'm just going to do multiple reads and hope that the bits I need will be uncorrupted. So, I'm just going to keep doing multiple captures, and when I get about 10 or so, go home, I suppose. Here I am at a desk with a mouse and a real microphone. And let's see what we can see. Here I have the capture, or rather a segment of it. I've top and tailed it so it's not dealing with like 3 GB of data. And you can clearly see that we power on then there's a blip as it does something then there's a pause and then it goes completely ham on the flash chip. So I suspect that this is initialization and this is when it starts executing code directly from the flash. So I have already hooked up the various analyzers. So, let's zoom in on here. And down the bottom here is the SPI clock. By default, every time the clock line goes up, the device will sample the master out slave in line, which is this one. And eight clocks gives us eight bits and a bite. And it has in fact transferred 06 which is the write enable command. And yes these all look like actual commands. So you got write enable. FF is not understood by this tool but it is in the data sheet which I've got here. Exit QPI mode. This was just part of resetting the flash chip. We read a status register. So here you can see eight clocks some traffic from the device to the chip that's sending the command and then here the chip replies with some data. So status register contains two. So that seems to be a fairly normal startup procedure. Then it does some stuff I don't really understand. It looks like it's sending commands to the flash chip. But the way the computer tells the flash chip a command's coming is by dropping this line, which is the chip select or enable line. So you can see that each of these commands here, it drops chip select, does the command, raises it again. So these are just going to be ignored by the flash chip. So I don't understand what's going on there at all. But then there's a long gap and then some more stuff happens. And here here is where it gets interesting. Yes, I have had a look at this before so I know what it's doing. We send the E7 command. 1 2 3 4 5 6 7 8 clocks. E7 is again not understood by this tool but it in the data sheet. And it is interesting because it is E7 write word read quad IO. This is the QSPI read command that's doing all the heavy lifting. If you look at this diagram, it sends the 8 bits of the command using normal SPI stuff. Then it uses QSBI mode to send 32 bits of addressing information and then it starts streaming data back from the device. Because there are four lines once it's in QSPI mode every clock transfers four bits that is a nibble and things are arranged so that we can just read off the address. This line here is the QSPI value being transferred. So what's happening is it sends the command. It then does 16 clocks, eight clocks, eight clocks transferring the address. Then there's a pause where the computer that's controlling all this sends two clocks and nothing happens and then it starts reading data. every two clocks transfers a bite. So the address that it's sending is 0 0 0 A5. If you look at the data sheet, there are in fact only 24 bits of address. The bottom eight bits are flags, therefore not part of the address. So, the actual address being read is 000000. Reasonable enough. Okay. Send the flags A5, which I'll get to later. Then there are two dummy clocks. And then the flash chip replies with 3 6 5 9. So, it is reading from address zero. Is it? Well, let's go over here to the hex dump. And if we go to address zero, you can see 3 65 9. We have successfully figured out that this is reading from the flash, which is is good. Okay, those flag bits A5. Now, according to the data sheet, the bottom four bits are ignored. In the top four bits, if they are set to ignored, ignored 1 Z, then we enter fast read quad IO mode. What this is for is to allow data to be read much more quickly from the device. After the current command is finished, chip select goes high, then it remembers that it's in this mode. When chip select goes low again, you don't have to transfer the command, which is of course 8:00. You can just get started directly transferring the address in in QSBI, which only takes, you know, 8:00. So, you eliminate 8 clocks worth of overhead entirely. So, here we should be seeing another read. I actually think it's lost clock there because that should be another zero anyway. Uh, I think the address is 000 1 A12. Then we've got A5 as as flag byes 55 as dummy and then we get C F09 and then chip select goes high meaning the end of a read. So the address is 1 A12. So if we go to A12 here we can see CFO9 CFO 9 chip select goes high chip select goes low and then we do another read. So I think I am successfully decoding the reads. And if we zoom out a little, you can see lots of reads one after the other as fast as possible. And it just keeps doing this forever. In fact, something is going wrong somewhere because the device is crashing, which is why when the signal analyzer was hooked up, we weren't getting any music. That'll be because 90 megahertz signaling is kind of touchy and having the signal analyzer attached is interfering with something, you know, like this clock not showing up. But I think I now have enough information to write a little program that scans the dump and figures out the addresses in the flash that it is reading from. Well, here is my program which decodes the reads from the logic analyzer capture. And because the capture is complete garbage, it's full of dropped clocks like there. I can't trust any of the data that the capture has produced. So I just pulled the bytes out of the ROM dump. And here are the results. And I am very confused cuz this is not machine code. It's reading pairs of bytes which all follow the same format. A slowly increasing low number and a more or less constant large number into lead with occasional reads from somewhere else. And this just keeps going. I think this is the audio streaming or at least it's trying to do audio streaming. these other things. Well, 15A, if I go to 15A, there's this big block of high entropy stuff at the beginning of the ROM. And this is where I would expect to find, you know, startup code. And it's reading some stuff from there, but the patterns don't really match machine code either. What I was hoping to see was clear patterns of this thing running programs from machine code and then I would be able to see things like function calls and determine where it's returning from a function and I know that has to be an RTS instruction. So that would give me a handle as to decoding whatever they've done to the 2 machine code from this. So I don't really know what's going on here. I wonder if there's a onboard ROM inside the blob that's doing a lot of the work. Maybe this is in fact an emulator and this is running a high-speed microcontroller and when the microcontroller runs the NEZ programs, it, you know, emulates it in software. But yeah, I'm going to have to tackle this in a different way. So, this is interesting. You're looking at my power supply which is currently turned on and showing the current draw. Currently zero. If I turn it on, current draw goes up to about 90 milliamps. Now, if I select a game, it goes up to 120 milliamps. This is suggesting to me that this thing is running an emulator and that when it's displaying the title screen, it's mostly idling and so is using less current. But when it starts the game, then whatever microcontroller is in this thing is running flat out emulating a NEZ, hence why it's using more current, which is kind of surprising to me because if this was an emulator, I would expect there to be a external ROM with the software on it. this relatively slow initialization of the SPI flash where it does one bite and then there's a long pause and it does the next bite does look rather as if the internal microcontroller is running its own code and then this huge long delay before it actually starts doing anything much with the flash. So, that does point at a microcontroller with its own ROM, except I spent some time poking through the flash figuring out what various bits were, or at least labeling them so I could identify them. I did find the ROMs for Super Mario and Super Contra which are at half a megabyte and 1 megabyte respectively. And above half a megabyte there's a whole bunch of relatively structured information and some stuff I haven't been able to decode. So that this for instance definitely does not look like machine code. It doesn't look like it's compressed or anything like that. This looks like an image, but it's not in any format I can decode, but there is also some chunks of actual 6502 machine code, which is what this is. Turns out CPU wreck was lying to me. It had completely failed to detect any of this or the actual NEZ ROMs that were in the flash, which is irritating. So, what are these? Well, one possibility is it just happens to be another NES ROM of the set, which I have yet to identify, but I don't think that's the case because it's surrounded by lots of emptiness, like quite a lot of emptiness. Also, the way NES ROMs work is they're divided into 16k pages. Some of the pages are program data and some of them are character data. The program data is accessed by the CPU, the character data by the ppu. And this block here is not aligned to a 16k boundary and is remarkably small. So I don't think this is a NEZ ROM. The other thing is that NES ROMs do have to have the standard 6502 reset vectors up at the top of memory. So I would expect to find them here. They're not here. So I don't really know what this is. If I disassemble it, I can go here to Imhex's disassembler. This, by the way, is Imhex, a binary analysis tool that I've been playing with. It is pretty good. It's its big feature is that you can it's got this scripting language which lets you define the structure of your binary. And when you run that, it will then apply the structure to the binary and pass it for you. So, here is the disassembly of that piece of code. And it looks like it loads at 6,000 hex. You see there's a JSR 6030 here. And 6030 here is in fact the start of a sub routine. And 6,000 hex is actually a valid location in the NEZ and it points at something in a cartridge. This says cartridge RAM, but this is entirely up to what the cartridge does. So, this makes sense. But looking at it, it seems to be a lot of little sub routines. So, not actually standalone code, but further down there is another block of 6502 code, which is this one. And this is aligned to a 16k boundary. And up at the top there are indeed some bytes. These bytes do not make any sense as reset vectors. So this is the address 0103. They're actually pointing into the 602 stack. So that would give 0103 as the interrupt vector, OCB as the reset vector, and 010 as the NMI vector. Uh where are they? Yeah, I mean these make sense as addresses, but they don't point at the ROM, they point at RAM. So something in here would have to initialize that. Now the interesting thing is that while this does look like a piece of NEZ ROM, I would expect it to be followed by the character ROM, which it's not. It's immediately followed by the Supercontra ROM, which is all of this. So this is peculiar. Now, I do not know how this thing actually finds the various ROMs. Somewhere there must be a table telling it which ROMs are at what location in the flash and what NEZ mapper is using. The mapper being the the memory manager chip that NES cartridges have. Emulators have to support all the various different types of memory managers. These are called mappers and they're identified by codes. If you download a NEZ ROM image like these ones I have here perfectly legally up at the top there's a header which is not part of the NES ROM at all. It's part of the NES file which tells it how many program ROMs there are, how many character ROMs there are and these two bytes contain various flags including which mapper is in use. Of course, this thing doesn't use the NEZ format, so there must be something somewhere. But my suspicion is that this stuff in the blocks I've labeled MC1 and MC2 could be part of the menuing system. That's only really a possibility. It's possible that the menuing system is done entirely by the onboard microcontroller. I would think this would be unlikely as it means that it has to be baked into the the mask ROM inside the blob and therefore is very difficult to modify. It's possible. If that were the case, then all of this stuff at the top would be the various menu images and so on in a fixed layout that the microcontroller ROM is decoding. But the more flexible way to do it is the menu is just yet another NES ROM. And if that were the case, then these two machine code blocks would be it. So I could try to reverse engineer these. If I disassemble the big one to to 8,000, what we got here is like perfectly normal 602 code. So this would be the entry point to the ROM. Probably if we jump to C378, which is here, which is a completely valid address because this is just after an RTS. This is where I'd expect a sub routine to start. 6383 is here. This is storing stuff into addresses in the 4,000hex range, which is exactly what we'd expect because this is where the various NEZ registers live. And it goes away and does stuff. Sad thing is that I haven't found much in the way of where are we? In the wrong place. This one. Haven't found much in the way of useful strings. I have found this cube technology company right by Anthony. Cube technology do have prior form in the bootleg nez world but I don't think this device that I'm dealing with matches anything listed here that I need to check this in a bit more detail. So, this does suggest that we're looking at something that's not just a ripped off nezrom and that this is something that's specially been written for this device. So, what I'm wondering is this capture that I got, it could be complete garbage. If the capture hardware was interfering with the signal enough that it wasn't booting, then it could never have actually been getting anywhere other than the very minimum of the startup sequence. So, it's entirely possible that this thing is supposed to be executing that startup NESROM, but is never actually getting there. I have no idea. So, I think I'm just going to have to disregard the capture entirely as being of any use whatsoever. That means that the next steps for reverse engineering this are going to have to be analytical, decompiling the ROM somehow or via experimentation. And the simplest experiment is to simply modify this startup ROM. We got at 7 CO is JSR 738. So if I change that to 4 C O C N and disassemble it again, we have a jump to C O. This should be an infinite loop. So if I write this to the flash, boot it, and the menu appears, then clearly this has nothing to do with the menu. If it hangs, it's hit this instruction. So let's try it and see what happens. Programmed, plugged in, power on. It's hung. Great. This is good news. That means that that piece of NEZ code was in fact part of the menu. This means I can now run arbitrary code on it. Although that arbitrary code does think it's a NEZ. Okay, let's do some more playing. Progress has been made. I loaded the menu ROM into GDRA, which you can see here. Here is the fingerprint left by our mysterious Anthony. It now occurs to me, is this Anthony the same Tony who wrote the code for the other thing I reverse engineered? Anyway, this is very clearly a NEZ. It's doing stuff with NEZ registers. It looks all NEZish, but it's more than that because it's also writing to a bunch of non- NEZ registers. And this is extremely indicative of one of these a VT369 or or really it could be any of these VR technology nox but I think it is the VT369. This is the most advanced NES on a chip clone. It's got lots of fun stuff like, you know, hardware multiplication and division, super fast CPU, 8 bit per pixel graphics, high resolution. This explains nicely why the menu that I was seeing before I broke the screen doesn't look like a NEZ. Once I figured this out, I then did something I should have done a long time before, which was I took the SHA1 fingerprint of the ROM I've got and I looked for it in MAME. And here it is. So, what I'm looking at is a 36P case. That is the double quote official double quote name for my device. And yes, there is some NEZ support. It doesn't actually work, but someone has seen one of these things before. Now, the reason why it doesn't work is that if I go up here and look into the memory map here for the VT369, there is a 4K ROM built into the CPU which handles stuff like initialization. And this very nicely explains this slow initialization that I was seeing in the SPI dump. The machine has started up. It started executing code out of ROM. It then goes and initializes the SPI flash does some stuff and only here does it actually set up all the things so that it starts reading from the SPI flash. And in fact the weird memory patterns that I was seeing can be very simply explained by this is a NEZ. It's got a pu graphics processor and an APU audio processor and they're going to be reading stuff from the ROM continuously. Like the PPU is going to be reading stuff from ROM just to draw stuff on the screen. So yeah, the actual CPU traffic is going to be buried inside here somewhere or not at all if the system crashes before it gets to that point. So somewhat sadly, it seems that this thing is actually pretty well understood, which makes my life considerably easier, but also means that there's not much to do with it. However, I said earlier that the main support for this thing isn't very good. In fact, it doesn't work at all. It just produces a gray screen. In fact, let me show you. we get a big warning that it doesn't work and we get a gray screen. The reason why it doesn't work is because nobody knows what the internal ROM is for this device. That's the internal ROM is the thing that's actually like initializing everything and handing off to this. Which does make me wonder, can I find a way to dump the internal ROM? The internal ROM is of course baked into this lump of epoxy here and completely inaccessible. So I would need to find a clever way to do it. I've already established that I can execute code on this chip. So I could write some code, stick it on this that reads the ROM and makes it available somehow. This thing is pretty short of IO ports. I do know where the IO ports are in memory and the buttons will be connected to them, but I don't know if they're birectional. They will of course be set up for doing reads by default. So, I might need something else. One of my tricks for doing this is to do reads from the flash in a particular pattern that my signal analyzer can pick up. But given how much traffic there is, that doesn't seem like it's a good idea. But there is one IO port that should be easily accessible, which is the one that turns the backlight on. There's also the audio, but that seems like it would be too much work. If I can identify how the code on this chip here is turning the backlight on, I can turn it on and off in patterns, read that with a signal analyzer, and bit bang serial bites slowly out of the thing and capture them. This will require analysis of the menu ROM on this thing to try and figure out what it's doing. This ROM is quite interesting. It's clearly divided into three parts. The reset vector at the end of the ROM points at CBO, which is a little unusual because normally you jump to the beginning of the ROM just because that's where the first bit of code is. Then below it, there's a big expanse of nothing, followed by some what look like library routines. And above it, starting at the beginning of the ROM at CO, there is another big chunk of code. This is the thing that ends in our write by Anthony string. Now the interesting thing about this is that if you go look at the decompile code, it's doing something and then it's looking at the values in CDO and CD1 and depending on what numbers it gets, it then sets different values to the pointer in address 8 that gerra is failing to decompile properly. And once it's done all that, it then goes away and does something with it all. And I've seen this before in the Tony. I think that what we're looking at here is code that's detecting what LCD panel is installed. That's done by this function here. And then it's using different initialization tables. So if I go look at C9 AF, well, okay, that's not doing a lot. But down here, we get triplets of register two values. register two values and so on until at the end we get two FFS and that's what tells it to stop. So I bet that if I could find a table of SC7789 IDs I should be able to find all of these things. But this means that what we're looking at here is the LCD initialization code. So I think what we've got is a basically a cut and shot ROM where it's assembled in a fairly slap dash fashion from binary chain. Got the library stuff which is not not there. It's here starting at F50O. We've got the the initialization stuff that is agnostic to the various different VT369 devices. And we have the chunk of code at the top that is initializing the extra hardware. So this suggests that the actual menu we're seeing is probably not in either of those two. It might actually be up here. There's not very much code here. But anyway, what I was looking for is the LCD initialization. So I bet that somewhere inside this function is whatever it's doing to turn the LCD backlight on. And that's the only bit I'm really interested in. So if I find where this is called from, which is here, and I put my infinite loop here just after the call to CO, and I flash it and I run it, I might be lucky and see the LCD come on, and then hit hang. I've reflashed and installed the chip. Power on. Press the on button. And let's see what we see. No backlight. Okay, I was wrong. Something else must be turning the screen on. But that does give me a useful lower bound. We know that the screen backlight on thing must be after the piece of code I patched. So we are actually making progress. Incidentally, I know I haven't broken it. I'm not sure how well this shows up on camera, but if I turn it on, stuff is actually appearing on the screen. It's just the backlight hasn't turned on. Right, I've got the other bound. I can do this. It's this. If I put my infinite loop just before it, the backlight doesn't turn on. If I put the infinite loop just after it, the backlight does turn on. And if I look at it, it's poking a couple of registers. And these are some of the many undocumented VT369 registers. But it is clearly setting a bit in 4144 and clearing a bit in 4146. And purely coincidentally, if we look down here, here it is setting a bit in 40144 and then setting the same bit in 4146. I bet this is turning the LCD on. And this is turning the LCD off. Okay, I should be able to control the LCD now. So here is my absurdly simple test program. We simply call the LCD on function and then we infinite loop and then this gets patched into the binary and we flash it and we power it on to see what happens. LCD comes on. Great. So, all I need to do now is to figure out where the backlight transistor is on the board. There's a number of transistors, so that's going to be irritating. Hook up the signal analyzer, write some code, and start clocking data out. Here is my test program. It is very simple. It just clocks through all the bytes in the ROM and sends them out in standard UART format at bit banging at about 30 boardish. Assuming I did this right, it should give us a nice clear signal that I can then read off using my logic analyzer. Unfortunately, there are two minor problems. The first one is the board's broken. It appears that me putting this chip in and out all the time has wrenched something and something in here is no longer making good contact. If I push down here and reset the board there, my program is running. You can see it blinking the backlight. But if I let go, it stops. So, I'm now very torn between taking this thing off and resoldering it and potentially breaking the board even more or bodgeging something. As you can see, there is rather a lot of hot glue in there and dealing with that is not going to be fun. The second problem is that my logic analyzer here which I do have hooked up there it is connected to ground and data is refusing to actually pick up the signals from the program. I don't know why the voltages look reasonable. It's about 3 volts oscillating up and down from zero. I can see the signals perfectly clearly on the oscilloscope. But this thing just returns a logic one for everything, which is deeply annoying. So, I'm going to have to go away and do some thinking. So, let's solve one problem by changing my program. So, now instead of clocking stuff out in new art format, it now clocks it out in Morse code and also quite slowly. I'm using Morse code because it's relatively robust over poor signal carriers. The second problem is solved using this rubber band here which puts tension on the socket and makes it make connection. So now it does actually work. If I reset the board, there is my program running. The third step is this phone. I'm going to use this to video this. Three hours later, I get my video, which looks like this. It is all done at a super low resolution because I knew this video would be huge. And the only thing I'm interested in is the brightness of the screen. You'll notice that the brightness does vary rather more than it should due to automatic brightness control, but I'm hoping that it will work out. out. Anyway, so what I do next is use this ffmpeg command. It scales the video down to one by one. It converts to grayscale and it outputs it as raw video like so. And you see that this video is 311744 frames long. If we look at the output file, it is 311744 bytes long. This means that each frame becomes a single bite of brightness in the file. Here's pulse view. I haven't tried this yet. Okay. Import raw analog data without header. All files. And here is our video file. And the data format is unsigned 8 bit one analog sample rate don't care. We get stuff when I zoom in. What do I see? It's not great, but that's a short long long long gap. Short short short long gap short short gap. Oh dear. I don't like this. Uh I think that gap here is actually okay. The format that this thing has been sent out as is basically hexadimal. So it's two nibbles encoded as Morse. But I think this is way too noisy to decode. So here is short long gap short. So short long is a and a single short is an e. Okay, let me try and clean this up a bit. Here is my very shoddy Python decoder program. We run that, we get a text file containing this. It's actually a CSV file. The decode is not perfect. There are some few bad entries such as this one which is at 570. So if we go look at that, it's in here. 5700. Here we go. I'm using Pulse View to actually turn the analog signal into binary. And there's a little dip there that actually should be between two DARs, but it hasn't registered. So, there is a missing space there. So that should really be five, which happens to be a zero. So I'm just going to manually fix this up like so. Okay, the next one is 64310. What's this? 642 6430. Same issue, but between two dits. So this should actually be dit da da da. So that's going to be da da da which happens to be a two. I've got one there. And the third one is here where very clearly it's not registered the gap between the two digits correctly. Let's just check that. 92354 354 should be in here. three. Yep, it's this one. Here we go. Five DS, five dits. But this gap is just too short. My decoder expects this to be four or more. But if I change the threshold to three or more, then it actually makes things much worse because there's some of these gaps here, which are three samples. So that's actually going to be a zero followed by a five. Okay. And that brings me to my second shoddy little program, which is this, which actually turns the CSV file into a binary like so. And this has produced a 4094 byte binary. Uh, that should be 4096. There's two bytes missing at the end. All right. So, stupid bug on my part. There's a oneb here that should be down there. So yeah, I need to do another one of these at the bottom of the program. Do not write Python like this. This code is terrible. Oh no, wait. That needs to be there. So it's now 4095 bytes, which is still not right. Here's my emitter. We start out at hex 10,000. We read a bite. We emit it. I nibble first. We increment the address. And then we check to see if we've rolled over to hex 2000. [gasps] [sighs] I don't see anything particularly wrong with that. So, I'm wondering if there's an issue somewhere in here where two bites have run into each other. Let's actually take some of these out and try that again. Aha. Aha. T9. Well, that shouldn't be there. which is here. Yeah, that's bad. But this won't affect the number of bytes. It's just a bad bite. I have no way to detect edge cases like that. There's no check summing or par or anything. So, I think I'm actually not going to fix that by hand. What I'm going to do is to rerun the whole 3-hour capture again in better conditions and hope I get a cleaner signal. I think I redid the recording. I used a much better phone that was capable of doing 60 frames per second. I also turned off the automatic brightness control. And as a result, we now have this beautiful crisp clean signal which is so much better than the old one. And after running my decoder, we end up with this file here. Now there is one odd thing which is there is a single bad decode 454708 here. You notice that there's this kind of long pulse here with a tiny little dip in the middle. That should be two DS. This should be a whole this whole thing should be a zero. So I was curious. So I went and checked out the video and in fact there is there you know spots that the brightness decreases slightly. That's all you get. So this is not a decode for an FFmpeg or a camera problem. It seems that the actual device has done something weird and I don't really understand why. But anyway, we know what it should be. It's another zero. So, let's just manually fix that up to about Yeah. Oh, 454 708 like so. And save that. And now I can decode it to bytes. Ah, that's not good. [clears throat] That should not be an O. 574317. Something is deeply wrong there. Each bite is two nibbles which are transmitted as two characters with a medium gap between them. So this is five DS gap. Five DS meaning 0 0. This is just three DARs. Wait, there's a small gap here. Oh, I know what's happening. This should be another DAR. Why isn't there a DAR there? Okay. 574300 1020 574320. That's That's off. That's the end of this dark. Off. Something happened. Off. On. I have no idea why that happened. It's probably the same issue as the other one, but that's really strange. Luckily, this is a long run of zeros, so we know what this should be. Like so. And now we have 4096. Is this correct? Doubtful. So, let's stick this thing into GIDra and see what happens. What have we got? We got stuff disassemble. Yeah, that's 642 machine code. That's That's not I wonder if that's a decoding bug. There are more bad bites here than I was expecting. I wonder if something else is going on. Also, some of this machine code looks weird. Why is it doing that? For example, possible this is not actually machine code. What's at the end? These look like 6502 startup vectors. Now these Yeah, that's code. That's Yeah. So this is it's it's one of the it's the IRQ. So yeah, this is going to be the startup ROM that the thing uses to actually initialize. Uh this is the reset vector, the main entry point which is here. Does this disassemble? That's so much better. Okay, I think that stuff at the top was not machine code. This means that my read actually looks plausible. Okay, that looks a lot better. So, it's doing stuff quite a lot of stuff. So, not actually that much stuff. So, this is the code that I expect to actually be doing the SPI flash initialization. So these are all registers that are unknown. I haven't found any documentation for them. This is very clearly waiting for something to be ready which is called from a whole bunch of places. So here we are sending bytes to a thing then we wait. Then we send more bytes to the thing then we wait. This is talking to an external peripheral. In fact, these numbers look faintly familiar. Let me pull up the logic analyzer view of the SBI flash. Okay, what have we got here? 06 FF 05. And that's coming back. 06 FF05. There's an 06. There's an FF. There's an 05. They're all being written to F to 4301. What's the next right to 4301? 35. So, what's the next bite that goes in is a 35. Okay, we found the SPI flash command and control registers. This actually suggests that the block at 430 is where the whole SPI ROM interface control registers are mapped. So I think that this is the SPI write data register and this is the SPI read data register. I'm actually going to rename some of these. This is TX and this is RX. One of the oddities of the SPI protocol is that the host, the controller controls the clock signal, which is the one down here. So if the device wants to send something back to the controller as is happening here then the host has to clock out the 8 bits so the device can send stuff back. So in fact sending and receiving on SPI is the same. The the SPI controller on the well controller has got two shift registers one for outgoing and one for ingoing. So this is filling the outgoing shift register with 35 and it clocks it out with this. It hasn't filled the register with anything which is why it's a zero but the device is sending stuff. So the receive register fills up with two. So the way we expect it to work, uh, here's our write to 35 is that we send the command. We then do another dummy transaction which populates RX. We then pull the value out of RX. I don't know why it's writing to RX here. That's completely speurious. If you go and look over here at the machine code, it hasn't actually initialized a with anything. So, the only reason it's done that is presumably to reset something inside the SPI controller. Okay, back at the dump, we then have this big long pause while the the ROM does stuff. And then we output an E7, which shifts the whole thing into quad SPI mode. Is there an E7 here? Doesn't look like it, but then I wouldn't expect it to be. That long pause suggests that it's finished doing this and it's gone away and done something else. Anyway, let's take a look at some of these functions. What's this doing? This is a delay loop, right? This is going to be our big long pause. And then we initialize a whole bunch of other stuff, including waiting for some SPI transactions. This actually looks like a very different system than the one that did these rights. These are sent a bite at time. Eight clocks each. These actually involve multiple bytes been sent consecutively. So I think that by this point we are no longer using that simple SPI flash command set. So what does this do? Oh, this is big. So this is doing a whole pile of initialization of other registers. These are now in the 41 block rather than the 43 block, fiddling with the power control. And then here we reset the system. By this point, the SPI flash must have been set up and this will be read out of the SPI flash. Here's an interesting thing. Looking at that very first startup routine, I can see that it looks at something in 41F and then depending on the result, it does one of three things. If this bit is set, it goes away and initializes the SPI flash which we've looked at which at the bottom of it calls 1 A2F. If however the top bit is clear, it just calls 182F. Then there's a third initialization thing which is 1904 here which is it's a different SPI flash initialization. So whatever that's doing clearly what this is doing is looking to see what kind of ROM the device has and going down the appropriate initialization route. And this one is I think if there's a memory map ROM. So I don't think this is anything to do with the SPI flash. In fact looking at this second initialization routine and the the results of the logic analyzer I think this is the one we're using. This is the smaller simpler one. And in fact, this is the point where the chip select line goes high and it just starts doing gibberish. The last two commands before that were 35 O read status register 2. 35 is the command and this is the result which is two. I think this one is this. So in fact it has read status register. It then does a command 26 and there's a long pause. Then it starts doing more stuff. So I think this is switching it to quad SPI mode. But there's more. Someone on the bootleg ROM forums who dealt with similar devices pointed me at this piece of code. Once the main ROM has started up, not the internal one, the one on the SBI flash, it reads bytes out of an external peripheral and stashes them into hex EO. And then this is a code library that's used by the rest of the system. And I think this is a copy protection system. This I squared CROM is inside the silicon blob where you can't get at it. The fact that it's read by the SBI flash means it's all completely useless. It's just annoying. So, I don't know what's going on there. But I'm going to have to dump that as well. And this is a bit more complex and a bit weird. This is Gidra doing a very bad job of decoding something that is reading in data one bit at a time. So this thing is telling the ROM to clock out the next bit. This is then read as part of some status register here. What it's actually doing is it reads the this will be a status presumably might not even be I squ C but it's shifting the value up until it rolls off the top of the bite into carry and then it shifts the carry into the bite being read. So eight times round and it will read a bite and then just repeat that until it reaches the end of the block. This bit is a little bit more complicated again. Gidra has failed to decompile this O2 code correctly. I don't think this is reading anything. I think this is initializing the ROM device that I'm now thinking is not actually I squared C and it may just be some serial bitwise shift register. But I am going to have to figure out how to dump this. So I'm going back to my Morse code program. Well, here is my new updated dumper, which is rather smaller and simpler than the other one. Here is the blinky light. Here is the thing loaded into pulse view producing a decently clean signal. This one is using groups of eight. short for a zero bit, long for a one bit. It's simpler and easier and faster than the Morse code thing. Now, you may be wondering why I dumped the big ROM using Morse code. Anyway, here is my decoder, which as you can see is also much simpler, and it produces 256 bytes of ROM. So this looks like stuff. So let's find something looks like an instruction. These EAS are not that 20 is a JSR. So that's disassembled. Yeah. Yeah. This is machine code except for that 1B at the end. Now, one of the things I found was that the main ROM was actually calling stuff here. And why is that not working? Alex EO. It's showing me the wrong EO. I want the one up here. So these are places where the main ROM is calling into this thing. So I knew that there was a thing at EO6. So what this is doing is a whole lot of manipulation of the serial ROM. If it is a serial ROM, it's all the same code that I saw before in the main ROM, but it's split up into multiple functions. Makes it a bit easier to understand. And an interesting thing is that here it's calling it easy to see over here. It's calling this routine EC6 several times. And what EC6 does is something a bit weird using EO as a temporary variable where it goes through it one bit at a time fiddling with various control registers. This function here uh I haven't updated but this reads a bit from the device and it does this eight times. I think that what this is doing is clocking out a command to the device while at the same time reading in a reply from the device. So this routine here is called with a value in a and it does one of these and then it does one of these which I think is sending out the command. Then it sends the value that was first passed in. There's a pause. And this reads 8 bits back in. So, is this another SPI flash device? No, I don't think it is. I've identified two commands. The one that's used to actually read as a ROM is ASKI0, which is hex 30. And the one which is used by the main routine for doing all sorts of stuff is hex 10. This one is followed by a single bite of payload which then seems to set the thing up to read a single bite. And looking at the SPI command table, which unfortunately is not in numerical order, I do not see either 10 hex or 30 hex in here. So, while I don't know what it is, I think that there is more to it than the 256 bytes I've just read. The main routine here, it does a hex10 command with 4A as the parameter, reads the bite that's just been read, and then does stuff with it. And what this is actually doing is loading one of the reset vectors from a table which is here. So here you can see the various table entries. There are two different types of NMI handlers. So these are programmed into the memory at the top of the stack and then at the very top of the ROM are the hardwired vectors that call them. So it's clearly using this thing to identify something about the device which is then used for setup. So if I want to emulate this, I'm going to have to know what values these return. I could dump them easily enough. It's just matter of knowing how it works. I can just change my program. But I would kind of like to know what the device is. I think 4a gets a device ID. It is actually called from a bunch of places. There's clearly a whole bunch of stuff. It looks like that this is setting the address to read from, but there's clearly more to the address than just these eight bits because by sending a zero, it's read the whole 256 bytes of the ROM out. So, I'm going to have to go and do some more research. I found this in the NZDEV wiki, which describes a particular setup, mapper 427. And these describe the various different types of cartridge you can get which is a VT369 device which has an I squared C bus attached to either port 4148 or 4150 which we're seeing here and that has a I squared Cbased double quote protection chip. Also it may have 24 CO4 EPROM connected to the same port. So this does actually describe what I'm seeing here where we have two I squared C devices attached to the same port. And when we are accessing the EPROM, it's using address hex 10. And when it's accessing the protection chip, whatever that is, it's using device hex 30. Except I'm still very confused because none of this looks like I squared C. I've got the data sheet for the device which the wiki describes which is a atmemell 24 which is a 512 by EROM and it's got the diagrams for the the various control sequences and these do not match what the code is doing. For example, random read, which I expect is what the the EPROM access code is doing. What you do is you send eight bytes for the device address. And the device address for EPROMs always starts with the binary 1000 and the bottom four bits describe which device and whether you're reading or writing. Then you send the address you wish to start reading from. Then you send the device address again and then you start receiving the data. But with this the read code is very straightforward. It sends hex 10. It sends the address and then it receives the value. If it was following this logic here, we would have to send the device twice. But it isn't. What's more, I squared C uses 9 bit bytes because every eight bits of data 1 2 3 4 5 6 7 8 is then followed by a acknowledge bit and we're not seeing that. So I don't know what is going on here. It's possible the wiki is wrong. It has happened. But the one thing I do know is approximately what the API looks like. So I can write a simple program. This is just based on the last one which loops through and reads all 256 available EROM values. This is completely leaving aside the fact that the data sheet here says that the device has 512 bytes. But the only reason I know that it's 512 bytes is because this wiki says it is and the wiki might be wrong. So I don't know. Anyway, let's dump the EPROM and see what it says. Well, here's the EPROM, and it seems to be mostly blank. I think these repeated OFFs are what you get in one of these EPROMs if you don't program anything into it. There are a few bytes that have been changed. And if I go look at the source code here, it's reading the bite at 4 A. And if we look at 4 A 9 A, it's that one, which is a zero. If we scroll down, there's another reader for a. Okay, here it's reading the bite at two, which is that one. You can see that is non zero. That has been modified. Here it's reading A2, which is here, and so on. So, I think I do actually have a correct EPROM image, but I have really no idea what any of this means. The actual values over here just seem to be written to various registers. Like the one at A2 goes into ppu control on the NEZ. If I go look at the documentation, ppu control here, the value being written is a8. So a is 10. That's one. NMI on zero. Read backdrop from X pins. Sprite size 8 by 16. Zero sets the background address. 8 is sprite pattern table one uh ignored in 8x6 mode. So that doesn't do anything. And the rest are zeros. So I don't know why this is in the EPROM. This is all stuff that has to be set correctly for the menu to work at all. So why would it be reading it from the EPROM which is designed for modifiable storage where you store like save games and settings and things like that rather than just having them hardwired into the flash chip. Maybe it's deliberately like that so that you can't run this flash image on a different device that doesn't have this EPROM. It's a very odd way to do it. So, I think that I now have everything I need for this device. I've got the main flash ROM, I've got the internal ROM, I've got the magic serial ROM, and I've got the EPROM. I don't really want to have to write my own emulator cuz that sounds like work. But the good news is I found an emulator that claims to support Mapper 427, which is what I think this is. So if I can put these things together in a way that the emulator understands, there's a faint possibility it might work depending on all sorts of stuff. Okay, so the first thing I need is an INZ header. So, I'm going to steal one from Super Mario Brothers. It is 16 bytes long. Then I need the the full flash ROM. Then I need the internal ROM. Then I need the magic serial ROM according to the emulator's author. So now I need to edit the header to make it correctish. Now we load our ROM into this edit current header. Interesting. Okay. Right. Now we have to feed in information here. So, we want NEZ 2. We want uh that didn't work right. 4 2 7 mapper 427. This one. Submapper. Submapper 0 has the I squed C port of 4148. Submapper one has it at 4150. So, we're going with one. Pro ROM kilobytes. Well, this thing is unified architecture, so it doesn't really have a distinction between programmur. So, I'm just going to put the whole two 2048 there and see what happens. MISROMs, we've got two. We've got the Yeah. Uh, typing text into this is hard because it won't let me delete the last character. So, if I delete the zero and type a two, I get 20. That's nice. Okay, we got two misgs. We've got the internal ROM and we've got the protection ROM. This stuff I don't know what it means. Console type is a VT369. This thing says that if there's a pro NVRAM field of five bytes, it knows about EPROM. So, uh, that's not right. I think this column here is trying to set the batterybacked NV RAM. If I set this, that's non batterybacked and that thing hasn't become enabled. So, I don't know what's going on there. Uh, we are both neither NTSC or PAL, I think. Input or expansion device. Don't think any of these apply to me. Okay. So, now if I go over to CPU and I do run, what happens? We get a blank gray screen. Okay, let's try the debugger. It seems to have completely failed to map our internal ROM into the right place. So maybe it is not mapper 427. The other plausible looking one was mapper 426. So let's try that instead. Gray screen. And yeah, it looks like the same thing has happened. Oh no, no, wait. There is something here. This looks like our code. Uh, does it? Yes, this is indeed our code. Okay, but it's not booting. It looks like with this configuration, as soon as you start the machine up, it has mapped our menu at the right place. So, it is now immediately executing the menu code here and is not executing the internal ROM. I don't honestly know if that's bad. So, here it's turning the LCD off. part of it initialization. It's initializes a bunch of registers. The bit I'm particularly interested in is the where it reads the I squared C protection ROM. So that's happening at DO3. It's not getting that far. That's why if I put a break point CB1F here, it works fine. So something is not right. This is going through and executing all this code and then it's getting stuck in an infinite loop somewhere. This is a little loop. It's waiting for this F4 value to change. So I bet that this thing is written from an interrupt of some description which is never being called. That mysterious value is actually being set. I can see a break point stop when it's trying to write it. But it is the wrong value. It is 1 F and it is coming from this code which is reading a value from some hardware register. So there is some piece of hardware on the emulator device that doesn't match what's on the real hardware. I don't think this is the right mapper. In fact, I suspect this might be a new mapper which will be a ton of work to make work. My replacement device arrived. It is subtly different from this one. Apart from, you know, having a functioning screen, this is intended for a different kind of phone. I didn't order the same one again. This has bumped the USB socket from here on this one up around here, but it is very clearly the same device. One cool thing I noticed is that if I turn it over, you can actually see through the translucent plastic the screen and the four LEDs that light it up and the ribbon cable, which is not particularly well put together. And if I turn on this flashlight, get things a little well oriented, you can actually see the components. That's the speaker. That is the battery. There is a bundle of wires and some sticky tape holding it all together. Here is the big PCB and there aren't any other components. Here's another interesting feature and I don't recall whether the other device had this or not and because I've dismantled it, I can't tell anymore, but this black bezel here is actually smaller than the screen. So, it overlaps part of the screen. If you look down here, you can actually see under the bezel revealing more screen. And yes, I have checked and this overlaps some of the play area of some games, which is a choice. Sadly, this is probably where this adventure is going to come to an end, at least for now. I was going to try to pack crude support in for this ROM image into a NEZ emulator, but there are two emulators that support the VT369 chip that this thing is based around. One of which is a fork of Nintend that only builds on Windows and I don't do Windows and the other is MAMEim and unfortunately the MAME support is poor and I would have to add quite a lot of functionality which is easy enough but first of I' have to learn how MAME works inside so I'm not going to I will upload the ROM images and stuff to various sites there are forums that collect them so none of this will go to waste I may look at main later but if I do that that will be a whole different project. So, I'm going to finish up here. At some point, I do want to retrofit this working one into a little games console thing with my quote controller unquote because these rubber keys are kind of terrible. And this is actually a decent enough little device. If you want bootleg NEZ games, shut up. If you want bootleg NES games, you could do worse. They're nicely presented. They don't have the, you know, the 400 in one cartridges where all the games are duplicates and ROM hacks of each other. These actually seem to be pretty legitimate ripped off pirate games. And I haven't found a game yet that doesn't just work perfectly. So, that's nice. But I will do all that if I do it off camera. So, I'm going to finish it here. I know nothing about nezes. It has been really interesting to learn. I hope some of my viewers, assuming I have any, found it interesting, too. So, as always, I hope you enjoyed this video. Please let me know what you think in the comments. And I will see you all next time.