MuSICA disassembly and adapting it for pure ASM

ページ 1/3
| 2 | 3

By shram86

Expert (117)

shram86 さんの画像

05-07-2019, 01:20

Hullo,

I took the replay.bin driver from the MuSICA distro and disassembled it by hand, for practice. (It is not yet completely labeled, but for reference, it is here: replay.z80 (google drive)

I'm attempting to adapt it for pure asm, and then later for MSX-DOS. I'm almost there, but I need help with the last step.

The driver appears to require the following BASIC statements before loading and executing:

10 clear20,&ha5b6:definta:dim a(1)
20 bload"music.bin",r

If any part of line 10 is changed (besides from adjusting "20" to an equally appropriate value) then it breaks -- usually causing a system reset.

The code I'm using is here:

 fname "music.bin"

 db $fe
 dw START
 dw EOF
 dw init

HIMEM: equ $fc4a
InitMus: equ $ce00
StartMus: equ $ce03
InitializeIRQ: equ 0CE34h

 org $9000
START:

MusLoc: db 0, 0, $b7, $a5

init:
    ;ld hl, $a5b6
    ;ld (HIMEM), hl 

    ld hl, player 
    ld de, $ce00
    ld bc, EOF-player 
    ldir

    ld hl, music 
    ld de, $a5b7 
    ld bc, player-music 
    ldir

    call InitMus

    ld hl, MusLoc
    push hl         ; store on stack
    pop ix          ; pop real addr to ix
    ld a, (ix+0)    ; a is first byte of song data
    ld l, (ix+2)    ; l is 2 bytes up
    ld h, (ix+3)    ; h is 3 bytes up
    call InitializeIRQ
    
loop: jp loop 

music:
incbin "testing1.bgm",7
player:
incbin "replay.bin",7
EOF: 

My question is: How would one emulate the clear $a5b6 statement in assembly, and the def/dim statements? I don't want to use BASIC code at all, if this is going to run under MSX-DOS.

I eagerly await any assistance any of you fine gentlemen can give :BA:

ログイン/登録して投稿

By zPasi

Champion (499)

zPasi さんの画像

05-07-2019, 08:21

shram86 wrote:

My question is: How would one emulate the clear $a5b6 statement in assembly, and the def/dim statements? I don't want to use BASIC code at all, if this is going to run under MSX-DOS.

Here: how-to-call-msx-basic-clear-command-in-assembly
Of course under DOS you cannot call BASIC ROM directly, you'll have to use inter-slot call.

But I'm not sure about the definta:dim a(1) part.

By shram86

Expert (117)

shram86 さんの画像

05-07-2019, 13:35

zPasi wrote:
shram86 wrote:

My question is: How would one emulate the clear $a5b6 statement in assembly, and the def/dim statements? I don't want to use BASIC code at all, if this is going to run under MSX-DOS.

Here: how-to-call-msx-basic-clear-command-in-assembly
Of course under DOS you cannot call BASIC ROM directly, you'll have to use inter-slot call.

But I'm not sure about the definta:dim a(1) part.

Thanks for the response. I saw that post yesterday and spent over an hour on it but I can't seem to get it to work. It always returns to basic with Syntax error in (stack address).

If I understand the code properly, pushing the expected entry point (eg the beginning of the asm program) to the stack and just replacing byte one of the nextline hook with c9h should work, but regardless of how I modify it, the same sort of Syntax error occurs.

I also tried the same method of calling the dim statement with the same result. *_*

By Giangiacomo Zaffini 2

Champion (300)

Giangiacomo Zaffini 2 さんの画像

05-07-2019, 16:28

You got my attention. It's not much for now though.
Do You know what these 20 bytes in RAM @a56b address and this scalar int a variabile (16-bits int?) in RAM are used for in music.bin? Let me look into Your disassembly and see.

By shram86

Expert (117)

shram86 さんの画像

05-07-2019, 17:38

Giangiacomo Zaffini 2 wrote:

You got my attention. It's not much for now though.
Do You know what these 20 bytes in RAM @a56b address and this scalar int a variabile (16-bits int?) in RAM are used for in music.bin? Let me look into Your disassembly and see.

Thanks ^^

I do not know what the string vars are used for, I don't think the argument after clear matters - the following works just as well:
10 clear1,&ha5b6:dima(1)
So I believe it's the clearing of the other variables in ram that is more important, and setting the max ram address of basic. The a() variable is passed originally as:

120 a(0)=0
130 a(1)=&ha5b7:rem begin mus address
140 a=usr1(varptr(a(0)))

This is easily simulated with the MusLoc pointer and calling InitializeIRQ manually (see PushArgs label for how it handles this in the disassembly).
I don't see anywhere where it checks for that variable or space anywhere else in the code, so I'm quite confused.

By Giangiacomo Zaffini 2

Champion (300)

Giangiacomo Zaffini 2 さんの画像

05-07-2019, 23:47

complete bgm.bas loader and player should be bgm.bas from ahiroe

100 CLEAR 100,&HA5B6:DEFINT A-Z:DIM I(1)
110 BLOAD"bgm.bin"
120 GOSUB 270:V=0:ST=0
130 PRINT"RET:Load BGM data":PRINT"0:Start BGM":PRINT"1:Stop BGM"
140 PRINT"+/- :Volume":PRINT"ESC:End"
150 PRINT"*:Pause":PRINT"/:Continue"
160 A$=INPUT$(1)
170 IF A$=CHR$(13) THEN GOSUB 350:GOSUB 290
180 IF A$="0" AND ST<>0 THEN GOSUB 290
190 IF A$="1" THEN GOSUB 320
200 IF A$="-" AND V<15 THEN V=V+1:GOSUB 340
210 IF A$="+" AND V>0 THEN V=V-1:GOSUB 340
220 IF A$="*" THEN V0=V:V=17:GOSUB 340
230 IF A$="/" THEN V=18:GOSUB 340:V=V0
240 IF A$=CHR$(27) THEN GOSUB 320:END
250 GOTO 160
260 'Initialize
270 DEFUSR=&HCE00:I=USR(0):RETURN
280 'Start BGM
290 I(0)=0:I(1)=ST:DEFUSR=&HCE03:I=USR(VARPTR(I(0))):RETURN
300 DEFUSR=&HCE03:I=USR(VARPTR(I(0))):RETURN
310 'Stop BGM
320 DEFUSR=&HCE06:I=USR(0):RETURN
330 'Master volume
340 I(0)=V:DEFUSR=&HCE09:I=USR(VARPTR(I(0))):RETURN
350 'Load BGM data & read start address
360 GOSUB 320:INPUT"File name";A$:A$=A$+".bgm":BLOAD A$
370 OPEN A$ FOR INPUT AS #1:A$=INPUT$(3,#1):CLOSE #1
380 ST=ASC(MID$(A$,2,1)) + ASC(MID$(A$,3,1))*256 - 65536!
390 PRINT "Top address =";HEX$(ST):RETURN

By shram86

Expert (117)

shram86 さんの画像

06-07-2019, 00:02

That's virtually the same player, it just has additional features (like specifying filename instead of defining it in the .bas program).

It doesn't seem to give any clarification on what I'm asking, but thanks Smile

By shram86

Expert (117)

shram86 さんの画像

06-07-2019, 01:16

Sort of solved!

The following code will load and play without any BASIC whatsoever.

What happens:
Using the eponymous Red Book, I figured out that CLEAR also resets the stack pointer (duh) as well as resizes memory in accordance to IO buffer size. However, after doing this, the IOALLOC command needs to be called to reset these buffers to their new location. Luckily, this command rets to its called location, and not to the BASIC next line interpreter - so very little modification is needed.

What you DO have to do is be careful with where you put variables after loading your ASM game. But for now, sweet sweet MuSICA.

If anyone has advice on how to get started adapting the disassembly to DOS, let me know. The only tricky part seems to be where it JUMPs to WRTPSG instead of CALLs it. Still puzzling that one out.

 fname "music.bin"

 db $fe
 dw START
 dw EOF
 dw init

HIMEM: equ $fc4a
InitMus: equ $ce00
StartMus: equ $ce03
InitializeIRQ: equ 0CE34h

IOALLOC: equ $7e6b  ; needs to be interslot call if DOS

 org $9000
START:

MusLoc: db 0, 0, $b7, $a5

init:
    ld hl, $a39d   ; (himem) - 267*2 [for io] + 1 [str arg] + 2
    ld ($f674), hl ; STKTOP
    ld hl, $a39c   ; (stktop-1)
    ld ($f672), hl ; MEMSIZ
    ld hl, $a5b6   ; musloc - 1 
    ld ($fc4a), hl ; HIMEM
    call IOALLOC

    ld hl, player 
    ld de, $ce00
    ld bc, EOF-player 
    ldir

    ld hl, music 
    ld de, $a5b7 
    ld bc, player-music 
    ldir

    call InitMus

    ld hl, MusLoc
    push hl         ; store on stack
    pop ix          ; pop real addr to ix
    ld a, (ix+0)    ; a is first byte of song data
    ld l, (ix+2)    ; l is 2 bytes up
    ld h, (ix+3)    ; h is 3 bytes up
    call InitializeIRQ
    
loop: jp loop 

music:
incbin "testing1.bgm",7
player:
incbin "replay.bin",7

EOF: 

By Giangiacomo Zaffini 2

Champion (300)

Giangiacomo Zaffini 2 さんの画像

06-07-2019, 02:06

OK then, as far as I understand, looking into chapter 4. BASIC of MSX Datapack volume 1, focusing on Figure 2.21 describing BASIC user zone

BASIC clear command modifies BASIC user zone,
BASIC clear command two arguments are:
first argument is size of string area, i.e. between STKTOP and MEMSIZ
second argument is value of HIMEM address, starting from HIMEM address is machine language area.

I'm quite sure music.bin needs having HIMEM moved from default value, in facts, even other MuSICA players move HIMEM. Why doesn't it do it by its own, it is unknown.

I think (please verify it) that moving HIMEM in assembly is just writing into HIMEM address 0fc4ah

HIMEM equ $0FC4A

HIMEM_NEW: ; new HIMEM
defw $0A5B6

ld de, HIMEM_NEW
add hl, de
ld a, (hl)
inc hl
ld h, (hl)
ld l, a
ld (HIMEM), hl ; set HIMEM

P.S. You already solved, for good then!

P.P.S. If You want a music.bin that is MSX1 compatible, follow tiny-yarou advice.

By Giangiacomo Zaffini 2

Champion (300)

Giangiacomo Zaffini 2 さんの画像

06-07-2019, 14:48

By shram86

Expert (117)

shram86 さんの画像

06-07-2019, 15:25

Giangiacomo Zaffini 2 wrote:

Saibara MuSICA specification

Excellent, thank you! Been looking for something like this.

ページ 1/3
| 2 | 3