Page 1 of 3
[Hard+Soft] Memory Base 128
Posted: Sun Apr 27, 2014 3:10 pm
by MooZ
Let's talk about this backup unit!
I'll post pictures of its electronic bowels later.
This little beast is plugged on the joypad port and I think I managed to isolate some routines from Shin Megami Tensei.
You can find it at offsets $1a440a and $902c0a in Track02.iso . It's usually mapped at $740a to $79cb.
mb128.asm contains what I managed to extract with etripator.
I hoped I'm wrong but it seems that the data is read 1 bit at a time (see line 659).
The code at $7xxx is called from $6b32:
Code: Select all
6b32: lda $79cc
beq $6b38
rts
6b38: lda #$00
jsr $7601
tii $7edd, $7add, $0200
lda #$01
jsr $7601
tii $7edd, $7cdd, $0200
inc $79cc
rts
So each call read 512 bytes. If you put a read breakpoint on the $7add-$7edd you'll end up at $6a8e.
Code: Select all
6a87: jsr $6b32
clx
6a8b: lda $6ab3,X
cmp $7ae1,X
bne $6a9a
inx
cpx #$0a
bne $6a8b
clc
rts
6a9a: sec
rts
So what are those 10 bytes at $6ab3 ? Well it's
And that's the shift-jis for
メモリベース128
And guess what that means? Yep that's
Memory Base - 128
Re: [Hard+Soft] Memory Base 128
Posted: Tue Apr 29, 2014 7:38 pm
by MooZ
Picture time! (click on the image for a larer version)
The memory is the Oki chip. It seems to be a MSM6389C, a 1,048,576-Word x 1-Bit Solid-State Recorder Data Register. That's coherent with the bit-banging code (1048576 bits = 128kB).
The NEC chip seems to be one of those infamous gate array.
Re: [Hard+Soft] Memory Base 128
Posted: Fri May 09, 2014 3:16 pm
by MooZ
Re: [Hard+Soft] Memory Base 128
Posted: Tue Jun 03, 2014 8:52 pm
by MooZ
Here's the piece of the code that was mislabeled as 8d77:
7d77
Some part of it are weird like the cmp #$00 / bcs (the branch is always taken). Another weird thing, if you use this routine in a standalone program and put it on a turbo everdrive, it will work on the first run. But if you reset the console using the board push-button, it will fail.
Re: [Hard+Soft] Memory Base 128
Posted: Sat Jul 12, 2014 5:32 pm
by MooZ
Here's a commented disassembly of
$740a. This routine transfers 512 bytes to the memory base 128.
Let's start with some helper macros.
Code: Select all
; Joypad delay (1 tick = 9 cycles).
wait_1 .macro
pha
pla
nop
.endm
Code: Select all
; Wait for 3 ticks.
wait_3 .macro
wait_1
wait_1
wait_1
.endm
Code: Select all
; Transfer a 0 bit to memory base 128.
transfer_bit_0 .macro
pha
lda #$00
sta joyport
wait_3
lda #$02
sta joyport
wait_1
pla
.endm
Code: Select all
; Transfer a 1 bit to memory base 128.
transfer_bit_1 .macro
pha
lda #$01
sta joyport
wait_3
lda #$03
sta joyport
wait_1
pla
.endm
Code: Select all
; Transfer a complete byte to memory base 128.
; The register A holds the value to transfer.
transfer_byte .macro
ldx #$08
.start_\@:
beq .end_\@
bit #$01
beq .even_\@
.odd_\@:
transfer_bit_1
bra .next_bit_\@
.even_\@:
transfer_bit_0
.next_bit_\@:
ror A
dex
bra byte_loop_start
.end_\@:
.endm
Code: Select all
; Check for memory base 128 presence.
mb128_check .macro
sei
pha
lda #$03
.loop_\@:
pha
jsr $77d7
pla
bcc .found_\@
dec A
bne .loop_\@
.not_found_\@:
; No memory base 128.
pla
cli
jmp $7f98
.found_\@:
.endm
Code: Select all
; Write 512 bytes from $7edd to memory base 128.
mb128_transfer512:
mb128_check
; There's a memory base 128 on the joypad line.
transfer_bit_0
transfer_bit_0
transfer_bit_0
pla
transfer_byte
lda #$00
transfer_byte
lda #$10
transfer_byte
transfer_bit_0
transfer_bit_0
transfer_bit_0
transfer_bit_0
; Transfer the data located from $7edd to $80dd
ldy #$dd
sty <$0d
ldy #$7e
sty <$0e
.transfer_loop:
ldy #$00
lda [$0d], Y
transfer_byte
; Move to next byte.
clc
lda <$0d
adc #$01
sta <$0d
lda <$0e
adc #$00
sta <$0e
; Check if we reacher $80dd
ldy <$0e
cpy #$80
bne .neq
ldy <$0d
cpy #$dd
.neq:
bne .transfer_loop
transfer_bit_0
cli
rts
Re: [Hard+Soft] Memory Base 128
Posted: Sat Jul 12, 2014 9:56 pm
by MooZ
Note that all the code posted are extracted from Shin Megami Tensei. I'm not responsible for the non optimized/silly code.
Here's the read routine:
Code: Select all
; Read 512 bytes from memory base 128 and store them at $7edd
mb128_read512:
mb128_check
transfer_bit_1
transfer_bit_0
transfer_bit_0
pla
transfer_byte
lda #$00
transfer_byte
lda #$10
transfer_byte
transfer_bit_0
transfer_bit_0
transfer_bit_0
transfer_bit_0
; Transfer to $7edd
ldx #$dd
stx <$0b
ldx #$7e
stx <$0c
.read_loop:
ldy #$00
lda #$00
sta [$0b], Y
; Read 8 bits from memory base 128
ldx #$00
.read_bit:
wait_1
transfer_bit_0
lda joyport
and #$01
clc
ror A
ror A
ora [$0b], Y
inx
cpx #$08
beq .next_byte
lsr A
sta [$0b], Y
bra .read_bit
.next_byte:
sta [$0b], Y
; Move to next byte.
clc
lda <$0b
adc #$01
sta <$0b
lda <$0c
adc #$00
sta <$0c
; Check if we reacher $80dd
ldx <$0c
cpx #$80
bne .neq
ldx <$0b
cpx #$dd
.neq:
bne .read_loop
cli
rts
Re: [Hard+Soft] Memory Base 128
Posted: Sun Jul 13, 2014 5:08 pm
by MooZ
I made some minor cleanup and put everything on cleanup:
https://gist.github.com/BlockoS/ad7098771aea4970886b
Well... now we'll need someone to figure out how the data is organised in the mb128.
Re: [Hard+Soft] Memory Base 128
Posted: Sun Oct 26, 2014 9:41 pm
by MooZ
Tadaima Yuusha Boshuuchuu has a backup manager (hold I+Select at boot). Here's the csv file in order to extract some piece of code that seems to be dealing with Memory Base 128.
The asm files are
(here).
Re: [Hard+Soft] Memory Base 128
Posted: Sun Dec 14, 2014 4:57 pm
by MooZ
$7770 is the routine for writing a byte to the mb128.
$77b8 is the routine for reading a byte from the mb128.
The commented version for $7770 can be found here :
tadaima_7770.asm
Below is a simplified pseudo C code version of $7770.
Code: Select all
fe = a;
for(x=8; x>0; --x) {
a = fe & 1;
fe >>= 1;
joypad = a;
wait(1);
joypad = 0x02 | a;
wait(3);
joypad = a;
wait(1);
}
In Shin Megami Tensei, we have something like:
Code: Select all
for(x=8; x>0; x--) {
bit = fe & 1;
if(bit) {
joypad = 0x01;
wait(3);
joypad = 0x03;
wait(1);
} else {
joypad = 0x00;
wait(3);
joypad = 0x02;
wait(1);
}
}
It's ... weird...
Re: [Hard+Soft] Memory Base 128
Posted: Sun Dec 14, 2014 6:36 pm
by MooZ
$7826 checks if there's a memory base 128.
tadaima_7826.asm
This time it's very similar to Shin Megami Tensei.
Code: Select all
for(nTry=0; nTry<3; nTry++) {
send_byte( 0xA8 );
send_bit( 0x00 );
A = joypad;
fe = A << 4;
send_bit(0x01);
A = joypad;
fe = fe | (A & 0x0F);
if(fe == 0x04) {
return found;
}
}
return not_found;
The main difference is that in Shin Megami Tensei, they test each nibble separately. If the first nibble read from the joypad port is not zero they don't bother fetching the second one.
Code: Select all
for(nTry=0; nTry<3; nTry++) {
send_byte( 0xA8 );
send_bit( 0x00 );
A = joypad;
if( A == 0x00 ) {
send_bit( 0x01 );
A = joypad;
if( A == 0x04 ) {
return found;
}
}
}
return not_found;