1

Hello
I stopped C developing because as I knew how to do some things in C but there was always one problem that annoyed me a lot, I stopped developing on the Neo in C and instead switched to 68k assembly language. But, here's my problem: my program works perfectly fine with an original MVS BIOS, but when I try it with an AES BIOS or an Unibios, then I just get a black screen and MAME debug option shows that it does some stuff then loop over this:

C116D0 | cmpm.w (a0)+, (a1)+
C116D2 | bne $C116DA
C116D4 | cmpa.l a1, a2
C116D6 | bne $c116d0

If someone has a clue on what happens here (@blastar ?) it would help me a lot.
avatar

2

hmm, I don't know the problem (yet)... a loop in the BIOS itself that checks something... and that infinitely. maybe it's some kind of validity/work check that fails because of a strange memory configuration?
you're certainly using your own entry in the XML file?

3

I don't know a thing about 68k assembly and even less on NeoGeo but maybe it's a uninitialized variable that causes some trouble?
avatar
"If you see strict DRM and copy protection that threatens the preservation of history, fight it: copy the work, keep it safe, and eventually share it so it never disappears. [...] no one living 500 years from now will judge your infringing deeds harshly when they can load up an ancient program and see it for themselves."

Benj Edwards - Why History Needs Software Piracy

- - -
Achat ou échange: topic de mes recherches Meilleur smiley = #helico# Obligatory XKCD

4

blastar (./2) :
hmm, I don't know the problem (yet)... a loop in the BIOS itself that checks something... and that infinitely. maybe it's some kind of validity/work check that fails because of a strange memory configuration?
you're certainly using your own entry in the XML file?
No, I use Super Sidekicks in MAME. One weird thing is that even the simple Hello world program from wiki.neogeodev.org has the same problem, and that both programs work on MVS
avatar

5

Maybe you can find some information here : http://www.ajworld.net/neogeodev/beginner/

6

Thanks for the link! Lots of useful info and I didn't know about it
avatar

7

Hi

Assuming a0 and a1, two address registers, are pointing to two memory sections,
the code seems to try to compare the content and the address location....

C116D0 | cmpm.w (a0)+, (a1)+ ... compare the word (cmpm.w) pointed by a0 and a1, set flags and post increment a0 and a1
C116D2 | bne $C116DA ... branch if not equal to instruction at $C116DA ... what ever follow
C116D4 | cmpa.l a1, a2 ... if equal the compare both addresses (address are long i.e. .l), set the flags
C116D6 | bne $c116d0 .... if not equal them loop back to $c116D0 to further compare the loop
C116DA | ... what ever follow here

So it seems this loop is trying to compare the content of two data section pointed by a0 and a1, and also their address location.
Could this piece of code be used by some sort of verification for security, usually one compare the address content but here
there is also some comparison for address location too ...

Hope this helps

Brahim :: Singapore
avatar

8

I'm not great with asm yet, but we don't know what a1 and a2 are pointed to do we? I think we can assume that a1 is pointing to a different place than a2 and that this code is looking for comparison.

It is fair to say that a1 is the cart and a2 is the system. A security verification makes sense.

Can you comment out these lines to see what happens?
avatar

9

I recommend to start from the source of 'aj/freem (e.g. ADPCM-A and ADPCM-B test thing)' or to use it as a base, it is well commented and a good start for your own code, it also made it easier for me to get back into development after a few years.
to learn the basics for ASM 'MarkeyJester's Motorola 68000 Beginner's Tutorial' is a good start.

10

I also read the tutorial from MarkeyJester. You might write a program in C and then rewrite some of the functions in asm. That's what I have been doing. I rewrote my collision detection code in asm and learned a lot from it.
avatar

11

Here is disassembly code of KOF '94 taken through internal disassember of MAME debugger. It's need to find an IDs of punch/kick swing and hit SFX samples according to weak, medium and strong attack types (and IDs of hitmark sprites according to this attack types and pallettes for this sprites also) in this pieces of code. Would anybody able to help me with it?

tromb Fichier joint : KOF '94 disassembly.zip
avatar

12

I marked all the addressations to $10FD96 (P1_CURRENT), $10FD97 (P1_CHANGE), $10FD9C (P2_CURRENT), $10FD9D (P2_CHANGE) I found with a comments (search this comments by "P1_CUR", "P1_CHNG", "P2_CUR", "P2_CHNG" text) in the KOF '94 disassembly. It's necessary to understand now, what in-game processes the pieces of code following after commented commands are responsible for.

