├── test ├── align.asm ├── addtest.asm └── subtest.asm ├── raytracing ├── align.asm ├── variables.asm ├── trace.asm ├── scene.asm ├── ground.asm ├── hitray.asm ├── spectrum.asm └── sphere.asm ├── align.asm ├── fint8.asm ├── fsquare.asm ├── mul8bit.asm ├── dot.asm ├── decimal.asm ├── LICENSE ├── hpfp.asm ├── dectab.asm ├── cross.asm ├── lpfpcalc.asm ├── divtab.asm ├── sigsqrt.asm ├── octa.asm ├── fixp.asm ├── fdivmul.asm ├── multab.asm ├── fint64.asm ├── octab.asm ├── README.md ├── faddsub-fast.asm ├── faddsub.asm ├── squaretab.asm ├── rotation.asm ├── subtab.asm └── addtab.asm /test/align.asm: -------------------------------------------------------------------------------- 1 | ../align.asm -------------------------------------------------------------------------------- /raytracing/align.asm: -------------------------------------------------------------------------------- 1 | ../align.asm -------------------------------------------------------------------------------- /align.asm: -------------------------------------------------------------------------------- 1 | ; Align to 256-byte page boundary 2 | DEFS (($ + $FF) / $100) * $100 - $ 3 | -------------------------------------------------------------------------------- /fint8.asm: -------------------------------------------------------------------------------- 1 | ; Convert unsigned 8-bit integer into floating-point number 2 | ; In: A = byte to convert 3 | ; Out: DE = floating point representation 4 | ; Pollutes: AF 5 | FBYTE: OR A 6 | JR Z,FBYTE0 ; zero converted to positive epsilon 7 | LD D,$48 8 | FBYTEL: RLA 9 | DEC D 10 | JR NC,FBYTEL 11 | LD E,A 12 | RET 13 | FBYTE0: LD D,A 14 | LD E,A 15 | RET 16 | 17 | -------------------------------------------------------------------------------- /raytracing/variables.asm: -------------------------------------------------------------------------------- 1 | DX: EQU $ 2 | DY: EQU DX+2 3 | DZ: EQU DY+2 4 | DD: EQU DZ+2 5 | DL: EQU DD+2 6 | PX: EQU DL+2 7 | PY: EQU PX+2 8 | PZ: EQU PY+2 9 | PP: EQU PZ+2 10 | PL: EQU PP+2 11 | TL: EQU PL+2 12 | PD: EQU TL+2 13 | CC: EQU PD+2 14 | CL: EQU CC+2 15 | BL: EQU CL+2 16 | SC: EQU BL+2 17 | DIST: EQU SC+2 18 | NEAREST:EQU DIST+2 19 | BOUNCE: EQU NEAREST+2 20 | GC: EQU BOUNCE+2 21 | B1C: EQU GC+6 22 | B2C: EQU B1C+6 23 | 24 | -------------------------------------------------------------------------------- /fsquare.asm: -------------------------------------------------------------------------------- 1 | ; Square of a floating-point number 2 | ; In: HL = number to square 3 | ; Out: HL = HL * HL 4 | ; Pollutes: AF 5 | FSQUARE:LD A,ROOT2F - $4001 6 | CP L 7 | LD A,H 8 | ADC A,A 9 | SUB A,$40 10 | JR C,FZERO2 11 | JP M,FINFTY ; overflow 12 | LD H,SQTAB/$100 13 | LD L,(HL) 14 | LD H,A 15 | RET 16 | 17 | ; Square root of a positive floating-point number 18 | FSQRT: LD A,H 19 | SUB $40 20 | SRA A 21 | LD H,SQRTAB/$100 22 | JR NC,FSQRT1 23 | INC H 24 | FSQRT1: ADD $40 25 | LD L,(HL) 26 | LD H,A 27 | RET 28 | -------------------------------------------------------------------------------- /mul8bit.asm: -------------------------------------------------------------------------------- 1 | ; 8 bit unsigned integer multiplication 2 | ; In: B,C multiplicands 3 | ; Out: HL product 4 | ; Pollutes: AF,AF',BC,DE 5 | MUL8: LD H,MULTAB/$100 6 | LD A,B 7 | ADD A,C 8 | RRA 9 | LD L,A 10 | LD E,(HL) 11 | INC H 12 | LD D,(HL) ; DE=((B+C)/2)^2 13 | PUSH DE 14 | LD A,B 15 | SUB A,C 16 | JR NC,NOSWAP 17 | NEG 18 | LD C,B 19 | AND A 20 | NOSWAP: RRA 21 | LD L,A 22 | EX AF,AF' ; save carry 23 | LD D,(HL) 24 | DEC H 25 | LD E,(HL) ; DE=((B-C)/2)^2 26 | POP HL 27 | AND A 28 | SBC HL,DE 29 | EX AF,AF' ; load carry 30 | RET NC 31 | LD B,0 32 | ADD HL,BC 33 | RET 34 | -------------------------------------------------------------------------------- /raytracing/trace.asm: -------------------------------------------------------------------------------- 1 | ; Raytracer 2 | ; Input: B = y coordinate from top, C = x coordinate from left 3 | ; Output: flag C = light 4 | 5 | ; Start ray 6 | TRACE: PUSH BC 7 | LD A,C 8 | CALL FBYTE 9 | LD HL,$C700 ; -128 10 | CALL FADD 11 | LD (DX),HL 12 | POP BC 13 | LD A,B 14 | CALL FBYTE 15 | LD HL,$C680 ; -96 16 | CALL FADD 17 | LD (DY),HL 18 | LD HL,$482C ; +300 19 | LD (DZ),HL 20 | LD HL,DX 21 | LD B,3 22 | CALL FLEN 23 | LD (DD),HL 24 | CALL FSQRT 25 | LD (DL),HL 26 | LD A,(POS) 27 | LD HL,GROUNDC 28 | LD DE,GC 29 | POSL: LD BC,6 30 | LDIR 31 | DEC A 32 | JR NZ,POSL 33 | LD (BOUNCE),A 34 | TRACEL: LD HL,BOUNCE 35 | DEC (HL) 36 | RET Z 37 | -------------------------------------------------------------------------------- /dot.asm: -------------------------------------------------------------------------------- 1 | ; Square norm of a vector 2 | ; Input: B = dimensions, HL = pointer to vector 3 | ; Output: HL = square norm 4 | ; Pollutes: AF, DE 5 | FLEN: LD E,(HL) 6 | INC HL 7 | LD D,(HL) 8 | EX DE,HL 9 | CALL FSQUARE 10 | DJNZ FLEN1 11 | RET 12 | FLEN1: PUSH HL 13 | EX DE,HL 14 | INC HL 15 | CALL FLEN 16 | EX DE,HL 17 | POP HL 18 | JP FADDP 19 | 20 | ; Scalar multiplication of two vectors 21 | ; Input: A = dimensions, HL,DE = pointers to vectors 22 | ; Output: BC = dot product, 23 | ; Pollutes: HL,DE,AF,AF' 24 | FDOT: PUSH AF 25 | LD C,(HL) 26 | INC HL 27 | LD B,(HL) 28 | PUSH HL 29 | EX DE,HL 30 | LD E,(HL) 31 | INC HL 32 | LD D,(HL) 33 | PUSH HL 34 | CALL FMUL 35 | LD C,L 36 | LD B,H 37 | POP DE 38 | POP HL 39 | POP AF 40 | DEC A 41 | RET Z 42 | INC HL 43 | INC DE 44 | PUSH BC 45 | CALL FDOT 46 | LD L,C 47 | LD H,B 48 | POP DE 49 | CALL FADD 50 | LD C,L 51 | LD B,H 52 | RET 53 | -------------------------------------------------------------------------------- /raytracing/scene.asm: -------------------------------------------------------------------------------- 1 | ; Look at object hit 2 | ; Input: HL distance of hitting, IX = object hit 3 | ; Pollutes: anything 4 | SCENEL: LD E,(IX+4) 5 | LD D,(IX+5) 6 | PUSH DE 7 | RET 8 | 9 | ; Intersection with scenery 10 | ; Input: IX = first object in scenery 11 | ; Output: CF = true if any object is hit by ray, HL = distance of hitting, IX = object hit 12 | ; Pollutes: anything 13 | SCENEI: LD HL,0 14 | LD (NEAREST),HL 15 | LD IX,SCENE 16 | SCLOOP: LD L,(IX+2) 17 | LD H,(IX+3) 18 | CALL JPHL 19 | JR NC,NOHITS 20 | LD DE,(NEAREST) 21 | LD A,E 22 | OR D 23 | JR Z,HITS 24 | LD DE,(DIST) 25 | OR A 26 | SBC HL,DE ; This is okay, as scaling factor is non-negative 27 | JR NC,NOHITS 28 | ADD HL,DE 29 | HITS: LD (DIST),HL 30 | LD (NEAREST),IX 31 | NOHITS: LD E,(IX+0) 32 | LD D,(IX+1) 33 | LD A,D 34 | OR E 35 | JR Z,HITSC 36 | PUSH DE 37 | POP IX 38 | JR SCLOOP 39 | JPHL: JP (HL) 40 | HITSC: LD HL,(NEAREST) 41 | LD A,H 42 | OR L 43 | RET Z 44 | PUSH HL 45 | POP IX 46 | LD HL,(DIST) 47 | SCF 48 | RET 49 | 50 | -------------------------------------------------------------------------------- /decimal.asm: -------------------------------------------------------------------------------- 1 | ; Note: The signs of mantissa and exponent are the 2 | ; same in binary and decimal representation, so 3 | ; these routines do not provide the latter. Display 4 | ; routines must insert these signs where appropriate. 5 | 6 | ; Decimal conversion for display (mantissa) 7 | ; In: 8 | ; DE = floating point number 9 | ; Out: 10 | ; C = decimal digit (possibly two) before point in binary 11 | ; A = two decimal digits after the point in BCD 12 | ; Pollutes: F, AF', BC, DE, HL 13 | F2BCD: LD H,DECTAB/$100 14 | LD L,D 15 | SLA L 16 | LD C,(HL) 17 | INC L 18 | LD B,(HL) 19 | CALL FMULP 20 | LD A,H 21 | SUB $38 22 | LD B,A 23 | LD A,1 24 | LD C,0 25 | F2BCDL: SLA L 26 | ADC A,A 27 | DAA 28 | JR NC,F2BCD0 29 | INC C 30 | F2BCD0: DJNZ F2BCDL 31 | RET 32 | 33 | ; Decimal conversion for display (exponent) 34 | ; In: A = binary exponent 35 | ; Out: H = decimal exponent 36 | ; Pollutes: AF, AF', BC, DE, L 37 | F2E10: AND $7F ; mask sign 38 | SUB A,$40 39 | JR NC,F2E10P ; positive exponent 40 | NEG 41 | F2E10P: LD B,A 42 | LD C,77 ; $100 * log10(2) 43 | CALL MUL8 44 | RET 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Daniel A. Nagy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /hpfp.asm: -------------------------------------------------------------------------------- 1 | ; Interfacing with the high-precision calculator in the ZX Spectrum ROM 2 | FP_CALC: EQU $28 3 | RSTK: EQU $3D ; No such thing needed on ZX81 4 | END_CALC: EQU $38 ; $34 for ZX81 5 | STK_STORE: EQU $2AB6 ; $12C3 for ZX81 6 | 7 | ; Store floating point number on the calculator stack 8 | ; Input: DE = number to stack 9 | ; Pollutes: AF, BC, DE, HL 10 | STKFP: LD A,D 11 | ADD A,A 12 | RR E 13 | LD BC,0 14 | LD D,B 15 | RR D 16 | RRCA 17 | ADD $41 18 | JP STK_STORE 19 | 20 | ; Retrieve floating point number from the calculator stack 21 | ; Output: DE = retrieved floating point number 22 | ; Pollutes: AF, BC, BC', DE', HL, HL' 23 | FPTODE: RST FP_CALC 24 | DEFB RSTK ; Remove for ZX81 25 | DEFB END_CALC 26 | LD A,(HL) 27 | INC HL 28 | LD E,(HL) 29 | SUB $41 30 | JR C,UNDERF 31 | ADD A,A 32 | JR C,OVERF 33 | INC HL 34 | LD D,(HL) 35 | SLA D 36 | RL E 37 | RRA 38 | SLA D ; only need CF 39 | LD D,A 40 | RET NC 41 | INC E 42 | RET NZ 43 | INC D 44 | XOR D 45 | ADD A,A 46 | RET NC 47 | DEC D 48 | JR OVERFE 49 | UNDERF: LD A,$80 50 | AND E 51 | LD D,A 52 | LD E,0 53 | RET 54 | OVERF: LD A,$7F 55 | OR E 56 | LD D,A 57 | OVERFE: LD E,$FF 58 | RET 59 | -------------------------------------------------------------------------------- /dectab.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "align.asm" 2 | DECTAB: DEFW $810f, $7db2, $7db2, $7db2 3 | DEFW $7db2, $7a5b, $7a5b, $7a5b 4 | DEFW $7716, $7716, $7716, $73bc 5 | DEFW $73bc, $73bc, $73bc, $7063 6 | DEFW $7063, $7063, $6d1c, $6d1c 7 | DEFW $6d1c, $69c7, $69c7, $69c7 8 | DEFW $69c7, $666c, $666c, $666c 9 | DEFW $6323, $6323, $6323, $5fd2 10 | DEFW $5fd2, $5fd2, $5fd2, $5c75 11 | DEFW $5c75, $5c75, $592a, $592a 12 | DEFW $592a, $55dd, $55dd, $55dd 13 | DEFW $55dd, $527d, $527d, $527d 14 | DEFW $4f31, $4f31, $4f31, $4be8 15 | DEFW $4be8, $4be8, $4be8, $4887 16 | DEFW $4887, $4887, $4539, $4539 17 | DEFW $4539, $41f4, $41f4, $41f4 18 | DEFW $3e90, $3e90, $3e90, $3e90 19 | DEFW $3b40, $3b40, $3b40, $3800 20 | DEFW $3800, $3800, $349a, $349a 21 | DEFW $349a, $349a, $3148, $3148 22 | DEFW $3148, $2e06, $2e06, $2e06 23 | DEFW $2aa3, $2aa3, $2aa3, $2aa3 24 | DEFW $2750, $2750, $2750, $240c 25 | DEFW $240c, $240c, $20ad, $20ad 26 | DEFW $20ad, $20ad, $1d58, $1d58 27 | DEFW $1d58, $1a13, $1a13, $1a13 28 | DEFW $16b8, $16b8, $16b8, $16b8 29 | DEFW $1360, $1360, $1360, $1019 30 | DEFW $1019, $1019, $0cc2, $0cc2 31 | DEFW $0cc2, $0cc2, $0968, $0968 32 | DEFW $0968, $0620, $0620, $0620 33 | DEFW $02cd, $02cd, $02cd, $02cd 34 | -------------------------------------------------------------------------------- /cross.asm: -------------------------------------------------------------------------------- 1 | ; Cross product of two 3D vectors 2 | ; In: IX,IY pointers to two multiplicands, HL pointer to result 3 | ; Out: HL=HL+5, BC=Cx, DE=Cz 4 | ; Pollutes: AF, AF' 5 | FCROSS: PUSH HL ; target address 6 | LD C,(IX+4) 7 | LD B,(IX+5) 8 | LD E,(IY+2) 9 | LD D,(IY+3) 10 | CALL FMUL ; Az * By 11 | PUSH HL 12 | LD C,(IX+2) 13 | LD B,(IX+3) 14 | LD E,(IY+4) 15 | LD D,(IY+5) 16 | CALL FMUL ; Ay * Bz 17 | POP DE 18 | CALL FSUB ; Ay * Bz - Az * By 19 | PUSH HL ; Cx 20 | 21 | LD C,(IX+0) 22 | LD B,(IX+1) 23 | LD E,(IY+4) 24 | LD D,(IY+5) 25 | CALL FMUL ; Ax * Bz 26 | PUSH HL 27 | LD C,(IX+4) 28 | LD B,(IX+5) 29 | LD E,(IY+0) 30 | LD D,(IY+1) 31 | CALL FMUL ; Az * Bx 32 | POP DE 33 | CALL FSUB ; Az * Bx - Ax * Bz 34 | PUSH HL ; Cy 35 | 36 | LD C,(IX+2) 37 | LD B,(IX+3) 38 | LD E,(IY+0) 39 | LD D,(IY+1) 40 | CALL FMUL ; Ay * Bx 41 | PUSH HL 42 | LD C,(IX+0) 43 | LD B,(IX+1) 44 | LD E,(IY+2) 45 | LD D,(IY+3) 46 | CALL FMUL ; Ax * By 47 | POP DE 48 | CALL FSUB ; Ax * By - Ay * Bx 49 | 50 | POP DE ; Cy 51 | POP BC ; Cx 52 | EX (SP),HL ; Cz 53 | LD (HL),C 54 | INC HL 55 | LD (HL),B 56 | INC HL 57 | LD (HL),E 58 | INC HL 59 | LD (HL),D 60 | POP DE 61 | LD (HL),E 62 | INC HL 63 | LD (HL),D 64 | RET 65 | -------------------------------------------------------------------------------- /lpfpcalc.asm: -------------------------------------------------------------------------------- 1 | ; Low-Precision Floating-Point Arithmetics 2 | ; (C) 2018 ePoint Systems, Daniel A. Nagy 3 | ; 4 | ; Numbers are represented in 16 bits as follows: 5 | ; bits 0..7 mantissa bits -8..-1, mantissa bit 0 is always 1, not represented 6 | ; bits 8..14 exponent bits 0..6, representing shifts in the 2^-64..2^+63 range 7 | ; bit 15 sign 0 for positive, 1 for negative 8 | ; 9 | ; Notes: 10 | ; For positive numbers, the ordering is the same as that of integer interpretation. 11 | ; No special values such as 0, Inf, NaN. 12 | 13 | ; floating point constants 14 | MINF: EQU $0000 ; Positive epsilon, 2^-64 5.421e-20 15 | MAXF: EQU $7FFF ; Maximal floating point number 2^64-2^55 1.841e+19 16 | ONEF: EQU $4000 ; One 1.000e+00 17 | ROOT2F: EQU $406A ; Square root of 2 1.414e+00 18 | F7F: EQU $46FC ; $7F i.e. 127 1.270e+02 19 | 20 | ; Subroutines 21 | INCLUDE "fdivmul.asm" 22 | INCLUDE "faddsub-fast.asm" 23 | INCLUDE "fsquare.asm" 24 | INCLUDE "mul8bit.asm" 25 | INCLUDE "fint64.asm" 26 | INCLUDE "decimal.asm" 27 | INCLUDE "rotation.asm" 28 | INCLUDE "octa.asm" 29 | INCLUDE "dot.asm" 30 | ; Lookup tables 31 | INCLUDE "addtab.asm" 32 | INCLUDE "subtab.asm" 33 | INCLUDE "multab.asm" 34 | INCLUDE "divtab.asm" 35 | INCLUDE "squaretab.asm" 36 | INCLUDE "dectab.asm" 37 | INCLUDE "octab.asm" 38 | -------------------------------------------------------------------------------- /raytracing/ground.asm: -------------------------------------------------------------------------------- 1 | ; Look at the ground 2 | ; Input: HL = scale factor of D to surface 3 | ; Output: CF color 4 | ; Pollutes: anything except IX 5 | GROUNDL:EX DE,HL 6 | CALL SCALED 7 | CALL HITRAY 8 | LD IX,BALL1 9 | SHADOWS:LD L,(IX+6) 10 | LD H,(IX+7) 11 | LD E,(HL) 12 | INC HL 13 | LD D,(HL) 14 | INC HL 15 | INC HL 16 | INC HL 17 | EX DE,HL 18 | CALL FSQUARE 19 | PUSH HL 20 | EX DE,HL 21 | LD E,(HL) 22 | INC HL 23 | LD D,(HL) 24 | EX DE,HL 25 | CALL FSQUARE 26 | POP DE 27 | CALL FADDP 28 | LD E,(IX+10) 29 | LD D,(IX+11) 30 | OR A 31 | SBC HL,DE 32 | CCF 33 | RET NC 34 | LD E,(IX+0) 35 | LD D,(IX+1) 36 | PUSH DE 37 | POP IX 38 | LD A,E 39 | OR D 40 | JR NZ,SHADOWS 41 | GROUNDX:LD HL,(GC) 42 | CALL GRL0 43 | PUSH AF 44 | LD HL,(GC+4) 45 | CALL GRL0 46 | POP BC 47 | XOR B 48 | RRCA 49 | RET 50 | 51 | GRL0: LD A,H 52 | CP $3F 53 | JR C,GRL1 54 | ADD A 55 | JR NC,GRL1 56 | CP $7D 57 | CCF 58 | GRL1: SBC A,A 59 | RET 60 | 61 | ; Ground intersection 62 | ; Output: CF = true if ray intersects ground, HL = scale factor of D vector 63 | ; Pollutes: anything except IX 64 | GROUNDI:LD L,(IX+6) 65 | LD H,(IX+7) 66 | INC HL 67 | INC HL 68 | LD C,(HL) 69 | INC HL 70 | LD B,(HL) 71 | LD HL,(DY) 72 | LD A,B 73 | OR H 74 | ADD A,A 75 | CCF 76 | RET NC 77 | CALL FDIV 78 | SCF 79 | RET 80 | -------------------------------------------------------------------------------- /divtab.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "align.asm" 2 | ; 2/x (range 1..1/2) mantissas. 3 | DIVTAB: DEFB $00,$FE,$FC,$FA,$F8,$F6,$F4,$F2 4 | DEFB $F0,$EF,$ED,$EB,$E9,$E7,$E5,$E4 5 | DEFB $E2,$E0,$DE,$DD,$DB,$D9,$D7,$D6 6 | DEFB $D4,$D2,$D1,$CF,$CE,$CC,$CA,$C9 7 | DEFB $C7,$C6,$C4,$C2,$C1,$BF,$BE,$BC 8 | DEFB $BB,$B9,$B8,$B6,$B5,$B3,$B2,$B1 9 | DEFB $AF,$AE,$AC,$AB,$AA,$A8,$A7,$A5 10 | DEFB $A4,$A3,$A1,$A0,$9F,$9D,$9C,$9B 11 | DEFB $9A,$98,$97,$96,$95,$93,$92,$91 12 | DEFB $90,$8E,$8D,$8C,$8B,$8A,$88,$87 13 | DEFB $86,$85,$84,$83,$82,$80,$7F,$7E 14 | DEFB $7D,$7C,$7B,$7A,$79,$78,$76,$75 15 | DEFB $74,$73,$72,$71,$70,$6F,$6E,$6D 16 | DEFB $6C,$6B,$6A,$69,$68,$67,$66,$65 17 | DEFB $64,$63,$62,$61,$60,$5F,$5E,$5E 18 | DEFB $5D,$5C,$5B,$5A,$59,$58,$57,$56 19 | DEFB $55,$54,$54,$53,$52,$51,$50,$4F 20 | DEFB $4E,$4E,$4D,$4C,$4B,$4A,$49,$49 21 | DEFB $48,$47,$46,$45,$44,$44,$43,$42 22 | DEFB $41,$40,$40,$3F,$3E,$3D,$3D,$3C 23 | DEFB $3B,$3A,$3A,$39,$38,$37,$37,$36 24 | DEFB $35,$34,$34,$33,$32,$32,$31,$30 25 | DEFB $2F,$2F,$2E,$2D,$2D,$2C,$2B,$2B 26 | DEFB $2A,$29,$29,$28,$27,$27,$26,$25 27 | DEFB $25,$24,$23,$23,$22,$21,$21,$20 28 | DEFB $1F,$1F,$1E,$1E,$1D,$1C,$1C,$1B 29 | DEFB $1A,$1A,$19,$19,$18,$17,$17,$16 30 | DEFB $16,$15,$15,$14,$13,$13,$12,$12 31 | DEFB $11,$10,$10,$0F,$0F,$0E,$0E,$0D 32 | DEFB $0D,$0C,$0B,$0B,$0A,$0A,$09,$09 33 | DEFB $08,$08,$07,$07,$06,$06,$05,$05 34 | DEFB $04,$04,$03,$03,$02,$02,$01,$01 35 | -------------------------------------------------------------------------------- /raytracing/hitray.asm: -------------------------------------------------------------------------------- 1 | ; Move the origin by D 2 | ; Pollutes: AF, AF', BC, DE, HL 3 | HITRAY: LD A,(POS) 4 | LD B,A 5 | LD HL,GC 6 | HRL: PUSH BC 7 | LD E,(HL) 8 | INC HL 9 | LD D,(HL) 10 | PUSH HL 11 | LD HL,(DX) 12 | EX DE,HL 13 | CALL FSUB 14 | EX DE,HL 15 | POP HL 16 | LD (HL),D 17 | DEC HL 18 | LD (HL),E 19 | INC HL 20 | INC HL 21 | LD E,(HL) 22 | INC HL 23 | LD D,(HL) 24 | PUSH HL 25 | LD HL,(DY) 26 | EX DE,HL 27 | CALL FSUB 28 | EX DE,HL 29 | POP HL 30 | LD (HL),D 31 | DEC HL 32 | LD (HL),E 33 | INC HL 34 | INC HL 35 | LD E,(HL) 36 | INC HL 37 | LD D,(HL) 38 | PUSH HL 39 | LD HL,(DZ) 40 | EX DE,HL 41 | CALL FSUB 42 | EX DE,HL 43 | POP HL 44 | LD (HL),D 45 | DEC HL 46 | LD (HL),E 47 | INC HL 48 | INC HL 49 | POP BC 50 | DJNZ HRL 51 | LD HL,(GC) 52 | CALL FRAC 53 | LD (GC),HL 54 | LD HL,(GC+4) 55 | CALL FRAC 56 | LD (GC+4),HL 57 | RET 58 | 59 | ; Scale D by DE 60 | ; Input: DE=scale factor 61 | ; Output: HL=DZ 62 | ; Pollutes: AF, AF', BC 63 | SCALED: PUSH DE 64 | LD BC,(DX) 65 | CALL FMUL 66 | LD (DX),HL 67 | POP DE 68 | PUSH DE 69 | LD BC,(DY) 70 | CALL FMUL 71 | LD (DY),HL 72 | POP DE 73 | PUSH DE 74 | LD BC,(DZ) 75 | CALL FMUL 76 | LD (DZ),HL 77 | POP DE 78 | RET 79 | 80 | ; DL by DE and DD by DE*DE 81 | ; Input: DE=scale factor 82 | ; Output: HL=DD 83 | ; Pollutes: AF, AF', BC, DE 84 | SCALEDL:LD BC,(DL) 85 | CALL FMUL 86 | LD (DL),HL 87 | CALL FSQUARE 88 | LD (DD),HL 89 | RET 90 | -------------------------------------------------------------------------------- /sigsqrt.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "align.asm" 2 | ; Signed half-squares table for numbers in the -1.0..+1.0 (-127..+127) range 3 | SIGSQRT:DEFB $00,$00,$00,$00,$00,$00,$00,$00 4 | DEFB $00,$00,$00,$00,$00,$00,$01,$01 5 | DEFB $01,$01,$01,$01,$01,$02,$02,$02 6 | DEFB $02,$02,$02,$03,$03,$03,$03,$04 7 | DEFB $04,$04,$04,$05,$05,$05,$05,$06 8 | DEFB $06,$06,$07,$07,$07,$08,$08,$08 9 | DEFB $09,$09,$0a,$0a,$0a,$0b,$0b,$0c 10 | DEFB $0c,$0d,$0d,$0d,$0e,$0e,$0f,$0f 11 | DEFB $10,$10,$11,$11,$12,$12,$13,$14 12 | DEFB $14,$15,$15,$16,$16,$17,$18,$18 13 | DEFB $19,$1a,$1a,$1b,$1b,$1c,$1d,$1d 14 | DEFB $1e,$1f,$20,$20,$21,$22,$22,$23 15 | DEFB $24,$25,$25,$26,$27,$28,$29,$29 16 | DEFB $2a,$2b,$2c,$2d,$2e,$2e,$2f,$30 17 | DEFB $31,$32,$33,$34,$35,$35,$36,$37 18 | DEFB $38,$39,$3a,$3b,$3c,$3d,$3e,$3f 19 | 20 | DEFB $40,$3f,$3e,$3d,$3c,$3b,$3a,$39 21 | DEFB $38,$37,$36,$35,$35,$34,$33,$32 22 | DEFB $31,$30,$2f,$2e,$2e,$2d,$2c,$2b 23 | DEFB $2a,$29,$29,$28,$27,$26,$25,$25 24 | DEFB $24,$23,$22,$22,$21,$20,$20,$1f 25 | DEFB $1e,$1d,$1d,$1c,$1b,$1b,$1a,$1a 26 | DEFB $19,$18,$18,$17,$16,$16,$15,$15 27 | DEFB $14,$14,$13,$12,$12,$11,$11,$10 28 | DEFB $10,$0f,$0f,$0e,$0e,$0d,$0d,$0d 29 | DEFB $0c,$0c,$0b,$0b,$0a,$0a,$0a,$09 30 | DEFB $09,$08,$08,$08,$07,$07,$07,$06 31 | DEFB $06,$06,$05,$05,$05,$05,$04,$04 32 | DEFB $04,$04,$03,$03,$03,$03,$02,$02 33 | DEFB $02,$02,$02,$02,$01,$01,$01,$01 34 | DEFB $01,$01,$01,$00,$00,$00,$00,$00 35 | DEFB $00,$00,$00,$00,$00,$00,$00,$00 36 | -------------------------------------------------------------------------------- /octa.asm: -------------------------------------------------------------------------------- 1 | ; Convert 3D FP vector to octahedral map index 2 | ; Input: (BC,DE,HL) = 3D vector 3 | ; Output: A = octahedral map index 4 | ; Pollutes: F, AF',BC, BC', DE, DE', HL, HL' 5 | V3D2O: PUSH HL 6 | PUSH DE 7 | PUSH BC 8 | RES 7,H 9 | RES 7,D 10 | CALL FADDP 11 | LD E,C 12 | LD D,B 13 | RES 7,D 14 | CALL FADDP 15 | POP BC 16 | PUSH HL 17 | CALL FDIV 18 | EXX 19 | POP HL 20 | POP BC 21 | CALL FDIV 22 | ; Convert HL to lower nibble in A, leave HL intact 23 | LD A,H 24 | AND $7F 25 | SUB $3D 26 | JR NC,V3D2O0 ; Too small, round to zero 27 | XOR A 28 | JR V3D2O2 29 | V3D2O0: CP 3 30 | JR C,V3D2O1 ; 1 or more 31 | LD A,7 32 | JR V3D2O2 33 | V3D2O1: INC A 34 | LD B,A 35 | LD A,L 36 | AND $F0 37 | INC A 38 | V3D2OL1:RLCA ;RRA 39 | DJNZ V3D2OL1 40 | AND $F ;$F0 41 | RRA ; Because there is no 0-step DJNZ 42 | V3D2O2: PUSH AF 43 | EXX 44 | ; Convert HL to upper nibble in A leave HL intact 45 | LD A,H 46 | AND $7F 47 | SUB $3D 48 | JR NC,V3D2O3 ; Too small, round to zero 49 | XOR A 50 | JR V3D2O5 51 | V3D2O3: SUB 3 52 | JR C,V3D2O4 ; 1 or more 53 | LD A,$70 54 | JR V3D2O5 55 | V3D2O4: NEG 56 | INC A 57 | LD B,A 58 | LD A,L 59 | AND $F0 60 | SCF 61 | V3D2OL2:RRA 62 | DJNZ V3D2OL2 63 | AND $F0 64 | V3D2O5: POP BC 65 | OR B 66 | XOR $88 67 | POP BC 68 | BIT 7,B 69 | JR Z,V3D2OU 70 | XOR $77 71 | RLCA 72 | RLCA 73 | RLCA 74 | RLCA 75 | V3D2OU: BIT 7,H 76 | JR Z,V3D2ON 77 | XOR $F0 78 | V3D2ON: EXX 79 | BIT 7,H 80 | RET Z 81 | XOR $F 82 | RET 83 | -------------------------------------------------------------------------------- /fixp.asm: -------------------------------------------------------------------------------- 1 | ; Convert floating point between -1.0 and +1.0 to signed integer between -127 and 127 2 | ; WARNING!!! Bounds not checked, does wreak havoc for out of bounds input. 3 | ; Input: DE = floating point number in the -1.0 .. +1.0 range 4 | ; Output: A = signed integer 5 | ; Pollutes: F,AF',BC,DE,HL 6 | FFIX: LD BC,F7F 7 | CALL FMUL 8 | LD A,H 9 | ADD A,A 10 | EX AF,AF' ; Save sign to F' 11 | RES 7,H 12 | LD A,$47 13 | SUB H 14 | CP 8 15 | JR NC,FFIX0 16 | LD B,A 17 | LD A,L 18 | SCF 19 | FFIXL: RRA 20 | OR A 21 | DJNZ FFIXL 22 | RRA 23 | ADC A,B ; Proper rounding 24 | EX AF,AF' 25 | JR NC,FFIXP 26 | EX AF,AF' 27 | NEG 28 | RET 29 | FFIZP: EX AF,AF' 30 | RET 31 | FFIX0: XOR A 32 | RET 33 | 34 | ; Convert floating point array as above 35 | ; In: HL = floating point array, DE = fixed point array, B = array size 36 | ; Pollutes: AF,AF',B,BC',DE,DE',HL,HL' 37 | FFIXA: LD A,(HL) 38 | INC HL 39 | EX AF,AF' 40 | LD A,(HL) 41 | INC HL 42 | EXX 43 | LD D,A 44 | EX AF,AF' 45 | LD E,A 46 | CALL FFIX 47 | EXX 48 | LD (DE),A 49 | INC DE 50 | DJNZ FFIXA 51 | RET 52 | 53 | ; Multiply two signed integers to be interpreted as above 54 | ; In: D,E = multiplicands 55 | ; Out: A = product 56 | ; Pollutes: F, HL 57 | MULFIX: LD H,SIGSQRT/256 58 | LD A,E 59 | ADD A,D 60 | JP PO,MULFIX1 61 | LD L,A 62 | LD A,(HL) 63 | LD L,E 64 | SUB A,(HL) 65 | LD L,D 66 | SUB A,(HL) 67 | RET 68 | MULFIX1:LD A,E 69 | SUB A,D 70 | LD L,A 71 | LD A,(HL) 72 | NEG 73 | LD L,E 74 | ADD A,(HL) 75 | LD L,D 76 | ADD A,(HL) 77 | RET 78 | 79 | 80 | -------------------------------------------------------------------------------- /test/addtest.asm: -------------------------------------------------------------------------------- 1 | ; Iterate through all values of HL >= DE and check FADDP 2 | ORG $C000 3 | DI 4 | EXX 5 | PUSH HL 6 | LD HL,0 7 | LD E,L 8 | LD D,H 9 | LOOP: PUSH HL 10 | PUSH DE 11 | CALL FADDP 12 | LD C,L 13 | LD B,H 14 | POP DE 15 | POP HL 16 | PUSH HL 17 | PUSH BC 18 | PUSH DE 19 | EX DE,HL 20 | CALL STKFP 21 | POP DE 22 | PUSH DE 23 | CALL STKFP 24 | POP DE 25 | POP BC 26 | PUSH DE 27 | PUSH BC 28 | RST $28 29 | DEFB $0F,$38 30 | CALL FPTODE 31 | EX DE,HL 32 | POP BC 33 | LD A,H 34 | CP B 35 | JR NZ,MISMATCH 36 | LD A,L 37 | CP C 38 | JR NZ,MISMATCH 39 | RST $28 40 | DEFB $02,$38 41 | POP DE 42 | POP HL 43 | INC L 44 | JR NZ,LOOP 45 | INC H 46 | BIT 7,H 47 | JR NZ,LOOP 48 | LD L,E 49 | LD H,D 50 | INC HL 51 | INC E 52 | JR NZ,LOOP 53 | INC D 54 | JR NZ,LOOP 55 | POP HL 56 | EXX 57 | LD BC,0 58 | EI 59 | RET 60 | MISMATCH: 61 | POP DE 62 | POP HL 63 | LD C,L 64 | LD B,H 65 | EXX 66 | POP HL 67 | EXX 68 | EI 69 | RET 70 | 71 | INCLUDE "../hpfp.asm" 72 | 73 | ; floating point constants 74 | MINF: EQU $0000 ; Positive epsilon, 2^-64 5.421e-20 75 | MAXF: EQU $7FFF ; Maximal floating point number 2^64-2^55 1.841e+19 76 | ONEF: EQU $4000 ; One 1.000e+00 77 | ROOT2F: EQU $406A ; Square root of 2 1.414e+00 78 | F7F: EQU $46FC ; $7F i.e. 127 1.270e+02 79 | 80 | ; Subroutines 81 | INCLUDE "../fdivmul.asm" 82 | INCLUDE "../faddsub.asm" 83 | INCLUDE "../mul8bit.asm" 84 | ; Lookup tables 85 | INCLUDE "../addtab.asm" 86 | INCLUDE "../subtab.asm" 87 | INCLUDE "../multab.asm" 88 | INCLUDE "../divtab.asm" 89 | -------------------------------------------------------------------------------- /test/subtest.asm: -------------------------------------------------------------------------------- 1 | ; Iterate through all values of HL >= DE and check FSUBP 2 | ORG $C000 3 | DI 4 | EXX 5 | PUSH HL 6 | LD HL,0 7 | LD E,L 8 | LD D,H 9 | LOOP: PUSH HL 10 | PUSH DE 11 | CALL FSUBP 12 | LD C,L 13 | LD B,H 14 | POP DE 15 | POP HL 16 | PUSH HL 17 | PUSH BC 18 | PUSH DE 19 | EX DE,HL 20 | CALL STKFP 21 | POP DE 22 | PUSH DE 23 | CALL STKFP 24 | POP DE 25 | POP BC 26 | PUSH DE 27 | PUSH BC 28 | RST $28 29 | DEFB $03,$38 30 | CALL FPTODE 31 | EX DE,HL 32 | POP BC 33 | LD A,H 34 | CP B 35 | JR NZ,MISMATCH 36 | LD A,L 37 | CP C 38 | JR NZ,MISMATCH 39 | RST $28 40 | DEFB $02,$38 41 | POP DE 42 | POP HL 43 | INC L 44 | JR NZ,LOOP 45 | INC H 46 | BIT 7,H 47 | JR NZ,LOOP 48 | LD L,E 49 | LD H,D 50 | INC HL 51 | INC E 52 | JR NZ,LOOP 53 | INC D 54 | JR NZ,LOOP 55 | POP HL 56 | EXX 57 | LD BC,0 58 | EI 59 | RET 60 | MISMATCH: 61 | POP DE 62 | POP HL 63 | LD C,L 64 | LD B,H 65 | EXX 66 | POP HL 67 | EXX 68 | EI 69 | RET 70 | 71 | INCLUDE "../hpfp.asm" 72 | 73 | ; floating point constants 74 | MINF: EQU $0000 ; Positive epsilon, 2^-64 5.421e-20 75 | MAXF: EQU $7FFF ; Maximal floating point number 2^64-2^55 1.841e+19 76 | ONEF: EQU $4000 ; One 1.000e+00 77 | ROOT2F: EQU $406A ; Square root of 2 1.414e+00 78 | F7F: EQU $46FC ; $7F i.e. 127 1.270e+02 79 | 80 | ; Subroutines 81 | INCLUDE "../fdivmul.asm" 82 | INCLUDE "../faddsub.asm" 83 | INCLUDE "../mul8bit.asm" 84 | ; Lookup tables 85 | INCLUDE "../addtab.asm" 86 | INCLUDE "../subtab.asm" 87 | INCLUDE "../multab.asm" 88 | INCLUDE "../divtab.asm" 89 | -------------------------------------------------------------------------------- /fdivmul.asm: -------------------------------------------------------------------------------- 1 | ; Reciprocal value 2 | ; In: HL denominator 3 | ; Out: HL reciprocal value 4 | ; Pollutes: AF 5 | FREC: LD A,H 6 | XOR $7F 7 | LD H,DIVTAB/$100 8 | LD L,(HL) 9 | LD H,A 10 | LD A,L 11 | OR L 12 | RET NZ ; not a power of 2 13 | LD A,H 14 | AND $80 15 | SET 7,H 16 | INC H 17 | JR Z,FRECH ; overflow 18 | XOR $80 19 | XOR H 20 | LD H,A 21 | RET 22 | FRECH: OR $7F 23 | LD H,A 24 | LD L,$FF 25 | RET 26 | 27 | ; Floating-point division 28 | ; In: BC numerator, HL denominator 29 | ; Out: HL fraction 30 | ; Pollutes: AF,AF',BC,DE 31 | FDIV: CALL FREC 32 | EX DE,HL 33 | ; continues with FMUL 34 | 35 | ; Floating-point multiplication 36 | ; In: DE, BC multiplicands 37 | ; Out: HL product 38 | ; Pollutes: AF,AF',BC,DE 39 | FMUL: LD A,B 40 | XOR D 41 | AND $80 42 | PUSH AF 43 | RES 7,B 44 | RES 7,D 45 | CALL FMULP 46 | POP AF 47 | OR H 48 | LD H,A 49 | RET 50 | 51 | ; Find the difference of two squares 52 | ; Input: HL=hypothenuse, DE=leg 53 | ; Output: HL=HL*HL-DE*DE computed as (HL-DE)*(HL+DE) 54 | FSQDIF: PUSH HL 55 | PUSH DE 56 | CALL FSUBP 57 | POP DE 58 | EX (SP),HL 59 | CALL FADDP 60 | EX DE,HL 61 | POP BC 62 | ; continue with FMULP 63 | 64 | ; Floating-point multiplication of positive numbers 65 | ; In: DE, BC multiplicands 66 | ; Out: HL product 67 | ; Pollutes: AF,AF',BC,DE 68 | FMULP: LD A,D 69 | ADD B 70 | CP $C0 71 | JR NC,FINFTY ; overflow 72 | SUB $40 73 | JR C,FZERO ; underflow 74 | LD H,A 75 | LD A,E 76 | ADD C 77 | LD L,A 78 | PUSH HL 79 | LD B,E 80 | JR NC,FMULN 81 | CALL MUL8 82 | RL L 83 | LD A,H 84 | ADC A,0 ; rounding 85 | POP HL 86 | ADD L 87 | RRA 88 | ADC A,0 89 | LD L,A 90 | INC H 91 | RET 92 | FMULN: CALL MUL8 93 | RL L 94 | LD A,H 95 | ADC A,0 96 | POP HL 97 | ADD L 98 | LD L,A 99 | RET NC 100 | SRA L 101 | JR NC,FMULL 102 | INC L ; rounding 103 | FMULL: INC H 104 | RET 105 | -------------------------------------------------------------------------------- /raytracing/spectrum.asm: -------------------------------------------------------------------------------- 1 | ; This code is ZX Spectrum specific 2 | ORG $C000 ; Use uncontended memory 3 | SCAN: EXX 4 | PUSH HL 5 | LD HL,$5800 6 | LP1: DEC HL 7 | LD B,8 8 | LP2: PUSH BC 9 | PUSH HL 10 | LD A,L 11 | ADD A,A 12 | ADD A,A 13 | ADD A,A 14 | ADD A,B 15 | DEC A 16 | LD C,A 17 | LD A,H 18 | RRCA 19 | RRCA 20 | RRCA 21 | RRCA 22 | RR L 23 | RRCA 24 | RR L 25 | LD A,L 26 | AND $F8 27 | LD L,A 28 | LD A,H 29 | AND 7 30 | OR L 31 | LD B,A 32 | CALL TRACE 33 | POP HL 34 | RR (HL) 35 | POP BC 36 | DJNZ LP2 37 | LD A,H 38 | CP $40 39 | JR NC,LP1 40 | POP HL 41 | EXX 42 | RET 43 | 44 | SCENE: 45 | GROUND: DEFW BALL1,GROUNDI,GROUNDL,GC 46 | BALL1: DEFW BALL2,SPHEREI,SPHEREL,B1C,$3F33,$3E71 ; r=0.6, r*r=0.36 47 | BALL2: DEFW 0,SPHEREI,SPHEREL,B2C,$3D9A,$3B48 ; r=0.2, r*r=0.04 48 | POS: DEFB 3 ; 3 positions 49 | GROUNDC:DEFW $BE33,$3F00,$0000 ; -0.3, 0.5, 0 50 | BALL1C: DEFW $BF33,$BE33,$4180 ; -0.6, -0.3, 3 51 | BALL2C: DEFW $3F33,$BF33,$4100 ; 0.6, -0.6, 2 52 | LIGHT: DEFW 0,$C000,0 53 | INCLUDE "trace.asm" 54 | LD IX,SCENE 55 | CALL SCENEI 56 | RET NC 57 | INCLUDE "scene.asm" 58 | INCLUDE "ground.asm" 59 | INCLUDE "sphere.asm" 60 | INCLUDE "hitray.asm" 61 | 62 | ; floating point constants 63 | MINF: EQU $0000 ; Positive epsilon, 2^-64 5.421e-20 64 | MAXF: EQU $7FFF ; Maximal floating point number 2^64-2^55 1.841e+19 65 | ONEF: EQU $4000 ; One 1.000e+00 66 | ROOT2F: EQU $406A ; Square root of 2 1.414e+00 67 | F7F: EQU $46FC ; $7F i.e. 127 1.270e+02 68 | 69 | ; Subroutines 70 | INCLUDE "../fdivmul.asm" 71 | INCLUDE "../faddsub.asm" 72 | ; INCLUDE "../faddsub-fast.asm" 73 | INCLUDE "../fsquare.asm" 74 | INCLUDE "../mul8bit.asm" 75 | INCLUDE "../fint8.asm" 76 | INCLUDE "../dot.asm" 77 | ; Lookup tables 78 | ; INCLUDE "../addtab.asm" 79 | ; INCLUDE "../subtab.asm" 80 | INCLUDE "../multab.asm" 81 | INCLUDE "../divtab.asm" 82 | INCLUDE "../squaretab.asm" 83 | ; Variables 84 | INCLUDE "variables.asm" 85 | -------------------------------------------------------------------------------- /multab.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "align.asm" 2 | ; 512 byte squares table 3 | MULTAB: DEFB 0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225 4 | DEFB 0,33,68,105,144,185,228,17,64,113,164,217,16,73,132,193 5 | DEFB 0,65,132,201,16,89,164,241,64,145,228,57,144,233,68,161 6 | DEFB 0,97,196,41,144,249,100,209,64,177,36,153,16,137,4,129 7 | DEFB 0,129,4,137,16,153,36,177,64,209,100,249,144,41,196,97 8 | DEFB 0,161,68,233,144,57,228,145,64,241,164,89,16,201,132,65 9 | DEFB 0,193,132,73,16,217,164,113,64,17,228,185,144,105,68,33 10 | DEFB 0,225,196,169,144,121,100,81,64,49,36,25,16,9,4,1 11 | DEFB 0,1,4,9,16,25,36,49,64,81,100,121,144,169,196,225 12 | DEFB 0,33,68,105,144,185,228,17,64,113,164,217,16,73,132,193 13 | DEFB 0,65,132,201,16,89,164,241,64,145,228,57,144,233,68,161 14 | DEFB 0,97,196,41,144,249,100,209,64,177,36,153,16,137,4,129 15 | DEFB 0,129,4,137,16,153,36,177,64,209,100,249,144,41,196,97 16 | DEFB 0,161,68,233,144,57,228,145,64,241,164,89,16,201,132,65 17 | DEFB 0,193,132,73,16,217,164,113,64,17,228,185,144,105,68,33 18 | DEFB 0,225,196,169,144,121,100,81,64,49,36,25,16,9,4,1 19 | DEFB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 20 | DEFB 1,1,1,1,1,1,1,2,2,2,2,2,3,3,3,3 21 | DEFB 4,4,4,4,5,5,5,5,6,6,6,7,7,7,8,8 22 | DEFB 9,9,9,10,10,10,11,11,12,12,13,13,14,14,15,15 23 | DEFB 16,16,17,17,18,18,19,19,20,20,21,21,22,23,23,24 24 | DEFB 25,25,26,26,27,28,28,29,30,30,31,32,33,33,34,35 25 | DEFB 36,36,37,38,39,39,40,41,42,43,43,44,45,46,47,48 26 | DEFB 49,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63 27 | DEFB 64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79 28 | DEFB 81,82,83,84,85,86,87,89,90,91,92,93,95,96,97,98 29 | DEFB 100,101,102,103,105,106,107,108,110,111,112,114,115,116,118,119 30 | DEFB 121,122,123,125,126,127,129,130,132,133,135,136,138,139,141,142 31 | DEFB 144,145,147,148,150,151,153,154,156,157,159,160,162,164,165,167 32 | DEFB 169,170,172,173,175,177,178,180,182,183,185,187,189,190,192,194 33 | DEFB 196,197,199,201,203,204,206,208,210,212,213,215,217,219,221,223 34 | DEFB 225,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254 35 | 36 | -------------------------------------------------------------------------------- /fint64.asm: -------------------------------------------------------------------------------- 1 | ; Convert positive floating-point number to 64 bit LSB-first integer (always possible) 2 | ; The target array must be cleared before calling 3 | ; In: DE - floating point number, HL - pointer to integer (not crossing 256-byte boundaries) 4 | ; Out: Non-zero bytes of integer array updated 5 | ; Pollutes: AF, BC 6 | INT64: LD A,D 7 | SUB $48 8 | JR C,INT64H ; there is a fractional part 9 | RRA 10 | RRA 11 | RRA 12 | AND $1F 13 | ADD L 14 | LD L,A 15 | LD A,D 16 | AND 7 17 | LD C,E 18 | LD B,1 19 | JR Z,INT648 ; exponent multiple of 8 20 | INT64L: RL C 21 | RL B 22 | DEC A 23 | JR NZ,INT64L 24 | INT648: LD (HL),C 25 | INC L 26 | LD (HL),B 27 | RET 28 | INT64H: CP -8 29 | RET C ; smaller than 1 30 | JR Z,INT641 ; one 31 | LD C,E 32 | SCF 33 | INT64R: RR C 34 | AND A 35 | INC A 36 | JR NZ,INT64R 37 | LD (HL),C 38 | RET 39 | INT641: LD (HL),1 40 | RET 41 | 42 | ; Convert 64 bit LSB-first integer to floating-point number 43 | ; In: HL pointing to MSB 44 | ; Out: BC = floating point representation 45 | ; Pollutes: AF,AF',HL 46 | INT64F: LD A,$7F 47 | EX AF,AF' 48 | XOR A 49 | LD B,8 50 | INT64FL:OR (HL) 51 | JR NZ,INT64F0 52 | DEC L 53 | EX AF,AF' 54 | SUB A,8 55 | EX AF,AF' 56 | DJNZ INT64FL 57 | LD BC,0 58 | RET 59 | INT64F0:DJNZ INT64F2 60 | INT64FB:ADD A,A 61 | JR C,INT64F1 62 | EX AF,AF' 63 | DEC A 64 | EX AF,AF' 65 | JR INT64FB ; use JP for speed 66 | INT64F2:DEC L 67 | LD C,(HL) 68 | INT64FD:RL C 69 | RLA 70 | JR C,INT64F1 71 | EX AF,AF' 72 | DEC A 73 | EX AF,AF' 74 | JR INT64FD ; use JP for speed 75 | INT64F1:LD C,A 76 | EX AF,AF' 77 | LD B,A 78 | RET 79 | 80 | ; Calculate the remainder of a 64 bit LSB-first integer 81 | ; after division by a floating point number 82 | ; In: HL pointing to byte AFTER the MSB of the number, DE divisor 83 | ; Out: array containing the remainder 84 | ; Pollutes: AF,AF',C,E,HL 85 | MOD64: LD A,$40 86 | EX AF,AF' 87 | MOD64N: DEC L 88 | LD A,E 89 | LD E,0 90 | SCF 91 | EX AF,AF' 92 | MOD64L: DEC A 93 | CP $48 94 | JR C,MOD648 ; too small, last 8 bits 95 | EX AF,AF' 96 | RRA 97 | RR E 98 | OR A 99 | JR Z,MOD64N 100 | CP (HL) 101 | JR NC,MOD64S 102 | JR NZ,MOD64S 103 | DEC L 104 | LD C,A 105 | LD A,(HL) 106 | SUB E 107 | LD (HL),A 108 | INC L 109 | MOD64C: LD A,(HL) 110 | SUB C 111 | LD (HL),A 112 | LD A,C 113 | MOD64S: EX AF,AF' 114 | CP D 115 | JR NZ,MOD64L 116 | RET 117 | MOD648: EX AF,AF' 118 | RRA 119 | OR A 120 | JR Z,MOD64N 121 | CP (HL) 122 | JR NC,MOD64S 123 | JR NZ,MOD64S 124 | LD C,A 125 | JR MOD64C 126 | -------------------------------------------------------------------------------- /raytracing/sphere.asm: -------------------------------------------------------------------------------- 1 | ; Look at a sphere 2 | ; Input: HL = scale factor of D to surface 3 | ; Output: CF color 4 | ; Pollutes: anything except IX 5 | SPHEREL:EX DE,HL 6 | CALL SCALED 7 | CALL SCALEDL 8 | CALL HITRAY 9 | LD L,(IX+6) 10 | LD H,(IX+7) 11 | PUSH HL ; *-N 12 | LD DE,DX 13 | LD A,3 14 | CALL FDOT ; -N*D 15 | INC H ; -2N*D 16 | LD C,L 17 | LD B,H 18 | LD L,(IX+10) 19 | LD H,(IX+11) 20 | CALL FDIV ; -2N*D/NN 21 | EX (SP),HL ; -L stacked, *PX = -*NX retrieved 22 | LD C,(HL) 23 | INC HL 24 | LD B,(HL) 25 | INC HL 26 | EX (SP),HL ; -L restored, pointer stacked 27 | EX DE,HL 28 | PUSH DE ; -L stacked 29 | CALL FMUL ; -L * -NX 30 | EX DE,HL 31 | LD HL,(DX) 32 | CALL FSUB 33 | LD (DX),HL 34 | POP HL ; -L restored 35 | EX (SP),HL ; -L stacked, pointer retrieved 36 | LD C,(HL) 37 | INC HL 38 | LD B,(HL) 39 | INC HL 40 | EX (SP),HL ; -L restored, pointer stacked 41 | EX DE,HL 42 | PUSH DE ; -L stacked 43 | CALL FMUL 44 | EX DE,HL 45 | LD HL,(DY) 46 | CALL FSUB 47 | LD (DY),HL 48 | POP HL ; -L restored 49 | EX (SP),HL ; -L stacked, pointer restored 50 | LD C,(HL) 51 | INC HL 52 | LD B,(HL) 53 | POP DE ; -L restored 54 | CALL FMUL 55 | EX DE,HL 56 | LD HL,(DZ) 57 | CALL FSUB 58 | LD (DZ),HL 59 | JP TRACEL 60 | 61 | ; Sphere intersection 62 | ; Output: CF = true if ray intersects sphere, HL = scale factor of D vector 63 | ; Pollutes: anything except IX 64 | SPHEREI:LD HL,(DX) 65 | PUSH HL 66 | LD HL,(DY) 67 | PUSH HL 68 | LD HL,(DZ) 69 | PUSH HL ; save D 70 | LD L,(IX+6) 71 | LD H,(IX+7) 72 | LD DE,PX 73 | PUSH DE 74 | LD BC,6 75 | LDIR 76 | POP HL 77 | LD DE,DX 78 | LD A,3 79 | CALL FDOT ; D * P 80 | AND A 81 | BIT 7,H 82 | JR NZ,RESTD ; sphere behind us 83 | LD C,L 84 | LD B,H 85 | LD HL,(DD) 86 | CALL FDIV 87 | PUSH HL ; save P * D / DD 88 | EX DE,HL 89 | CALL SCALED 90 | LD HL,(DX) 91 | LD DE,(PX) 92 | CALL FSUB 93 | CALL FSQUARE 94 | PUSH HL 95 | LD HL,(DY) 96 | LD DE,(PY) 97 | CALL FSUB 98 | CALL FSQUARE 99 | POP DE 100 | CALL FADDP 101 | PUSH HL 102 | LD HL,(DZ) 103 | LD DE,(PZ) 104 | CALL FSUB 105 | CALL FSQUARE 106 | POP DE 107 | CALL FADDP 108 | LD E,(IX+10) 109 | LD D,(IX+11) 110 | OR A 111 | SBC HL,DE 112 | JR C,SPHEREH 113 | RESTD2: POP HL 114 | JR RESTD 115 | SPHEREH:ADD HL,DE 116 | EX DE,HL 117 | CALL FSUBP 118 | CALL FSQRT 119 | LD C,L 120 | LD B,H 121 | LD HL,(DL) 122 | CALL FDIV 123 | POP DE ; P * D / DD 124 | EX DE,HL 125 | CALL FSUBP 126 | SCF 127 | RESTD: POP DE 128 | LD (DZ),DE 129 | POP DE 130 | LD (DY),DE 131 | POP DE 132 | LD (DX),DE 133 | RET 134 | -------------------------------------------------------------------------------- /octab.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "align.asm" 2 | ; Octahedral skybox 3D signed integer coordinates, 768 bytes 3 | OCTX: DEFB -8,-24,-40,-56,-72,-88,-104,-120,-120,-104,-88,-72,-56,-40,-24,-8 4 | DEFB -8,-24,-40,-56,-72,-88,-104,-104,-104,-104,-88,-72,-56,-40,-24,-8 5 | DEFB -8,-24,-40,-56,-72,-88,-88,-88,-88,-88,-88,-72,-56,-40,-24,-8 6 | DEFB -8,-24,-40,-56,-72,-72,-72,-72,-72,-72,-72,-72,-56,-40,-24,-8 7 | DEFB -8,-24,-40,-56,-56,-56,-56,-56,-56,-56,-56,-56,-56,-40,-24,-8 8 | DEFB -8,-24,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-40,-24,-8 9 | DEFB -8,-24,-24,-24,-24,-24,-24,-24,-24,-24,-24,-24,-24,-24,-24,-8 10 | DEFB -8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8,-8 11 | DEFB 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 12 | DEFB 8,24,24,24,24,24,24,24,24,24,24,24,24,24,24,8 13 | DEFB 8,24,40,40,40,40,40,40,40,40,40,40,40,40,24,8 14 | DEFB 8,24,40,56,56,56,56,56,56,56,56,56,56,40,24,8 15 | DEFB 8,24,40,56,72,72,72,72,72,72,72,72,56,40,24,8 16 | DEFB 8,24,40,56,72,88,88,88,88,88,88,72,56,40,24,8 17 | DEFB 8,24,40,56,72,88,104,104,104,104,88,72,56,40,24,8 18 | DEFB 8,24,40,56,72,88,104,120,120,104,88,72,56,40,24,8 19 | OCTY: DEFB -8,-8,-8,-8,-8,-8,-8,-8,8,8,8,8,8,8,8,8 20 | DEFB -24,-24,-24,-24,-24,-24,-24,-8,8,24,24,24,24,24,24,24 21 | DEFB -40,-40,-40,-40,-40,-40,-24,-8,8,24,40,40,40,40,40,40 22 | DEFB -56,-56,-56,-56,-56,-40,-24,-8,8,24,40,56,56,56,56,56 23 | DEFB -72,-72,-72,-72,-56,-40,-24,-8,8,24,40,56,72,72,72,72 24 | DEFB -88,-88,-88,-72,-56,-40,-24,-8,8,24,40,56,72,88,88,88 25 | DEFB -104,-104,-88,-72,-56,-40,-24,-8,8,24,40,56,72,88,104,104 26 | DEFB -120,-104,-88,-72,-56,-40,-24,-8,8,24,40,56,72,88,104,120 27 | DEFB -120,-104,-88,-72,-56,-40,-24,-8,8,24,40,56,72,88,104,120 28 | DEFB -104,-104,-88,-72,-56,-40,-24,-8,8,24,40,56,72,88,104,104 29 | DEFB -88,-88,-88,-72,-56,-40,-24,-8,8,24,40,56,72,88,88,88,-72 30 | DEFB -72,-72,-72,-56,-40,-24,-8,8,24,40,56,72,72,72,72 31 | DEFB -56,-56,-56,-56,-56,-40,-24,-8,8,24,40,56,56,56,56,56 32 | DEFB -40,-40,-40,-40,-40,-40,-24,-8,8,24,40,40,40,40,40,40 33 | DEFB -24,-24,-24,-24,-24,-24,-24,-8,8,24,24,24,24,24,24,24 34 | DEFB -8,-8,-8,-8,-8,-8,-8,-8,8,8,8,8,8,8,8,8 35 | OCTZ: DEFB -112,-96,-80,-64,-48,-32,-16,0,0,-16,-32,-48,-64,-80,-96,-112 36 | DEFB -96,-80,-64,-48,-32,-16,0,16,16,0,-16,-32,-48,-64,-80,-96 37 | DEFB -80,-64,-48,-32,-16,0,16,32,32,16,0,-16,-32,-48,-64,-80 38 | DEFB -64,-48,-32,-16,0,16,32,48,48,32,16,0,-16,-32,-48,-64 39 | DEFB -48,-32,-16,0,16,32,48,64,64,48,32,16,0,-16,-32,-48 40 | DEFB -32,-16,0,16,32,48,64,80,80,64,48,32,16,0,-16,-32 41 | DEFB -16,0,16,32,48,64,80,96,96,80,64,48,32,16,0,-16 42 | DEFB 0,16,32,48,64,80,96,112,112,96,80,64,48,32,16,0 43 | DEFB 0,16,32,48,64,80,96,112,112,96,80,64,48,32,16,0 44 | DEFB -16,0,16,32,48,64,80,96,96,80,64,48,32,16,0,-16 45 | DEFB -32,-16,0,16,32,48,64,80,80,64,48,32,16,0,-16,-32 46 | DEFB -48,-32,-16,0,16,32,48,64,64,48,32,16,0,-16,-32,-48 47 | DEFB -64,-48,-32,-16,0,16,32,48,48,32,16,0,-16,-32,-48,-64 48 | DEFB -80,-64,-48,-32,-16,0,16,32,32,16,0,-16,-32,-48,-64,-80 49 | DEFB -96,-80,-64,-48,-32,-16,0,16,16,0,-16,-32,-48,-64,-80,-96 50 | DEFB -112,-96,-80,-64,-48,-32,-16,0,0,-16,-32,-48,-64,-80,-96,-112 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Low-Precision Floating-Point Arithmetic Library for Z80 2 | 3 | ## Introduction 4 | The purpose of this library is to provide fast floating-point operations for 5 | visualizations and simulations. In particular, 3D games and especially simulators 6 | can benefit from it. Extensive use of look-up tables and 8-bit arithmetics 7 | provide for adequate performance. 8 | 9 | The library uses 9-bit mantissa in the \[1..2) range and 7 bit signed exponent. 10 | It provides approx. 3 significant decimal digits of precision that allows it to 11 | accurately represent integers in the \[0..512\] range. This enables an angular 12 | resolution of almost 0.1 degree (for comparison, the Solar and Lunar discs are 13 | approx. 0.5 degrees in diameter) and sub-pixel resolution for the displays of 14 | typical 8-bit computers. The representable range is between (10⁻²⁰..10²⁰) giving 15 | the user more than 1000 light years or range if the unit is 1 meter or nanometer 16 | precision if the unit is 1 light second, in which case the entire observable 17 | universe fits into the range. 18 | 19 | However, users must exercise extra caution with numerical stability when using 20 | low-precision floating-point arithmetics, as precision degrades very rapidly with 21 | accummulating errors. In particular, subtraction can be highly inaccurate and 22 | division by the result of a subtraction can arbitrarily magnify such errors. 23 | 24 | The library also provides conversion into unsigned 64-bit integers (cannot 25 | overflow) as well as the means of calculating the remainder of a 64-bit integer 26 | after division by a floating-point number. This is useful for accurately 27 | representing time and cyclic events, such as the rotation and orbital movement 28 | of planets and other bodies. 29 | 30 | ## Specification 31 | 32 | Floating-point numbers are represented as 16 bits, typically stored in Z80 register 33 | pairs. Bits are interpreted as follows: 34 | 35 | bits| semantics 36 | --- | --- 37 | 0-7 | Mantissa bits -8..-1. Mantissa bit 0 is always 1, not represented 38 | 8-14| Exponent bits 0..6. The actual exponent is this number minus 64. Thus, 64 corresponds to 0 39 | 15 | Sign. 0 for positive, 1 for negative 40 | 41 | This representation provides for preserving lexicographic ordering for positive 42 | numbers. 43 | 44 | No special values such as `0`, `Inf` or `NaN` are represented. Undeflows 45 | result in the smallest representable number, ε=2⁻⁶⁴. Please note that this number 46 | does not always behave as an algebraic zero. In particular, ε+ε≠ε even though 0+0=0. 47 | While it is generally advised to avoid checking for strict equality in most cases, 48 | strict equality with ε should never be used as a zero check. Overflows result in 49 | the largerst representable number, 2⁶⁴. This also does not behave as algebraic 50 | infinity in many cases. As there is no zero and no infinity, no operations can 51 | result in `NaN`. Every result is a number. 52 | 53 | ## Numerical Tips 54 | 55 | Finding a *leg* *b* given the *hypothenuse* *c=a+δ* and the other leg *a* of a right triangle should 56 | be computed very carefully to avoid catastrophic loss of precision. In particular, **do not use** ~~*b* = SQRT(*c*²-*a*²)~~, but *b* = SQRT(*δ*(2*a* + *δ*)), based on the *c*²-*a*² = (*c* - *a*)(*c* + *a*) identity. 57 | 58 | Similarly, when calculating sin² α of an angle between two unit vectors *a* and *b*, **do not** take the shortcut of using ~~1-(*a*⋅*b*)²~~. Instead, use the inner product of (*a*⋅*b*)*a* - *b* with itself. 59 | -------------------------------------------------------------------------------- /faddsub-fast.asm: -------------------------------------------------------------------------------- 1 | ; Add two positive floating-point numbers 2 | ; In: HL,DE numbers to add 3 | ; Out: HL = sum HL + DE 4 | ; Pollutes: AF,DE 5 | FADDP: LD A,H 6 | SUB D 7 | JR NC,FADDPL 8 | EX DE,HL 9 | NEG 10 | FADDPL: JR Z,FADD0 ; same magnitude 11 | CP 10 12 | RET NC ; magnitude too different, just return the bigger number 13 | ADD A,ADDTAB/$100 - 1 14 | LD D,A 15 | LD A,(DE) 16 | OR A 17 | JR Z,FADD2 18 | ADD A,L 19 | LD L,A 20 | RET NC 21 | SRL A 22 | FADD1: ADC A,0 23 | LD L,A 24 | INC H 25 | BIT 7,H ; check overflow 26 | RET Z 27 | FINFTY: LD HL,MAXF ; positive maxfloat 28 | RET 29 | FADD2: LD E,A 30 | FADD0: LD A,L 31 | ADD A,E 32 | RRA 33 | JR FADD1 34 | 35 | 36 | ; Round towards zero 37 | ; In: HL any floating-point number 38 | ; Out: HL same number rounded towards zero 39 | ; Pollutes: AF,B 40 | FINT: LD A,H 41 | AND $7F 42 | SUB $40 43 | JR C,FZERO ; Completely fractional 44 | FINT2: SUB 8 45 | RET NC ; Already integer 46 | NEG 47 | AND 7 48 | JR Z,FINT0 49 | LD B,A 50 | LD A,$FF 51 | FINTL: ADD A,A 52 | DJNZ FINTL 53 | AND L 54 | FINT0: LD L,A 55 | RET 56 | FZERO: LD HL,MINF 57 | RET 58 | 59 | ; Fractional part, remainder after division by 1 60 | ; In: HL any floating-point number 61 | ; Out: HL fractional part, with sign intact 62 | ; Pollutes: AF,AF',BC,DE 63 | FRAC: LD A,H 64 | AND $7F 65 | SUB $40 66 | RET C ; Pure fraction 67 | PUSH HL 68 | CALL FINT2 69 | EX DE,HL 70 | POP HL 71 | JR FSUB 72 | 73 | ; Remainder after division 74 | ; In: BC dividend, HL modulus 75 | ; Out: HL remainder 76 | ; Pollutes: AF,AF',BC,DE 77 | FMOD: PUSH BC ; Stack: dividend 78 | PUSH HL ; Stack: dividend, modulus 79 | CALL FDIV 80 | CALL FINT ; integer ratio 81 | EX DE,HL ; DE = int(BC/HL) 82 | POP BC ; Stack: dividend; BC = modulus 83 | CALL FMUL ; Stack: dividend 84 | EX DE,HL 85 | POP HL 86 | ; continue with FSUB 87 | 88 | ; Subtract two floating-point numbers 89 | ; In: HL,DE numbers to subtract, no restrictions 90 | ; Out: HL = difference HL - DE 91 | ; Pollutes: AF,AF',BC,DE 92 | FSUB: LD A,D 93 | XOR $80 94 | LD D,A ; DE = -DE 95 | ; continue with FADD 96 | 97 | ; Add two floating-point numbers 98 | ; In: HL,DE numbers to add, no restrictions 99 | ; Out: HL = sum HL + DE 100 | ; Pollutes: AF,AF',BC,DE 101 | FADD: LD B,H 102 | LD C,D 103 | LD A,B 104 | XOR C 105 | ADD A,A 106 | EX AF,AF' 107 | RES 7,H 108 | RES 7,D 109 | CALL FCPP 110 | JR NC,FADDNS ; no swap 111 | EX DE,HL 112 | LD B,C 113 | FADDNS: EX AF,AF' 114 | JR C,FADDS 115 | CALL FADDP 116 | JR FADDHB 117 | FADDS: CALL FSUBP 118 | FADDHB: LD A,B 119 | AND $80 120 | OR H 121 | LD H,A 122 | RET 123 | 124 | ; Compare two positive floating point numbers 125 | ; In: HL,DE numbers to compare 126 | ; Out: C flag if DE>HL, Z flag if DE=HL 127 | ; Pollutes: A 128 | FCPP: LD A,H 129 | CP D 130 | RET NZ 131 | LD A,L 132 | CP E 133 | RET 134 | 135 | ; Subtract two positive floating-point numbers 136 | ; In: HL,DE numbers to subtract, HL >= DE 137 | ; Out: HL = difference HL - DE 138 | ; Pollutes: AF,DE,HL' 139 | FSUBP: LD A,H 140 | SUB D 141 | JR Z,FSUB0 ; same magnitude, cleared C flag 142 | CP 10 143 | RET NC ; magnitude too different, just return the bigger number 144 | EXX 145 | LD H,BITTAB/$100 146 | LD L,A 147 | DEC L 148 | EX AF,AF' 149 | LD A,(HL) 150 | EXX 151 | AND E 152 | EX AF,AF' 153 | ADD A,ADDTAB/$100 - 1 154 | LD D,A 155 | LD A,(DE) 156 | OR A 157 | JR Z,FSUB2 ; $1.FF / 2 = $1.00 (SBC A,$FF with C=1 does not change A, but sets carry) 158 | NEG 159 | ADD A,L 160 | LD L,A 161 | RET C 162 | FSUB2: LD A,L 163 | OR A 164 | JR Z,FZERO3 ; $1.00 - $1.00 = 0 165 | FSUBL2: LD D,H 166 | LD H,SUBTAB/$100 167 | LD A,(HL) 168 | INC H 169 | EX AF,AF' 170 | JR Z,FSUB1 171 | INC H 172 | FSUB1: EX AF,AF' 173 | LD L,(HL) 174 | ADD A,D 175 | JR NC,FZERO2 ; underflow 176 | LD H,A 177 | RET 178 | FSUB0: LD A,L 179 | SUB A,E 180 | LD L,A 181 | JR NZ,FSUBL2 182 | FZERO3: LD H,L 183 | RET 184 | 185 | ; Return epsilon 186 | FZERO2: LD HL,MINF 187 | RET 188 | -------------------------------------------------------------------------------- /faddsub.asm: -------------------------------------------------------------------------------- 1 | ; Add two positive floating-point numbers 2 | ; In: HL,DE numbers to add 3 | ; Out: HL = sum HL + DE 4 | ; Pollutes: AF,DE 5 | FADDP: CALL FCPP 6 | JR NC,FADDPX 7 | EX DE,HL 8 | ; Continue with FADDPX 9 | 10 | ; Add two positive floating-point numbers 11 | ; In: HL,DE numbers to add, HL >= DE 12 | ; Out: HL = sum HL + DE 13 | ; Pollutes: AF,DE 14 | FADDPX: LD A,H 15 | SUB D 16 | JR Z,FADD0 ; same magnitude, cleared C flag 17 | CP 10 18 | RET NC ; magnitude too different, just return the bigger number 19 | RR E 20 | DEC A 21 | JR Z,FADDLE 22 | FADDL: SRL E 23 | DEC A 24 | JR NZ,FADDL 25 | FADDLE: LD A,L 26 | ADC A,E ; rounding 27 | LD L,A 28 | RET NC 29 | SRL A 30 | FADD1: ADC A,0 ; rounding 31 | LD L,A 32 | FADD2: INC H 33 | BIT 7,H ; check overflow 34 | RET Z 35 | FINFTY: LD HL,MAXF ; positive maxfloat 36 | RET 37 | FADD0: LD A,L 38 | ADD A,E 39 | RRA 40 | JR FADD1 41 | 42 | ; Round towards zero 43 | ; In: HL any floating-point number 44 | ; Out: HL same number rounded towards zero 45 | ; Pollutes: AF,B 46 | FINT: LD A,H 47 | AND $7F 48 | SUB $40 49 | JR C,FZERO ; Completely fractional 50 | FINT2: SUB 8 51 | RET NC ; Already integer 52 | NEG 53 | AND 7 54 | JR Z,FINT0 55 | LD B,A 56 | LD A,$FF 57 | FINTL: ADD A,A 58 | DJNZ FINTL 59 | AND L 60 | FINT0: LD L,A 61 | RET 62 | FZERO: LD HL,MINF 63 | RET 64 | 65 | ; Fractional part, remainder after division by 1 66 | ; In: HL any floating-point number 67 | ; Out: HL fractional part, with sign intact 68 | ; Pollutes: AF,AF',BC,DE 69 | FRAC: LD A,H 70 | AND $7F 71 | SUB $40 72 | RET C ; Pure fraction 73 | PUSH HL 74 | CALL FINT2 75 | EX DE,HL 76 | POP HL 77 | JR FSUB 78 | 79 | ; Remainder after division 80 | ; In: BC dividend, HL modulus 81 | ; Out: HL remainder 82 | ; Pollutes: AF,AF',BC,DE 83 | FMOD: PUSH BC ; Stack: dividend 84 | PUSH HL ; Stack: dividend, modulus 85 | CALL FDIV 86 | CALL FINT ; integer ratio 87 | EX DE,HL ; DE = int(BC/HL) 88 | POP BC ; Stack: dividend; BC = modulus 89 | CALL FMUL ; Stack: dividend 90 | EX DE,HL 91 | POP HL 92 | ; continue with FSUB 93 | 94 | ; Subtract two floating-point numbers 95 | ; In: HL,DE numbers to subtract, no restrictions 96 | ; Out: HL = difference HL - DE 97 | ; Pollutes: AF,AF',BC,DE 98 | FSUB: LD A,D 99 | XOR $80 100 | LD D,A ; DE = -DE 101 | ; continue with FADD 102 | 103 | ; Add two floating-point numbers 104 | ; In: HL,DE numbers to add, no restrictions 105 | ; Out: HL = sum HL + DE 106 | ; Pollutes: AF,AF',BC,DE 107 | FADD: LD B,H 108 | LD C,D 109 | LD A,B 110 | XOR C 111 | ADD A,A 112 | EX AF,AF' 113 | RES 7,H 114 | RES 7,D 115 | CALL FCPP 116 | JR NC,FADDNS ; no swap 117 | EX DE,HL 118 | LD B,C 119 | FADDNS: EX AF,AF' 120 | JR C,FADDS 121 | CALL FADDPX 122 | JR FADDHB 123 | FADDS: CALL FSUBP 124 | FADDHB: LD A,B 125 | AND $80 126 | OR H 127 | LD H,A 128 | RET 129 | 130 | ; Compare two positive floating point numbers 131 | ; In: HL,DE numbers to compare 132 | ; Out: C flag if DE>HL, Z flag if DE=HL 133 | ; Pollutes: A 134 | FCPP: LD A,H 135 | CP D 136 | RET NZ 137 | LD A,L 138 | CP E 139 | RET 140 | 141 | ; Subtract two positive floating-point numbers 142 | ; In: HL,DE numbers to subtract, HL >= DE 143 | ; Out: HL = difference HL - DE 144 | ; Pollutes: AF,DE 145 | FSUBP: LD A,H 146 | SUB D 147 | JR Z,FSUB0 ; same magnitude, cleared C flag 148 | CP 10 149 | RET NC ; magnitude too different, just return the bigger number 150 | RR E 151 | DEC A 152 | JR Z,FSUBLE 153 | FSUBL: SRL E 154 | DEC A 155 | JR NZ,FSUBL 156 | FSUBLE: SBC A,A 157 | LD D,A ; save C flag to D 158 | LD A,L 159 | SBC A,E ; rounding 160 | LD L,A 161 | JR C,FSUBN 162 | RRC D ; restore C flag from D 163 | RET NC 164 | INC L 165 | RET NZ 166 | JP FADD2 167 | FSUB0: LD A,L 168 | SUB A,E 169 | JR Z,FZERO2 170 | LD D,0 171 | FSUBN: RRC D ; restore C flag from D 172 | FSUBL2: DEC H 173 | BIT 7,H 174 | JR NZ,FZERO2 175 | ADC A,A 176 | JR NC,FSUBL2 177 | LD L,A 178 | RET 179 | 180 | ; Return epsilon 181 | FZERO2: LD HL,MINF 182 | RET 183 | -------------------------------------------------------------------------------- /squaretab.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "align.asm" 2 | ; Mantissas of squares 3 | SQTAB: DEFB $00,$02,$04,$06,$08,$0A,$0C,$0E 4 | DEFB $10,$12,$14,$16,$19,$1B,$1D,$1F 5 | DEFB $21,$23,$25,$27,$2A,$2C,$2E,$30 6 | DEFB $32,$34,$37,$39,$3B,$3D,$40,$42 7 | DEFB $44,$46,$49,$4B,$4D,$4F,$52,$54 8 | DEFB $56,$59,$5B,$5D,$60,$62,$64,$67 9 | DEFB $69,$6B,$6E,$70,$73,$75,$77,$7A 10 | DEFB $7C,$7F,$81,$84,$86,$89,$8B,$8E 11 | DEFB $90,$93,$95,$98,$9A,$9D,$9F,$A2 12 | DEFB $A4,$A7,$A9,$AC,$AF,$B1,$B4,$B6 13 | DEFB $B9,$BC,$BE,$C1,$C4,$C6,$C9,$CC 14 | DEFB $CE,$D1,$D4,$D6,$D9,$DC,$DF,$E1 15 | DEFB $E4,$E7,$EA,$EC,$EF,$F2,$F5,$F7 16 | DEFB $FA,$FD 17 | ; Squares from $6A, mantissa of sqrt(2) 18 | DEFB $00,$01,$03,$04,$06,$07 19 | DEFB $09,$0A,$0B,$0D,$0E,$10,$11,$13 20 | DEFB $14,$16,$17,$19,$1A,$1C,$1D,$1F 21 | DEFB $20,$22,$23,$25,$26,$28,$29,$2B 22 | DEFB $2C,$2E,$2F,$31,$32,$34,$35,$37 23 | DEFB $39,$3A,$3C,$3D,$3F,$40,$42,$44 24 | DEFB $45,$47,$48,$4A,$4C,$4D,$4F,$50 25 | DEFB $52,$54,$55,$57,$59,$5A,$5C,$5D 26 | DEFB $5F,$61,$62,$64,$66,$67,$69,$6B 27 | DEFB $6D,$6E,$70,$72,$73,$75,$77,$78 28 | DEFB $7A,$7C,$7E,$7F,$81,$83,$85,$86 29 | DEFB $88,$8A,$8C,$8D,$8F,$91,$93,$94 30 | DEFB $96,$98,$9A,$9B,$9D,$9F,$A1,$A3 31 | DEFB $A5,$A6,$A8,$AA,$AC,$AE,$AF,$B1 32 | DEFB $B3,$B5,$B7,$B9,$BB,$BC,$BE,$C0 33 | DEFB $C2,$C4,$C6,$C8,$CA,$CB,$CD,$CF 34 | DEFB $D1,$D3,$D5,$D7,$D9,$DB,$DD,$DF 35 | DEFB $E1,$E2,$E4,$E6,$E8,$EA,$EC,$EE 36 | DEFB $F0,$F2,$F4,$F6,$F8,$FA,$FC,$FE 37 | 38 | ; Mantissas of square roots 39 | SQRTAB: DEFB $00,$00,$01,$01,$02,$02,$03,$03 40 | DEFB $04,$04,$05,$05,$06,$06,$07,$07 41 | DEFB $08,$08,$09,$09,$0A,$0A,$0B,$0B 42 | DEFB $0C,$0C,$0D,$0D,$0E,$0E,$0F,$0F 43 | DEFB $10,$10,$10,$11,$11,$12,$12,$13 44 | DEFB $13,$14,$14,$15,$15,$16,$16,$17 45 | DEFB $17,$17,$18,$18,$19,$19,$1A,$1A 46 | DEFB $1B,$1B,$1C,$1C,$1C,$1D,$1D,$1E 47 | DEFB $1E,$1F,$1F,$20,$20,$20,$21,$21 48 | DEFB $22,$22,$23,$23,$24,$24,$24,$25 49 | DEFB $25,$26,$26,$27,$27,$27,$28,$28 50 | DEFB $29,$29,$2A,$2A,$2A,$2B,$2B,$2C 51 | DEFB $2C,$2D,$2D,$2D,$2E,$2E,$2F,$2F 52 | DEFB $30,$30,$30,$31,$31,$32,$32,$33 53 | DEFB $33,$33,$34,$34,$35,$35,$35,$36 54 | DEFB $36,$37,$37,$37,$38,$38,$39,$39 55 | DEFB $3A,$3A,$3A,$3B,$3B,$3C,$3C,$3C 56 | DEFB $3D,$3D,$3E,$3E,$3E,$3F,$3F,$40 57 | DEFB $40,$40,$41,$41,$42,$42,$42,$43 58 | DEFB $43,$44,$44,$44,$45,$45,$46,$46 59 | DEFB $46,$47,$47,$48,$48,$48,$49,$49 60 | DEFB $49,$4A,$4A,$4B,$4B,$4B,$4C,$4C 61 | DEFB $4D,$4D,$4D,$4E,$4E,$4E,$4F,$4F 62 | DEFB $50,$50,$50,$51,$51,$52,$52,$52 63 | DEFB $53,$53,$53,$54,$54,$55,$55,$55 64 | DEFB $56,$56,$56,$57,$57,$58,$58,$58 65 | DEFB $59,$59,$59,$5A,$5A,$5B,$5B,$5B 66 | DEFB $5C,$5C,$5C,$5D,$5D,$5D,$5E,$5E 67 | DEFB $5F,$5F,$5F,$60,$60,$60,$61,$61 68 | DEFB $61,$62,$62,$63,$63,$63,$64,$64 69 | DEFB $64,$65,$65,$65,$66,$66,$66,$67 70 | DEFB $67,$68,$68,$68,$69,$69,$69,$6A 71 | DEFB $6A,$6B,$6B,$6C,$6D,$6E,$6E,$6F 72 | DEFB $70,$70,$71,$72,$72,$73,$74,$74 73 | DEFB $75,$76,$77,$77,$78,$79,$79,$7A 74 | DEFB $7B,$7B,$7C,$7D,$7D,$7E,$7F,$7F 75 | DEFB $80,$81,$81,$82,$83,$83,$84,$85 76 | DEFB $85,$86,$87,$87,$88,$89,$89,$8A 77 | DEFB $8B,$8B,$8C,$8C,$8D,$8E,$8E,$8F 78 | DEFB $90,$90,$91,$92,$92,$93,$94,$94 79 | DEFB $95,$95,$96,$97,$97,$98,$99,$99 80 | DEFB $9A,$9A,$9B,$9C,$9C,$9D,$9E,$9E 81 | DEFB $9F,$9F,$A0,$A1,$A1,$A2,$A2,$A3 82 | DEFB $A4,$A4,$A5,$A6,$A6,$A7,$A7,$A8 83 | DEFB $A9,$A9,$AA,$AA,$AB,$AC,$AC,$AD 84 | DEFB $AD,$AE,$AF,$AF,$B0,$B0,$B1,$B1 85 | DEFB $B2,$B3,$B3,$B4,$B4,$B5,$B6,$B6 86 | DEFB $B7,$B7,$B8,$B9,$B9,$BA,$BA,$BB 87 | DEFB $BB,$BC,$BD,$BD,$BE,$BE,$BF,$BF 88 | DEFB $C0,$C1,$C1,$C2,$C2,$C3,$C3,$C4 89 | DEFB $C5,$C5,$C6,$C6,$C7,$C7,$C8,$C8 90 | DEFB $C9,$CA,$CA,$CB,$CB,$CC,$CC,$CD 91 | DEFB $CE,$CE,$CF,$CF,$D0,$D0,$D1,$D1 92 | DEFB $D2,$D2,$D3,$D4,$D4,$D5,$D5,$D6 93 | DEFB $D6,$D7,$D7,$D8,$D8,$D9,$DA,$DA 94 | DEFB $DB,$DB,$DC,$DC,$DD,$DD,$DE,$DE 95 | DEFB $DF,$DF,$E0,$E1,$E1,$E2,$E2,$E3 96 | DEFB $E3,$E4,$E4,$E5,$E5,$E6,$E6,$E7 97 | DEFB $E7,$E8,$E8,$E9,$EA,$EA,$EB,$EB 98 | DEFB $EC,$EC,$ED,$ED,$EE,$EE,$EF,$EF 99 | DEFB $F0,$F0,$F1,$F1,$F2,$F2,$F3,$F3 100 | DEFB $F4,$F4,$F5,$F5,$F6,$F6,$F7,$F7 101 | DEFB $F8,$F8,$F9,$F9,$FA,$FA,$FB,$FB 102 | DEFB $FC,$FC,$FD,$FD,$FE,$FE,$FF,$FF 103 | -------------------------------------------------------------------------------- /rotation.asm: -------------------------------------------------------------------------------- 1 | ; Unit quaternion multiplication and normalization, if necessary 2 | ; Input: {RIJK}{12} the two multiplicands 3 | ; Output: {RIJK}1 the product quaternion 4 | ; Pollutes: AF,AF',BC,DE,HL 5 | QMUL: LD BC,(R1) 6 | LD DE,(R2) 7 | CALL FMUL 8 | PUSH HL 9 | LD BC,(I1) 10 | LD DE,(I2) 11 | CALL FMUL 12 | PUSH HL 13 | LD BC,(J1) 14 | LD DE,(J2) 15 | CALL FMUL 16 | POP DE 17 | CALL FADD 18 | PUSH HL 19 | LD BC,(K1) 20 | LD DE,(K2) 21 | CALL FMUL 22 | POP DE 23 | CALL FADD 24 | POP DE 25 | EX DE,HL 26 | CALL FSUB 27 | PUSH HL ; real 28 | LD BC,(K1) 29 | LD DE,(J2) 30 | CALL FMUL 31 | PUSH HL 32 | LD BC,(R1) 33 | LD DE,(I2) 34 | CALL FMUL 35 | PUSH HL 36 | LD BC,(R2) 37 | LD DE,(I1) 38 | CALL FMUL 39 | POP DE 40 | CALL FADD 41 | PUSH HL 42 | LD BC,(J1) 43 | LD DE,(K2) 44 | CALL FMUL 45 | POP DE 46 | CALL FADD 47 | POP DE 48 | CALL FSUB 49 | PUSH HL ; i 50 | LD BC,(I1) 51 | LD DE,(K2) 52 | CALL FMUL 53 | PUSH HL 54 | LD BC,(R1) 55 | LD DE,(J2) 56 | CALL FMUL 57 | PUSH HL 58 | LD BC,(J1) 59 | LD DE,(R2) 60 | CALL FMUL 61 | POP DE 62 | CALL FADD 63 | PUSH HL 64 | LD BC,(K1) 65 | LD DE,(I2) 66 | CALL FMUL 67 | POP DE 68 | CALL FADD 69 | POP DE 70 | CALL FSUB 71 | PUSH HL ; j 72 | LD BC,(J1) 73 | LD DE,(I2) 74 | CALL FMUL 75 | PUSH HL 76 | LD BC,(R1) 77 | LD DE,(K2) 78 | CALL FMUL 79 | PUSH HL 80 | LD BC,(I1) 81 | LD DE,(J2) 82 | CALL FMUL 83 | POP DE 84 | CALL FADD 85 | PUSH HL 86 | LD BC,(K1) 87 | LD DE,(R2) 88 | CALL FMUL 89 | POP DE 90 | CALL FADD 91 | POP DE 92 | CALL FSUB 93 | LD (K1),HL ; k 94 | ; Normalize 95 | CALL FSQUARE 96 | EX (SP),HL 97 | LD (J1),HL 98 | CALL FSQUARE 99 | POP DE 100 | CALL FADD 101 | EX (SP),HL 102 | LD (I1),HL 103 | CALL FSQUARE 104 | POP DE 105 | CALL FADD 106 | EX (SP),HL 107 | LD (R1),HL 108 | CALL FSQUARE 109 | POP DE 110 | CALL FADD 111 | LD DE,ONEF 112 | CALL FSUB 113 | LD A,H 114 | ADD A,A 115 | CP $70 116 | RET C ; deviation from 1 smaller than 2^-8 117 | EX DE,HL 118 | INC D 119 | LD HL,ONEF 120 | CALL FSUB 121 | PUSH HL ; 1/norm 122 | LD C,L 123 | LD B,H 124 | LD DE,(R1) 125 | CALL FMUL 126 | LD (R1),HL 127 | POP BC 128 | PUSH BC 129 | LD DE,(I1) 130 | CALL FMUL 131 | LD (I1),HL 132 | POP BC 133 | PUSH BC 134 | LD DE,(J1) 135 | CALL FMUL 136 | LD (J1),HL 137 | POP BC 138 | LD DE,(K1) 139 | CALL FMUL 140 | LD (K1),HL 141 | RET 142 | 143 | ; Inverse quaternion 144 | ; Input: {RIJK}1 = quaternion to invert 145 | ; Output: {RIJK}1 = inverse 146 | ; Pollutes: A,C 147 | QINV: LD C,$80 148 | LD A,(I1+1) 149 | XOR C 150 | LD (I1+1),A 151 | LD A,(J1+1) 152 | XOR C 153 | LD (J1+1),A 154 | LD A,(K1+1) 155 | XOR C 156 | LD (K1+1),A 157 | RET 158 | 159 | ; Convert unit quaternion to rotation matrix 160 | QMAT: LD HL,(I1) 161 | CALL FSQUARE 162 | PUSH HL 163 | EX DE,HL 164 | LD HL,(J1) 165 | CALL FSQUARE 166 | PUSH HL 167 | CALL FADDP 168 | INC H 169 | SET 7,H 170 | LD DE,ONEF 171 | CALL FADD 172 | LD (Z3),HL 173 | POP DE 174 | LD HL,(K1) 175 | CALL FSQUARE 176 | PUSH HL 177 | CALL FADDP 178 | INC H 179 | SET 7,H 180 | LD DE,ONEF 181 | CALL FADD 182 | LD (X1),HL 183 | POP HL 184 | POP DE 185 | CALL FADDP 186 | INC H 187 | SET 7,H 188 | LD DE,ONEF 189 | CALL FADD 190 | LD (Y2),HL 191 | LD BC,(K1) 192 | LD DE,(R1) 193 | CALL FMUL 194 | PUSH HL 195 | PUSH HL 196 | LD BC,(I1) 197 | LD DE,(J1) 198 | CALL FMUL 199 | POP DE 200 | PUSH HL 201 | CALL FSUB 202 | INC H 203 | LD (X2),HL 204 | POP HL 205 | POP DE 206 | CALL FADD 207 | INC H 208 | LD (Y1),HL 209 | LD BC,(J1) 210 | LD DE,(R1) 211 | CALL FMUL 212 | PUSH HL 213 | PUSH HL 214 | LD BC,(I1) 215 | LD DE,(K1) 216 | CALL FMUL 217 | POP DE 218 | PUSH HL 219 | CALL FSUB 220 | INC H 221 | LD (Z1),HL 222 | POP HL 223 | POP DE 224 | CALL FADD 225 | INC H 226 | LD (X3),HL 227 | LD BC,(I1) 228 | LD DE,(R1) 229 | CALL FMUL 230 | PUSH HL 231 | PUSH HL 232 | LD BC,(K1) 233 | LD DE,(J1) 234 | CALL FMUL 235 | POP DE 236 | PUSH HL 237 | CALL FSUB 238 | INC H 239 | LD (Y3),HL 240 | POP HL 241 | POP DE 242 | CALL FADD 243 | INC H 244 | LD (Z2),HL 245 | RET 246 | 247 | 248 | ; First quaternion 249 | R1: DEFS 2 250 | I1: DEFS 2 251 | J1: DEFS 2 252 | K1: DEFS 2 253 | ; Second quaternion 254 | R2: DEFS 2 255 | I2: DEFS 2 256 | J2: DEFS 2 257 | K2: DEFS 2 258 | ; Rotation Matrix 259 | X1: DEFS 2 260 | Y1: DEFS 2 261 | Z1: DEFS 2 262 | X2: DEFS 2 263 | Y2: DEFS 2 264 | Z2: DEFS 2 265 | X3: DEFS 2 266 | Y3: DEFS 2 267 | Z3: DEFS 2 268 | -------------------------------------------------------------------------------- /subtab.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "align.asm" 2 | ; 768 byte table for renormalization after subtraction 3 | SUBTAB: DEFB $00, $f8, $f9, $f9, $fa, $fa, $fa, $fa 4 | DEFB $fb, $fb, $fb, $fb, $fb, $fb, $fb, $fb 5 | DEFB $fc, $fc, $fc, $fc, $fc, $fc, $fc, $fc 6 | DEFB $fc, $fc, $fc, $fc, $fc, $fc, $fc, $fc 7 | DEFB $fd, $fd, $fd, $fd, $fd, $fd, $fd, $fd 8 | DEFB $fd, $fd, $fd, $fd, $fd, $fd, $fd, $fd 9 | DEFB $fd, $fd, $fd, $fd, $fd, $fd, $fd, $fd 10 | DEFB $fd, $fd, $fd, $fd, $fd, $fd, $fd, $fd 11 | DEFB $fe, $fe, $fe, $fe, $fe, $fe, $fe, $fe 12 | DEFB $fe, $fe, $fe, $fe, $fe, $fe, $fe, $fe 13 | DEFB $fe, $fe, $fe, $fe, $fe, $fe, $fe, $fe 14 | DEFB $fe, $fe, $fe, $fe, $fe, $fe, $fe, $fe 15 | DEFB $fe, $fe, $fe, $fe, $fe, $fe, $fe, $fe 16 | DEFB $fe, $fe, $fe, $fe, $fe, $fe, $fe, $fe 17 | DEFB $fe, $fe, $fe, $fe, $fe, $fe, $fe, $fe 18 | DEFB $fe, $fe, $fe, $fe, $fe, $fe, $fe, $fe 19 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 20 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 21 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 22 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 23 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 24 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 25 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 26 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 27 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 28 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 29 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 30 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 31 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 32 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 33 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 34 | DEFB $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff 35 | 36 | DEFB $00, $00, $00, $80, $00, $40, $80, $c0 37 | DEFB $00, $20, $40, $60, $80, $a0, $c0, $e0 38 | DEFB $00, $10, $20, $30, $40, $50, $60, $70 39 | DEFB $80, $90, $a0, $b0, $c0, $d0, $e0, $f0 40 | DEFB $00, $08, $10, $18, $20, $28, $30, $38 41 | DEFB $40, $48, $50, $58, $60, $68, $70, $78 42 | DEFB $80, $88, $90, $98, $a0, $a8, $b0, $b8 43 | DEFB $c0, $c8, $d0, $d8, $e0, $e8, $f0, $f8 44 | DEFB $00, $04, $08, $0c, $10, $14, $18, $1c 45 | DEFB $20, $24, $28, $2c, $30, $34, $38, $3c 46 | DEFB $40, $44, $48, $4c, $50, $54, $58, $5c 47 | DEFB $60, $64, $68, $6c, $70, $74, $78, $7c 48 | DEFB $80, $84, $88, $8c, $90, $94, $98, $9c 49 | DEFB $a0, $a4, $a8, $ac, $b0, $b4, $b8, $bc 50 | DEFB $c0, $c4, $c8, $cc, $d0, $d4, $d8, $dc 51 | DEFB $e0, $e4, $e8, $ec, $f0, $f4, $f8, $fc 52 | DEFB $00, $02, $04, $06, $08, $0a, $0c, $0e 53 | DEFB $10, $12, $14, $16, $18, $1a, $1c, $1e 54 | DEFB $20, $22, $24, $26, $28, $2a, $2c, $2e 55 | DEFB $30, $32, $34, $36, $38, $3a, $3c, $3e 56 | DEFB $40, $42, $44, $46, $48, $4a, $4c, $4e 57 | DEFB $50, $52, $54, $56, $58, $5a, $5c, $5e 58 | DEFB $60, $62, $64, $66, $68, $6a, $6c, $6e 59 | DEFB $70, $72, $74, $76, $78, $7a, $7c, $7e 60 | DEFB $80, $82, $84, $86, $88, $8a, $8c, $8e 61 | DEFB $90, $92, $94, $96, $98, $9a, $9c, $9e 62 | DEFB $a0, $a2, $a4, $a6, $a8, $aa, $ac, $ae 63 | DEFB $b0, $b2, $b4, $b6, $b8, $ba, $bc, $be 64 | DEFB $c0, $c2, $c4, $c6, $c8, $ca, $cc, $ce 65 | DEFB $d0, $d2, $d4, $d6, $d8, $da, $dc, $de 66 | DEFB $e0, $e2, $e4, $e6, $e8, $ea, $ec, $ee 67 | DEFB $f0, $f2, $f4, $f6, $f8, $fa, $fc, $fe 68 | 69 | DEFB $00, $80, $40, $c0, $20, $60, $a0, $e0 70 | DEFB $10, $30, $50, $70, $90, $b0, $d0, $f0 71 | DEFB $08, $18, $28, $38, $48, $58, $68, $78 72 | DEFB $88, $98, $a8, $b8, $c8, $d8, $e8, $f8 73 | DEFB $04, $0c, $14, $1c, $24, $2c, $34, $3c 74 | DEFB $44, $4c, $54, $5c, $64, $6c, $74, $7c 75 | DEFB $84, $8c, $94, $9c, $a4, $ac, $b4, $bc 76 | DEFB $c4, $cc, $d4, $dc, $e4, $ec, $f4, $fc 77 | DEFB $02, $06, $0a, $0e, $12, $16, $1a, $1e 78 | DEFB $22, $26, $2a, $2e, $32, $36, $3a, $3e 79 | DEFB $42, $46, $4a, $4e, $52, $56, $5a, $5e 80 | DEFB $62, $66, $6a, $6e, $72, $76, $7a, $7e 81 | DEFB $82, $86, $8a, $8e, $92, $96, $9a, $9e 82 | DEFB $a2, $a6, $aa, $ae, $b2, $b6, $ba, $be 83 | DEFB $c2, $c6, $ca, $ce, $d2, $d6, $da, $de 84 | DEFB $e2, $e6, $ea, $ee, $f2, $f6, $fa, $fe 85 | DEFB $01, $03, $05, $07, $09, $0b, $0d, $0f 86 | DEFB $11, $13, $15, $17, $19, $1b, $1d, $1f 87 | DEFB $21, $23, $25, $27, $29, $2b, $2d, $2f 88 | DEFB $31, $33, $35, $37, $39, $3b, $3d, $3f 89 | DEFB $41, $43, $45, $47, $49, $4b, $4d, $4f 90 | DEFB $51, $53, $55, $57, $59, $5b, $5d, $5f 91 | DEFB $61, $63, $65, $67, $69, $6b, $6d, $6f 92 | DEFB $71, $73, $75, $77, $79, $7b, $7d, $7f 93 | DEFB $81, $83, $85, $87, $89, $8b, $8d, $8f 94 | DEFB $91, $93, $95, $97, $99, $9b, $9d, $9f 95 | DEFB $a1, $a3, $a5, $a7, $a9, $ab, $ad, $af 96 | DEFB $b1, $b3, $b5, $b7, $b9, $bb, $bd, $bf 97 | DEFB $c1, $c3, $c5, $c7, $c9, $cb, $cd, $cf 98 | DEFB $d1, $d3, $d5, $d7, $d9, $db, $dd, $df 99 | DEFB $e1, $e3, $e5, $e7, $e9, $eb, $ed, $ef 100 | DEFB $f1, $f3, $f5, $f7, $f9, $fb, $fd, $ff 101 | 102 | BITTAB: DEFB $01, $02, $04, $08, $10, $20, $40, $80 103 | -------------------------------------------------------------------------------- /addtab.asm: -------------------------------------------------------------------------------- 1 | INCLUDE "align.asm" 2 | ; 2.25 kilobyte shift-and-round table for addition and subtraction 3 | ADDTAB: DEFB $80, $81, $81, $82, $82, $83, $83, $84 4 | DEFB $84, $85, $85, $86, $86, $87, $87, $88 5 | DEFB $88, $89, $89, $8a, $8a, $8b, $8b, $8c 6 | DEFB $8c, $8d, $8d, $8e, $8e, $8f, $8f, $90 7 | DEFB $90, $91, $91, $92, $92, $93, $93, $94 8 | DEFB $94, $95, $95, $96, $96, $97, $97, $98 9 | DEFB $98, $99, $99, $9a, $9a, $9b, $9b, $9c 10 | DEFB $9c, $9d, $9d, $9e, $9e, $9f, $9f, $a0 11 | DEFB $a0, $a1, $a1, $a2, $a2, $a3, $a3, $a4 12 | DEFB $a4, $a5, $a5, $a6, $a6, $a7, $a7, $a8 13 | DEFB $a8, $a9, $a9, $aa, $aa, $ab, $ab, $ac 14 | DEFB $ac, $ad, $ad, $ae, $ae, $af, $af, $b0 15 | DEFB $b0, $b1, $b1, $b2, $b2, $b3, $b3, $b4 16 | DEFB $b4, $b5, $b5, $b6, $b6, $b7, $b7, $b8 17 | DEFB $b8, $b9, $b9, $ba, $ba, $bb, $bb, $bc 18 | DEFB $bc, $bd, $bd, $be, $be, $bf, $bf, $c0 19 | DEFB $c0, $c1, $c1, $c2, $c2, $c3, $c3, $c4 20 | DEFB $c4, $c5, $c5, $c6, $c6, $c7, $c7, $c8 21 | DEFB $c8, $c9, $c9, $ca, $ca, $cb, $cb, $cc 22 | DEFB $cc, $cd, $cd, $ce, $ce, $cf, $cf, $d0 23 | DEFB $d0, $d1, $d1, $d2, $d2, $d3, $d3, $d4 24 | DEFB $d4, $d5, $d5, $d6, $d6, $d7, $d7, $d8 25 | DEFB $d8, $d9, $d9, $da, $da, $db, $db, $dc 26 | DEFB $dc, $dd, $dd, $de, $de, $df, $df, $e0 27 | DEFB $e0, $e1, $e1, $e2, $e2, $e3, $e3, $e4 28 | DEFB $e4, $e5, $e5, $e6, $e6, $e7, $e7, $e8 29 | DEFB $e8, $e9, $e9, $ea, $ea, $eb, $eb, $ec 30 | DEFB $ec, $ed, $ed, $ee, $ee, $ef, $ef, $f0 31 | DEFB $f0, $f1, $f1, $f2, $f2, $f3, $f3, $f4 32 | DEFB $f4, $f5, $f5, $f6, $f6, $f7, $f7, $f8 33 | DEFB $f8, $f9, $f9, $fa, $fa, $fb, $fb, $fc 34 | DEFB $fc, $fd, $fd, $fe, $fe, $ff, $ff, $00 35 | 36 | DEFB $40, $40, $41, $41, $41, $41, $42, $42 37 | DEFB $42, $42, $43, $43, $43, $43, $44, $44 38 | DEFB $44, $44, $45, $45, $45, $45, $46, $46 39 | DEFB $46, $46, $47, $47, $47, $47, $48, $48 40 | DEFB $48, $48, $49, $49, $49, $49, $4a, $4a 41 | DEFB $4a, $4a, $4b, $4b, $4b, $4b, $4c, $4c 42 | DEFB $4c, $4c, $4d, $4d, $4d, $4d, $4e, $4e 43 | DEFB $4e, $4e, $4f, $4f, $4f, $4f, $50, $50 44 | DEFB $50, $50, $51, $51, $51, $51, $52, $52 45 | DEFB $52, $52, $53, $53, $53, $53, $54, $54 46 | DEFB $54, $54, $55, $55, $55, $55, $56, $56 47 | DEFB $56, $56, $57, $57, $57, $57, $58, $58 48 | DEFB $58, $58, $59, $59, $59, $59, $5a, $5a 49 | DEFB $5a, $5a, $5b, $5b, $5b, $5b, $5c, $5c 50 | DEFB $5c, $5c, $5d, $5d, $5d, $5d, $5e, $5e 51 | DEFB $5e, $5e, $5f, $5f, $5f, $5f, $60, $60 52 | DEFB $60, $60, $61, $61, $61, $61, $62, $62 53 | DEFB $62, $62, $63, $63, $63, $63, $64, $64 54 | DEFB $64, $64, $65, $65, $65, $65, $66, $66 55 | DEFB $66, $66, $67, $67, $67, $67, $68, $68 56 | DEFB $68, $68, $69, $69, $69, $69, $6a, $6a 57 | DEFB $6a, $6a, $6b, $6b, $6b, $6b, $6c, $6c 58 | DEFB $6c, $6c, $6d, $6d, $6d, $6d, $6e, $6e 59 | DEFB $6e, $6e, $6f, $6f, $6f, $6f, $70, $70 60 | DEFB $70, $70, $71, $71, $71, $71, $72, $72 61 | DEFB $72, $72, $73, $73, $73, $73, $74, $74 62 | DEFB $74, $74, $75, $75, $75, $75, $76, $76 63 | DEFB $76, $76, $77, $77, $77, $77, $78, $78 64 | DEFB $78, $78, $79, $79, $79, $79, $7a, $7a 65 | DEFB $7a, $7a, $7b, $7b, $7b, $7b, $7c, $7c 66 | DEFB $7c, $7c, $7d, $7d, $7d, $7d, $7e, $7e 67 | DEFB $7e, $7e, $7f, $7f, $7f, $7f, $80, $80 68 | 69 | DEFB $20, $20, $20, $20, $21, $21, $21, $21 70 | DEFB $21, $21, $21, $21, $22, $22, $22, $22 71 | DEFB $22, $22, $22, $22, $23, $23, $23, $23 72 | DEFB $23, $23, $23, $23, $24, $24, $24, $24 73 | DEFB $24, $24, $24, $24, $25, $25, $25, $25 74 | DEFB $25, $25, $25, $25, $26, $26, $26, $26 75 | DEFB $26, $26, $26, $26, $27, $27, $27, $27 76 | DEFB $27, $27, $27, $27, $28, $28, $28, $28 77 | DEFB $28, $28, $28, $28, $29, $29, $29, $29 78 | DEFB $29, $29, $29, $29, $2a, $2a, $2a, $2a 79 | DEFB $2a, $2a, $2a, $2a, $2b, $2b, $2b, $2b 80 | DEFB $2b, $2b, $2b, $2b, $2c, $2c, $2c, $2c 81 | DEFB $2c, $2c, $2c, $2c, $2d, $2d, $2d, $2d 82 | DEFB $2d, $2d, $2d, $2d, $2e, $2e, $2e, $2e 83 | DEFB $2e, $2e, $2e, $2e, $2f, $2f, $2f, $2f 84 | DEFB $2f, $2f, $2f, $2f, $30, $30, $30, $30 85 | DEFB $30, $30, $30, $30, $31, $31, $31, $31 86 | DEFB $31, $31, $31, $31, $32, $32, $32, $32 87 | DEFB $32, $32, $32, $32, $33, $33, $33, $33 88 | DEFB $33, $33, $33, $33, $34, $34, $34, $34 89 | DEFB $34, $34, $34, $34, $35, $35, $35, $35 90 | DEFB $35, $35, $35, $35, $36, $36, $36, $36 91 | DEFB $36, $36, $36, $36, $37, $37, $37, $37 92 | DEFB $37, $37, $37, $37, $38, $38, $38, $38 93 | DEFB $38, $38, $38, $38, $39, $39, $39, $39 94 | DEFB $39, $39, $39, $39, $3a, $3a, $3a, $3a 95 | DEFB $3a, $3a, $3a, $3a, $3b, $3b, $3b, $3b 96 | DEFB $3b, $3b, $3b, $3b, $3c, $3c, $3c, $3c 97 | DEFB $3c, $3c, $3c, $3c, $3d, $3d, $3d, $3d 98 | DEFB $3d, $3d, $3d, $3d, $3e, $3e, $3e, $3e 99 | DEFB $3e, $3e, $3e, $3e, $3f, $3f, $3f, $3f 100 | DEFB $3f, $3f, $3f, $3f, $40, $40, $40, $40 101 | 102 | DEFB $10, $10, $10, $10, $10, $10, $10, $10 103 | DEFB $11, $11, $11, $11, $11, $11, $11, $11 104 | DEFB $11, $11, $11, $11, $11, $11, $11, $11 105 | DEFB $12, $12, $12, $12, $12, $12, $12, $12 106 | DEFB $12, $12, $12, $12, $12, $12, $12, $12 107 | DEFB $13, $13, $13, $13, $13, $13, $13, $13 108 | DEFB $13, $13, $13, $13, $13, $13, $13, $13 109 | DEFB $14, $14, $14, $14, $14, $14, $14, $14 110 | DEFB $14, $14, $14, $14, $14, $14, $14, $14 111 | DEFB $15, $15, $15, $15, $15, $15, $15, $15 112 | DEFB $15, $15, $15, $15, $15, $15, $15, $15 113 | DEFB $16, $16, $16, $16, $16, $16, $16, $16 114 | DEFB $16, $16, $16, $16, $16, $16, $16, $16 115 | DEFB $17, $17, $17, $17, $17, $17, $17, $17 116 | DEFB $17, $17, $17, $17, $17, $17, $17, $17 117 | DEFB $18, $18, $18, $18, $18, $18, $18, $18 118 | DEFB $18, $18, $18, $18, $18, $18, $18, $18 119 | DEFB $19, $19, $19, $19, $19, $19, $19, $19 120 | DEFB $19, $19, $19, $19, $19, $19, $19, $19 121 | DEFB $1a, $1a, $1a, $1a, $1a, $1a, $1a, $1a 122 | DEFB $1a, $1a, $1a, $1a, $1a, $1a, $1a, $1a 123 | DEFB $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b 124 | DEFB $1b, $1b, $1b, $1b, $1b, $1b, $1b, $1b 125 | DEFB $1c, $1c, $1c, $1c, $1c, $1c, $1c, $1c 126 | DEFB $1c, $1c, $1c, $1c, $1c, $1c, $1c, $1c 127 | DEFB $1d, $1d, $1d, $1d, $1d, $1d, $1d, $1d 128 | DEFB $1d, $1d, $1d, $1d, $1d, $1d, $1d, $1d 129 | DEFB $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e 130 | DEFB $1e, $1e, $1e, $1e, $1e, $1e, $1e, $1e 131 | DEFB $1f, $1f, $1f, $1f, $1f, $1f, $1f, $1f 132 | DEFB $1f, $1f, $1f, $1f, $1f, $1f, $1f, $1f 133 | DEFB $20, $20, $20, $20, $20, $20, $20, $20 134 | 135 | DEFB $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8 136 | DEFB $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8 137 | DEFB $ 9, $ 9, $ 9, $ 9, $ 9, $ 9, $ 9, $ 9 138 | DEFB $ 9, $ 9, $ 9, $ 9, $ 9, $ 9, $ 9, $ 9 139 | DEFB $ 9, $ 9, $ 9, $ 9, $ 9, $ 9, $ 9, $ 9 140 | DEFB $ 9, $ 9, $ 9, $ 9, $ 9, $ 9, $ 9, $ 9 141 | DEFB $ a, $ a, $ a, $ a, $ a, $ a, $ a, $ a 142 | DEFB $ a, $ a, $ a, $ a, $ a, $ a, $ a, $ a 143 | DEFB $ a, $ a, $ a, $ a, $ a, $ a, $ a, $ a 144 | DEFB $ a, $ a, $ a, $ a, $ a, $ a, $ a, $ a 145 | DEFB $ b, $ b, $ b, $ b, $ b, $ b, $ b, $ b 146 | DEFB $ b, $ b, $ b, $ b, $ b, $ b, $ b, $ b 147 | DEFB $ b, $ b, $ b, $ b, $ b, $ b, $ b, $ b 148 | DEFB $ b, $ b, $ b, $ b, $ b, $ b, $ b, $ b 149 | DEFB $ c, $ c, $ c, $ c, $ c, $ c, $ c, $ c 150 | DEFB $ c, $ c, $ c, $ c, $ c, $ c, $ c, $ c 151 | DEFB $ c, $ c, $ c, $ c, $ c, $ c, $ c, $ c 152 | DEFB $ c, $ c, $ c, $ c, $ c, $ c, $ c, $ c 153 | DEFB $ d, $ d, $ d, $ d, $ d, $ d, $ d, $ d 154 | DEFB $ d, $ d, $ d, $ d, $ d, $ d, $ d, $ d 155 | DEFB $ d, $ d, $ d, $ d, $ d, $ d, $ d, $ d 156 | DEFB $ d, $ d, $ d, $ d, $ d, $ d, $ d, $ d 157 | DEFB $ e, $ e, $ e, $ e, $ e, $ e, $ e, $ e 158 | DEFB $ e, $ e, $ e, $ e, $ e, $ e, $ e, $ e 159 | DEFB $ e, $ e, $ e, $ e, $ e, $ e, $ e, $ e 160 | DEFB $ e, $ e, $ e, $ e, $ e, $ e, $ e, $ e 161 | DEFB $ f, $ f, $ f, $ f, $ f, $ f, $ f, $ f 162 | DEFB $ f, $ f, $ f, $ f, $ f, $ f, $ f, $ f 163 | DEFB $ f, $ f, $ f, $ f, $ f, $ f, $ f, $ f 164 | DEFB $ f, $ f, $ f, $ f, $ f, $ f, $ f, $ f 165 | DEFB $10, $10, $10, $10, $10, $10, $10, $10 166 | DEFB $10, $10, $10, $10, $10, $10, $10, $10 167 | 168 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 169 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 170 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 171 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 172 | DEFB $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5 173 | DEFB $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5 174 | DEFB $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5 175 | DEFB $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5 176 | DEFB $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5 177 | DEFB $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5 178 | DEFB $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5 179 | DEFB $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5, $ 5 180 | DEFB $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6 181 | DEFB $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6 182 | DEFB $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6 183 | DEFB $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6 184 | DEFB $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6 185 | DEFB $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6 186 | DEFB $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6 187 | DEFB $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6, $ 6 188 | DEFB $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7 189 | DEFB $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7 190 | DEFB $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7 191 | DEFB $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7 192 | DEFB $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7 193 | DEFB $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7 194 | DEFB $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7 195 | DEFB $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7, $ 7 196 | DEFB $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8 197 | DEFB $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8 198 | DEFB $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8 199 | DEFB $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8, $ 8 200 | 201 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 202 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 203 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 204 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 205 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 206 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 207 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 208 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 209 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 210 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 211 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 212 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 213 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 214 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 215 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 216 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 217 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 218 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 219 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 220 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 221 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 222 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 223 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 224 | DEFB $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3, $ 3 225 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 226 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 227 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 228 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 229 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 230 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 231 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 232 | DEFB $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4, $ 4 233 | 234 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 235 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 236 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 237 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 238 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 239 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 240 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 241 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 242 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 243 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 244 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 245 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 246 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 247 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 248 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 249 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 250 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 251 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 252 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 253 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 254 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 255 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 256 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 257 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 258 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 259 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 260 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 261 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 262 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 263 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 264 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 265 | DEFB $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2, $ 2 266 | 267 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 268 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 269 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 270 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 271 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 272 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 273 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 274 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 275 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 276 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 277 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 278 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 279 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 280 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 281 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 282 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 283 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 284 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 285 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 286 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 287 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 288 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 289 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 290 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 291 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 292 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 293 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 294 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 295 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 296 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 297 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 298 | DEFB $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1, $ 1 299 | --------------------------------------------------------------------------------