Is Anyone Willing to Explain This C++ Code?

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Is Anyone Willing to Explain This C++ Code?
by on (#144382)
Okay, I know what you're all thinking: Why don't you learn C++ yourself? Well, If you find a tutorial that isn't a thousand pages long and is not in book form, then I might consider. (I think koitsu might have showed me something on C? If he did, I don't know where it is.) Basically, this is an extension of the Irem M92 thread, but it's main focus is on translating this, which admittedly, doesn't look like any small task: https://github.com/OpenEmu/UME-Core/blo ... ideo/m92.c I would be offering money, but I'm 99% sure my mother won't let me...
Re: Is Anyone Willing to Explain This C Code?
by on (#144384)
That's C++ code, not C code. Looks like it's filled with macros, so you could run it through a preprocessor to get the actual code.
Re: Is Anyone Willing to Explain This C Code?
by on (#144385)
Oops... :lol: I'll change the title... I've always wondered, is there such a thing as C+?

Edit: What the heck is a preprocessor? And are the macros just like they are in ASM, but instead they use C++, meaning they exist so you don't need to write the same or nearly the same code over and over again?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144386)
If you're building with GCC, you can run CPP (c preprocessor) on it and see the result of all Preprocessor directives. This will perform all the #includes and everything, so you might have to cut all that stuff out first before reading it. I think that will also remove the comments as well.

I think you invoke it by "cpp file.c > output.txt" or something like that. You need GCC (mingw or cygwin) installed.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144387)
Hmm, the paletteram_xBBBBBGGGGGRRRRR_word_w would score quite high as the longest function name. Hopefully it's used only once.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144388)
C++ mangled function names make that look short.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144389)
Well, at least we now it uses the same color setup as the SNES. :wink:

Oh, you know, one thing I don't understand is how there was no real reference used in the making of this. Wouldn't it have been easier to make a sheet with all the hardware info before making this? Do you think that maybe I should email the author of the page to see if he made one as a reference?

Edit: Oh, a random observation: When System 16 said the Irem M107 had twice as many colors, it must have meant colors total instead of color palettes because it has the same number of color palettes as the M92. It would probably have been a lot easier to do that instead of increasing the color palettes, seeing that every color in CGRAM (or whatever it's called here) has an unused bit for every color. I wonder if it's like the Neo Geo in that it has a half brightness bit, or if it has an extra green. I personally like the half brightness better.

Edit: I emailed the author of the page. We'll see what happens...
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144398)
Dwedit wrote:
C++ mangled function names make that look short.

Well yeah, when you look at nested templates, the result is quite surprising!
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144417)
Jarhmander wrote:
Dwedit wrote:
C++ mangled function names make that look short.

Well yeah, when you look at nested templates, the result is quite surprising!

Yep! So thank god we have the mangled names so we don't have to look at those really long names, huh?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144497)
Good news! I've contacted the person who made that code, so I'm at least one step closer to figuring this whole thing out. He showed me this: https://github.com/OpenEmu/UME-Core/blo ... vers/m92.c which helps explain things a ton. I've been looking at 80186 related stuff, and I found this which I think is what I'm looking for. It's supposed to be the instruction set for it.

Attachment:
IntelCodeTable.pdf [146.9 KiB]
Downloaded 164 times

If this is correct, it actually doesn't look that bad! It actually seems to share quite a bit of similarities (at least compared to ARM. I actually looked at the 68000 and it left my head spinning.) with the 65816 instruction set. Well, at least I don't have to deal with things like this anyway! (I now know why x86 is considered a mess.)

Wikipedia wrote:
Instruction: VFMADDSUBPD xmm0, xmm1, xmm2, xmm3
Opcode: C4E3 WvvvvL01 5D /r /is4
Meaning: Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values

One thing though, do I need to find a special 80186 assembler, or will any x86 assembler do as long as I don't use any instructions that come after? (By judging instruction earlier, I don't think I'd even want to.)
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144499)
Why are you linking to the OpenEmu copy of MAME instead of... actual MAME? :? (There probably aren't any significant differences between the two, but...)

That instruction set isn't very complete. It's missing a few instructions, like movsb and movsw, and it doesn't cover addressing modes or segmentation at all. If someone made the same chart for 68000, you'd think it looked like 65816 too.

As far as assemblers go, I recommend NASM or YASM. They can easily be configured to generate only valid 80186 opcodes.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144500)
Espozo wrote:
Wikipedia wrote:
Instruction: VFMADDSUBPD xmm0, xmm1, xmm2, xmm3
Opcode: C4E3 WvvvvL01 5D /r /is4
Meaning: Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values

I told you to ignore things newer than 8086 ;p
MMX and SSE instructions are ... really an entirely different universe than the older ones.
Quote:
One thing though, do I need to find a special 80186 assembler, or will any x86 assembler do as long as I don't use any instructions that come after?
Almost all assemblers have a directive that will specify the instruction set. (e.g. nasm has "CPU 80186"). One almost-unusable instruction present in the original 8088/8086 that they removed from later cores is POP CS.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144501)
Joe wrote:
Why are you linking to the OpenEmu copy of MAME instead of... actual MAME? (There probably aren't any significant differences between the two, but...)

The guy who made it pointed me to it. I don't think a document like this is even on actual mame.

Joe wrote:
That instruction set isn't very complete. It's missing a few instructions, like movsb and movsw, and it doesn't cover addressing modes or segmentation at all. If someone made the same chart for 68000, you'd think it looked like 65816 too.

Ok. It looked rather small. (One can dream. :roll: ) I guess I should just stick with this? http://en.wikipedia.org/wiki/X86_instruction_listings

Joe wrote:
As far as assemblers go, I recommend NASM or YASM. They can easily be configured to generate only valid 80186 opcodes.

I'm going to take a look...

Oh yeah, and lidnariq, the thing is so preposterously large, I almost though someone put it in the webpage as a joke, until I saw other ones just like it... The instruction is so complex, that even when I read the description, I still understand what it does.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144503)
The wikipedia reference isn't very good for actually programming...
I'd try a few of the other search results for "8086 instruction set", such as
http://www.gabrielececchetti.it/Teachin ... on_set.pdf
http://www.ing.unlp.edu.ar/electrotecni ... on_set.pdf
http://mai.kvk.uni-obuda.hu/documents/t ... erview.pdf
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144504)
The one thing though is that I'm looking at the 80816, so there are a bit more instructions, but I could still probably use those. I looked at NASM, but after I opened the rar file, a billion files spewed out, and I couldn't even find the exe/bat file. I then got YASM, and it was only one file. I think you know which one I chose. :wink:
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144505)
NASM comes with a large pile of examples, which are probably good reference.

