Disassembling Juno First

Pagina 1/2
| 2

Door Metalion

Paragon (1559)

afbeelding van Metalion

28-07-2022, 18:25

Hi everyone,

I'm disassembling Juno First for the fun of it.
I thought it would be easy, but I must say some of its code is baffling me.

It starts already with the start address of the ROM being 030Dh. OK, after some research I found out that some roms can have a bizarre mirroring, and therefore I suppose that the "correct" address is 430Dh. And it seems to fit, since there's a RET at 430Ch.

T430Dh	3EF0....  >ð..	LD	A,0F0h
T430Fh	D3AA....  Óª..	OUT	(0AAh),A		; PortC (8255) Keyb Row

; Erases RAM from 0E000h to E800h
T4311h	F3......  ó...	DI
T4312h	2100E0..  !.à.	LD	HL,0E000h
T4315h	1101E0..  ..à.	LD	DE,0E001h
T4318h	01FF07..  .ÿ..	LD	BC,007FFh
T431Bh	3600....  6...	LD	(HL),000h
T431Dh	EDB0....  í°..	LDIR

T431Fh	ED56....  íV..	IM	1			; sets Z80 in IM1 (normal mode)
T4321h	3100E5..  1.å.	LD	SP,0E500h		; puts SP @ 0E500h

First part is well understood, except for the fact that I have no idea what does exactly sending the F0h value to port AAh of the PPI. But the strangest part is yet to come:

; unknown effect
T4324h	214E1D..  !N..	LD	HL,01D4Eh
T4327h	0608....  ....	LD	B,008h
T4329h	1680....  .€..	LD	D,080h
T432Bh	5E......  ^...	LD	E,(HL)
T432Ch	EF......  ï...	RST	40			; RST 028h
T432Dh	23......  #...	INC	HL			;
T432Eh	14......  ....	INC	D			;
T432Fh	10FA....  .ú..	DJNZ	0FAh			; Jump to 0432BH

It uses RST 028h (GETYPR), but according to the documentation, that call returns the type of DAC (decimal accumulator) ? WTF ???
The program uses RST 028h a couple of times after that, always using DE as input.
What does it do ?

Aangemeld of registreer om reacties te plaatsen

Van Pencioner

Scribe (1507)

afbeelding van Pencioner

28-07-2022, 20:28

seems to be an obfuscation
i checked with msxsyssrc (disassembled MSX BIOS) and it nails down to:

;       Subroutine      GETYPR
;       Inputs          ________________________
;       Outputs         ________________________

C5597:  LD      A,(VALTYP)
        CP      8
        JR      NC,J55A3
        SUB     3
        OR      A
        SCF
        RET

J55A3:  SUB     3
        OR      A
        RET

which actually does only change accumulator and flags. and loop which calls it also changes some registers so maybe actual result is the value of those registers after this 'useless' looping

Van Metalion

Paragon (1559)

afbeelding van Metalion

28-07-2022, 21:03

Not sure it's an obfuscation, because they're using this RST 028h in several places after that, always with DE as input. Here are 2 examples:

T4388h	110040..  ..@.	LD	DE,04000h
T438Bh	EF......  ï...	RST	40
T43BEh	118245..  .‚E.	LD	DE,04582h
T43C1h	EF......  ï...	RST	40

I followed a little bit the BIOS call at 028h on a MSX2, and at some point it it reads EXPTBL (0FCC1h), then calls a portion of code in the RAM variables section (0F38Ch), in which some output is done on port A8h (PPI), and then a jump is made to (ix), which contains 0521Ch, which calls another part of the ROM ... It's indeed complicated, and it seems very strange.

I'm wondering if it's not checking for slot configuration, or something similar.

Grauw wrote on his page :

GETYPR
Remark : Not a very clear routine to me, please mail us if you know more about it.

Van NYYRIKKI

Enlighted (5940)

afbeelding van NYYRIKKI

28-07-2022, 21:29

Hi,

