Skip to content

Commit

Permalink
Added stereo support
Browse files Browse the repository at this point in the history
Added support for stereo sound in a way that allows the program to fall back on mono when necessary. This is not a breaking change.
  • Loading branch information
maxotaku11niku committed Aug 24, 2023
1 parent ebd074a commit 8c144ac
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 11 deletions.
14 changes: 12 additions & 2 deletions 98video.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ Header:
Screen resolution spec (bit 4)
0x00 640x400 (pixel aspect 1:1)
0x10 640x200 (pixel aspect 1:2)
Unused (bit 5-7)
Audio channel spec (bit 5)
0x00 Mono
0x20 Stereo (if ADPCM, else also mono)
Unused (bit 6-7)
high byte uint8 Unused
0x0A uint4[16][3] colour table (rg br gb ...) for all 16 initial colours

Frame Data:
Audio Data:
0x00 uint16 length of audio data (16-bit words, n)
0x02 uint16[n] Audio data
0x02 uint16[n] Audio data (mean level)
var uint16[n] Audio data (stereo difference, only if stereo specified, otherwise it is left out)
ADPCM:
The audio data is in 8-bit signed ADPCM format which expands to signed 16-bit PCM
Buzzer audio:
Expand All @@ -38,6 +42,12 @@ ADPCM codec:
abs(data) <= 0x18: decrement bitshift by 1 after this sample.
abs(data) >= 0x68: increment bitshift by 1 after this sample.
(My decoder actually uses an acceleration table it creates at startup just to speed things up by using an acceptable amount of memory)
Stereo encoding:
The mean level signal (m) is always included as this is the mono signal. Stereo is encoded through a difference signal (d), which uses the same ADPCM encoding as the mean level signal.
To get the right (r) and left (l) signals, we apply the following transformations:
l = m + d
r = m - d
This ordering is arbitrary.
Video Frame Header:
0x00 low byte UUUU IRGB planes to update (automatically determines how many plane sections and which planes they correspond to, U is reserved for 256 colour board compatibility)
high byte 0000 000P update palette?
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ $(PROCESS)/98videop.o : $(BUILD)/$(OFILES)
ld -T doscom.lds -m i386pe -o $(PROCESS)/98videop.o $^

$(BUILD)/$(OFILES) : $(SOURCES)/$(ASMFILES)
as $< -o $@ -march=i386 -mtune=i386 --32
as $< -o $@ -march=i386 -mtune=i286 --32
12 changes: 9 additions & 3 deletions doscom.lds
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
/* Simple GNU ld linker script to build a DOS .COM executable */

MEMORY
{
segment (wxa) : ORIGIN = 0, LENGTH = 64K
}

SECTIONS
{
. = 0x100;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
.text ALIGN(0x10) : { *(.text) } >segment
.data ALIGN(0x10) : { *(.data) *(.rdata) } >segment
.bss (NOLOAD) : ALIGN(0x10) { *(.bss) } >segment
/DISCARD/ : { *(.rdata$zzz) *(.reloc) } >segment
}
128 changes: 123 additions & 5 deletions src/98videoplayer.asm
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
;#FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
;#OTHER DEALINGS IN THE SOFTWARE.

.arch i486
.arch i286
.intel_syntax noprefix
.code16 ;#This is intended to run in real mode