I'm still somewhat partial to the oooolld Turbo Assembler, but it's so much easier for me to use NASM nowadays...
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144507)
Espozo wrote:
The guy who made it pointed me to it. I don't think a document like this is even on actual mame.
What about this? :P
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144509)
That's odd... I wonder why he showed me the other thing...
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144512)
Well, I wrote "mov DS, AX" (kind of like "tax" in 65816 instruction set? what things, (I don't know what to call them) are there in the 80186? I mean like accumulator, x and y) in an otherwise blank .asm document and ran it through yasm and it gave me a file, so I at least know it's working. I tried looking up a good tutorial for yasm, but I only found a giant thing I don't feel like looking through (it doesn't really even seem that stubborn if it ran what I gave it) and all I really want to know right now is how to make it only use 80186 instructions. (Never mind. CPU 80186 seems to work on yasm also.) The main thing I wanted to ask though was I remember looking at Neo Geo Dev once, and instead of making everything from scratch, people just hijacked a rom of Super Side Kicks and only changed files that they needed to. (As in if you just want text to appear on the screen, you can just use the pre existing chr rom file.) The problem is, I have no clue what file is for. I opened up GunForce 2, and this is what I got: (I've never even heard of any of these file types before.)

a2_000.8a
a2_010.8b
a2_020.8c
a2_030.8d
a2_c0.1a
a2_c1.1b
a2_c2.3a
a2_c3.3b
a2_da.1l
a2_sh0.3l
a2_sl0.5l
a2_h0-a.6h
a2_h1-a.6f
a2_l0-a.8h
a2_l1-a.8f

How can there be so many files? The only file that I know what is for is "a2_da.1l", as it has all the pcm instruments. If it's anything like the Neo Geo, you just get your custom file, rename it, and replace it with the pre existing one. Mame acts like files are missing for some reason, so I remember someone made a .bat file that you run and it opens up some sort of debugging mode, where the game will actually run. Why it doesn't just run in the first place is beyond me, unless it looks and sees that the game isn't actually Super Side Kicks and stops you from attempting to run it.

Edit: Oh, apparently, yasm doesn't recognize "#". How does it tell what's a number and what's a register?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144519)
Espozo wrote:
what things, (I don't know what to call them) are there in the 80186? I mean like accumulator, x and y
Those are called registers. The 80186 has the following 16-bit registers: AX, CX, DX, BX, SP, BP, SI, DI, ES, CS, SS, DS, FLAGS, IP. Additionally, AX, CX, DX, and BX can be accessed as pairs of 8-bit registers: AL, CL, DL, BL, AH, CH, DH, and BH.
Espozo wrote:
I've never even heard of any of these file types before.
MAME names files based on the labels that would be visible to someone repairing their arcade system. The "extension" has nothing to do with the file contents; they're all just dumps of whatever was in the original ROM chips.
Espozo wrote:
How can there be so many files?
There is one file per chip.
Espozo wrote:
Mame acts like files are missing for some reason, so I remember someone made a .bat file that you run and it opens up some sort of debugging mode, where the game will actually run. Why it doesn't just run in the first place is beyond me, unless it looks and sees that the game isn't actually Super Side Kicks and stops you from attempting to run it.
MAME verifies files for accuracy, and will complain or refuse to run if the file doesn't match what it expects. You have to override this behavior to run a modified game.
Espozo wrote:
Oh, apparently, yasm doesn't recognize "#". How does it tell what's a number and what's a register?
I'll assume by "number" you mean "immediate", and by "register" you mean "the equivalent to 6502's absolute", which is called "direct". In NASM syntax, immediate values have no prefix or suffix, and direct addresses are inside [] square brackets. (YASM uses NASM syntax by default.)
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144520)
Joe wrote:
Espozo wrote:
what things, (I don't know what to call them) are there in the 80186? I mean like accumulator, x and y
Those are called registers. The 80186 has the following 16-bit registers: AX, CX, DX, BX, SP, BP, SI, DI, ES, CS, SS, DS, FLAGS, IP. Additionally, AX, CX, DX, and BX can be accessed as pairs of 8-bit registers: AL, CL, DL, BL, AH, CH, DH, and BH.

Well, that's a lot... (or do the 65816 and 6502 just have a very small amount of registers? I recall ARM having about the amount you showed.)

Joe wrote:
Espozo wrote:How can there be so many files?There is one file per chip.

:shock: Is each ROM chip kind of like a ROM bank? Why not just have one giant ROM bank?

Joe wrote:
MAME verifies files for accuracy, and will complain or refuse to run if the file doesn't match what it expects. You have to override this behavior to run a modified game.

That's a bit silly... Why not just give a warning message but let you continue anyway?

Joe wrote:
Espozo wrote:
Oh, apparently, yasm doesn't recognize "#". How does it tell what's a number and what's a register?
I'll assume by "number" you mean "immediate", and by "register" you mean "the equivalent to 6502's absolute", which is called "direct". In NASM syntax, immediate values have no prefix or suffix, and direct addresses are inside [] square brackets. (YASM uses NASM syntax by default.)

Yeah, that's what I meant. I've been doing this stuff for almost a year now and I still don't know any of the terminology. :oops:

So, If I were to take an "immediate" and store it in a "direct", I'd do something like this?

Code:
mov  [F8800], 1F

Oh yeah, one thing I noticed about the files for each game is that they aren't always (or ever, from what I've seen) the same file extension, but there are always 15 files. I wouldn't be surprised if there were files between the games that had the same purpose (like storing pcm samples) but just had different names. One last thing, I doubt it, but do you thing I could try to open one of the files with a chr rom editor? Aside from being 4bpp, I just don't know if the planar or packed pixel, or what. It shouldn't be too hard to figure out.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144521)
Espozo wrote:
So, If I were to take an "immediate" and store it in a "direct", I'd do something like this?
Code:
mov  [F8800], 1F

Except that you need to specify the size of the operand ... and I don't think you can specify a far address literally? But if you can, you'll have to specify it as a segmented pointer.

i.e. mov BYTE PTR [F000h:8800h], 1Fh or something like that.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144523)
Do you think you could explain what the "BYTE PTR" means and also what "h" is? also shouldn't "[F000h:8800h]" be "[000Fh:8800h]" ? Why do you even need the ":"? Just because?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144524)
"BYTE" = you're writing an octet, as opposed to a "WORD" (16-bit value)
(or DWORD or QWORD on later machines, or TWORD if you have an 8087)
"PTR" = pointer, because you're doing a memory access without going through a register
"h" is how most some x86 assemblers mark hexadecimal arguments. eta: You can also use the C-like [0xF880:0].
And, no, the 8086 holds a 20-bit address in two 16-bit registers, by taking (SEGMENT<<4)+OFFSET, so the absolute address 0xF8800 is at the segmented address F880h:0h or F000h:8800h or F376h:50A0h
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144525)
Joe wrote:
Why are you linking to the OpenEmu copy of MAME instead of... actual MAME?

In my experience while building the citations for my list of arcade system boards' pixel clock rates, the web-based source code viewer at mamedev.org appeared to have some sort of throttling on how many source code files I could view in a day, after which point I started getting errors. I might be confused about the cause of this though, and the move to GitHub might have started to fix things.

On the other hand, since when is the MAME license (or any other noncommercial license) acceptable in a repository on GitHub's "open source" plan?

Quote:
MAME verifies files for accuracy, and will complain or refuse to run if the file doesn't match what it expects. You have to override this behavior to run a modified game.

What's the preferred way to override this behavior?

Espozo wrote:
Is each ROM chip kind of like a ROM bank? Why not just have one giant ROM bank?

For the same reason that several NES games have separate PRG ROM and CHR ROM chips: each one is connected to a separate bus. Also for the same reason that several Super NES games have several PRG ROM chips and very early NROM-128-class boards (RTROM and STROM) had two PRG ROM chips: sometimes two small chips are cheaper than one large chip.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144526)
tepples wrote:
MAME verifies files for accuracy, and will complain or refuse to run if the file doesn't match what it expects. You have to override this behavior to run a modified game.What's the preferred way to override this behavior?

