Universal PT2 player for ZX Spectrum and MSX computers Release 1 (c)2005 S.V.Bulba http://bulba.at.kz Release date: 26 of February 2005 Common remarks -------------- This PT2-player subject is to replace standard buggy PT2-player and to play all subversions of PT2 by one player only. Also Phantom Family PT2.4 modules can be loaded at any address. Project was compiled in assembler for Win32: ZXASM, Z80 cross-platform assembler version 1.4.2 (C) Copyright 1997-2002 by Ilya G. Aniskovets Files ----- PT2Play.asm - source Z80 assembler code. ZX_Asms\PT2Play.h - same text is prepared for Alasm. ZX_Asms\PT2Play.txt - same text is prepared for ZX Asm 3.10. PT2Play - assembled binary code block to load at #C000 address. To compile MSX version, comment ZX Spectrum R_OUT function and uncomment its MSX version. Entry points ------------ Before playing call START (loading) address. Player are not realocable, so you need to assemble with other ORG value, if you want to load code at other than #C000 address, also you can place VARS area to any other address too. After calling START AY is stop any sounding. At START+10 is located SETUP byte, where bit 0 is used to control looping of melody. At any time you can set bit 0 to disable loop. Bit 7 can be checked at any moment, it is set after reaching end of module (finishing playing of last position). In current compilation module must be loaded after variables (by default). Of course, you can change it in source or in assembled code. Also you can specify module address in HL as follows: LD HL,PT2ModuleAddress CALL START+3 By calling START you are proceeding INIT procedure, which prepares corresponding note and volume tables. Also you can call START after stopping playing to mute AY sound. In last case you can call START+8 to simple mute AY sound, to continue playing simply continue calling START+5 as usually. To play, call START+5 address each 1/50 of second (interrupt). During running PLAY subprogram no any interrupts are expected, it is your task to right call PLAY. For example, next program is totaly right: CALL #C000 ;calling init EI ;enable interrupts _LP HALT ;wait for next interrupt CALL #C005 ;call play, player uses 8500 tacts max, ;so no interrupt can be before next HALT XOR A ;test keyboard IN A,(#FE) CPL AND 15 JR Z,_LP ;1 first way to mute sound (you can resume playing from current place): CALL #C008 ;mute AY sound ;2 second way to mute sound (resuming playing is able only from begin): ;2 CALL #C000 ;reset AY to stop sound RET At START+11 address word pointer is placed. This is pointer to module to current position. To calculate position number use code like this: LD HL,(START+11) LD DE,-PT2ModuleAddress-131 ADD HL,DE In HL register will be position number (H will be 0 if module is not modified). Example of playing without loop: LD A,1 LD (START+10),A CALL START EI LOOP HALT CALL START+5 LD A,(START+10) RLA JR NC,LOOP RET Loop three times: CALL START LD A,3 EI LOOP PUSH AF HALT CALL START+5 POP AF LD HL,START+10 SLA (HL) JR NC,LOOP DEC A JR NZ,LOOP CALL START+8 RET Read also all comments in source file. Thanks ------ Very big thanks to all who helped, and especcially to: Spectre for optimization and using. Ivan Roshin for tables generators. Alfonso D.C. aka Dioniso for info about MSX computers. Sergey Bulba 12-26 of February 2005