Nope, the "correct address" is not $430D, but indeed $030D as it says... You are reading the correct routine, but from wrong address... and that is exactly why you are lost with the RST $28... It is not GETYPR, but the routine in $0028 that you have now incorrectly mapped to $4028.

There is no secrets in I/O $AA writing, just some basic initialization.. (Caps lock off, key click, cassette motor off and keyboard row reset.)

Van Metalion

Paragon (1559)

afbeelding van Metalion

29-07-2022, 12:19

Thanks Nyyrikki, that's the correct answer.

The 4028h routine does indeed a VRAM write initialization with the address in DE.
It's a nice trick to use the mirroring to be able to call that with a simple RST 28h ! Smile
And, it's also a nice trick that allows you to have your own ISR in 38h without any complex slot manipulation.

But how does the emulator knows about the correct mirroring ?

EDIT: but it does not make the code more understandable.
The loop sends 8 16-bit values consecutively to the VDP port 99h, that do stricly nothing:

- 8000h : read 0000h (but it does not fetch the data)
- 8162h : read 0162h (but it does not fetch the data)
- 8201h : read 0201h (but it does not fetch the data)
- 831Eh : read 031Eh (but it does not fetch the data)
- 8401h : read 0401h (but it does not fetch the data)
- 850Eh : read 050Eh (but it does not fetch the data)
- 8600h : read 0600h (but it does not fetch the data)
- 8701h : read 0701h (but it does not fetch the data)

Van NYYRIKKI

Enlighted (5940)

afbeelding van NYYRIKKI

29-07-2022, 13:50

Metalion wrote:

But how does the emulator knows about the correct mirroring ?

Emulators usually use a database that has the information of ROM mappers, mirroring and stuff. ie. OpenMSX calculates a SHA checksum of the ROM and uses that to search the hardware info. This way user can rename the ROM-file, but correct information can be still found from database.

There is always possibility that for some reason the file is not in database. User has edited number of lives, ROM database is too old or so... In this case the emulators try to make best guess using all kinds of algorithms. Sometimes they get lucky and sometimes not. In case of not, user then needs to input the hardware type manually. How hard is that depends of the emulator, but ie. BlueMSX has a dropdown menu on ROM mounting screen.

If we talk strictly about mirroring (=<32KB) and not ie, if the ROM uses ASCII or Konami mapper, then for emulator it is pretty safe to always expect that all ROMs are mirrored. Only case where it might cause a problem is if the ROM exits to BASIC, because then it is possible that init routine is accidentally executed two times instead of once. Even when it happens, this very rarely causes any fatal issue.

Quote:

EDIT: but it does not make the code more understandable.
The loop sends 8 16-bit values consecutively to the VDP port 99h, that do stricly nothing:

I don't understand what you mean by "nothing"(?) If you send data out, it always does something... ie. in the "unknown effect" routine you posted it clearly dumps values from $01D4 to all VDP registers and this way sets up screen mode, sprites, colors, interrupts, pattern addresses and stuff like that.

Van Metalion

Paragon (1559)

afbeelding van Metalion

29-07-2022, 14:37

Thanks for the explanation about mirroring.

The mirroring on Juno First is special: there is only 8K of code, and it's repeated 4 times to fill the 32K. But the code is executed in the first bank (0000h-1FFFh) without any slot manipulation. How does the MSX mirrors the code in those addresses without deselecting the BIOS in that slot ?

NYYRIKKI wrote:

I don't understand what you mean by "nothing"(?) If you send data out, it always does something... ie. in the "unknown effect" routine you posted it clearly dumps values from $01D4 to all VDP registers and this way sets up screen mode, sprites, colors, interrupts, pattern addresses and stuff like that.

Read again my message: the loop reads VRAM at 8 different addresses but does not fetch the data.
So it does nothing, in effect.

Van ducasp

Hero (575)

afbeelding van ducasp

29-07-2022, 14:50

NYYRIKKI wrote:
Metalion wrote:

But how does the emulator knows about the correct mirroring ?