Are you asking because you don't know how, or because you want to ask me how I think you should override it? I use a .bat file that contains the following:

Code:
(name of mame exe file here) (game rar name here) -debug -nofilter -video d3d -waitvsync -window
pause


I actually kind of like it better than Mame normally, because you don't have that dumb filter that makes me feel like my vision is even worse than it is.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144527)
Here's a cool little discovery I made: apparently, the graphics for the BG tiles (I haven't found sprites yet) are spread across 4 chips, one for each bit per pixel. It's at least nice to know that there are only 10 (as if that's small) files left to look at.

Attachment:
Irem M92 chr rom.png
Irem M92 chr rom.png [ 67.66 KiB | Viewed 1826 times ]
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144528)
Splitting bitplanes across multiple chips is an obvious way to improve performance.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144529)
Espozo wrote:
Here's a cool little discovery I made: apparently, the graphics for the BG tiles (I haven't found sprites yet) are spread across 4 chips, one for each bit per pixel.

Which means it'd take about 15 minutes to make a tool to translate them in and out of Super NES 4-bit tile format by reinterleaving the bytes.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144530)
Espozo wrote:
-nofilter[...]I actually kind of like it better than Mame normally, because you don't have that dumb filter that makes me feel like my vision is even worse than it is.
I recently discovered that MESS has a drum machine emulator in it.The only video output on this drum machine is a single HD44780 LCD, with 16x2 6x8-dot characters.

Having MESS blow that tiny thing up to full screen with bilinear filtering? Bleh.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144531)
Espozo wrote:
Well, that's a lot... (or do the 65816 and 6502 just have a very small amount of registers? I recall ARM having about the amount you showed.)
It's not really that many. Of the 14 registers in the 80(1)86, 7 are useful for common tasks. Compare that to the 68000, which has 15 useful registers, or MIPS, which has about 25! (For reference, the 6502 has 6 registers, and only 3 are useful for common tasks.)
Espozo wrote:
So, If I were to take an "immediate" and store it in a "direct", I'd do something like this?
Code:
mov  [F8800], 1F
That's basically correct. You'll have to fix the syntax, and the 80(1)86 is limited to 16-bit offsets. You'll probably end up doing something along these lines:
Code:
mov ax, 0xF800
mov ds, ax
mov byte [0x800], 0x1F

lidnariq wrote:
PTR
This is MASM syntax, not NASM syntax.
Espozo wrote:
I actually kind of like it better than Mame normally, because you don't have that dumb filter that makes me feel like my vision is even worse than it is.
I don't think MAME has any filters by default. Do you have something in one of your .ini files?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144532)
Not so obvious to me. :oops: To bad no consoles that I'm aware of do this. Maybe we would have seen 3 4bpp BG layers on the SNES...

Quote:
Which means it'd take about 15 minutes to make a tool to translate them in and out of Super NES 4-bit tile format by reinterleaving the bytes.

Not that I have any clue how to make one...

lidnariq wrote:
Espozo wrote:
-nofilter[...]I actually kind of like it better than Mame normally, because you don't have that dumb filter that makes me feel like my vision is even worse than it is.
I recently discovered that MESS has a drum machine emulator in it.The only video output on this drum machine is a single HD44780 LCD, with 16x2 6x8-dot characters.

Having MESS blow that tiny thing up to full screen with bilinear filtering? Bleh.

What? Drum emulator?

You know though, this whole things been pretty fun! (For me, anyway.) Hopefully, I'll be able to show you guys something simple at some point.

Edit: about the filter thing, I mean it does this:

Attachment:
Blurry.png
Blurry.png [ 31.22 KiB | Viewed 2100 times ]
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144535)
Espozo wrote:
What? Drum emulator?
https://github.com/mamedev/mame/blob/master/src/mess/drivers/alesis.c

Emulator for the Alesis HR-16 and SR-16 drum machines.

I don't really understand why it's in MESS, but, hey, whatever. The hardware in it isn't all that different from half of an arcade machine.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144557)
Good news again! I'm pretty sure I found what files hold the sprite graphics, because this:
Attachment:
sprite chr rom.png
sprite chr rom.png [ 19.83 KiB | Viewed 2056 times ]

Looks remarkably like this:
Attachment:
GunForce 2 Sprites.png
GunForce 2 Sprites.png [ 38.22 KiB | Viewed 2056 times ]

There are also 3 other files that are named similarly to that one and they seem to supplement it because they appear to have each bit per pixel spread across 4 chips just like the BG tiles. The graphics in the files I found also seem to be very 16x16 ish, so I think I'm right.

Well, here's something that says how many files have had their purpose discovered:

a2_000.8a = Sprite Graphics Bit 1
a2_010.8b = Sprite Graphics Bit 2
a2_020.8c = Sprite Graphics Bit 3
a2_030.8d = Sprite Graphics Bit 4
a2_c0.1a = BG Graphics Bit 1
a2_c1.1b = BG Graphics Bit 2
a2_c2.3a = BG Graphics Bit 3
a2_c3.3b = BG Graphics Bit 4
a2_da.1l = PCM Samples
a2_sh0.3l = ???
a2_sl0.5l = ???
a2_h0-a.6h = ???
a2_h1-a.6f = ???
a2_l0-a.8h = ???
a2_l1-a.8f = ???

Oh, and also, do you think this code looks good?

Code:
CPU 80186

  mov ax, 0xF800
  mov ds, ax
  mov byte [0x800], 0x1F

infinite_loop:
  jmp infinite_loop

"0xf8800" is the first color in cgram (or whatever it's called here) and "0x1F" is, just like on the SNES and GBA, solid red. So if I'm not mistaken, this code should turn the screen red. I ran it through yasm and it made a file, which is good. By the way, why do we need the "0x"? Do I actually need to specify where the code starts somehow?

Edit: Oh yeah, do you think I could run the remaining files through some sort of disassembler and see if it gives me anything logical? Where could I find one?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144564)
I lost power twice while typing up my reply. Clearly someone doesn't want me to answer your questions. :lol:
Espozo wrote:
Oh, and also, do you think this code looks good?
It looks like it will do what you expect it to do. You still need to put some code at the reset address, or the CPU will get stuck executing garbage instead of running your code.
Espozo wrote:
By the way, why do we need the "0x"?
Why do we need "$" in 6502 assembly?
Espozo wrote:
Do I actually need to specify where the code starts somehow?
If you don't specify, the assembler assumes it starts at offset 0. This is not the same as physical/linear address 0.
Espozo wrote:
Oh yeah, do you think I could run the remaining files through some sort of disassembler and see if it gives me anything logical? Where could I find one?
I usually use objdump. There's also ndisasm (included with NASM) and unidasm (included with MAME). Also, don't forget MAME has a built-in debugger. For short snippets of code, I sometimes use this disassembler.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144568)
Joe wrote:
I lost power twice while typing up my reply. Clearly someone doesn't want me to answer your questions.

I was almost done writing and I accidentally exited out of the window like an idiot... :oops:

Well, anyway, I replaced each of the 6 files with the one that I made, and here are the results:

a2_sh0.3l and a2_sl0.5l: Runs, but with no sound. It passes the self check.

