See all articles from SINCUS v5 n2
;###########################
;# BEEPING SECTION #
;###########################
;Beeper Routine. Enter with DE=number of cycles-1, HL=a value
; that varies with the time of 1 cycle
; Identical to Spectrum at 03B5
03F3 F3 DI
03F4 7D LD A,L
03F5 CB3D SRL L
03F7 CB3D SRL L
03F9 2F CPL
03FA E603 AND #03
03FC 4F LD C,A
03FD 0600 LD B,#00
03FF DD210F04 LD IX,TLOOP
0403 DD09 ADD IX,BC
0405 3A485C LD A,(BORDCR) ;So we don't change border color
0408 E638 AND #38
040A 0F RRCA
040B 0F RRCA
040C 0F RRCA
040D F608 OR #08 ;Border color in format for port FE
;Top of the timing loop for 1 cycle
040F 00 TLOOP NOP
0410 00 NOP
0411 00 NOP
0412 04 INC B
0413 0C INC C
;Wait loop between half cycles
0414 0D L0414 DEC C
0415 20FD JR NZ,L0414
0417 0E3F LD C,#3F
0419 05 DEC B
041A C21404 JP NZ,#0414
041D EE10 XOR #10 ;Switch the "BEEP" bit
041F D3FE OUT (#FE),A ;Ship it out
0421 44 LD B,H
0422 4F LD C,A
0423 CB67 BIT 4,A
0425 2009 JR NZ,L0430 ;If cycle only half done
;Here if a cycle is complete
0427 7A LD A,D
0428 B3 OR E
0429 2809 JR Z,L0434 ;If we're done with all our cycles
;Here if not. Update counters and loop again
042B 79 LD A,C
042C 4D LD C,L
042D 1B DEC DE
042E DDE9 JP (IX)
;Here if cycle only half done. Loop again
0430 4D L0430 LD C,L
0431 0C INC C
0432 DDE9 JP (IX)
0434 FB L0434 EI
0435 C9 RET
;BEEP Handler
; Identical To Spectrum at 03F8
0436 EF BEEP RST #28 ;Run FP Calculator. Two numbers are on
;the FP stack already; duration & pitch
0437 31 DEFB #31 ;DUP
0438 27 DEFB #27 ;INT
0439 C0 DEFB #C0 ;STORE IN LOC 0
043A 03 DEFB #03 ;-
043B 34 DEFB #34 ;STACK IMMEDIATE
043C EC DEFB #EC ;These 5 bytes form the
043D 6C DEFB #6C ; IMMEDIATE operand, a
043F 98 DEFB #98 ; floating point number
043F 1F DEFB #1F ; of the value
0440 F5 DEFB #F5 ; .0577622606
0441 04 DEFB #04 ;*
0442 A1 DEFB #A1 ;1
0443 0F DEFB #0F ;+
0444 38 DEFB #38 ;END
0445 21925C LD HL,MEMBOT
0448 7E LD A,(HL)
0449 A7 AND A
044A 205E JR NZ,L04AA
044C 23 INC HL
044D 4E LD C,(HL)
044E 23 INC HL
044F 46 LD B,(HL)
0450 78 LD A,B
0451 17 RLA
0452 9F SBC A,A
0453 B9 CP C
0454 2054 JR NZ,L04AA
0456 23 INC HL
0457 BE CP (HL)
0458 2050 JR NZ,L04AA
045A 78 LD A,B
045B C63C ADD A,#3C
045D F26304 JP P,#0463
0460 E2AA04 JP PO,#04AA
0463 06FA LD B,#FA
0465 04 L0465 INC B
0466 D60C SUB #0C
0468 30FB JR NC,L0465
046A C60C ADD A,#0C
046C C5 PUSH BC
046D 21AC04 LD HL,SEMIT ;Address of semitone table
0470 CDC537 CALL #37C5 ;Count A F.P. numbers into the table
0473 CD7337 CALL #3773 ;Put number on the calculator stack
0476 EF RST #28 ;RUN The FP Calculator. FP Stack now
; has duration, pitch * .0577622606,
; and the value just stacked
0477 04 DEFB #04 ;*
0478 38 DEFB #38 ;END
0479 F1 POP AF
047A 86 ADD A,(HL)
047B 77 LD (HL),A
047C EF RST #28 ;RUN The FP Calculator. FP Stack
; already contains duration,frequency
047D C0 DEFB #C0 ;STORE LOC 0 ---the frequency
047E 02 DEFB #02 ;DROP
047F 31 DEFB #31 ;DUP
0480 38 DEFB #38 ;END
0481 CD1E1F CALL #1F1E ;Put value on calculator stack into A
0484 FE0B CP #0B
0486 3022 JR NC,L04AA
0488 EF RST #28 ;RUN The FP Calculator. FP Stack now
; has duration
0489 E0 DEFB #E0 ;GET FROM LOC 0 --- the frequency
048A 04 DEFB #04 ;*
048B E0 DEFB #E0 ;GET FROM LOC 0 --- the frequency
048C 34 DEFB #34 ;STACK IMMEDIATE
048D 80 DEFB #80 ; *Only for Spectrum. Here
048E 43 DEFB #43 ; the *it's a BUG!!! value should
048F 55 DEFB #55 ; value *instead be 441250, to
0490 9F DEFB #9F ; *compensate for TS2068's
0491 80 DEFB #80 ; 437500 *slightly faster clock
0492 01 DEFB #01 ;SWAP
0493 05 DEFB #05 ;/
0494 34 DEFB #34 ;STACK IMMEDIATE
0495 35 DEFB #35 ; the value
0496 71 DEFB #71 ; 30.125
0497 03 DEFB #03 ;-
0498 38 DEFB #38 ;END
0499 CD231F CALL #1F23 ;Put value on calculator stack in BC
049C C5 PUSH BC
049D CD231F CALL #1F23 ;Put value on calculator stack in BC
04A0 E1 POP HL
04A1 50 LD D,B
04A2 59 LD E,C
04A3 7A LD A,D
04A4 B3 OR E
04A5 C8 RET Z
04A6 1B DEC DE
04A7 C3F303 JP #03F3
04AA CF L04AA RST 8
04AB 0A DEFB #0A ;Error B: Integer Out Of Range
;Semitone Table. Contains the frequencies of the 12 semitones
; in the octave starting at middle C. All floating point
; numbers in 5-byte format
; Identical to Spectrum at 046E
04AC 89 SEMIT DEFB #89 ;
04AD 02 DEFB #02 ; 261.63 Hz
04AE D0 DEFB #D0 ;
04AF 12 DEFB #12 ; = C
04B0 86 DEFB #86 ;
04B1 89 DEFB #89 ;
04B2 0A DEFB #0A ; 277.18 Hz
04B3 97 DEFB #97 ;
04B4 60 DEFB #60 ; = C#
04B5 75 DEFB #75 ;
04B6 89 DEFB #89 ;
04B7 12 DEFB #12 ; 293.66 Hz
04B8 D5 DEFB #D5 ;
04B9 17 DEFB #17 ; = D
04BA 1F DEFB #1F ;
04BB 89 DEFB #89 ;
04BC 1B DEFB #1B ; 311.13 Hz
04BD 90 DEFB #90 ;
04BE 41 DEFB #41 ; = D#
04BF 02 DEFB #02 ;
04C0 89 DEFB #89 ;
04C1 24 DEFB #24 ; 329.63 Hz
04C2 D0 DEFB #D0 ;
04C3 53 DEFB #53 ; = E
04C4 CA DEFB #CA ;
04C5 89 DEFB #89 ;
04C6 2E DEFB #2E ; 349.23 Hz
04C7 9D DEFB #9D ;
04C8 36 DEFB #36 ; = F
04C9 B1 DEFB #B1 ;
04CA 89 DEFB #89 ;
04CB 38 DEFB #38 ; 369.99 Hz
04CC FF DEFB #FF ;
04CD 49 DEFB #49 ; = F#
04CE 3E DEFB #3E ;
04CF 89 DEFB #89 ;
04D0 43 DEFB #43 ; 392 Hz
04D1 FF DEFB #FF ;
04D2 6A DEFB #6A ; = G
04D3 73 DEFB #73 ;
04D4 89 DEFB #89 ;
04D5 4F DEFB #4F ; 415.30 Hz
04D6 A7 DEFB #A7 ;
04D7 00 DEFB #00 ; = G#
04D8 54 DEFB #54 ;
04D9 89 DEFB #89 ;
04DA 5C DEFB #5C ; 440 Hz
04DB 00 DEFB #00 ;
04DC 00 DEFB #00 ; = A
04DD 00 DEFB #00 ;
04DE 89 DEFB #89 ;
04DF 69 DEFB #69 ; 466.16 Hz
04E0 14 DEFB #14 ;
04E1 F6 DEFB #F6 ; = A#
04E2 24 DEFB #24 ;
04E3 89 DEFB #89 ;
04E4 76 DEFB #76 ; 493.88 Hz
04E5 F1 DEFB #F1 ;
04E6 10 DEFB #10 ; = B
04E7 05 DEFB #05 ;
;###############################################
;This routine isn't used by the ROM. It's probably a debug
; routine left in by the programmers. It evaluates a BASIC
; string expression & sets the MSB of the last character of the
; string. (This allows it to be used by the Message Printer
; routine.)
; This has no comparable Spectrum Routine
04E8 CD5428 CALL #2854 ;Evaluate next expression per CH_ADD
04EB 3A3B5C LD A,(FLAGS)
04EE 87 ADD A,A
04EF FAED1B JP M,#1BED ;Syntax error, if it's a numeric expr.
04F2 E1 POP HL
04F3 D0 RET NC ;Return if only checking syntax
04F4 E5 PUSH HL
04F5 CDAF2F CALL #2FAF ;POP string specs into A/B/C/D/E regs.
04F8 62 LD H,D
04F9 6B LD L,E ;Start address of the string
04FA 0D DEC C ;Assumes string length <255 chars
04FB F8 RET M ;Return if string length = 0
04FC 09 ADD HL,BC ;HL=Address of last character
04FD CBFE SET 7,(HL) ;Set MSB of last character
04FF C9 RET
;###############################################
;# Section for Printing To Screen and Printer #
;###############################################
;Print the character in the A register into the current channel
; Similar to Spectrum at 09F4
0500 CD1A06 CALL #061A ;Get the current PRINT position
0503 FE20 CP #20 ;ASCII space character. All characters
0505 D2F005 JP NC,#05F0 ; equal or larger are printable, so JP
0508 FE0C CP #0C ;This has been added by Timex
050A 2007 JR NZ,L0513 ; JUMP if it's a DELETE character
050C FDCB0166 BIT 4,(IY+1) ;FLAGS; new bit not used by Spectrum,
0510 CAF005 JP Z,#05F0 ; it's zero if we're in K mode
0513 FE06 L0513 CP #06 ;If its value is less than 6, then
0515 3869 JR C,L0580 ; print a "?"
0517 FE18 CP #18 ;This prints a "?" if it's in the
0519 3065 JR NC,L0580 ; range 18 - 1F
051B 212205 LD HL,#0522 ;Compute the address of the routine
051E 5F LD E,A ; to handle a PRINT control code
051F 1600 LD D,#00 ; (from 06 - 17)
0521 19 ADD HL,DE
0522 5E LD E,(HL)
0523 19 ADD HL,DE
0524 E5 PUSH HL ;a RET will cause a "JP" to the code
0525 C31A06 JP #061A ;Get current PRINT position & "JP"
;Displacement table for control characters. Add the displacement
; to the address of the displacement byte to find the address of
; the handler routine.
; Identical to Spectrum at 0A11
0528 4E DEFB #4E ;PRINT comma displacement
0529 57 DEFB #57 ;EDIT
052A 10 DEFB #10 ;cur left
052B 29 DEFB #29 ;cur right
052C 54 DEFB #54 ;cur down
052D 53 DEFB #53 ;cur up
052E 52 DEFB #52 ;DELETE
052F 37 DEFB #37 ;ENTER
0530 50 DEFB #50 ;unused -- to an error routine
0531 4F DEFB #4F ; same thing here
0532 5F DEFB #5F ;INK control
0533 5E DEFB #5E ;PAPER control
0534 5D DEFB #5D ;FLASH control
0535 5C DEFB #5C ;BRIGHT control
0536 5B DEFB #5B ;INVERSE control
0537 5A DEFB #5A ;OVER control
0538 54 DEFB #54 ;AT control
0539 53 DEFB #53 ;TAB control
;Move the cursor left one character. Corrects a bug in the
; Spectrum code.
; Similar to Spectrum at 0A23
053A 0C INC C
053B 3E22 LD A,#22
053D B9 CP C
053E 2011 JR NZ,L0551
0540 FDCB014E BIT 1,(IY+1) ;FLAGS - Printer/Screen
0544 2009 JR NZ,L054F ;If printer
0546 04 INC B
0547 0E02 LD C,#02
0549 3E19 LD A,#19 ;Timex corrected a bug in Spectrum ROM
054B B8 CP B
054C 2003 JR NZ,L0551
054E 05 DEC B
054F 0E21 L054F LD C,#21
0551 C31409 L0551 JP #0914 ;Get address of first character byte
;Move the cursor right one character
; Identical to Spectrum at 0A3D
0554 3A915C LD A,(P_FLAG) ;Keep old value
0557 F5 PUSH AF
0558 FD365701 LD (IY+87),#01 ;P_FLAG - OVER 1
055C 3E20 LD A,#20 ;ASCII space
055E CDF005 CALL #05F0 ;PRINTs the space
0561 F1 POP AF
0562 32915C LD (P_FLAG),A ;Restore old value
0565 C9 RET
;Handle an ENTER character
; Identical to Spectrum at 0A4F
0566 FDCB014E BIT 1,(IY+1) ;FLAGS - Printer/Screen
056A C2230A JP NZ,#0A23 ;If printer
056D 0E21 LD C,#21
056F CD9007 CALL #0790 ;Will scroll, if needed
0572 05 DEC B
0573 C31409 JP #0914 ;Get address of first character byte
;Handle a PRINT comma by shifting to the next print zone
; Identical to Spectrum at 0A5F
0576 CD1A06 CALL #061A ;Gets current PRINT position (AGAIN!)
0579 79 LD A,C
057A 3D DEC A
057B 3D DEC A
057C E610 AND #10
057E 185A JR L05DA ;To TAB over the right number of spaces
;Handle an unprintable character by substituting a "?"
; Identical to Spectrum at 0A69
0580 3E3F L0580 LD A,"?" ;Change unprintable character
0582 186C JR L05F0 ;Print the question mark
;Handle the control characters that require "follow up" info
; Characters include INK -- OVER
; Identical to Spectrum at 0A6D
0584 119E05 LD DE,#059E ;Code address - after we've gotten
; the "follow up" byte(s)
0587 320F5C LD (TVDATA + 1),A ;Save it, till we need it
058A 180B JR L0597 ;Change current channel output to DE
;Here for AT & TAB
058C 118405 LD DE,#0584 ;Temp current channel output
058F 1803 JR L0594 ;Save "follow up" & change channel
;Here for INK - OVER
0591 119E05 LD DE,#059E ;Temp current channel output
0594 320E5C L0594 LD (TVDATA),A ;Save the "follow up" byte
0597 2A515C L0597 LD HL,(CURCHL) ;Change channel
059A 73 LD (HL),E
059B 23 INC HL
059C 72 LD (HL),D
059D C9 RET
;Only after all "follow up" bytes are in, do we end up here,
; through the current channel output
059E 110005 LD DE,#0500 ;The original current channel output
05A1 CD9705 CALL #0597 ;We can restore it now
05A4 2A0E5C LD HL,(TVDATA) ;Get the "follow up" byte(s)
05A7 57 LD D,A
05A8 7D LD A,L
05A9 FE16 CP #16
05AB DABB23 JP C,#23BB ;If it's INK - OVER
05AE 2029 JR NZ,L05D9 ;If it's TAB
05B0 44 LD B,H ;Here for AT
05B1 4A LD C,D
05B2 3E1F LD A,#1F
05B4 91 SUB C ;Internal column notation is backwards
05B5 380C JR C,L05C3
05B7 C602 ADD A,#02
05B9 4F LD C,A
05BA FDCB014E BIT 1,(IY+1) ;FLAGS - Printer/Screen
05BE 2016 JR NZ,L05D6 ;If printer
05C0 3E16 LD A,#16
05C2 90 SUB B ;Internal line numbers are backwards
05C3 DA291F L05C3 JP C,#1F29 ;If integer out of range
05C6 3C INC A
05C7 47 LD B,A
05C8 04 INC B
05C9 FDCB0246 BIT 0,(IY+2) ;TV_FLAG - Lower screen
05CD C29007 JP NZ,#0790 ;If lower screen-may need scrolling
05D0 FDBE31 CP (IY+49) ;DF_SZ
05D3 DAC107 JP C,#07C1 ;If Out of screen, print error msg
05D6 C31409 L05D6 JP #0914 ;Get address of first character byte
;Here for a TAB character
05D9 7C L05D9 LD A,H
05DA CD1A06 L05DA CALL #061A ;Get current PRINT position
05DD 81 ADD A,C
05DE 3D DEC A
05DF E61F AND #1F ;Number of spaces to PRINT
05E1 C8 RET Z ;If number is 0
05E2 57 LD D,A
05E3 FDCB01C6 SET 0,(IY+1) ;FLAGS - Suppress leading space
05E7 3E20 L05E7 LD A,#20 ;ASCII space
05E9 CD7607 CALL #0776 ;Prints one space character
05EC 15 DEC D
05ED 20F8 JR NZ,L05E7 ;Loop to PRINT proper number of spaces
05EF C9 RET
;Handle printable characters
; Identical to Spectrum at 0AD9
05F0 CD3B06 L05F0 CALL #063B ;Print character & update position
;Save the present line/column position
; Identical to Spectrum at 0ADC
05F3 FDCB014E BIT 1,(IY+1) ;FLAGS - Printer/Screen
05F7 201A JR NZ,L0613 ;If printer
05F9 FDCB0246 BIT 0,(IY+2) ;TV_FLAG - Lower Screen
05FD 2008 JR NZ,L0607 ;If lower screen
05FF ED43885C LD (S_POSN),BC ;Save Upper screen info
0603 22845C LD (DF_CC),HL
0606 C9 RET
0607 ED438A5C L0607 LD (SPOSNL),BC ;Save lower screen info
060B ED43825C LD (ECHO_E),BC
060F 22865C LD (DFCCL),HL
0612 C9 RET
0613 FD7145 L0613 LD (IY+69),C ;P_POSN - Save printer info
0616 22805C LD (PR_CC),HL
0619 C9 RET
;Get present line/column position
; Identical to Spectrum at 0B03
061A FDCB014E BIT 1,(IY+1) ;FLAGS - Printer/Screen
061E 2014 JR NZ,L0634 ;If printer
0620 ED4B885C LD BC,(S_POSN) ;Get upper screen info
0624 2A845C LD HL,(DF_CC)
0627 FDCB0246 BIT 0,(IY+2) ;TV_FLAG - Upper/Lower Screen
062B C8 RET Z ;If it's Upper Screen
062C ED4B8A5C LD BC,(SPOSNL) ;Well then, get lower screen info
0630 2A865C LD HL,(DFCCL)
0633 C9 RET
0634 FD4E45 L0634 LD C,(IY+69) ;P_POSN - Get printer info
0637 2A805C LD HL,(PR_CC)
063A C9 RET
;Here for all characters that put junk on the screen
; -Normal characters, tokens, graphics, & UDG's. Contains
; additions for non-Spectrum characters
; Similar to Spectrum at 0B24
063B FE0C CP #0C ;DELETE
063D 2004 JR NZ,L0643
063F 3E7A LD A,#7A ;z - the special characters follow this
0641 1851 JR L0694
0643 FE7C L0643 CP #7C ;STICK
0645 284D JR Z,L0694
0647 FE7E CP #7E ;FREE
0649 2849 JR Z,L0694
064B FE7B CP #7B ;ON ERR
064D 380A JR C,L0659
064F FE80 CP #80 ;Next 4 instructions added for DELETE
0651 3006 JR NC,L0659
0653 FDCB0166 BIT 4,(IY+1) ;FLAGS - New flag bit
0657 283B JR Z,L0694 ;Jump if "K" mode
;Here's where the Spectrum version starts
; This part is identical to Spectrum at 0B24
0659 FE80 L0659 CP #80 ;Highest value for a "regular" char
065B 383D JR C,L069A ;If it's a regular, single character
065D FE90 CP #90 ;Lowest value for a UDG character
065F 3026 JR NC,L0687 ;For User Defined Graphics & Tokens
0661 47 LD B,A ;Here for Coarse Graphic Characters
0662 CD6D06 CALL #066D ;Build the graphic character
0665 CD1A06 CALL #061A ;Get back the current position
0668 11925C LD DE,MEMBOT ;Graphic was built in calculator memory
066B 1847 JR L06B4 ;Print it out
;Build the coarse graphic characters (80-8F) on the fly
; Identical to Spectrum at 0B38
066D 21925C LD HL,MEMBOT ;Calculator's memory area
0670 CD7306 CALL #0673 ;Causes the following code to run twice
0673 CB18 RR B ;Logical contortions to "build" the
0675 9F SBC A,A ; Coarse Graphics, without having to
0676 E60F AND #0F ; waste the 128 bytes needed to store
0678 4F LD C,A ; their pixel patterns
0679 CB18 RR B
067B 9F SBC A,A
067C E6F0 AND #F0
067E B1 OR C
067F 0E04 LD C,#04
0681 77 L0681 LD (HL),A
0682 23 INC HL
0683 0D DEC C
0684 20FB JR NZ,L0681
0686 C9 RET
;Now find out wether it's a UDG or a Token
; Identical to Spectrum at 0B52
0687 D6A5 L0687 SUB #A5 ;The lowest Token value
0689 3009 JR NC,L0694 ;If it's a token
068B C615 ADD A,#15 ;Shift UDG values so UDG(a)=0, etc
068D C5 PUSH BC
068E ED4B7B5C LD BC,(UDG) ;Base address of UDG area
0692 180B JR L069F ;To where the UDG gets printed
0694 CD4507 L0694 CALL #0745 ;Expand token into ASCII, & print it
0697 C31A06 JP #061A ;Gets current print position
069A C5 L069A PUSH BC ;For regular characters
069B ED4B365C LD BC,(CHARS) ;Base address - regular character table
069F EB L069F EX DE,HL
06A0 213B5C LD HL,FLAGS
06A3 CB86 RES 0,(HL) ;For a leading space
06A5 FE20 CP #20 ;An ASCII space
06A7 2002 JR NZ,L06AB ;If it's not a space
06A9 CBC6 SET 0,(HL) ;NO leading space if it already is one
06AB 2600 L06AB LD H,#00 ;Figure out the address of the 8
06AD 6F LD L,A ; byte pixel pattern for the character
06AE 29 ADD HL,HL
06AF 29 ADD HL,HL
06B0 29 ADD HL,HL
06B1 09 ADD HL,BC
06B2 C1 POP BC
06B3 EB EX DE,HL