Emulators usually use a database that has the information of ROM mappers, mirroring and stuff. ie. OpenMSX calculates a SHA checksum of the ROM and uses that to search the hardware info. This way user can rename the ROM-file, but correct information can be still found from database.

There is always possibility that for some reason the file is not in database. User has edited number of lives, ROM database is too old or so... In this case the emulators try to make best guess using all kinds of algorithms. Sometimes they get lucky and sometimes not. In case of not, user then needs to input the hardware type manually. How hard is that depends of the emulator, but ie. BlueMSX has a dropdown menu on ROM mounting screen.

If we talk strictly about mirroring (=<32KB) and not ie, if the ROM uses ASCII or Konami mapper, then for emulator it is pretty safe to always expect that all ROMs are mirrored. Only case where it might cause a problem is if the ROM exits to BASIC, because then it is possible that init routine is accidentally executed two times instead of once. Even when it happens, this very rarely causes any fatal issue.

Quote:

EDIT: but it does not make the code more understandable.
The loop sends 8 16-bit values consecutively to the VDP port 99h, that do stricly nothing:

I don't understand what you mean by "nothing"(?) If you send data out, it always does something... ie. in the "unknown effect" routine you posted it clearly dumps values from $01D4 to all VDP registers and this way sets up screen mode, sprites, colors, interrupts, pattern addresses and stuff like that.

That default mirroring on emulators is a fact and I've wasted quite a few hours when making a rom bios for a device that has no mirroring and getting that bios executing twice when debugging. It was a simple 16KB rom and emulators make it mirror since they don't know what it is as it is not on their databases... Tongue

Van NYYRIKKI

Enlighted (5940)

afbeelding van NYYRIKKI

29-07-2022, 15:16

Metalion wrote:

How does the MSX mirrors the code in those addresses without deselecting the BIOS in that slot ?

No magic here either, this is result of how the cartridge init works... At start we are on BASIC memory configuration. It first reads the header from #4000 using RDSLT calls and when the header is found, it reads init address from #4002 again using RDSLT calls. Then it simply calls the address (in this case $030D) using CALSLT. In order to reach the address it has to switch the slot visible and that is pretty much all there is to say about the subject. This is just how the interslot calls work on MSX. How ever please note that because RDSLT was used the cartridge ROM is not visible on Z80 address space $4000-$FFFF

Quote:

Read again my message: the loop reads VRAM at 8 different addresses but does not fetch the data.
So it does nothing, in effect.

Ok, this part I still fail to see on you message, but can you copy/paste example? Maybe there is something that just does not meet the eye.

Van NYYRIKKI

Enlighted (5940)

afbeelding van NYYRIKKI

29-07-2022, 15:36

ducasp wrote:

That default mirroring on emulators is a fact and I've wasted quite a few hours when making a rom bios for a device that has no mirroring and getting that bios executing twice when debugging. It was a simple 16KB rom and emulators make it mirror since they don't know what it is as it is not on their databases... Tongue

When developing there is quite easy way around it. Put to start of init LD A,H:CP $80:RET NC
This is not standardized way, but it works due to how the init works. (See previous post)

Van Grauw

Ascended (10618)

afbeelding van Grauw

29-07-2022, 18:09

Metalion wrote:

but it does not make the code more understandable.
The loop sends 8 16-bit values consecutively to the VDP port 99h, that do stricly nothing:

- 8000h : read 0000h (but it does not fetch the data)
- 8162h : read 0162h (but it does not fetch the data)
- 8201h : read 0201h (but it does not fetch the data)
- 831Eh : read 031Eh (but it does not fetch the data)
- 8401h : read 0401h (but it does not fetch the data)
- 850Eh : read 050Eh (but it does not fetch the data)
- 8600h : read 0600h (but it does not fetch the data)
- 8701h : read 0701h (but it does not fetch the data)

If bit 7 of the high byte is set it is a register write. So it initializes VDP registers 0-7. Unless I misunderstand what you wrote there.

Pagina 1/2
| 2