a2_h0-a.6h and a2_l0-a.8h: The screen is dark, and the self check doesn't even start. cgram (or whatever it's called here) is filled with 2 1bit RGB palettes in every 16 color palette. The game does this before it starts the self test normally. I'm pretty sure these files have to do with the CPUs. There are 2 files, so should there be 1 for each CPU?

Joe wrote:
Espozo wrote:
Oh, and also, do you think this code looks good?
It looks like it will do what you expect it to do. You still need to put some code at the reset address, or the CPU will get stuck executing garbage instead of running your code.

That's probably why. I'll fix it and report the behavior later.

a2_h1-a.6f and a2_l1-a.8f: These go to the self check, but they give these respectively:

Attachment:
Self Test.png
Self Test.png [ 3.98 KiB | Viewed 2032 times ]

Then it turns to something like this... (It is different for each file changed. This is the second one.)

Attachment:
Result....png
Result....png [ 20.4 KiB | Viewed 2032 times ]

The game actually runs completely normal, despite it looking like that...

Edit: Oh yeah, this is sad, but what do you mean by "put some code at the reset address"?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144572)
Espozo wrote:
Edit: Oh yeah, this is sad, but what do you mean by "put some code at the reset address"?
The 8086 family always starts executing code at FFFF:0000. (Unlike the 6502, which reads a 16 bit pointer from $FFFC) Unfortunately, I don't immediately see in MAME's source what's mapped at that location, so I'm not certain what happens next in the M92.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144574)
Do you know if there's a way to search for "FFFF:0000" on this webpage? https://github.com/mamedev/mame/blob/ma ... vers/m92.c
The search bar at the top looks through al the documents on the website, not the specific document.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144577)
Well, I did find this in the source:
AM_RANGE(0xffff0, 0xfffff) AM_ROM AM_REGION("maincpu", 0x7fff0)
so the hardware on the board causes the values at FFFF:0 to be fetched from 7FFF:0 ... which maybe means it's here?
Code:
ROM_START( bmaster ) /* M92-B-B PCB used for program rom locations */
        ROM_REGION( 0x100000, "maincpu", 0 )
        ROM_LOAD16_BYTE( "bm_d-h0-b.5m", 0x000001, 0x40000, CRC(49b257c7) SHA1(cb4917ef6c5f959094f95b8535ea12e6b9b0bcc2) )
        ROM_LOAD16_BYTE( "bm_d-l0-b.5f", 0x000000, 0x40000, CRC(a873523e) SHA1(9aee134c299e12064842e16db296f4259eccdf5b) )

I forget whether ROM_LOAD16_BYTE's 3rd argument is in bytes loaded, or range written. If the former, then I guess it is there...
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144578)
So now we need to see what's at 7FFF:0 instead of FFFF:0?

Edit: The author of the web page I showed earlier said that the V30 only does stuff with the sound, so all I need to worry about is the V33 for now. I really have no idea how to work two CPUs at a time, so that's nice to hear. it looks like things are really starting to come along! :)

Edit 2: Actually, I'm going to show the message the person sent me because maybe it will be useful. I'm sure he wouldn't mind.

Quote:
If you look back in the driver link I sent, you can see how the roms are used:

ROM_START( gunforc2 )
ROM_REGION( 0x100000, "maincpu", 0 )
ROM_LOAD16_BYTE("a2-h0-a.6h", 0x000001, 0x040000, CRC(49965e22) SHA1(077283c66a4cc2c47221c5f3267f440223615a15) )
ROM_LOAD16_BYTE("a2-l0-a.8h", 0x000000, 0x040000, CRC(8c88b278) SHA1(0fd8e663619dcd8c81b3baa290bb0e72c185273a) )
ROM_LOAD16_BYTE("a2-h1-a.6f", 0x080001, 0x040000, CRC(34280b88) SHA1(3fd3cdf8acfa845abacb0708fb48741ee44dbf13) )
ROM_LOAD16_BYTE("a2-l1-a.8f", 0x080000, 0x040000, CRC(c8c13f51) SHA1(fde3fd983ebb920f79e6898aa0576da9dd9f0c15) )

So those 4 are the main program, you can see l0/h0 load to 0 in the memory map, and h1/l1 load to 0x80000. Now because this is a 16 bit CPU and these roms are 8 bit how it actually works is the 'h' rom provides the high byte for the 16 bit word, and 'l the low bit - so to be able to disassemble you have to interleave these roms byte by byte. Hope that makes sense!

If you find a debug version of Mame, or compile it yourself you can run the game with the debugger and then save out the roms already interleaved. This would be a good start to modify things, as you could hook a subroutine and copy your own program code there. You can use the built-in Mame debugger to try stuff out.

The V30 just does the sound - it doesn't affect gameplay at all - so the V33 communicates just by writing a byte and firing an interrupt on the V30 to tell it the byte is ready to be read (see m92_soundlatch_w)

Edit 3: (Yeah, I know...) From what he said, it seems that I'd have to split whatever code I'm making between two files? Why are there four then? I guess just for the extra space? Because of how it's set up, I guess "a2_sh0.3l" is the high byte for the sound CPU, or the V30, (hence the "h") and "a2_sl0.5l" is low byte for it. (hence the "l")
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144614)
Just thinking, tepples said it would "it'd take about 15 minutes to make a tool to translate them in and out of Super NES 4-bit tile format by reinterleaving the bytes." when he was referring to graphics, and, would it be too bad if someone made a tool that would alternate between two files to take bytes to put them into one larger file and also do the same thing except reverse? :oops: This is because of the way the M92 looks between two chips for the code.

Edit: Wait, I'm stupid. Why would I want to put the two files together? All I want is the ability to split a file apart. Surely there must be something someone has made...

Edit 2: I've tried to see if someone had already made a tool that could do this, but I've ran into the worst of luck. I followed a download link to one someone said they made and it gave me a 404 error, and 2 others weren't "compatible with my computer" or whatever because they were for 16 bit processors. (What, can a 64 bit processor not perform 16 bit instructions?)
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144838)
Well, I used Kasumi's newly made file splitter and split the assembled version of this:

Code:
CPU 80186

  mov ax, 0xF800
  mov ds, ax
  mov byte [0x800], 0x1F

infinite_loop:
  jmp infinite_loop

into 2 files because of the 8 bit rom thing and I replaced "a2-h0-a.6h" and "a2-h1-a.6f" with the 2 newly made ones (I made tried it both ways, with the first file going to "a2-h0-a.6h" and then with it going to "a2-h1-a.6f") and ran it in the Mame debugger, but unfortunately, it didn't work both times, with it just loading a black screen and not even going to the self test. This is also what it looked like in the debugger both times:

Attachment:
Mame Dubugger.png
Mame Dubugger.png [ 19.54 KiB | Viewed 1917 times ]

(Is this essentially just 0s the whole way through?)

I'm also pretty sure it isn't the file splitter's fault, because both files are exactly half as large as the original, (6 vs. 12) so I don't have the slightest clue what's wrong. It appears that the program isn't starting at the right place?

Edit: I'm not sure if this is of any use to anyone, but this is how the game normally looks: (How in the world could there be ???)
Attachment:
GunForce 2 Original.png
GunForce 2 Original.png [ 20.3 KiB | Viewed 1915 times ]
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144842)
Espozo wrote:
Is this essentially just 0s the whole way through?
Yes.

