Streams and Channels ==================== To be compatible with the Interface 1 and other add-on devices, channel information blocks at CHANS must be in this format. ; CHANNEL INFORMATION BLOCKS ; -------------------------- ; Short channel block (first four blocks in CHANS area) ; IX+00 (2 bytes): Address of PRINT# routine ; IX+02 (2 bytes): Address of INPUT# routine ; IX+04 (1 byte) : Name of channel (ASCII character code) ; Long channel block (any subsequent block in CHANS) ; IX+00 (2 bytes): Address of PRINT# routine or #0008 for Interface 1 channel ; IX+02 (2 bytes): Address of INPUT# routine or #0008 for Interface 1 channel ; IX+04 (1 byte) : Name of channel (ASCII character code). ; IX+05 (2 bytes): Address of Interface 1 PRINT# routine or #1234 identifier ; IX+07 (2 bytes): Address of Interface 1 INPUT# routine or CLOSE# routine ; IX+09 (2 bytes): Length of channel information block (minimum #000B). ; IX+0B onwards : Any additional information. Entry/exit parameters --------------------- Channel blocks can be any length, and so an opened channel can store information there. To be able to access it it is conventional to point IX to the block being used by the stream. This is easily done on entry to the PRINT# and INPUT# routines with: LD IX,(CURCHL) ; IX=>control block for the channel being used PRINT# entry: A=character Main registers and IX can be corrupted IY and alternate registers must be preserved Colour control characters must return NC to prevent errors INPUT# entry: No entry parameters Main registers and IX can be corrupted IY and alternate registers must be preserved If carry set: A=returned character If carry clear: Z =No character, not at EOF NZ=At EOF ; Test if channel is Interface 1 channel ; -------------------------------------- ; IX=>channel block LD A,(IX+1) ; Get output high byte AND A ; Is it zero? JR Z,Interface1 ; Zero, Interface 1 channel JR NZ,NotInterface1 ; Non-zero, not Interface 1 channel ; Close a channel - CLOSE#IX ; -------------------------- ; IX=>channel block LD A,(IX+1) ; Get output high byte AND A ; Is it zero? JR Z,CloseInterface1 ; Zero, Interface 1 channel LD L,(IX+7) ; Get CLOSE address LD H,(IX+8) LD A,H ; Test if it is zero OR L CALL NZ,CallHL ; Call it if non-zero ; Open a channel - OPEN#a,b$ ; -------------------------- ; A=stream, B=channel character ; ADD A,3:CP 19 ; Allow -3 to 15 JR NC,Error_BadStream ; Out of range ADD A,STRMSlo LD L,A LD H,STRMShi ; HL=stream offset PUSH HL ; Save stream offset LD E,(HL):INC HL ; Get stream entry LD D,(HL) LD HL,(CHANS):PUSH HL ; Save CHANS start LD A,D:OR E ; Is it open? JR Z,Open2 ; Closed, open it ADD HL,DE ; Point to channel block LD A,(HL) ; Get output high byte AND A ; Test high byte JP Z,&1725 ; High byte is zero, pass to Interface 1 ; .Open2 POP HL:PUSH HL ; Get CHANS back LD A,B:AND &DF:LD C,A ; Ensure character is upper case LD B,4+1 ; First four are short entries .OpenLp LD D,H:LD E,L ; DE=HL=>start of entry LD A,(HL):CP &80 ; At end of CHANS? JP Z,Report_F ; No more channels, error CALL &18BB:INC HL ; Get channel character CP C:JR Z,OpenFound ; Matching character DJNZ OpenLp ; Step on for first four entries INC B ; Ensure loop returns here CALL &18BB:INC HL ; Get length low byte LD H,(HL):LD L,A ; Get channel length to HL ADD HL,DE:JR OpenLp ; Point to next channel ; .OpenFound POP HL:INC DE ; Get CHANS, point to output high byte LD A,(DE):AND A ; Is this an Interface 1 channel? JR Z,&1725 ; Don't open Interface 1 channel EX DE,HL SBC HL,DE:EX DE,HL ; DE=channel offset POP HL:JP &0A83 ; Set stream offset ; Quick attachment to channel 'P' ; ------------------------------- ENTRY LD HL,(23631) ; CHANS LD DE,15 ADD HL,DE ; HL=>'P' output address LD DE,PRCHAR ; DE=new output routine LD (HL),E INC HL LD (HL),D RET