Files
2026-08-31 21:04:48 +03:00

426 lines
8.5 KiB
NASM

ifndef _mtc_asm_defined
define _mtc_asm_defined
module MTC
;enum-like
struct StreamType
PT3 db 0
PT2 db 0
TS db 0
TFC db 0
Unknown db 0
ends
struct StreamData
Type db 0
Data1 dw 0
Data2 dw 0
Init dw 0
Play dw 0
Mute dw 0
ends
Start
ifndef NoPrologue
ld hl,End
jr Init
jp Play
jp Mute
endif
ifdef HaveFormatCheck
include "format.asm"
;in HL - module addr
;out Z - is mtc
CheckFormat
EqualTo "M"
EqualTo "T"
EqualTo "C"
EqualTo "1"
EqualTo 0
EqualTo 0
ret
display "MTC checker size: ",$-CheckFormat
endif
;in HL - module addr
Init ld ix,Streams
ld (ix+StreamData.Type),StreamType.Unknown
call ParseChunk
cp ChunkId.MTC1
call z,ParseMTC1
call MergeStreams
ld ix,Streams
.initstreams
ld a,(ix+StreamData.Type)
cp StreamType.Unknown
ret z
ld l,(ix+StreamData.Data1)
ld h,(ix+StreamData.Data1+1)
ld e,(ix+StreamData.Data2)
ld d,(ix+StreamData.Data2+1)
ld c,(ix+StreamData.Init)
ld b,(ix+StreamData.Init+1)
push ix
call jp_bc
pop ix
ld bc,StreamData
add ix,bc
jr .initstreams
Play ld ix,Streams
.playstreams
ld a,(ix+StreamData.Type)
cp StreamType.Unknown
ret z
ld c,(ix+StreamData.Play)
ld b,(ix+StreamData.Play+1)
push ix
call jp_bc
pop ix
ld bc,StreamData
add ix,bc
jr .playstreams
Mute ld ix,Streams
.mutestreams
ld a,(ix+StreamData.Type)
cp StreamType.Unknown
ret z
ld c,(ix+StreamData.Mute)
ld b,(ix+StreamData.Mute+1)
push ix
call jp_bc
pop ix
ld bc,StreamData
add ix,bc
jr .mutestreams
jp_bc push bc
ret
;in hl - chunk start
;out a - chunkid
;out hl - chunk data start
;out bc - chunk data size
;corrupt de
ParseChunk
ld de,ChunkId
.checkid
ld b,4
dup 4
ld a,(de)
inc e
cp (hl)
inc hl
jr nz,$+3
dec b
edup
;nz if last byte is not matched
;nz if b != 0 (not all bytes matched)
ld a,e
jr z,.matched
cp ChunkId.Unknown
jr z,.getdata
dec hl,hl,hl,hl
jr .checkid
.matched
sub 4
.getdata
;skip higher bytes of size, assume they are zero
inc hl
inc hl
ld b,(hl)
inc hl
ld c,(hl)
inc hl
ret
;put streams in gap
Streams
MinStreamsCount=3 ;approx: ts+tfm
ds MinStreamsCount*StreamData ;approx
Streams.End
display "MTC: loosed ",256-low $," bytes"
align 256
ChunkId
.MTC1=low $
db "MTC1"
.TRCK=low $
db "TRCK"
.DATA=low $
db "DATA"
.NAME=low $
db "NAME"
.AUTH=low $
db "AUTH"
.ANNO=low $
db "ANNO"
.PROP=low $
db "PROP"
.Unknown=low $
MaxStreamsCount=(ChunkId-Streams)/StreamData
display "MTC: max streams ",MaxStreamsCount
macro MoveNextChunk
;chunk is always aligned at word boundary, so correct odd length
push bc
pop af
adc hl,bc
endm
;in hl - content
;in bc - size
ParseMTC1
push hl
add hl,bc
ex (sp),hl
; (sp) - end of avail data
.nextchunk
call ParseChunk
push hl,bc
cp ChunkId.TRCK
call z,ParseTrack
pop bc,hl
MoveNextChunk
pop bc
;hl- end of chunk
;de- end of avail
sbc hl,bc
ret z ;last chunk
add hl,bc
push bc
jr .nextchunk
;in hl - content
;in bc - size
ParseTrack
push hl
add hl,bc
ex (sp),hl
; (sp) - end of avail data
.nextchunk
call ParseChunk
push hl,bc
cp ChunkId.DATA
call z,ParseData
exa
pop bc,hl
MoveNextChunk
pop bc
exa
ret z ;data is parsed
;hl- end of chunk
;de- end of avail
and a
sbc hl,bc
ret z ;last chunk
add hl,bc
push bc
jr .nextchunk
;in hl - content
;in bc - size
;out Z - data parsed and added as stream
ParseData
call ParseTFC
call nz,ParseTS
call nz,ParsePT2
jr nz,ParsePT3
ret
ParseTFC
push hl,bc
call TFC.CheckFormat
pop bc,hl
ret nz
ld a,StreamType.TFC
exx
ld hl,TFC.Init
ld de,TFC.Play
ld bc,TFC.Mute
call FillStream
AddStream
ld bc,StreamData
add ix,bc
ld (ix+StreamData.Type),StreamType.Unknown
xor a;set Z
ret
ParseTS
push hl,bc
call TS.CheckFormatKnownSize
pop bc,hl
ret nz
call FillTS
jr AddStream
ParsePT2
push hl,bc
call PT2.CheckFormat
pop bc,hl
ret nz
ld a,StreamType.PT2
exx
ld hl,PT2.Init
call FillPts
jr AddStream
ParsePT3
push hl,bc
call PT3.CheckFormat
pop bc,hl
ret nz
ld a,StreamType.PT3
exx
ld hl,PT3.Init
call FillPts
jr AddStream
FillTS ld a,StreamType.TS
exx
ld hl,TS.Init
FillPts ld de,PTS.PLAY
ld bc,PTS.MUTE
FillStream
ld (ix+StreamData.Type),a
ld (ix+StreamData.Init),l
ld (ix+StreamData.Init+1),h
ld (ix+StreamData.Play),e
ld (ix+StreamData.Play+1),d
ld (ix+StreamData.Mute),c
ld (ix+StreamData.Mute+1),b
exx
ld (ix+StreamData.Data1),l
ld (ix+StreamData.Data1+1),h
ld (ix+StreamData.Data2),e
ld (ix+StreamData.Data2+1),d
ret
;some business-logic related to supported players
MergeStreams
ld a,(Streams+StreamData.Type)
cp StreamType.Unknown
ret z ;no streams
ld a,(Streams+StreamData+StreamData.Type)
cp StreamType.Unknown
ret z ;single stream
;sort streams according to type, use simple bubblesort
Sort
assert 0 == ((Streams ^ Streams.End) >> 8)
assert 0 == StreamData.Type
ld de,Streams
ld hl,Streams+StreamData
ld c,0;swaps mark
.cycle
ld a,(de)
cp StreamType.Unknown
jr z,.end
cp (hl)
jr c,.next
jr z,.next
ld b,StreamData
.swapitems
ld a,(de)
ld c,(hl)
ld (hl),a
ld a,c
ld (de),a
inc l
inc e
djnz .swapitems
ld c,h
jr .cycle
.next
ld e,l
ld a,l
add a,StreamData
ld l,a
jr .cycle
.end
ld a,c
and a
jr nz,Sort
;try merge streams
; X X merged to X (last is taken)
; PT3 PT3 merged to TS
Merge
assert 0 == StreamData.Type
ld de,Streams
ld hl,Streams+StreamData
.cycle
ld a,(de)
cp StreamType.Unknown
ret z
cp (hl)
jr z,.perform
ld e,l
ld a,l
add a,StreamData
ld l,a
jr .cycle
.perform
cp StreamType.PT3
jr nz,.generic
;merge PT3 streams to TS
push hl,de
push hl,de
inc l
ld e,(hl)
inc l
ld d,(hl) ;data1
pop hl
inc l
ld a,(hl)
inc l
ld h,(hl)
ld l,a ;data2
pop ix
call FillTS
pop de,hl
.generic
;for other types just take last one
ld b,StreamData
.copyitems
ld a,(hl)
ld (de),a
inc l
inc e
djnz .copyitems
ld a,(de)
cp StreamType.Unknown
jr nz,.generic
jr MergeStreams
endmod
ifndef NoPrologue
define NoPrologue
endif
ifndef HaveFormatCheck
define HaveFormatCheck
endif
ifndef ONtfm
define ONtfm
endif
include "PTSPlay.asm"
include "pt3.asm"
include "pt2.asm"
include "ts.asm"
include "tfc.asm"
MTC.End
display "MTC module size: ",MTC.End-MTC.Start
endif