As mentioned earlier, you need to put some code at linear address 0xFFFF0 (ROM address 0x7FFF0) or the CPU will begin executing garbage instead of your code.
Espozo wrote:
I'm not sure if this is of any use to anyone, but this is how the game normally looks:
That corresponds to the following code:
Code:
cli
jmp 0x0040:0xE354
MAME is using mnemonics from NEC instead of Intel, which is why they don't look like x86 instructions.
Espozo wrote:
(How in the world could there be ???)
Those are invalid opcodes.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144845)
Joe wrote:
As mentioned earlier, you need to put some code at linear address 0xFFFF0 (ROM address 0x7FFF0) or the CPU will begin executing garbage instead of your code.

How do you do that though? I know this is probably basic stuff...

Joe wrote:
Those are invalid opcodes.

You mean like numbers that don't respond to anything? What are they even doing there? How does the processor even handle something like that?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144852)
More recent processors will essentially BRK on invalid opcodes, calling one of the interrupt vectors.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144854)
Older machines like the 8086 and 80186 don't TRAP on invalid instructions, and will do something random instead. Usually NOP, but not always:
http://stackoverflow.com/questions/2811 ... el-8086-88
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144856)
Espozo wrote:
How do you do that though? I know this is probably basic stuff...
I, personally, would use section directives to force the assembler to output data in a certain way.

For example:
Code:
section reset start=0x7fff0 vstart=0
    cli
    jmp ...

Espozo wrote:
You mean like numbers that don't respond to anything?
Yes.
Espozo wrote:
What are they even doing there?
Padding for the unused part of the ROM. The MAME debugger doesn't know what's code and what isn't, so it assumes everything is code.
Espozo wrote:
How does the processor even handle something like that?
Like most x86-compatible CPUs, the V33 will invoke interrupt 6 when it encounters an invalid opcode. In this case, I doubt it ever tries to execute those invalid opcodes.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144857)
lidnariq wrote:
Older machines like the 8086 and 80186 don't TRAP on invalid instructions,
The 80186 does.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144860)
Well, I wrote this:

Code:
CPU 80186

section reset start=0x7fff0 vstart=0
  cli
  jmp main_code

main_code:
  mov ax, 0xF800
  mov ds, ax
  mov byte [0x800], 0x1F

infinite_loop:
  jmp infinite_loop

and I assembled it, and ran it through the file splitter. I then made it into the rom and tried it, and then I changed the order of the files and tried it.

Unfortunatelly, none of them worked and this is what I got:

Attachment:
Result 1.png
Result 1.png [ 20.32 KiB | Viewed 1838 times ]

Attachment:
Result 2.png
Result 2.png [ 20.59 KiB | Viewed 1838 times ]
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144861)
Espozo wrote:
Well, I wrote this:
First, you need a separate section directive for the rest of your code. (Later, you'll probably need more section directives.) Second, you must use a far jump to reach the rest of your code, not a near jump. For example:
Code:
section code vstart=0 align=16

main_code:
  mov ax, 0xF800
  mov ds, ax
  mov byte [0x800], 0x1F

infinite_loop:
  jmp infinite_loop

section reset start=0x7fff0 vstart=0

  cli
  jmp (section.code.start >> 4):main_code

Espozo wrote:
Unfortunatelly, none of them worked and this is what I got:
It looks like one of the two files you're using is full of zeroes instead of containing the correct data.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144920)
I actually tried you code, (with "CPU 80186" at the beginning) but the debugger just shows the instruction for the value 0 all the way through and obviously doesn't work. One strange thing I noticed is that each file is 256KB long, and it used to be 6 bytes with the code that showed something in the debugger. Is there something wrong with your code?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144934)
You know, could someone actually just tell me what everything means here? I switched the order you had the code to where the bottom is now at the top like so:

Code:
CPU 80186

section reset start=0x7fff0 vstart=0

  cli
  jmp (section.code.start >> 4):main_code

section code vstart=0 align=16

main_code:
  mov ax, 0xF800
  mov ds, ax
  mov byte [0x800], 0x1F

infinite_loop:
  jmp infinite_loop

and this is what I get in the debugger, which is at least better than having nothing like it used to:

Attachment:
Debugger.png
Debugger.png [ 19.88 KiB | Viewed 1787 times ]

I'm guessing that it jumps to an area with no code in it instead of the correct area, because if I let it run, it fills up with "add [bw+ix],al".

This has proven to be far more complicated than I had originally anticipated...
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144946)
Edit: Never mind. I just found the key piece of information: viewtopic.php?p=144842#p144842

Quote:
MAME is using mnemonics from NEC instead of Intel, which is why they don't look like x86 instructions.

I Googled around and found this (PDF) for the NEC V30NX. I have to assume this CPU is extremely close to the V30/V33 used on this board, but I could easily be wrong.

Upon reviewing Chapter 3, I was greeted with official definitions for all registers (BW = general-purpose register, IX = index register), and Chapter 3.6 clearly denotes that there are BR and DI opcodes on the V30 CPU. The Appendix List has a chart of all the opcodes. BR = Branch, DI = I have not the slightest idea ("CPU control" is too vague). There doesn't appear to be a "clear" definition of what all the opcodes do.

Skimming more of the instruction set of that PDF shows me that there are many opcodes and registers that are "similar" to 8086/8088 but the official explanations of them all is missing (there's the Appendix but it really doesn't describe their functionality).

So I'm left thinking this:

DI = NEC V30 opcode for what Intel calls CLI
BR = NEC V30 opcode for what Intel calls JMP
IX = NEC V30 register for some particular Intel index register (there are multiples and I don't know which one)
BW = NEC V30 register for possibly Intel's BX register? Again not sure.

You basically get to learn the mapping between Intel and NEC V30 when looking at MAME's debugger -- unless someone know of a way to force the debugger to display Intel mnemonics.

Good luck with this -- this would drive me absolutely batshit crazy. "The code I write is technically working as intended, but what I see in real-time in the debugger isn't the syntax I use in the code itself".

Thus, you probably just need to execute the code/step through it. The MAME debugger documentation is abysmal, so I wish you luck there too. :-)
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144949)
Espozo wrote:
One strange thing I noticed is that each file is 256KB long, and it used to be 6 bytes with the code that showed something in the debugger. Is there something wrong with your code?
No, that's intentional. The assembler can automatically put code in the right place in the ROM file, so that's what I did. You should be able to just split the output file from my example and load it with MAME. (Now that I look, I forgot to pad it to the correct size. It probably should have been exactly 512kiB total/256kiB each, but it's a few bytes short.)
Espozo wrote:
You know, could someone actually just tell me what everything means here?
I'll do my best.
Espozo wrote:
I switched the order you had the code to where the bottom is now at the top like so:
That probably broke it.

Anyway, time to explain things.
Code:
section code vstart=0 align=16
The first section is named "code". Its origin (vstart) is 0. It is aligned to a 16-byte boundary, since x86 segments are 16-byte aligned. Its physical location in the output is unspecified, so YASM puts it after the previous section. Since I put this section first, it ends up at the beginning of the ROM.
Code:
main_code:
---snip---
  jmp infinite_loop
This is the code you want to run immediately after reset. You could replace this with whatever you want, as long as you update the reset vector to point to the correct label.
Code:
section reset start=0x7fff0 vstart=0
The second section is named "reset". It starts at 0x7FFF0 in the ROM file. Its origin is 0.
Code:
  cli
  jmp (section.code.start >> 4):main_code
This disables most interrupts, then performs a far jump to the start of your code. The purpose of "section.code.start >> 4" is to calculate the segment that should be used to access the "code" section. Since the code section is at the beginning of the ROM right now, I could have just written jmp 0:main_code. At some point you'll be moving the code section to make room for the IVT, so I made sure it will automatically correct itself when that happens.
Espozo wrote:
I'm guessing that it jumps to an area with no code in it instead of the correct area, because if I let it run, it fills up with "add [bw+ix],al".
You should probably step through it instead of letting it run. At least that way, you'll be able to see what it's doing right before it jumps off to nowhere. (Plus, if anything triggers a NMI, it'll jump off to nowhere anyway since you don't have a NMI handler yet.)
Espozo wrote:
This has proven to be far more complicated than I had originally anticipated...
Don't worry. Once you've got the basic setup code functioning, it'll get easier.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144952)
koitsu wrote:
Thus, you probably just need to execute the code/step through it. The MAME debugger documentation is abysmal, so I wish you luck there too. :-)

