diff --git a/software/Makefile b/software/Makefile index 3df1e9a..afaa768 100644 --- a/software/Makefile +++ b/software/Makefile @@ -34,7 +34,8 @@ SUBDIRS=\ joyconf\ keymap\ loadpzx\ - playrmov + playrmov\ + playzxm .PHONY: all all: build diff --git a/software/playzxm/.gitignore b/software/playzxm/.gitignore new file mode 100644 index 0000000..82e29a6 --- /dev/null +++ b/software/playzxm/.gitignore @@ -0,0 +1,5 @@ +# SPDX-FileCopyrightText: 2021 Ivan Tatarinov +# +# SPDX-License-Identifier: CC0-1.0 + +build diff --git a/software/playzxm/Makefile b/software/playzxm/Makefile new file mode 100644 index 0000000..87ffe8a --- /dev/null +++ b/software/playzxm/Makefile @@ -0,0 +1,84 @@ +# SPDX-FileCopyrightText: 2021 Ivan Tatarinov +# +# SPDX-License-Identifier: GPL-3.0-or-later +# +# Supported environments: +# * GNU on Linux, FreeBSD etc. +# * GNU on Windows NT (using MinGW/MSYS/Cygwin/WSL) +# +# Build: +# make [ ...] +# Install / Uninstall: +# make [prefix=] install | uninstall +# Clean: +# make clean | distclean +# +# where: +# is one of values for `BINS' variable prefixed with "build/" +# (see target `all' below). +# is a prefix directory to install files into. + +include ../../sdk/common.mk + +srcdir = . +# Use uppercase for FAT filesystem +prefix ?= . +exec_prefix ?= $(prefix) +bindir ?= $(exec_prefix)/BIN + +INSTALL ?= install +INSTALL_PROGRAM ?= $(INSTALL) +RM = rm -f + +INCLUDEDIR = ../../sdk/include +AS = sjasmplus +ifeq ($(USE_SJASMPLUS_VERSION),sjasmplus) +AFLAGS = --nobanner +else ifeq ($(USE_SJASMPLUS_VERSION),z00m128) +AFLAGS = --nologo +else +AFLAGS = +endif +AFLAGS += -I$(INCLUDEDIR) + +BINS=\ + PLAYZXM + +.PHONY: all +all: $(foreach t,$(BINS),build/$(t)) + +build\ +$(DESTDIR)$(bindir): + mkdir -p $@ + +build/PLAYZXM: $(srcdir)/playzxm.asm\ + $(INCLUDEDIR)/zxuno.def\ + $(INCLUDEDIR)/esxdos.def\ + $(INCLUDEDIR)/regs.mac\ + $(INCLUDEDIR)/filezxm.def\ + | build + $(AS) $(AFLAGS) --raw=$@ $< + +# $1 = target +# No need in execution mode for FAT filesystem +define install_bin_rule = +$$(DESTDIR)$$(bindir)/$1: build/$1 | $$(DESTDIR)$$(bindir) + $$(INSTALL_PROGRAM) -m 644 $$< $$@ +endef + +$(foreach t,$(BINS),$(eval $(call install_bin_rule,$(t)))) + +.PHONY: install +install: $(foreach t,$(BINS),$(DESTDIR)$(bindir)/$(t)) + +.PHONY: uninstall +uninstall: + $(RM) $(foreach t,$(BINS),$(DESTDIR)$(bindir)/$(t)) + +.PHONY: clean +clean: + rm -f $(foreach t,$(BINS),build/$(t)) + +.PHONY: distclean +distclean: + rm -rf build diff --git a/software/playzxm/playzxm.asm b/software/playzxm/playzxm.asm index 0c90b3b..f1737f6 100644 --- a/software/playzxm/playzxm.asm +++ b/software/playzxm/playzxm.asm @@ -1,266 +1,311 @@ -; API de ESXDOS. -include "esxdos.inc" -include "errors.inc" - -; PLAYZXM : un comando para ESXDOS 0.8.5 que permite reproducir videos en formato -; ZXM en blanco y negro y color. - -; Video: cabecera + secuencia lineal de frames. -; Cabecera (256 bytes): -; Offset Contenido -; 0 'Z' -; 1 'X' -; 2 'M' -; 16-17 Numero de frames que tiene el video (no usado en esta rutina) -; 18 Numero de sectores (de 512 bytes) que ocupa cada frame: 12 para BW, 14 para color -; Resto de posiciones: reservado - -; Cada frame: en blanco y negro, 6144 bytes en formato pantalla de Spectrum. Un pixel a 1 se muestra en negro. A 0, en blanco. -; en color, 256 bytes de relleno + 6912 bytes en formato pantalla de Spectrum -; NOTA: el relleno es simplemente para que cada frame ocupe un número entero de sectores. El relleno se pone a 0 -; o a lo que se quiera, ya que no se hace nada con él. - - -;Para ensamblar con PASMO como archivo binario (no TAP) - -BORDERCLR equ 23624 -PAPERCOLOR equ 23693 -BANKM equ 7ffdh -PILA equ 3deah ;valor sugerido por Miguel Ângelo para poner la pila en el área de comando - - org 2000h ;comienzo de la ejecución de los comandos ESXDOS. - -Main proc - ld a,h - or l - jr z,PrintUso ;si no se ha especificado nombre de fichero, imprimir uso - call RecogerNFile - - di - ld (BackupSP),sp - ld sp,PILA - ei - call PlayFichero - push af - call Cls - pop af - ld sp,(BackupSP) - ret - -PrintUso ld hl,Uso -BucPrintMsg ld a,(hl) - or a - ret z - rst 10h - inc hl - jr BucPrintMsg - endp - - -RecogerNFile proc ;HL apunta a los argumentos (nombre del fichero) - ld de,BufferNFich -CheckCaracter ld a,(hl) - or a - jr z,FinRecoger - cp " " - jr z,FinRecoger - cp ":" - jr z,FinRecoger - cp 13 - jr z,FinRecoger - ldi - jr CheckCaracter -FinRecoger xor a - ld (de),a - inc de ;DE queda apuntando al buffer este que se necesita en OPEN, no sé pa qué. - ret - endp - - -PlayFichero proc - xor a - rst 08h - db M_GETSETDRV ;A = unidad actual - ld b,FA_READ ;B = modo de apertura - ld hl,BufferNFich ;HL = Puntero al nombre del fichero (ASCIIZ) - rst 08h - db F_OPEN - ret c ;Volver si hay error - ld (FHandle),a - - call SetupVideoMemory - call ReadHeader - jr c,FinPlay - -BucPlayVideo ld hl,(StartScreen) - ld bc,(LFrame) - ld a,(FHandle) - rst 08h - db F_READ - jr c,FinPlay ;si error, fin de lectura - ld a,b - or c - jr z,FinPlay ;si no hay más que leer, fin de lectura - - call SwitchScreens - ld bc,7ffeh - in a,(c) ;Detectar si se ha pulsado SPACE - and 1 - jr z,FinPlay - - jr BucPlayVideo - -FinPlay ld a,(FHandle) - rst 08h - db F_CLOSE - - call RestoreVideoMemory - - or a ;Volver sin errores a ESXDOS - ret - endp - - -ReadHeader proc - ld a,(FHandle) - ld bc,256 - ld hl,32768 - rst 08h - db F_READ - ret c - - ld hl,32768 - ld a,'Z' - cpi - jr nz,NoZXM - ld a,'X' - cpi - jr nz,NoZXM - ld a,'M' - cpi - jr nz,NoZXM - - ld hl,32768+18 - ld a,(hl) - add a,a - ld b,a - ld c,0 - ld (LFrame),bc - - ld bc,49152 ;Principio buffer pantalla para BW - ld (StartScreen),bc - ld a,(hl) - cp 12 ;B/W ? - jr z,ZXMOk - - ld bc,49152-256 ;Principio buffer pantalla para color - ld (StartScreen),bc - -ZXMOk or a - ret - -NoZXM scf - ret - endp - - -SetupVideoMemory proc - di - ld bc,BANKM - ld a,00010111b ;banco 7, pantalla normal, ROM 3 - ld (Banco),a - out (c),a - - ld hl,0c000h + 6144 - ld de,04000h + 6144 - ld bc,768 -SetAttr ld a,64+56 - ld (hl),a - ld (de),a - inc hl - inc de - dec bc - ld a,b - or c - jr nz,SetAttr - - xor a - ld bc,0fc3bh - out (c),a - inc b - in a,(c) - ld (BackupConfig),a - or 20h - out (c),a - - xor a - out (254),a - - ei - ret - endp - - -RestoreVideoMemory proc - di - xor a - ld bc,0fc3bh - out (c),a - inc b - ld a,(BackupConfig) - out (c),a - - ld bc,BANKM - ld a,00010000b ;banco 0, pantalla normal, ROM 3 - out (c),a - ei - ret - endp - - -SwitchScreens proc - halt - ld a,(Banco) - xor 00001010b ;conmutamos de la pantalla normal a la shadow y de la 7 a la 5 - ld (Banco),a - ld bc,BANKM - out (c),a - ret - endp - - -Cls proc - ld a,(BORDERCLR) - sra a - sra a - sra a - and 7 - out (254),a - ld hl,16384 - ld de,16385 - ld bc,6143 - ld (hl),l - ldir - inc hl - inc de - ld bc,767 - ld a,(PAPERCOLOR) - ld (hl),a - ldir - ret - endp - - - ; 01234567890123456789012345678901 -Uso db " playzxm moviefile.zxm",13,13 - db "Plays a video file encoded in",13 - db "ZXM (colour/BW) format.",13,0 - -FHandle db 0 -Banco db 0 -BackupSP dw 0 -BackupConfig db 0 -StartScreen dw 0 -LFrame dw 0 - -BufferNFich equ $ ;resto de la RAM para el nombre del fichero \ No newline at end of file +; playzxm - a command for ESXDOS 0.8.5 that allows to play videos in ZXM +; format in Black&White and Color. +; +; Copyright (C) 2016-2021 Antonio Villena +; Contributors: +; 2021 Ivan Tatarinov +; +; This program is free software: you can redistribute it and/or modify +; it under the terms of the GNU General Public License as published by +; the Free Software Foundation, version 3. +; +; This program is distributed in the hope that it will be useful, +; but WITHOUT ANY WARRANTY; without even the implied warranty of +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +; GNU General Public License for more details. +; +; You should have received a copy of the GNU General Public License +; along with this program. If not, see . +; +; SPDX-FileCopyrightText: Copyright (C) 2016-2021 Antonio Villena +; +; SPDX-FileContributor: 2021 Ivan Tatarinov +; +; SPDX-License-Identifier: GPL-3.0-only + +; Compatible compilers: +; SJAsmPlus, + + define PROGRAM "playzxm" + define VERSION "0.1" + define DESCRIPTION "Plays a video file encoded in", 13, "ZXM (colour/BW) format." + define COPYRIGHT 127, " 2016-2021 Antonio Villena" + define LICENSE "License: GNU GPL 3.0" + + include "zxuno.def" + include "esxdos.def" + include "regs.mac" + include "filezxm.def" + +BORDERCLR: equ 23624 +PAPERCOLOR: equ 23693 +BANKM: equ $7ffd +STACK_TOP: equ $3dea ; Value suggested by Miguel Ângelo to + ; put the stack in the command area +ScreenAddr: equ $4000 +FileBuffer: equ $8000 + + org $2000 ; entry point of ESXDOS program + +;----------------------------------------------------------------------------- +; Subroutine +; In: HL = pointer to the command line arguments string (ASCIIZ) + +Main: + ld a,h + or l + jr nz, Init ; If no filename specified, show usage +; jr ShowUsage ; No need, it follows + +;----------------------------------------------------------------------------- +; Subroutine + +ShowUsage: ld hl, aUsage +; jr Print ; No need, it follows + +;----------------------------------------------------------------------------- +; Subroutine +; In: HL = pointer to an ASCIIZ string + +Print: ld a, (hl) + or a + ret z + rst $10 + inc hl + jr Print + +;----------------------------------------------------------------------------- +; Subroutine +; In: HL = pointer to the command line arguments string (ASCIIZ) + +Init: + ld de, FileName +; call GetFileName ; inline + +;----------------------------------------------------------------------------- +; Subroutine +; In: HL = pointer to the command line arguments (filename) +; DE = pointer to the output ASCIIZ string (filename) +; Out: DE = pointer to terminating 0 character of output string + +.GetFileName: ld a, (hl) + or a + jr z, .End + cp " " + jr z, .End + cp ":" + jr z, .End + cp 13 + jr z, .End + ldi + jr .GetFileName +.End: xor a + ld (de),a +; ret ; skipped + +; continue Init() + inc de ; DE remains pointing to the buffer that is + ; needed in OPEN, I don't know what for + di + ld (BackupSP), sp + ld sp, STACK_TOP + ei + + call PlayFile + push af + call Cls + pop af + ld sp, (BackupSP) + ret + +;----------------------------------------------------------------------------- +; Subroutine + +PlayFile: ld_a 0 + esxdos M_GETSETDRV ; A = current drive + ld b, FA_READ ; B = file open mode + ld hl, FileName ; HL = pointer to file name (ASCIIZ) + esxdos F_OPEN + ret c ; Return on error + ld (FileHandle), a + + call SetupVideoMemory + + call ReadHeader + jr c, .Stop ; Stop on error + +.Loop: ld hl, (StartScreen) + ld bc, (FrameLength) + ld a, (FileHandle) + esxdos F_READ + jr c, .Stop ; Stop on error + ld a, b + or c + jr z, .Stop ; Stop on end of data + + call SwitchScreens + ld bc, $7ffe + in a, (c) ; Detect if SPACE pressed + and %00000001 + jr nz, .Loop + +.Stop: ld a, (FileHandle) + esxdos F_CLOSE + + call RestoreVideoMemory + + or a ; Return to ESXDOS without errors (CY=0) + ret + +;----------------------------------------------------------------------------- +; Subroutine + +ReadHeader: ld a, (FileHandle) + ld bc, file_zxm_header_t + ld hl, FileBuffer + esxdos F_READ + ret c ; Return on error + + ld hl, FileBuffer + file_zxm_header_t.a_magic + ld a, 'Z' + cpi + jr nz, BadFormat + ld a, 'X' + cpi + jr nz, BadFormat + ld a, 'M' + cpi + jr nz, BadFormat + assume_hl FileBuffer + file_zxm_header_t.a_reserved_0 + + chg_hl FileBuffer + file_zxm_header_t.b_sectors_per_frame + ld a, (hl) + add a, a ; BC = b_sectors_per_frame * 512 + ld b, a ; + undef_b ; + ld_c 0 ; + ld (FrameLength), bc + + chg_bc $c000 ; Screen buffer for BW + ld (StartScreen), bc + ld a, (hl) ; A = b_sectors_per_frame + cp 12 ; B/W ? + jr z, ReadOK + + chg_bc $c000 - 256 ; Screen buffer for color + ld (StartScreen), bc + +ReadOK: or a ; Success + ret + +BadFormat: scf ; Error + ret + +;----------------------------------------------------------------------------- +; Subroutine + +SetupVideoMemory: + di + ld_bc BANKM + ld_a %00010111 ; Bank 7, normal display, ROM 3 + ld (Bank), a + out (c), a + + ld hl, $c000 + 6144 + ld de, ScreenAddr + 6144 + chg_bc 768 +.Loop: ld a, 64+56 + ld (hl), a + ld (de), a + inc hl + inc de + dec bc + ld a, b + or c + jr nz, .Loop + assume_a 0 + assume_bc 0 + + chg_bc zxuno_port + chg_a 0 + out (c), a + chg_bc zxuno_data + in a, (c) + undef_a + ld (BackupConfig), a + or %00100000 + out (c), a + + chg_a 0 + out (254), a + + ei + ret + +;----------------------------------------------------------------------------- +; Subroutine + +RestoreVideoMemory: + di + ld_bc zxuno_port + ld_a 0 + out (c), a + chg_bc zxuno_data + ld a, (BackupConfig) + undef_a + out (c), a + chg_bc BANKM + chg_a %00010000 ; Bank 0, normal display, ROM 3 + out (c), a + ei + ret + +;----------------------------------------------------------------------------- +; Subroutine + +SwitchScreens: + halt + ld a, (Bank) + xor %00001010 ; Switch from the normal screen to the + ld (Bank), a ; shadow screen and from 7 to 5 + ld_bc BANKM + out (c), a + ret + +;----------------------------------------------------------------------------- +; Subroutine + +Cls: ld a,(BORDERCLR) + .3 sra a + and %00000111 + out (254), a + ld hl, ScreenAddr ; L = 0 + ld de, ScreenAddr+1 + ld bc, 6144-1 + ld (hl), l + ldir + assume_bc 0 + inc hl + inc de + chg_bc 768-1 + ld a, (PAPERCOLOR) + ld (hl), a + ldir + ret + +; 01234567890123456789012345678901 +aUsage: db PROGRAM, " version ", VERSION, 13 + db DESCRIPTION, 13 + db COPYRIGHT, 13 + db LICENSE, 13 + db 13 + db "Usage:", 13 + db " .", PROGRAM, " moviefile.zxm", 13, 0 + +FileHandle: db 0 +Bank: db 0 +BackupSP: dw 0 +BackupConfig: db 0 +StartScreen: dw 0 +FrameLength: dw 0 +FileName: ; Rest of RAM for filename