tromb Fichier joint : KOF '94 disassembly (commented).zip
avatar

13

This ASM you pasted from AES bios is the security code check based on offset 0x182 from the 68k header. If your hanging on a blank screen then this check is failing / drawing crosshatch while no tiles are present to display screen correctly.

See https://wiki.neogeodev.org/index.php?title=Security_code for more info.
www.universebios.com

14

Here is a code executing after first joypad interaction string I found in KoF '94 disassembly. Well, please check, did I understood all in the commented strings correctly.

0330B8: 1039 0010 FD96 move.b $10fd96.l, D0 ; P1_CURRENT value moving to D0 0330BE: 0240 000F andi.w #$f, D0 ; D0 first 4 bits (active joystick directions) check 0330C2: D040 add.w D0, D0 ; *2 because word-reads/writes (long too!) must be even!!! 0330C4: 41FA 002C lea ($2c,PC) ; ($330f2), A0 0330C8: 4E71 nop 0330CA: 3230 0000 move.w (A0,D0.w), D1 ; read a word (2 bytes, because of this D0*2), word-reads/writes must be even!!! 0330CE: 6B20 bmi $330f0 ; end of suroutine if result of [$330f2]+D0 moving to D1 is negative 0330D0: 203C 0002 0000 move.l #$20000, D0 0330D6: 4EB9 0000 27EC jsr $27ec.l ; jump to $27ec subroutine (this subroutine code will be quoted separately) 0330DC: 2944 0050 move.l D4, ($50,A4) 0330E0: 2945 0058 move.l D5, ($58,A4) 0330E4: 4844 swap D4 0330E6: 4845 swap D5 0330E8: D96C 0024 add.w D4, ($24,A4) 0330EC: DB6C 0026 add.w D5, ($26,A4) 0330F0: 4E75 rts 0027EC: 2800 move.l D0, D4 ; move #$20000 to D4 0027EE: 3A01 move.w D1, D5 ; move [$330f2]+((P1_CURRENT value&#$f)*2) to D5 0027F0: 6100 0010 bsr $2802 ; goto $2802 subroutine 0027F4: C144 exg D0, D4 0027F6: 1205 move.b D5, D1 0027F8: 6100 000C bsr $2806 ; repeat an analogic actions without of addition of #$40 to D1 at the begin 0027FC: C145 exg D0, D5 0027FE: 4485 neg.l D5 002800: 4E75 rts002802: 0601 0040 addi.b #$40, D1 ;([$330f2]+((P1_CURRENT value&#$f)*2))+#$40 002806: 0281 0000 00FF andi.l #$ff, D1 00280C: 4A01 tst.b D1 00280E: 6A02 bpl $2812 ;if (([$330f2]+((P1_CURRENT value&#$f)*2))+#$40)&#$ff is positive then goto $2812 subroutine 002810: 4480 neg.l D0 ;else D0=#$-20000 002812: D241 add.w D1, D1 002814: 41F9 00C0 4000 lea $c04000.l, A0 00281A: 3230 1000 move.w (A0,D1.w), D1 ;((([$330f2]+((P1_CURRENT value&#$f)*2))+#$40)&#$ff)+$c04000 00281E: 0C41 0001 cmpi.w #$1, D1 002822: 6704 beq $2828 ;end the subroutine if ((([$330f2]+((P1_CURRENT value&#$f)*2))+#$40)&#$ff)+$c04000=1 002824: 6000 0004 bra $282a ;else goto $282a subroutine 002828: 4E75 rts 00282A: 4A80 tst.l D0 ; is D0 = 0 ? 00282C: 40C3 move SR, D3 ; save statusregister.w (also CCR) to D3 00282E: 6722 beq $2852 ; if D0 = 0 then goto $2852 002830: 6A02 bpl $2834 ; if D0 > 0 then goto $2834 002832: 4480 neg.l D0 ; else D0 = D0 * -1 002834: 3400 move.w D0, D2 ; d0.w to d2.w (lower) 002836: 4840 swap D0 ; swap d0 lower <> higher 002838: C4C1 mulu.w D1, D2 ; d2 = d2 * d1 00283A: 0682 0000 8000 addi.l #$8000, D2 ; mask highest bit 002840: 4242 clr.w D2 ; clear lower 002842: 4842 swap D2 ; swap higher <> lower 002844: C0C1 mulu.w D1, D0 ; d0 = d1 * d0 002846: D082 add.l D2, D0 ; d0 = d0 + D2 002848: 44C3 move D3, CCR ; restore statusregister.b from D3 to CCR 00284A: 6A02 bpl $284e ; if D0 > 0 then end the subroutine ahead of time 00284C: 4480 neg.l D0 ; else d0 * -1 00284E: 4E75 rts
avatar