Well, I stepped through it, and this is where "br" brought me. The whole thing looks like that:

Attachment:
Wow..png
Wow..png [ 45.36 KiB | Viewed 1747 times ]
Joe wrote:
That probably broke it.

That's the only way anything even showed up though. (The picture above was where the older code led.)

You know, when people talk about a reset vector, are they talking about the same thing on the SNES? Like the arcade board has a reset button on it? I originally thought the reset button just turned the system on and off, but games that normally can't save will often save high score and options in the options menu and whatnot.

By the way, I just posted something on some Mame forum about if there is a way to force it to display x86 instructions, so hopefully, I'll hear from them soon.

It still is kind of weird though, Joe, that what you wrote doesn't even display anything. I don't see anything wrong if you're describing it correctly. Is it because it needs to be exactly the right size or something like you kind of said?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144955)
Espozo wrote:
You know, when people talk about a reset vector, are they talking about the same thing on the SNES?
All CPUs have a reset vector. When a CPU is powered on or reset, it begins executing the reset vector.
Espozo wrote:
I originally thought the reset button just turned the system on and off, but games that normally can't save will often save high score and options in the options menu and whatnot.
As long as RAM contents are maintained, the CPU can't tell the difference between power-on and reset. For example, some NES games without nonvolatile RAM can also keep high scores across a reset.
Espozo wrote:
It still is kind of weird though, Joe, that what you wrote doesn't even display anything. I don't see anything wrong if you're describing it correctly. Is it because it needs to be exactly the right size or something like you kind of said?
It sounds like I'll need to check this out in the MAME debugger.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144957)
Well Joe, here you go. Best of luck! :)

(Mod edit: ROM removal)
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144961)
It's probably a bad idea to post copyrighted ROMs.

So! As it turns out, you are correct: MAME doesn't load your replacement ROMs if they are too small.

With that in mind, I have made a slight correction:
Code:
cpu 80186

section code vstart=0 align=16

main_code:
  mov ax, 0xF800
  mov ds, ax
  mov byte [0x800], 0x1F

infinite_loop:
  jmp infinite_loop

section reset start=0x7fff0 vstart=0

  cli
  jmp (section.code.start >> 4):main_code
 
  times 16-($-$$) db 0
After padding the reset section to 16 bytes long, the entire file is exactly 512kiB, which is enough to make MAME load it as expected.
Attachment:
gunforc2.png
gunforc2.png [ 32.19 KiB | Viewed 1721 times ]
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144962)
Joe wrote:
It's probably a bad idea to post copyrighted ROMs.

Oops... :oops: (That's what banned me from the last website I was on...)
I'll get rid of it pronto! (Although I doubt Irem is going to come back from the grave to get me. :roll:

Joe wrote:
Attachment:
gunforc2.png

Is that is what I think it is? :shock:
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144971)
Oh and one thing, Espozo: cli might confuse you because its behaviour is opposite on x86 compared to 65xxx:

65xxx = sei = disables interrupts (i of P becomes 1), cli = enables interrupts (i of P becomes 0)
x86 = sti = enables interrupts (i of FLAGS becomes 1), cli = disables interrupts (i of FLAGS becomes 0)

65xxx = P = 8-bit CPU flag/status register
x86 = FLAGS = 16-bit CPU flag/status register (later extended to 32-bits (EFLAGS) and 64-bits (RFLAGS))

And as Joe more or less said -- yes, every CPU has some form of vectors (reset, interrupt, etc.). You can stop reading here if you don't wanna get hung up on interrupt vectors and the like (i.e. I recommend you stop reading here, haha ;-) ).

x86's interrupt vectors are crazy -- way more advanced than 65xxx because there's so many different hardware interrupts: there's the capability for 256 independent interrupt vectors on the x86 through the IDT (which is just a dedicated 1024-byte area of memory in RAM (0x0000 to 0x03FF) entirely for 32-bit vectors address). The table there on Wikipedia should give you some idea of the kinds of (hardware) interrupts the x86 handles. Bytes 0-3 = division by zero handler, bytes 4-7 = debugger handler, bytes 8-11 = NMI handler, etc..

NMI will probably be the one that looks familiar to you from the SNES ("hey I know that / have heard of that one!") -- except with one huge difference: NMI on PC isn't tied to VBlank (often called Vsync on PC). Note that I said PC and not x86! -- it's completely possible at the hardware level to tie VBlank to NMI on the x86 (maybe arcade boards do this? Not sure!), but on PC architecture this is not how they did it. Instead, on PC architecture (during MS-DOS days, etc. -- things are different now with video cards today), waiting for Vsync on PC required that you sit in a loop waiting for bit 3 of I/O register 0x3DA (one of the VGA status registers) to become 0. See the bottom of this page (C code ahead, but it's easy to understand, kinda. They have two loops there: the first spins the CPU waiting for bit 3 to become 1 (waiting for VBlank to finish in case you're already in VBlank), the second spins the CPU waiting for bit 3 to become 0 (waiting for VBlank to start so you can begin doing your graphics updates/palette changes)).

P.S. -- Feeling big nostalgia for PC after writing this. It's all stuff that isn't used like how it was back in the early 90s -- now with more advanced OSes, 32-bit/64-bit stuff, crazy hardware, etc. lots of stuff is much more complex. But the IDT is still there today, workin' as designed.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144985)
Well, I've been looking, and I think this says how each sprite is set up?