Expand Down Expand Up @@ -221,6 +221,9 @@ video_read_end_magicnum: ;#Set various options
int 0x18 ;#PC98 CRT BIOS: Set display options (640x200, display page 0, colour mode)
pop ax
video_read_fullres:
and bx, 0x0020
shr bx, 5
mov cs:is_stereo, bl
and ax, 0x0007
mov cs:audiospec, ax
xor ax, ax
Expand Down Expand Up @@ -581,19 +584,25 @@ PROCEDURE_frameloop: ;#void frameloop(void)
mov cx, ax
push cx
mov cs:filebuffercurpos, si
mov bl, cs:is_stereo
test bl, bl
jz notstereo
shl ax, 1
notstereo:
shl ax, 1
add ax, 4
call PROCEDURE_tryreadsection
mov al, cs:using_86
mov si, cs:filebuffercurpos
cmp al, 0x01
jne frameloop_buzaudio
test al, al
jz frameloop_buzaudio
jmp frameloop_86audio
;#Decode ADPCM for buzzer PCM
frameloop_buzaudio:
pop bp
push bp
mov di, cs:samplebufferptr
push cs
pop es
Expand Down Expand Up @@ -643,14 +652,23 @@ frameloop_buzaudio_pushloop:
mov cx, 0x0010
rep stosb ;#Add padding to reduce clipping(?)
pop cx
pop ax
mov bl, cs:is_stereo
test bl, bl
jz no_skip_stereodata
shl ax, 1
add si, ax ;#Needed to skip over unused stereo difference data (buzzer audio is forced mono)
no_skip_stereodata:
jmp frameloop_videodata_process
frameloop_86audio:
;#Decode ADPCM for 86 PCM
test bl, bl
jnz frameloop_86audio_stereo
pop di
mov dx, 0xA46C
mov cx, cs:adpcmshiftval
frameloop_86audio_pushloop:
frameloop_86audio_mono_pushloop:
lodsw
push ax
xor ah, ah
Expand Down Expand Up @@ -690,7 +708,104 @@ frameloop_86audio_pushloop:
out dx, al
mov cl, cs:[bx+accelerationtable_adpcm]
dec di
jnz frameloop_86audio_pushloop
jnz frameloop_86audio_mono_pushloop
jmp frameloop_videodata_process
frameloop_86audio_stereo:
pop bp
mov dx, 0xA46C
mov cl, cs:adpcmshiftval
mov ch, cs:adpcmshiftval_diff
mov bx, bp
shl bx, 1
frameloop_86audio_stereo_pushloop:
lodsw
push ax
xor ah, ah
mov di, cx
and di, 0x00FF
shl di, 8
add di, ax
cbw
shl ax, cl
add ax, cs:lastsample
mov cs:lastsample, ax
mov cl, cs:[di+accelerationtable_adpcm]
mov al, [bx+si-2]
xor ah, ah
xchg cl, ch
mov di, cx
and di, 0x00FF
shl di, 8
add di, ax
cbw
shl ax, cl
add ax, cs:lastsample_diff
mov cs:lastsample_diff, ax
mov cl, cs:[di+accelerationtable_adpcm]
mov di, ax
mov ax, cs:lastsample
push bx
mov bx, ax
add ax, di
xchg al, ah ;#output left sample
out dx, al
xchg al, ah
out dx, al
sub bx, di
mov ax, bx
xchg al, ah ;#output right sample
out dx, al
xchg al, ah
out dx, al
pop bx
xchg cl, ch
pop ax
xchg al, ah
xor ah, ah
mov di, cx
and di, 0x00FF
shl di, 8
add di, ax
cbw
shl ax, cl
add ax, cs:lastsample
mov cs:lastsample, ax
mov cl, cs:[di+accelerationtable_adpcm]
mov al, [bx+si-1]
xor ah, ah
xchg cl, ch
mov di, cx
and di, 0x00FF
shl di, 8
add di, ax
cbw
shl ax, cl
add ax, cs:lastsample_diff
mov cs:lastsample_diff, ax
mov cl, cs:[di+accelerationtable_adpcm]
mov di, ax
mov ax, cs:lastsample
push bx
mov bx, ax
add ax, di
xchg al, ah ;#output left sample
out dx, al
xchg al, ah
out dx, al
sub bx, di
mov ax, bx
xchg al, ah ;#output right sample
out dx, al
xchg al, ah
out dx, al
pop bx
xchg cl, ch
dec bp
jnz frameloop_86audio_stereo_pushloop
mov cs:adpcmshiftval_diff, ch
xor ch, ch
add si, bx
frameloop_videodata_process:
mov cs:adpcmshiftval, cx
Expand Down Expand Up @@ -944,6 +1059,7 @@ frameloop_stopplaneread:
old_timer_vector_offset: .word 0x0000
old_timer_vector_segment: .word 0x0000
using_86: .byte 0x00
is_stereo: .byte 0x00
current_buzzer_shiftdown: .byte 0x00
old_interrupt_mask: .byte 0x00
current_sample_midpoint: .word 0x0000
Expand All @@ -959,7 +1075,9 @@ frameloop_stopplaneread:
framesleft: .word 0x0000
audiospec: .word 0x0000
lastsample: .word 0x0000
lastsample_diff: .word 0x0000
adpcmshiftval: .word 0x0000
adpcmshiftval_diff: .word 0x0000
numframes_lo: .word 0x0000
numframes_hi: .word 0x0000 ;#32-bit to support very long videos
filehandle: .word 0x0000
Expand Down

0 comments on commit 8c144ac

Please sign in to comment.