15

002852: 7000 moveq #$0, D0 002854: 4E75 rts
This subroutine seriously embarrased me. As you see in the previous post, it's executing if D0=0. Why to zeroize D0 again then, and multiply 0 by -1 after?
avatar

16

This is not a subroutine, since it is called by "beq". It's just an early exit that returns zero if D0 is zero.

The function looks like a typical 32 bit x 32 bit multiplication routine, so it makes sense (zero multiplied by anything is always zero).
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

17

Now, what do you think, what concrete in-game processes might be hidden behind all the code I quoted? What it responsible for?
avatar

18

0331C8: 1039 0010 FD96 move.b $10fd96.l, D0 ; P1_CURRENT value moving to D0 0331CE: 0240 000F andi.w #$f, D0 ; D0 first 4 bits (active joystick directions) check 0331D2: 41FA 0020 lea ($20,PC) ; ($331f4), A0 0331D6: 4E71 nop 0331D8: 7200 moveq #$0, D1 ; D1=0 0331DA: 1230 0000 move.b (A0,D0.w), D1 ; D1=[$331f4]+D0 (why to zeroize D1 before it?) 0331DE: 6B00 0012 bmi $331f2 ; end of suroutine if result of [$331f4]+D0 moving to D1 is negative 0331E2: D241 add.w D1, D1 0331E4: D241 add.w D1, D1 ; else ([$331f4]+D0)*4 (why so strange way to do it has been selected?) 0331E6: 41FA 001C lea ($1c,PC) ; ($33204), A0 0331EA: 4E71 nop 0331EC: 2070 1000 movea.l (A0,D1.w), A0 ; A0=[$33204]+(([$331f4]+D0)*4) 0331F0: 4E90 jsr (A0) ; goto [$33204]+(([$331f4]+(P1_CURRENT value&#$f))*4) address 0331F2: 4E75 rts
avatar

19

VasiliyFamiliya (./18) :
0331D8: 7200 moveq #$0, D1 ; D1=0 0331DA: 1230 0000 move.b (A0,D0.w), D1 ; D1=($331f4)+D0 (why to zeroize D1 before it?)
move.b only modifies the lowest byte. To use D1 as a word or double-word value, you need to clear the upper bytes manually; that's what the moveq before does.

VasiliyFamiliya (./18) :
add.w D1, D1 add.w D1, D1 ; else (($331f4)+D0)*4 (why so strange way to do it has been selected?)
Because it executes faster than a multiplication or a bit shift.

VasiliyFamiliya (./18) :
(($331f4)+D0)*4
You should not use parentheses both for grouping and for addressing, this is confusing.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

20

Zerosquare (./19):
VasiliyFamiliya (./18) :
0331D8: 7200 moveq #$0, D1 ; D1=0 0331DA: 1230 0000 move.b (A0,D0.w), D1 ; D1=($331f4)+D0 (why to zeroize D1 before it?)
move.b only modifies the lowest byte. To use D1 as a word or double-word value, you need to clear the upper bytes manually; that's what the moveq before does.

VasiliyFamiliya (./18) :
add.w D1, D1 add.w D1, D1 ; else (($331f4)+D0)*4 (why so strange way to do it has been selected?)
Because it executes faster than a multiplication or a bit shift.


Thank you!

Zerosquare (./19):
VasiliyFamiliya (./18) :
(($331f4)+D0)*4
You should not use parentheses both for grouping and for addressing, this is confusing.

Now I put all the addresses in the comments (excepting auto-generated by MAME disassembler) to square brackets instead of parentheses.