Code:
392 void m92_state::ppan_draw_sprites(bitmap_ind16 &bitmap, const rectangle &cliprect)
393 {
394    UINT16 *source = m_spriteram->live(); // sprite buffer control is never triggered
395    int offs, layer;
396
 
397    for (layer = 0; layer < 8; layer++)
398    {
399       for (offs = 0; offs < m_sprite_list; )
400       {
401          int x = source[offs+3] & 0x1ff;
402          int y = source[offs+0] & 0x1ff;
403          int code = source[offs+1];
404          int color = source[offs+2] & 0x007f;
405          int pri = (~source[offs+2] >> 6) & 2;
406          int curlayer = (source[offs+0] >> 13) & 7;
407          int flipx = (source[offs+2] >> 8) & 1;
408          int flipy = (source[offs+2] >> 9) & 1;
409          int numcols = 1 << ((source[offs+0] >> 11) & 3);
410          int numrows = 1 << ((source[offs+0] >> 9) & 3);
411          int row, col, s_ptr;

I know by looking through one of the files that oam (or "sprite ram" as it's called here) is located at "0xe0000" through "0xeffff". I actually haven't even found out how many sprites there are, so if you get the space for how large "sprite ram" is (2048 bytes, I'm pretty sure) and divide it by how many bytes each entry is, you should get the answer.

You know, this is kind of random, but is the self test something that goes on in software? I would have thought it would have done it even before it looked at any of the code, but it doesn't. One really weird thing is that cgram is filled out even if you don't write anything. (The red color that was being loaded to color 0 just wrote over the first black color, but everything else is still filled out. I would have thought all the colors would have been black from start up.)
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144989)
Espozo wrote:
Well, I've been looking, and I think this says how each sprite is set up?
Yup.
Quote:
I actually haven't even found out how many sprites there are, so if you get the space for how large "sprite ram" is (2048 bytes, I'm pretty sure) and divide it by how many bytes each entry is, you should get the answer.
Well, first, since that table shows indexing as offs+0, +1, +2, +3 it's four words per entry.
Also, right after what you quoted, offs += 4 * numcols;... looks like it has the ability to staple multiple entries together for some kind of metasprite support.
Also the loop iterates to a maximum of m_sprite_list, which elsewhere appears to provide the ability to dynamically choose the number of entries in OAM, up to a maximum of 1024 words of sprites = 2048 bytes you saw = 256 entries.

The format appears to be:
Code:
  fedc ba98 7654 3210
0 LLLW WHHy yyyy yyyy
1 tttt tttt tttt tttt
2        YX plll llll
3         x xxxx xxxx
L - layer
W,H - width, height (0,1,2,3 = 1,2,4,8)
X,Y - reflect X,Y
x,y - x,y coordinate
t - tile ("code")
p - priority
l - color

Quote:
You know, this is kind of random, but is the self test something that goes on in software?
Should be...
Quote:
I would have thought all the colors would have been black from start up.)
RAM rarely contains a specific value on power-up...
Re: Is Anyone Willing to Explain This C++ Code?
by on (#144991)
koitsu wrote:
But the IDT is still there today, workin' as designed.
What you described is the IVT, which is still there today... right up until the OS starts to boot and throws it away in favor of the IDT. (And even then, only if the computer still has BIOS compatibility. UEFI machines without BIOS compatibility won't have an IVT at all.)

So much for nostalgia, huh? :P

Espozo wrote:
Code:
392 void m92_state::ppan_draw_sprites(...
Careful; that function is only used as part of the "ppan" driver. You're using "gunforc2", which uses m92_state::draw_sprites().
Espozo wrote:
is the self test something that goes on in software?
Yes.
Espozo wrote:
One really weird thing is that cgram is filled out even if you don't write anything.
MAME's M92 driver doesn't appear to be very accurate. You will need to test on a real M92 to verify behavior.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145013)
lidnariq wrote:
2 YX plll llll
3 x xxxx xxxx

Now I know why arcade machines are known to be "ineficient". They could have saved an entire byte (and I'm sure they could have done something to put the other 5 unused bytes to use.) Didn't the Genesis actually have 8 bytes per sprite, or am I just hallucinating?

lidnariq wrote:
("code")

Why they named it "code" is completely beyond me.

You know, I've now been trying to change the "code" of sprite 0 to where it is using tile 1 instead of 0 (tile 0 is completely transparent). I am guessing this should show a 16x16 sprite in the top left corner of the screen, but I don't know if this is correct:

Code:
  mov ax, 0xE000
  mov ds, ax
  mov byte [0x002], 0x01

The problem is that I still don't get the whole 20 bit address thing. What is the relationship between the number we are first moving to ax, and the second number (the [0x002])? Why are we moving a number to ax instead of ds in the first place? Is it because there isn't an instruction for it? Does storing a number to ds for 20 bit addresses? The number of the address is supposed to be "E0002", but I don't know if it is here.

Joe wrote:
MAME's M92 driver doesn't appear to be very accurate.

No kidding. :roll: Look at the cut scenes in Ninja Baseball Bat Man. (In earlier versions of Mame, it also used to sound awful.)

Joe wrote:
You will need to test on a real M92 to verify behavior.

I'm up for donations. :wink:
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145016)
Espozo wrote:
Now I know why arcade machines are known to be "inefficient". They could have saved an entire byte
Except that they're working with 16-bit quantities there, and you can't fit four words into seven bytes...

Quote:
Code:
  mov ax, 0xE000
  mov ds, ax
  mov byte [0x002], 0x01

The problem is that I still don't get the whole 20 bit address thing.
It was an awkward hack originally intended for extensibility that got enshrined verbatim. (no, seriously, they originally intended to allow the amount of overlap—the 16 in segment*16+offset—to change) Oops.
Quote:
What is the relationship between the number we are first moving to ax, and the second number (the [0x002])?
They're just a particular splitting of the 20-bit pointer into two 16-bit words, one of 4000 different possible ones. (Because of how 16-bit pointers overflow, they also can be used to ensure that memory access only happens to a specific 64 KiB window)
Quote:
Why are we moving a number to ax instead of ds in the first place? Is it because there isn't an instruction for it?
Exactly.
Quote:
Does storing a number to ds for 20 bit addresses?
I don't understand the question...
Quote:
The number of the address is supposed to be "E0002", but I don't know if it is here.
Yeah, E000:0002 is equal to the flat pointer E0002.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145017)
lidnariq wrote:
Espozo wrote:
Now I know why arcade machines are known to be "inefficient". They could have saved an entire byte
Except that they're working with 16-bit quantities there, and you can't fit four words into seven bytes...

Why does it have to be words and not bytes? The processor seems capable of working with bytes, as evidenced by writing "1F" to cgram.

lidnariq wrote:
[
Quote:
Does storing a number to ds for 20 bit addresses?
I don't understand the question...

Yeah, I didn't mean to say that. :lol: What I meant to say is that does storing the number to ds make it to where it is 20 bit. I assume so.

You know, so far, It seems that 65xx assembly has proven to be the most structurally sound assembly language I've seen. What I was trying to do above could have just been

Code:
lda #$01
sta $0E0002

on the SNES. I originally thought it was cool that you could essentially get rid of "lda" and just load and store in one instruction, but it isn't good when you have to do it 3 times...

Anyway, I actually did try my code, but I don't see anything, and tile number 1 does have something, unlike 0. I assume there is a register somewhere that controls if sprites or BGs are on or off, like on the SNES.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145021)
Espozo wrote:
Why does it have to be words and not bytes? The processor seems capable of working with bytes, as evidenced by writing "1F" to cgram.
Oh, sure, but multiplying by eight (by SHL AL, 1 three times, or MOV CL,3 / SHL AL,CL) is faster than multiplying by seven. (MUL is slooooow. IMUL is sloooooooower)

Quote:
does storing the number to ds make it to where it is 20 bit?
Mm. So the 65816 supports three different ways of talking about memory access:
* direct page, 8 bits immediate (with a 16-bit offset) ( i.e. value of 16-bit D register + value of immediate)
* 16 bits immediate (with a 8-bit "bank") (value of 8-bit B register * 65536 + immediate)
* literal 24-bit pointer

In contrast, the 8086 only supports something that's closest to the middle of the three. (segment * 16 + offset). If you omit the explicit segment, it'll pick one for you (usually DS, but occasionally SS or ES, depending)

Also, even as crippled as the 8086's memory addressing was, it does support adding multiple registers together on a single access. (e.g. mov [BX+SI+7], al)

Quote:
I originally thought it was cool that you could essentially get rid of "lda" and just load and store in one instruction, but it isn't good when you have to do it 3 times...
That's a sign you shouldn't be doing it three times ;)

e.g. instead, try using the rep movsb or rep stosb (or movsw or stosw) instructions.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145031)
Well, relating to sprites, I forgot about how I found something called "sprite control" located at 0xF9000 through 0xF900F, so it's only 16 bits long. I look at the other file, and this is what I found:

Code:
62 WRITE16_MEMBER(m92_state::m92_spritecontrol_w)
63 {
64    COMBINE_DATA(&m_spritecontrol[offset]);
65    // offset0: sprite list size (negative)
66    // offset1: ? (always 0)
67    // offset2: sprite control
68    // offset3: ? (always 0)
69    // offset4: sprite dma
70    // offset5: ?
71
 
72    /* Sprite control - display all sprites, or partial list */
73    if (offset==2 && ACCESSING_BITS_0_7)
74    {
75       if ((data & 0xff) == 8)
76          m_sprite_list = (((0x100 - m_spritecontrol[0]) & 0xff) * 4);
77       else
78          m_sprite_list = 0x400;
79
 
80       /* Bit 0 is also significant */
81    }
82
 
83    /* Sprite buffer - the data written doesn't matter (confirmed by several games) */
84    if (offset==4)
85    {
86       /* this implementation is not accurate: still some delayed sprites in gunforc2 (might be another issue?) */
87       m_spriteram->copy();
88       m_sprite_buffer_busy = 0;
89
 
90       /* Pixel clock is 26.6666MHz (some boards 27MHz??), we have 0x800 bytes, or 0x400 words to copy from
91       spriteram to the buffer.  It seems safe to assume 1 word can be copied per clock. */
92       timer_set(attotime::from_hz(XTAL_26_66666MHz) * 0x400, TIMER_SPRITEBUFFER);
93    }
94 //  logerror("%04x: m92_spritecontrol_w %08x %08x\n",space.device().safe_pc(),offset,data);
95 }

So if you write a number to offset 0, (which is 0xF9000?) the number of sprites will be the same as the number you moved there? What's up with this then?

Code:
67    // offset2: sprite control
...
72    /* Sprite control - display all sprites, or partial list */
73    if (offset==2 && ACCESSING_BITS_0_7)
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145041)
That code says you need to write a value to 0xF9000 that will determine how many sprites to draw, then write 8 (or a word with 8 in the low byte) to 0xF9004 to make the sprite drawing logic use that number. Afterwards, write any value to 0xF9008 to copy the sprites from sprite RAM to the internal drawing buffer.

It looks like this logic was designed specifically for rep movsw.

Edit: these registers start at 0xF9000, not 0xF0000.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145080)
You know, this is horribly inefficient, (I'm still learning) but I expanded upon the older code to try to make it display the one sprite, but it doesn't appear to work. Do you see a problem (other than it's horribly inefficient)?

Code:
cpu 80186

section code vstart=0 align=16

main_code:
  mov ax, 0xF800
  mov ds, ax
  mov byte [0x800], 0x1F

  mov ax, 0xE000
  mov ds, ax
  mov byte [0x002], 0x01

  mov ax, 0xF000
  mov ds, ax
  mov byte [0x000], 0x01

  mov ax, 0xF000
  mov ds, ax
  mov byte [0x004], 0x08

  mov ax, 0xF000
  mov ds, ax
  mov byte [0x008], 0x01

infinite_loop:
  jmp infinite_loop

section reset start=0x7fff0 vstart=0

  cli
  jmp (section.code.start >> 4):main_code
 
  times 16-($-$$) db 0

I'm just curious Joe, but are you interested in this?
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145099)
Espozo wrote:
Do you see a problem (other than it's horribly inefficient)?
The addresses I wrote in my previous post are wrong, so that's part of the reason why it doesn't work! :oops: (I'd better go back and fix that.)

Anyway, here are the three address ranges you want:
Code:
   AM_RANGE(0xf8000, 0xf87ff) AM_RAM AM_SHARE("spriteram")
   AM_RANGE(0xf8800, 0xf8fff) AM_READWRITE(m92_paletteram_r, m92_paletteram_w)
   AM_RANGE(0xf9000, 0xf900f) AM_WRITE(m92_spritecontrol_w) AM_SHARE("spritecontrol")
It looks like you want your second write to go to 0xF8002 instead of 0xE0002, and the third through fifth to go to 0xF9000 instead of 0xF0000.
Espozo wrote:
I'm just curious Joe, but are you interested in this?
Low-level programming is fun. Granted, I prefer to focus my efforts on PCs and game consoles rather than arcade machines, but at the end of the day it's all pretty similar.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145100)
Well, I guess this is kind of like a PC game console, because it is like a game console (obviously) but it uses the x86 architecture (I don't know of any game console that does, or at least any one from this time period.)
Part of the reason I'm doing this is for the novelty of it, but I also like overdraw, but I don't want to do anything on the GBA because I'm not a huge fan of the screen... It's also cool that it's by Irem.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145107)
Espozo wrote:
I don't know of any game console that does, or at least any one from this time period.
IBM was seriously trying to make the PCjr count as a game console. They rather screwed it up, though.

That said, the Tandy 1000 fixed most of the stupid. In fact, so successfully that people forgot that both the extended video modes and sound were originally due to IBM.

As far as arcade hardware goes, x86-based PCs seemed to be the preferred controller for laserdisc games. Not really clear why...
Re: Is Anyone Willing to Explain This C++ Code?
by on (#145429)
I guess I just can't make up my mind, because I think I actually want to look at the Irem M107, which was actually Irem's last and most powerful arcade board, instead of the M92. Don't worry though, they're pretty much the same as they have the same CPU (except the one in the M107 is clocked 5Mhz faster, bringing it to 14 from 9) and nearly the same video hardware, except it had 4 BG layers instead of 3, has 16 instead of 15 bit color (I'm not sure what the last bit does, but it should be easy to figure out) and has 512 sprites instead of 256. (I'm not sure if the overdraw changed any, but I wasn't even sure what the M92's was to begin with). Because of the increased sprite ram, it appears many things have been shifted, like cgram. I found this page that helps a bit: https://github.com/Neo2003/mame4all-pi- ... s/m107.cpp I made the screen turn red on the M107 as a test, and here is the picture: (The display is sideways because the game I'm using as a base is a vertical shooter, but you can rotate the screen in Mame in the settings.)

Attachment:
M107.png
M107.png [ 2.34 KiB | Viewed 2351 times ]

I'm probably not going to be doing anything on this for quite a while though, because I want to do some more SNES stuff first.
Re: Is Anyone Willing to Explain This C++ Code?
by on (#146159)
Well, I was bored and I thought I might try something, so I looked at the tile data for 4 of the rom chips in an M107 game and put them through a program katsumi made that interweaves the bits from 4 different files together, and I did this on two different sets of files and I got this:

Attachment:
Tile Data.png
Tile Data.png [ 53.83 KiB | Viewed 2314 times ]

So not only do the bits from the 4 files get interweaved, each tile from the 2 sets of 4 files does also. Why did they make it so complex, dang it! :x