04BA6E: 4DF9 0010 FD96 lea $10fd96.l, A6 ; P1_CURRENT value moving to A6 04BA74: 4EBA 019E jsr ($19e,PC) ; ($4bc14) 04BA78: 4E71 nop 04BA7A: 082C 0000 00C9 btst #$0, ($c9,A4) 04BA80: 6700 0014 beq $4ba96 04BA84: 4EBA 004C jsr ($4c,PC) ; ($4bad2) 04BA88: 4E71 nop 04BA8A: 4EBA 01BA jsr ($1ba,PC) ; ($4bc46) 04BA8E: 4E71 nop 04BA90: 4EBA 0218 jsr ($218,PC) ; ($4bcaa) 04BA94: 4E71 nop 04BA96: 4E75 rts04BDBA: 4DF9 0010 FD96 lea $10fd96.l, A6 ; P1_CURRENT value moving to A6 04BDC0: 4EBA 0034 jsr ($34,PC) ; ($4bdf6) 04BDC4: 4E71 nop 04BDC6: 4EBA 0570 jsr ($570,PC) ; ($4c338) 04BDCA: 4E71 nop 04BDCC: 4EBA 0730 jsr ($730,PC) ; ($4c4fe) 04BDD0: 4E71 nop 04BDD2: 4EBA 052A jsr ($52a,PC) ; ($4c2fe) 04BDD6: 4E71 nop 04BDD8: 4E75 rts04CD6E: 4DF9 0010 FD96 lea $10fd96.l, A6 ; P1_CURRENT value moving to A6 04CD74: 4EBA 0034 jsr ($34,PC) ; ($4cdaa) 04CD78: 4E71 nop 04CD7A: 4EBA 026A jsr ($26a,PC) ; ($4cfe6) 04CD7E: 4E71 nop 04CD80: 4EBA 0348 jsr ($348,PC) ; ($4d0ca) 04CD84: 4E71 nop 04CD86: 4EBA 0224 jsr ($224,PC) ; ($4cfac) 04CD8A: 4E71 nop 04CD8C: 4E75 rts04D28A: 4DF9 0010 FD96 lea $10fd96.l, A6 ; P1_CURRENT value moving to A6 04D290: 4EBA 0034 jsr ($34,PC) ; ($4d2c6) 04D294: 4E71 nop 04D296: 4EBA 0254 jsr ($254,PC) ; ($4d4ec) 04D29A: 4E71 nop 04D29C: 4EBA 0360 jsr ($360,PC) ; ($4d5fe) 04D2A0: 4E71 nop 04D2A2: 4EBA 020E jsr ($20e,PC) ; ($4d4b2) 04D2A6: 4E71 nop 04D2A8: 4E75 rts04DB40: 4DF9 0010 FD96 lea $10fd96.l, A6 ; P1_CURRENT value moving to A6 04DB46: 4EBA 002E jsr ($2e,PC) ; ($4db76) 04DB4A: 4E71 nop 04DB4C: 4EBA 016C jsr ($16c,PC) ; ($4dcba) 04DB50: 4E71 nop 04DB52: 4EBA 012C jsr ($12c,PC) ; ($4dc80) 04DB56: 4E71 nop 04DB58: 4E75 rts04E1D6: 4DF9 0010 FD96 lea $10fd96.l, A6 ; P1_CURRENT value moving to A6 04E1DC: 4EBA 0034 jsr ($34,PC) ; ($4e212) 04E1E0: 4E71 nop 04E1E2: 4EBA 0158 jsr ($158,PC) ; ($4e33c) 04E1E6: 4E71 nop 04E1E8: 4EBA 01F2 jsr ($1f2,PC) ; ($4e3dc) 04E1EC: 4E71 nop 04E1EE: 4EBA 01B2 jsr ($1b2,PC) ; ($4e3a2) 04E1F2: 4E71 nop 04E1F4: 4E75 rts
avatar

21

What is lenght of opcode by 04B1D6 address? I need to know it to count the ($22,PC) address in the 04B1D6 command.
avatar

22

How should I to understand this string?

04B1FA: 3031 3233 move.w INVALID 31, D0
And isn't it a time to puzzle out finally, what concrete in-game processes are hiding behind all these computations and endless numbers interchange between registers and/or memory, before I get confused in my comments by bell, book and candle? Just look to 04B1B4 string, and you'll see how impossibly long and complicated the expressions became!
avatar

23

Thoses are the controls of the palette editor (debug dip 2-1)

190413043126301272.png

24

HPMAN (./23):
Thoses are the controls of the palette editor (debug dip 2-1)

190413043126301272.png


What part of code I listed previously is this post about?
avatar

25

4ac34+

26

HPMAN (./25):
4ac34+

It means, I searched the attacks functions in the wrong place for all this time?
avatar

27

Obviously, yep.

28

HPMAN (./27):
Obviously, yep.

Where should I search the attack functions then?
avatar

29

No idea, never had a deep look into this game.

30

But what's about pieces of code by 04BA6E, 04BDBA, 04CD6E, 04D28A, 04DB40 and 04E1D6 addresses?
avatar