JohnPCAE Posted January 13, 2022 Author Share Posted January 13, 2022 (edited) Still turning the crank on the software...I've tested most of the boundary conditions for sprite exclusion and they're working, though I can think of some more tests I can run. I've also started more testing of the experimental emulator. So far it's passing my speed tests, which is a good thing. I've only tested the actual functionality of a few opcodes so far, but I've also done a major reorganization of my extended opcodes to make them more standardized. I'm putting together a reference that I can post here, but keep in mind that it's subject to change. INSTRUCTION OPCODE LOGIC NOTES ----------------------------------------------------------------------------------------------------- HLT 000000 0000 000 000 halt cpu SDBD 000000 0000 000 001 sdbd_mode = true EIS 000000 0000 000 010 enable_interrupts DIS 000000 0000 000 011 disable_interrupts J (RB,)DEST(,e/d) 000000 0000 000 100 j/jsr [rb] ena/dis interrupts TCI 000000 0000 000 101 CLRC 000000 0000 000 110 C = 0 SETC 000000 0000 000 111 C = 1 INCR RD 000000 0000 001 ddd RD++ DECR RD 000000 0000 010 ddd RD-- COMR RD 000000 0000 011 ddd RD = ~RD NEGR RD 000000 0000 100 ddd RD = -RD ADCR RD 000000 0000 101 ddd RD += C GSWD RR 000000 0000 110 0rr NOP 000000 0000 110 10m 6 SIN 000000 0000 110 11m 6 RSWD RS 000000 0000 111 sss SHX type,RR(,2) 000000 0001 hhh mrr RR shx= 1/2 MOVR RS,RD 000000 0010 sss ddd RD = RS ADDR RS,RD 000000 0011 sss ddd RD += RS SUBR RS,RD 000000 0100 sss ddd RD -= RS CMPR RS,RD 000000 0101 sss ddd set_flags(RD - RS) ANDR RS,RD 000000 0110 sss ddd RD &= RS XORR RS,RD 000000 0111 sss ddd RD ^= RS B DISP(,E) 000000 1000 ze cccc if cond: R7+=disp/-=(disp+1) MVO RS,dst 000000 1001 xxx sss dst = RS 1 MVI src,RD 000000 1010 xxx ddd RD = src 1 ADD src,RD 000000 1011 xxx ddd RD += src 1 SUB src,RD 000000 1100 xxx ddd RD -= src 1 CMP src,RS 000000 1101 xxx sss set_flags(RD - src) 1 AND src,RD 000000 1110 xxx ddd RD &= src 1 XOR src,RD 000000 1111 xxx ddd RD ^= src 1 OR@ RM,RD 000001 0000 mmm ddd RD |= [RM] 2 ANDN@ RM,RD 000001 0001 mmm ddd RD &= ~[RM] 2 XORN@ RM,RD 000001 0010 mmm ddd RD ^= ~[RM] 2 ORN@ RM,RD 000001 0011 mmm ddd RD |= ~[RM] 2 NAND@ RM,RD 000001 0100 mmm ddd RD = ~(RD & [RM]) 2 XNOR@ RM,RD 000001 0101 mmm ddd RD = ~(RD ^ [RM]) 2 NOR@ RM,RD 000001 0110 mmm ddd RD = ~(RD | [RM]) 2 TST@ RM,RD 000001 0111 mmm ddd set_flags(RD & [RM]) 2 XCHG@ RM,RD 000001 1000 mmm ddd RD <--> [RM] 2 ADC@ RM,RD 000001 1010 mmm ddd RD += [RM] + C 2 SBC@ RM,RD 000001 1011 mmm ddd RD -= ([RM] + ~C) 2 SLL@ RM,RD 000001 1100 mmm ddd RD <<= [RM] 2 SLR@ RM,RD 000001 1101 mmm ddd RD >>= [RM] 2 SAR@ RM,RD 000001 1110 mmm ddd RD >>>= [RM] 2 ROL@ RM,RD 000001 1111 mmm ddd RD rol= [RM] 2 ROR@ RM,RD 000010 0000 mmm ddd RD ror= [RM] 2 MUL@ RM,RD 000010 0001 mmm ddd RD *= [RM] 2, 4 IMUL@ RM,RD 000010 0010 mmm ddd RD *= [RM] 2, 5 DIV@ RM,RD 000010 0011 mmm ddd RD /= [RM] 2, 4 IDIV@ RM,RD 000010 0100 mmm ddd RD /= [RM] 2, 5 REM@ RM,RD 000010 0100 mmm ddd RD = RD % [RM] 2, 4 IREM@ RM,RD 000010 0110 mmm ddd RD = RD % [RM] 2, 5 MAX@ RM,RD 000010 0111 mmm ddd RD = max(RD,[RM]) 2, 4 IMAX@ RM,RD 000010 1000 mmm ddd RD = max(RD,[RM]) 2, 5 MIN@ RM,RD 000010 1010 mmm ddd RD = min(RD,[RM]) 2, 4 IMIN@ RM,RD 000010 1011 mmm ddd RD = min(RD,[RM]) 2, 5 MVOC@ RS,dst 000010 1100 xxx sss dst = ~RD 1 MVON@ RS,dst 000010 1101 xxx sss dst = -RD 1 MVI@ src+RD,RD 000010 1110 xxx ddd RD = [src + RD] 1, 3 MVI@ src+2*RD,RD 000010 1111 xxx ddd RD = [src + 2 * RD] 1, 3 ORR RS,RD 000011 0000 sss ddd RD |= RS ANDNR RS,RD 000011 0001 sss ddd RD &= ~RS XORNR RS,RD 000011 0010 sss ddd RD ^= ~RS ORNR RS,RD 000011 0011 sss ddd RD |= ~RS NANDR RS,RD 000011 0100 sss ddd RD = ~(RD & RS) XNORR RS,RD 000011 0101 sss ddd RD = ~(RD ^ RS) NORR RS,RD 000011 0110 sss ddd RD = ~(RD | RS) INCLR RD 000011 0111 ddd ddd lowbyte(RD)++ 7 TSTR RA,RB 000011 0111 aaa bbb set_flags(RA & RB) 8 DECLR RD 000011 1000 ddd ddd lowbyte(RD)-- 7 XCHGR RA,RB 000011 1000 aaa bbb RA <--> RB 8 ADCR RS,RD 000011 1010 sss ddd RD += RS + C SBCR RS,RD 000011 1011 sss ddd RD -= (RS + ~C) SLLR RD,RA 000011 1100 ddd aaa RD <<= RA SLRR RD,RA 000011 1101 ddd aaa RD >>= RA SARR RD,RA 000011 1110 ddd aaa RD >>>= RA ROLR RD,RA 000011 1111 ddd aaa RD rol= RA RORR RD,RA 000100 0000 ddd aaa RD ror= RA MULR RD,RA 000100 0001 sss ddd RD *= RS 4 IMULR RD,RA 000100 0010 sss ddd RD *= RS 5 DIVR RD,RA 000100 0011 sss ddd RD /= RS 4 IDIVR RD,RA 000100 0100 sss ddd RD /= RS 5 REMR RD,RA 000100 0101 sss ddd RD = RD % RS 4 IDEMR RD,RA 000100 0110 sss ddd RD = RD % RS 5 MAXR RS,RD 000100 0111 sss ddd RD = max(RD,RS) 4 IMAXR RS,RD 000100 1000 sss ddd RD = max(RD,RS) 5 MINR RS,RD 000100 1010 sss ddd RD = min(RD,RS) 4 IMINR RS,RD 000011 1011 sss ddd RD = min(RD,RS) 5 FPIMULR RS,RD 000100 1100 sss ddd RD *= RS 5, 9 FPIDIVR RS,RD 000100 1101 sss ddd RD /= RS 5, 9 FPIREMR RS,RD 000100 1110 sss ddd RD = RD % RS 5, 9 MULRW RA,RB 000100 1111 aaa bbb R1:R0 = RA * RB 4, 10 IMULRW RA,RB 000101 0000 aaa bbb R1:R0 = RA * RB 5, 10 DIVRW RV,RD 000101 0001 aaa bbb R0 = RD / RV; R1 = RD % RV 4 IDIVRW RV,RD 000101 0010 aaa bbb R0 = RD / RV; R1 = RD % RV 5 UNPR RB,RA 000101 0011 bbb aaa RB = RA >> 8; RA &= 0xFF 11 PCKR RS,RD 000101 0100 sss ddd RA = (RA & 0xFF) | (RB << 8) 12 SBCR RD 000101 0101 000 ddd RD -= C B2AH RD 000101 0101 001 ddd RD = ascii_hex(RD) 13 SHLD RD:R0,a 000101 0101 dd aaaa RD = (RD << a) | (R0 >> (16-a)) 14 AH2B RD 000101 0110 000 ddd RD = value_of(RD) 15 DIV5 RD 000101 0110 001 ddd RD /= 5 4 SHRD RS:R0,a 000101 0110 ss aaaa R0 = (R0 >> a) | (RS >> (16-a)) 16 MVID@ RM+disp16,RD 000101 0111 mmm ddd RD = [RM + disp16] 17 MVOD@ RM+disp16,RS 000101 1000 mmm sss [RM + disp16] = RS 17 VMOV@@ RMS,RMD 000101 1010 mmm ddd v3d[RMD] = v3d[RMS] 18 LOOP RD,dest 000101 1010 ddd ddd RD--; R7 += disp16 if RD != 0 19 BA/BNBE dest 000101 1010 110 110 R7 += disp16 if ((C or Z) = 0) BNA/BBE dest 000101 1010 111 111 R7 += disp16 if ((C or Z) = 1) DADD@@ RMS,RMD 000101 1011 sss ddd [RMD] += [RMS] 20 DSUB@@ RMS,RMD 000101 1100 sss ddd [RMD] -= [RMS] 20 CL0R RD 000101 1101 000 ddd RD = count_leading_zeroes(RD) 21 CL1R RD 000101 1101 001 ddd RD = count_leading_ones(RD) 22 CT0R RD 000101 1101 010 ddd RD = count_trailing_zeroes(RD) 23 CT1R RD 000101 1101 011 ddd RD = count_trailing_ones(RD) 24 SUBGER0 RD 000101 1101 100 ddd if RD >= R0, RD -= R0 4 DIV3 RD 000101 1101 101 ddd RD /= 3 4 DIV100 RD 000101 1101 110 ddd RD /= 100 4 DUPLR RD 000101 1101 111 ddd RD = (RD & 0xFF) | (RD << 8) FPMULD@@ RMS,RMD 000101 1110 sss ddd [RMD] *= [RMS] 4, 20 IFPMULD@@ RMS,RMD 000101 1111 sss ddd [RMD] *= [RMS] 5, 20 MVO@ R0,RS 000110 0000 000 sss [R0] = RS MVI@ R0,RD 000110 0000 001 ddd RD = [R0] ADD@ R0,RD 000110 0000 010 ddd RD += [R0] SUB@ R0,RD 000110 0000 011 ddd RD -= [R0] CMP@ R0,RD 000110 0000 100 ddd set_flags(RD - [R0]) AND@ R0,RD 000110 0000 101 ddd RD &= [R0] XOR@ R0,RD 000110 0000 110 ddd RD ^= [R0] MVOC@ R0,RS 000110 0000 111 sss [R0] = ~RS MVON@ R0,RS 000110 0001 000 sss [R0] = -RS MVI@ R0+RD,RD 000110 0001 001 ddd RD = [R0 + RD] MVI@ R0+2*RD,RD 000110 0001 010 ddd RD = [R0 + 2 * RD] ABSR RD 000110 0001 011 ddd RD = |RD| NABSR RD 000110 0001 100 ddd RD = -|RD| POW2R RD 000110 0001 101 ddd RD = 1 << RD 25 SGNR RD 001010 0001 110 ddd RD = sign(RD) 5, 26 ABSD@ RMD 000110 0001 111 ddd [RMD] = |[RMD]| 5, 20 OR ADDR, RD 000110 0010 000 ddd RD |= [ADDR] 27 ANDN ADDR, RD 000110 0010 001 ddd RD &= ~[ADDR] 27 XORN ADDR, RD 000110 0010 010 ddd RD ^= ~[ADDR] 27 ORN ADDR, RD 000110 0010 011 ddd RD |= ~[ADDR] 27 NAND ADDR, RD 000110 0010 100 ddd RD = ~(RD & [ADDR]) 27 XNOR ADDR, RD 000110 0010 101 ddd RD = ~(RD ^ [ADDR]) 27 NOR ADDR, RD 000110 0010 110 ddd RD = ~(RD | [ADDR]) 27 TST ADDR, RD 000110 0010 111 ddd set_flags(RD & [ADDR]) 27 XCHG ADDR, RD 000110 0011 000 ddd RD <--> [ADDR] 27 ADC ADDR, RD 000110 0011 001 ddd RD += [ADDR] + C 27 SBC ADDR, RD 000110 0011 010 ddd RD -= ([ADDR] + ~C) 27 SLL RD,ADDR 000110 0011 011 ddd RD <<= [ADDR] 27 SLR RD,ADDR 000110 0011 100 ddd RD >>= [ADDR] 27 SAR RD,ADDR 000110 0011 101 ddd RD >>>= [ADDR] 27 ROL RD,ADDR 000110 0011 110 ddd RD rol= [ADDR] 27 ROR RD,ADDR 000110 0011 111 ddd RD ror= [ADDR] 27 MUL ADDR,RD 000110 0100 000 ddd RD *= [ADDR] 4, 27 IMUL ADDR,RD 000110 0100 001 ddd RD *= [ADDR] 5, 27 DIV ADDR,RD 000110 0100 010 ddd RD /= [ADDR] 4, 27 IDIV ADDR,RD 000110 0100 011 ddd RD /= [ADDR] 5, 27 REM ADDR,RD 000110 0100 100 ddd RD = RD % [ADDR] 4, 27 IREM ADDR,RD 000110 0100 101 ddd RD = RD % [ADDR] 5, 27 FPMULD@@ ADDR,RMD 000110 0100 110 ddd [RMD] *= [ADDR] 4, 27, 28 IFPMULD@@ ADDR,RMD 000110 0100 111 ddd [RMD] *= [ADDR] 5, 27, 28 VMOV@@ ADDR,RMD 000110 0101 000 ddd v3d[RMD] = v3d[ADDR] 18, 27 DADD@@ ADDR,RMD 000110 0101 001 ddd [RMD] += [ADDR] 20, 27 DSUB@@ ADDR,RMD 000110 0101 010 ddd [RMD] -= [ADDR] 20, 27 LOOPE RD,dest 000110 0101 011 ddd RD--; R7 += disp16 if RD!=0 & Z=1 19 BREVR R0 000110 0101 011 110 R0 = bit_reverse(R0) BREVR R1 000110 0101 011 111 R1 = bit_reverse(R1) LOOPNE RD,dest 000110 0101 100 ddd RD--; R7 += disp16 if RD!=0 & Z=0 19 BREVR R2 000110 0101 100 110 R2 = bit_reverse(R2) BREVR R3 000110 0101 100 111 R3 = bit_reverse(R3) LOOPS RD,dest 000110 0101 101 ddd RD--; R7 += disp16 if RD!=0 & S=1 19 BREVR R4 000110 0101 101 110 R4 = bit_reverse(R4) BREVR R5 000110 0101 101 111 R5 = bit_reverse(R5) LOOPNS RD,dest 000110 0101 110 ddd RD--; R7 += disp16 if RD!=0 & S=0 19 COMC 000110 0101 110 110 C = !C ENAEXT 000110 0101 110 111 enable_extended_opcodes 29 DBTR RD 000110 0101 111 ddd RD = double_bits(RD) 30 REV4R RD 000110 0110 000 ddd RD = RD[3:0][7:4][11:8][15:12] 31 REV4HR RD 000110 0110 001 ddd RD = RD[11:8][15:12][3:0][7:4] 32 FPINVD@ RMD 000110 0110 010 ddd [RMD] = 1/[RMD] 5, 28 MVOIA DATA, ADDR 000110 0110 011 000 [ADDR] = DATA 33 ADDIA DATA, ADDR 000110 0110 011 001 [ADDR] += DATA 33 SUBIA DATA, ADDR 000110 0110 011 010 [ADDR] -= DATA 33 CMPIA DATA, ADDR 000110 0110 011 011 set_flags([ADDR] - DATA) 33 ANDIA DATA, ADDR 000110 0110 011 100 [ADDR] &= DATA 33 XORIA DATA, ADDR 000110 0110 011 101 [ADDR] ^= DATA 33 ORIA DATA, ADDR 000110 0110 011 110 [ADDR] |= DATA 33 ANDNIA DATA, ADDR 000110 0110 011 111 [ADDR] &= ~DATA 33 XORNIA DATA, ADDR 000110 0110 100 000 [ADDR] ^= ~DATA 33 ORNIA DATA, ADDR 000110 0110 100 001 [ADDR] |= ~DATA 33 NANDIA DATA, ADDR 000110 0110 100 010 [ADDR] = ~([ADDR] & DATA) 33 XNORIA DATA, ADDR 000110 0110 100 011 [ADDR] = ~([ADDR] ^ DATA) 33 NORIA DATA, ADDR 000110 0110 100 100 [ADDR] = ~([ADDR] | DATA) 33 TSTIA DATA, ADDR 000110 0110 100 101 set_flags([ADDR] & DATA) 33 XCHGIA DATA, ADDR 000110 0110 100 110 [ADDR] <--> DATA 33, 34 ADCIA DATA, ADDR 000110 0110 100 111 [ADDR] += DATA + C 33 SBCIA DATA, ADDR 000110 0110 101 000 [ADDR] -= (DATA + ~C) 33 SLLIA DATA, ADDR 000110 0110 101 001 [ADDR] <<= DATA 33 SLRIA DATA, ADDR 000110 0110 101 010 [ADDR] >>= DATA 33 SARIA DATA, ADDR 000110 0110 101 011 [ADDR] >>>= DATA 33 ROLIA DATA, ADDR 000110 0110 101 100 [ADDR] rol= DATA 33 RORIA DATA, ADDR 000110 0110 101 101 [ADDR] ror= DATA 33 MULIA DATA, ADDR 000110 0110 101 110 [ADDR] *= DATA 4, 33 IMULIA DATA, ADDR 000110 0110 101 111 [ADDR] *= DATA 5, 33 DIVIA DATA, ADDR 000110 0110 110 000 [ADDR] /= DATA 4, 33 IDIVIA DATA, ADDR 000110 0110 110 001 [ADDR] /= DATA 5, 33 REMIA DATA, ADDR 000110 0110 110 010 [ADDR] = [ADDR] % DATA 4, 33 IREMIA DATA, ADDR 000110 0110 110 011 [ADDR] = [ADDR] % DATA 5, 33 SWAP RD 000110 0110 110 1dd swap_bytes(RD) 35 STCP RD 000110 0110 111 ddd C = parity(RD) 36 DISEXT 000110 0110 111 111 disable_extended_opcodes 29 POW10RL RD 000110 0111 000 ddd RD = low_word(pow(10,RD)) 37 POW10RH RD 000110 0111 001 ddd RD = high_word(pow(10,RD)) 37 FPISQRTR RD 000110 0111 010 ddd RD = 1 / sqrt(RD) 4, 9, 38 Notes ----- 1. If xxx is 0, uses direct addressing instead (@R0 is not supported). 2. @R0 is supported. Direct addressing is handled by a different opcode. 3. Src is not altered. Auto-increment for SDBD purposes arises from RD (Src is the base address, RD is the index address). 4. Operands are treated as unsigned. 5. Operands are treated as signed. 6. m should have no effect 7. Changes the low byte only, leaving the high byte unaltered. 8. aaa is always different from bbb 9. Operands are treated as 16-bit fixed-point numbers in 8.8 format. 10. Produces a 32-bit result with the high word placed in R1 and the low word placed in R0. 11. Unpacks the two bytes in RA into RA and RB. 12. Packs the low bytes of RA and RB into RA. 13. RD <-- hexadecimal ASCII representation of the low byte of RD (e.g. 0x000A --> 3041 "0A") 14. Shifts bits from R0 into RD. R0 is unaltered. RD may be in the range R1..R3. 15. RD = binary value (0..255) of hexadecimal ASCII characters stored in RD. Invalid characters in a byte result in that byte being interpreted as 0 (e.g. 3041 --> 0x0A, 2F41 --> 0x0A). Ignores case. 16. Shifts bits from RS into R0. RS is unaltered. C = low bit of R0 shifted out if a > 0. RS may be in the range R1..R3. 17. Does ***not*** change RM if mmm>3. Supports SDBD. 18. Copies a 3-vector from [Src] to [RMD]. Each vector component is 32 bits, for a total copy of 6 words. 19. ddd < 6 20. Operands are 32 bits in size. 21. RD = number of consecutive 0 bits in RD starting at the MSB 22. RD = number of consecutive 1 bits in RD starting at the MSB 23. RD = number of consecutive 0 bits in RD starting at the LSB 24. RD = number of consecutive 1 bits in RD starting at the LSB 25. If RD > 15, result is 0. 26. Result is either -1, 0, or 1. 27. Direct addressing mode version. 28. Operands are treated as 32-bit fixed-point values in 16.16 format. 29. No effect in the emulator (extended opcodes are always active). Reserved for a physical CPU. 30. RD = doubled bits of low byte of RD (e.g. 0x0011 --> 0x0303) 31. Reverses the order of the 4-bit nibbles in RD (e.g. 0x0123 --> 0x3120). 32. Reverses the order of the 4-bit nibbles in each byte of RD (e.g. 0x0123 --> 0x1032). 33. Three-word instruction: the second word is an address and the third word is an immediate value. SDBD is not supported. 34. If running from ROM, net effect is [ADDR] = DATA. 35. RD is indexed by dd + 4, i.e. RD is in the range R4..R7. 36. ddd <> 7. If RD contains an odd number of 1 bits, C = 1, else C = 0 (sets carry as RD parity) 37. If RD > 9, the result is 0. 38. Uses fast-inverse-square-root approximation algorithm with one iteration. Edited January 13, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 15, 2022 Author Share Posted January 15, 2022 (edited) Below is the final specification for emulated instructions in the software. I've tested only a handful, so there's some testing ahead. I might not wait to complete that before making everything public though since new software is easy to drop into the Pico. Going forward, I have to build the final versions of the hardware design to verify them, and then it should be time to make everything public. ========================================================================== OVERLAY VIDEO EXTENDED INSTRUCTION SET ========================================================================== INSTRUCTION OPCODE LOGIC NOTES ----------------------------------------------------------------------------------------------------- HLT 000000 0000 000 000 halt cpu SDBD 000000 0000 000 001 sdbd_mode = true EIS 000000 0000 000 010 enable_interrupts DIS 000000 0000 000 011 disable_interrupts J (RB,)DEST(,e/d) 000000 0000 000 100 j/jsr [rb] ena/dis interrupts TCI 000000 0000 000 101 CLRC 000000 0000 000 110 C = 0 SETC 000000 0000 000 111 C = 1 INCR RD 000000 0000 001 ddd RD++ DECR RD 000000 0000 010 ddd RD-- COMR RD 000000 0000 011 ddd RD = ~RD NEGR RD 000000 0000 100 ddd RD = -RD ADCR RD 000000 0000 101 ddd RD += C GSWD RR 000000 0000 110 0rr NOP 000000 0000 110 10m 6 SIN 000000 0000 110 11m 6 RSWD RS 000000 0000 111 sss SHX type,RR(,2) 000000 0001 hhh mrr RR shx= 1/2 MOVR RS,RD 000000 0010 sss ddd RD = RS ADDR RS,RD 000000 0011 sss ddd RD += RS SUBR RS,RD 000000 0100 sss ddd RD -= RS CMPR RS,RD 000000 0101 sss ddd set_flags(RD - RS) ANDR RS,RD 000000 0110 sss ddd RD &= RS XORR RS,RD 000000 0111 sss ddd RD ^= RS B DISP(,E) 000000 1000 ze cccc if cond: R7+=disp/-=(disp+1) MVO RS,dst 000000 1001 xxx sss dst = RS 1 MVI src,RD 000000 1010 xxx ddd RD = src 1 ADD src,RD 000000 1011 xxx ddd RD += src 1 SUB src,RD 000000 1100 xxx ddd RD -= src 1 CMP src,RS 000000 1101 xxx sss set_flags(RD - src) 1 AND src,RD 000000 1110 xxx ddd RD &= src 1 XOR src,RD 000000 1111 xxx ddd RD ^= src 1 OR@ RM,RD 000001 0000 mmm ddd RD |= [RM] 2 ANDN@ RM,RD 000001 0001 mmm ddd RD &= ~[RM] 2 XORN@ RM,RD 000001 0010 mmm ddd RD ^= ~[RM] 2 ORN@ RM,RD 000001 0011 mmm ddd RD |= ~[RM] 2 NAND@ RM,RD 000001 0100 mmm ddd RD = ~(RD & [RM]) 2 XNOR@ RM,RD 000001 0101 mmm ddd RD = ~(RD ^ [RM]) 2 NOR@ RM,RD 000001 0110 mmm ddd RD = ~(RD | [RM]) 2 TST@ RM,RD 000001 0111 mmm ddd set_flags(RD & [RM]) 2 XCHG@ RM,RD 000001 1000 mmm ddd RD <--> [RM] 2 ADC@ RM,RD 000001 1010 mmm ddd RD += [RM] + C 2 SBC@ RM,RD 000001 1011 mmm ddd RD -= ([RM] + ~C) 2 SLL@ RM,RD 000001 1100 mmm ddd RD <<= [RM] 2 SLR@ RM,RD 000001 1101 mmm ddd RD >>= [RM] 2 SAR@ RM,RD 000001 1110 mmm ddd RD >>>= [RM] 2 ROL@ RM,RD 000001 1111 mmm ddd RD rol= [RM] 2 ROR@ RM,RD 000010 0000 mmm ddd RD ror= [RM] 2 MUL@ RM,RD 000010 0001 mmm ddd RD *= [RM] 2, 4 IMUL@ RM,RD 000010 0010 mmm ddd RD *= [RM] 2, 5 DIV@ RM,RD 000010 0011 mmm ddd RD /= [RM] 2, 4 IDIV@ RM,RD 000010 0100 mmm ddd RD /= [RM] 2, 5 REM@ RM,RD 000010 0100 mmm ddd RD = RD % [RM] 2, 4 IREM@ RM,RD 000010 0110 mmm ddd RD = RD % [RM] 2, 5 MAX@ RM,RD 000010 0111 mmm ddd RD = max(RD,[RM]) 2, 4 IMAX@ RM,RD 000010 1000 mmm ddd RD = max(RD,[RM]) 2, 5 MIN@ RM,RD 000010 1010 mmm ddd RD = min(RD,[RM]) 2, 4 IMIN@ RM,RD 000010 1011 mmm ddd RD = min(RD,[RM]) 2, 5 MVOC@ RS,dst 000010 1100 xxx sss dst = ~RD 1 MVON@ RS,dst 000010 1101 xxx sss dst = -RD 1 MVI@ src+RD,RD 000010 1110 xxx ddd RD = [src + RD] 1, 3 MVI@ src+2*RD,RD 000010 1111 xxx ddd RD = [src + 2 * RD] 1, 3 ORR RS,RD 000011 0000 sss ddd RD |= RS ANDNR RS,RD 000011 0001 sss ddd RD &= ~RS XORNR RS,RD 000011 0010 sss ddd RD ^= ~RS ORNR RS,RD 000011 0011 sss ddd RD |= ~RS NANDR RS,RD 000011 0100 sss ddd RD = ~(RD & RS) XNORR RS,RD 000011 0101 sss ddd RD = ~(RD ^ RS) NORR RS,RD 000011 0110 sss ddd RD = ~(RD | RS) INCLR RD 000011 0111 ddd ddd lowbyte(RD)++ 7 TSTR RA,RB 000011 0111 aaa bbb set_flags(RA & RB) 8 DECLR RD 000011 1000 ddd ddd lowbyte(RD)-- 7 XCHGR RA,RB 000011 1000 aaa bbb RA <--> RB 8 ADCR RS,RD 000011 1010 sss ddd RD += RS + C SBCR RS,RD 000011 1011 sss ddd RD -= (RS + ~C) SLLR RD,RA 000011 1100 ddd aaa RD <<= RA SLRR RD,RA 000011 1101 ddd aaa RD >>= RA SARR RD,RA 000011 1110 ddd aaa RD >>>= RA ROLR RD,RA 000011 1111 ddd aaa RD rol= RA RORR RD,RA 000100 0000 ddd aaa RD ror= RA MULR RD,RA 000100 0001 sss ddd RD *= RS 4 IMULR RD,RA 000100 0010 sss ddd RD *= RS 5 DIVR RD,RA 000100 0011 sss ddd RD /= RS 4 IDIVR RD,RA 000100 0100 sss ddd RD /= RS 5 REMR RD,RA 000100 0101 sss ddd RD = RD % RS 4 IDEMR RD,RA 000100 0110 sss ddd RD = RD % RS 5 MAXR RS,RD 000100 0111 sss ddd RD = max(RD,RS) 4 IMAXR RS,RD 000100 1000 sss ddd RD = max(RD,RS) 5 MINR RS,RD 000100 1010 sss ddd RD = min(RD,RS) 4 IMINR RS,RD 000011 1011 sss ddd RD = min(RD,RS) 5 FPIMULR RS,RD 000100 1100 sss ddd RD *= RS 5, 9 FPIDIVR RS,RD 000100 1101 sss ddd RD /= RS 5, 9 FPIREMR RS,RD 000100 1110 sss ddd RD = RD % RS 5, 9 MULRW RA,RB 000100 1111 aaa bbb R1:R0 = RA * RB 4, 10 IMULRW RA,RB 000101 0000 aaa bbb R1:R0 = RA * RB 5, 10 DIVRW RV,RD 000101 0001 aaa bbb R0 = RD / RV; R1 = RD % RV 4 IDIVRW RV,RD 000101 0010 aaa bbb R0 = RD / RV; R1 = RD % RV 5 UNPR RB,RA 000101 0011 bbb aaa RB = RA >> 8; RA &= 0xFF 11 PCKR RS,RD 000101 0100 sss ddd RA = (RA & 0xFF) | (RB << 8) 12 SBCR RD 000101 0101 000 ddd RD -= C B2AH RD 000101 0101 001 ddd RD = ascii_hex(RD) 13 SHLD RD:R0,a 000101 0101 dd aaaa RD = (RD << a) | (R0 >> (16-a)) 14 AH2B RD 000101 0110 000 ddd RD = value_of(RD) 15 DIV5 RD 000101 0110 001 ddd RD /= 5 4 SHRD RS:R0,a 000101 0110 ss aaaa R0 = (R0 >> a) | (RS >> (16-a)) 16 MVID@ RM+disp16,RD 000101 0111 mmm ddd RD = [RM + disp16] 17 MVOD@ RM+disp16,RS 000101 1000 mmm sss [RM + disp16] = RS 17 VMOV@@ RMS,RMD 000101 1010 mmm ddd v3d[RMD] = v3d[RMS] 18 LOOP RD,dest 000101 1010 ddd ddd RD--; R7 += disp16 if RD != 0 19 BA/BNBE dest 000101 1010 110 110 R7 += disp16 if (C = 1) and (Z = 0) BNA/BBE dest 000101 1010 111 111 R7 += disp16 if (C = 0) or (Z = 1) DADD@@ RMS,RMD 000101 1011 sss ddd [RMD] += [RMS] 20 DSUB@@ RMS,RMD 000101 1100 sss ddd [RMD] -= [RMS] 20 CL0R RD 000101 1101 000 ddd RD = count_leading_zeroes(RD) 21 CL1R RD 000101 1101 001 ddd RD = count_leading_ones(RD) 22 CT0R RD 000101 1101 010 ddd RD = count_trailing_zeroes(RD) 23 CT1R RD 000101 1101 011 ddd RD = count_trailing_ones(RD) 24 SUBGER0 RD 000101 1101 100 ddd if RD >= R0, RD -= R0 4 DIV3 RD 000101 1101 101 ddd RD /= 3 4 DIV100 RD 000101 1101 110 ddd RD /= 100 4 DUPLR RD 000101 1101 111 ddd RD = (RD & 0xFF) | (RD << 8) FPMULD@@ RMS,RMD 000101 1110 sss ddd [RMD] *= [RMS] 4, 20 FPIMULD@@ RMS,RMD 000101 1111 sss ddd [RMD] *= [RMS] 5, 20 MVO@ R0,RS 000110 0000 000 sss [R0] = RS MVI@ R0,RD 000110 0000 001 ddd RD = [R0] ADD@ R0,RD 000110 0000 010 ddd RD += [R0] SUB@ R0,RD 000110 0000 011 ddd RD -= [R0] CMP@ R0,RD 000110 0000 100 ddd set_flags(RD - [R0]) AND@ R0,RD 000110 0000 101 ddd RD &= [R0] XOR@ R0,RD 000110 0000 110 ddd RD ^= [R0] MVOC@ R0,RS 000110 0000 111 sss [R0] = ~RS MVON@ R0,RS 000110 0001 000 sss [R0] = -RS MVI@ R0+RD,RD 000110 0001 001 ddd RD = [R0 + RD] MVI@ R0+2*RD,RD 000110 0001 010 ddd RD = [R0 + 2 * RD] ABSR RD 000110 0001 011 ddd RD = |RD| NABSR RD 000110 0001 100 ddd RD = -|RD| POW2R RD 000110 0001 101 ddd RD = 1 << RD 25 SGNR RD 001010 0001 110 ddd RD = sign(RD) 5, 26 ABSD@ RMD 000110 0001 111 ddd [RMD] = |[RMD]| 5, 20 OR ADDR, RD 000110 0010 000 ddd RD |= [ADDR] 27 ANDN ADDR, RD 000110 0010 001 ddd RD &= ~[ADDR] 27 XORN ADDR, RD 000110 0010 010 ddd RD ^= ~[ADDR] 27 ORN ADDR, RD 000110 0010 011 ddd RD |= ~[ADDR] 27 NAND ADDR, RD 000110 0010 100 ddd RD = ~(RD & [ADDR]) 27 XNOR ADDR, RD 000110 0010 101 ddd RD = ~(RD ^ [ADDR]) 27 NOR ADDR, RD 000110 0010 110 ddd RD = ~(RD | [ADDR]) 27 TST ADDR, RD 000110 0010 111 ddd set_flags(RD & [ADDR]) 27 XCHG ADDR, RD 000110 0011 000 ddd RD <--> [ADDR] 27 ADC ADDR, RD 000110 0011 001 ddd RD += [ADDR] + C 27 SBC ADDR, RD 000110 0011 010 ddd RD -= ([ADDR] + ~C) 27 SLL RD,ADDR 000110 0011 011 ddd RD <<= [ADDR] 27 SLR RD,ADDR 000110 0011 100 ddd RD >>= [ADDR] 27 SAR RD,ADDR 000110 0011 101 ddd RD >>>= [ADDR] 27 ROL RD,ADDR 000110 0011 110 ddd RD rol= [ADDR] 27 ROR RD,ADDR 000110 0011 111 ddd RD ror= [ADDR] 27 MUL ADDR,RD 000110 0100 000 ddd RD *= [ADDR] 4, 27 IMUL ADDR,RD 000110 0100 001 ddd RD *= [ADDR] 5, 27 DIV ADDR,RD 000110 0100 010 ddd RD /= [ADDR] 4, 27 IDIV ADDR,RD 000110 0100 011 ddd RD /= [ADDR] 5, 27 REM ADDR,RD 000110 0100 100 ddd RD = RD % [ADDR] 4, 27 IREM ADDR,RD 000110 0100 101 ddd RD = RD % [ADDR] 5, 27 FPMULD@@ ADDR,RMD 000110 0100 110 ddd [RMD] *= [ADDR] 4, 27, 28 FPIMULD@@ ADDR,RMD 000110 0100 111 ddd [RMD] *= [ADDR] 5, 27, 28 VMOV@@ ADDR,RMD 000110 0101 000 ddd v3d[RMD] = v3d[ADDR] 18, 27 DADD@@ ADDR,RMD 000110 0101 001 ddd [RMD] += [ADDR] 20, 27 DSUB@@ ADDR,RMD 000110 0101 010 ddd [RMD] -= [ADDR] 20, 27 LOOPE RD,dest 000110 0101 011 ddd RD--; R7 += disp16 if RD!=0 & Z=1 19 BREVR R0 000110 0101 011 110 R0 = bit_reverse(R0) BREVR R1 000110 0101 011 111 R1 = bit_reverse(R1) LOOPNE RD,dest 000110 0101 100 ddd RD--; R7 += disp16 if RD!=0 & Z=0 19 BREVR R2 000110 0101 100 110 R2 = bit_reverse(R2) BREVR R3 000110 0101 100 111 R3 = bit_reverse(R3) LOOPS RD,dest 000110 0101 101 ddd RD--; R7 += disp16 if RD!=0 & S=1 19 BREVR R4 000110 0101 101 110 R4 = bit_reverse(R4) BREVR R5 000110 0101 101 111 R5 = bit_reverse(R5) LOOPNS RD,dest 000110 0101 110 ddd RD--; R7 += disp16 if RD!=0 & S=0 19 COMC 000110 0101 110 110 C = !C ENAEXT 000110 0101 110 111 enable_extended_opcodes 29 DBTR RD 000110 0101 111 ddd RD = double_bits(RD) 30 REV4R RD 000110 0110 000 ddd RD = RD[3:0][7:4][11:8][15:12] 31 REV4HR RD 000110 0110 001 ddd RD = RD[11:8][15:12][3:0][7:4] 32 FPINVD@ RMD 000110 0110 010 ddd [RMD] = 1 / [RMD] 4, 28 MVOIA DATA, ADDR 000110 0110 011 000 [ADDR] = DATA 33 ADDIA DATA, ADDR 000110 0110 011 001 [ADDR] += DATA 33 SUBIA DATA, ADDR 000110 0110 011 010 [ADDR] -= DATA 33 CMPIA DATA, ADDR 000110 0110 011 011 set_flags([ADDR] - DATA) 33 ANDIA DATA, ADDR 000110 0110 011 100 [ADDR] &= DATA 33 XORIA DATA, ADDR 000110 0110 011 101 [ADDR] ^= DATA 33 ORIA DATA, ADDR 000110 0110 011 110 [ADDR] |= DATA 33 ANDNIA DATA, ADDR 000110 0110 011 111 [ADDR] &= ~DATA 33 XORNIA DATA, ADDR 000110 0110 100 000 [ADDR] ^= ~DATA 33 ORNIA DATA, ADDR 000110 0110 100 001 [ADDR] |= ~DATA 33 NANDIA DATA, ADDR 000110 0110 100 010 [ADDR] = ~([ADDR] & DATA) 33 XNORIA DATA, ADDR 000110 0110 100 011 [ADDR] = ~([ADDR] ^ DATA) 33 NORIA DATA, ADDR 000110 0110 100 100 [ADDR] = ~([ADDR] | DATA) 33 TSTIA DATA, ADDR 000110 0110 100 101 set_flags([ADDR] & DATA) 33 XCHGIA DATA, ADDR 000110 0110 100 110 [ADDR] <--> DATA 33, 34 ADCIA DATA, ADDR 000110 0110 100 111 [ADDR] += DATA + C 33 SBCIA DATA, ADDR 000110 0110 101 000 [ADDR] -= (DATA + ~C) 33 SLLIA DATA, ADDR 000110 0110 101 001 [ADDR] <<= DATA 33 SLRIA DATA, ADDR 000110 0110 101 010 [ADDR] >>= DATA 33 SARIA DATA, ADDR 000110 0110 101 011 [ADDR] >>>= DATA 33 ROLIA DATA, ADDR 000110 0110 101 100 [ADDR] rol= DATA 33 RORIA DATA, ADDR 000110 0110 101 101 [ADDR] ror= DATA 33 MULIA DATA, ADDR 000110 0110 101 110 [ADDR] *= DATA 4, 33 IMULIA DATA, ADDR 000110 0110 101 111 [ADDR] *= DATA 5, 33 DIVIA DATA, ADDR 000110 0110 110 000 [ADDR] /= DATA 4, 33 IDIVIA DATA, ADDR 000110 0110 110 001 [ADDR] /= DATA 5, 33 REMIA DATA, ADDR 000110 0110 110 010 [ADDR] = [ADDR] % DATA 4, 33 IREMIA DATA, ADDR 000110 0110 110 011 [ADDR] = [ADDR] % DATA 5, 33 SWAP RD 000110 0110 110 1dd swap_bytes(RD) 35 STCP RD 000110 0110 111 ddd C = parity(RD) 36 DISEXT 000110 0110 111 111 disable_extended_opcodes 29 POW10RL RD 000110 0111 000 ddd RD = low_word(pow(10,RD)) 37 POW10RH RD 000110 0111 001 ddd RD = high_word(pow(10,RD)) 37 FPISQRTR RD 000110 0111 010 ddd RD = 1 / sqrt(RD) 4, 9, 38 FPLNR RS,RD 000110 0111 011 ddd RD = ln(RD) 4, 9 FPEXPR RS,RD 000110 0111 100 ddd RD = exp(RD) 5, 9 FPSINR RS,RD 000110 0111 101 ddd RD = sin(RD) 5, 9, 40 FPCOSR RS,RD 000110 0111 110 ddd RD = cos(RD) 5, 9, 40 FPIINVD@ RMD 000110 0111 111 ddd [RMD] = 1 / [RMD] 5, 28 FPATAN2R RS,RD 000110 1000 sss ddd RD = atan2(RS,RD) 5, 9, 39 Notes ----- 1. If xxx is 0, uses direct addressing instead (@R0 is not supported). 2. @R0 is supported. Direct addressing is handled by a different opcode. 3. Src is not altered. Auto-increment for SDBD purposes arises from RD (Src is the base address, RD is the index address). 4. Operands are treated as unsigned. 5. Operands are treated as signed. 6. m should have no effect 7. Changes the low byte only, leaving the high byte unaltered. 8. aaa is always different from bbb 9. Operands are treated as 16-bit fixed-point numbers in 8.8 format. 10. Produces a 32-bit result with the high word placed in R1 and the low word placed in R0. 11. Unpacks the two bytes in RA into RA and RB. 12. Packs the low bytes of RA and RB into RA. 13. RD <-- hexadecimal ASCII representation of the low byte of RD (e.g. 0x000A --> 3041 "0A") 14. Shifts bits from R0 into RD. R0 is unaltered. RD may be in the range R1..R3. 15. RD = binary value (0..255) of hexadecimal ASCII characters stored in RD. Invalid characters in a byte result in that byte being interpreted as 0 (e.g. 3041 --> 0x0A, 2F41 --> 0x0A). Ignores case. 16. Shifts bits from RS into R0. RS is unaltered. C = low bit of R0 shifted out if a > 0. RS may be in the range R1..R3. 17. Does ***not*** change RM if mmm>3. Supports SDBD. 18. Copies a 3-vector from [Src] to [RMD]. Each vector component is 32 bits, for a total copy of 6 words. 19. ddd < 6 20. Operands are 32 bits in size. 21. RD = number of consecutive 0 bits in RD starting at the MSB 22. RD = number of consecutive 1 bits in RD starting at the MSB 23. RD = number of consecutive 0 bits in RD starting at the LSB 24. RD = number of consecutive 1 bits in RD starting at the LSB 25. If RD > 15, result is 0. 26. Result is either -1, 0, or 1. 27. Direct addressing mode version. 28. Operands are treated as 32-bit fixed-point values in 16.16 format. 29. No effect in the emulator (extended opcodes are always active). Reserved for a physical CPU. 30. RD = doubled bits of low byte of RD (e.g. 0x0011 --> 0x0303) 31. Reverses the order of the 4-bit nibbles in RD (e.g. 0x0123 --> 0x3120). 32. Reverses the order of the 4-bit nibbles in each byte of RD (e.g. 0x0123 --> 0x1032). 33. Three-word instruction: the second word is an address and the third word is an immediate value. SDBD is not supported. 34. If running from ROM, net effect is [ADDR] = DATA. 35. RD is indexed by dd + 4, i.e. RD is in the range R4..R7. 36. ddd <> 7. If RD contains an odd number of 1 bits, C = 1, else C = 0 (sets carry as RD parity) 37. If RD > 9, the result is 0. 38. Uses fast-inverse-square-root approximation algorithm with one iteration. 39. RS is the X value and RD is the Y value. Result is in radians and is accurate to 0.01 radians. 40. RD must be expressed in radians in the range -2*pi .. 2*pi. Result might be off by 1/256 (the LSB). Edited January 15, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 16, 2022 Author Share Posted January 16, 2022 (edited) I found a block of mistakes in my specification posted above. The section in question should read like this: SLLR RD,RA 000011 1100 aaa ddd RD <<= RA SLRR RD,RA 000011 1101 aaa ddd RD >>= RA SARR RD,RA 000011 1110 aaa ddd RD >>>= RA ROLR RD,RA 000011 1111 aaa ddd RD rol= RA RORR RD,RA 000100 0000 aaa ddd RD ror= RA MULR RS,RD 000100 0001 sss ddd RD *= RS 4 IMULR RS,RD 000100 0010 sss ddd RD *= RS 5 DIVR RS,RD 000100 0011 sss ddd RD /= RS 4 IDIVR RS,RD 000100 0100 sss ddd RD /= RS 5 REMR RS,RD 000100 0101 sss ddd RD = RD % RS 4 IREMR RS,RD 000100 0110 sss ddd RD = RD % RS 5 . . . MVOD@ RS,RM+disp16 000101 1000 mmm sss [RM + disp16] = RS 17 Edited January 16, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 18, 2022 Author Share Posted January 18, 2022 I haven't the slightest idea where the RAM space came from, but I managed to squeeze in a few extra instructions at the end (see below). Most are intended to ease blitting sprites to the screen in various graphics modes. The last two instructions were added just to fill out the opcode block. They could possibly be used for precise time measurement. Testing is going well. I greatly simplified the emulator code with C macros to make the testing space much smaller. I'm almost at the point where I just have to build and validate the final hardware design before posting everything. MVONZx RS, dst 000110 1010 xxx sss If RS <> 0, [dst] = RS BLIT4@ RS, RM 000110 1011 00m sss blit_with_transparency(RS -> [RM]) 42 BLIT16@ RS, RM 000110 1011 01m sss blit_with_transparency(RS -> [RM]) 43 BLIT256@ RS, RM 000110 1011 10m sss blit_with_transparency(RS -> [RM]) 44 MVONZ@ RS, R0 000110 1011 110 sss If RS <> 0, [R0] = RS BREVBR RD 000110 1011 111 ddd RD = bit_reverse_bytes(RD) 45 RUNCLR 000110 1011 111 110 R0 = low word of cycle counter RUNCHR 000110 1011 111 111 R0 = high word of cycle counter 42. RM must be R4 or R5. Pairs of bits are written from RS to [RM] if they are not 00. 43. RM must be R4 or R5. Sets of 4 bits are written from RS to [RM] if they are not 0000. 44. RM must be R4 or R5. Bytes are written from RS to [RM] if they are not 0. 45. ddd < 6. Reverses the bits of individual bytes in RD. 1 Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 20, 2022 Author Share Posted January 20, 2022 (edited) I've been doing lots of testing of the emulation engine and I wound up running into problems with certain kinds of instructions not having enough time to run, so I looked into the possibility of overclocking the Pico. It turns out that people have been overclocking the heck out of it and someone went so far as to plot what speeds it can achieve, at what internal core voltage, and what its internal temperature reaches. Long story short, ramping it up to 155MHz is just enough to solve my speed issues and the internal temperature goes up by only about 2 degrees F (so we're talking basically 70 to 72 degrees F, still room temperature). It turns out that the reason for the Pico's advertised maximum speed of 133MHz is due to the rating of its flash chip (which at any rate can handle far higher speeds). I can't run from flash because of its latency and so everything needs to run from the Pico's internal RAM which doesn't suffer from such limitations, and it turns out that the Pico can run at 155MHz standing on its head according to the data. This is a good thing not only because it solves the speed issues but also means that a PAL version might be possible in the future. It would have to run at 166MHz to keep up with the 17MHz PAL color frequency, which would add another degree or two Fahrenheit to its temperature, but according to the data even clocked up to 420MHz (!) it only reaches a temperature of 40C. So things are looking much better for a potential PAL version. I'm tempted to just run it at 166MHz now to standardize the code for synchronizing with the Intellivision bus. I suppose one could use the power LED header on my mainboard to connect a tiny fan, but from everything I've seen it's entirely unnecessary, especially since my design suspends the Pico such that there's an air gap below it. A PAL version of my circuit board would require changes to how it counts scan lines since there are more than 256 on a PAL screen and I haven't even looked into how to do that, but at least it seems possible from the standpoint of the software in the Pico. Of course I don't even have any PAL equipment, but that's a bridge to be crossed at another time. EDIT: I recalibrated for 166MHz and it's running like a champ, and the CPU is stone-cold, so I'll probably just leave it there. That way a PAL version would only require recoding of the output routines to duplicate certain scanlines and reverse the color phases (if I understand PAL correctly, correct me if I'm wrong!) Edited January 20, 2022 by JohnPCAE 1 Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 22, 2022 Author Share Posted January 22, 2022 (edited) Testing, testing, and more testing, and some bug-fixing. I managed to squeeze in just a few more instructions: BLIT2A@ RS, RM 000110 1100 00m sss [RM] |= RS 46 BLIT4A@ RS, RM 000110 1100 01m sss blit_with_transparency(RS -> [RM]) 46 BLIT16A@ RS, RM 000110 1100 10m sss blit_with_transparency(RS -> [RM]) 46 BLIT256A@ RS, RM 000110 1100 11m sss blit_with_transparency(RS -> [RM]) 46 46. Adds a 16-bit immediate to RM after auto-incrementing it. Net result is RM = RM + 1 + imm16. The new instructions are meant to make blitting easier. It lets you blit to a buffer and automatically add the buffer pitch to the destination register so that it's positioned at the right position on the next scan line. I also slightly altered the VMOV@@ instruction. It copies 16 bytes instead of 12, and it requires that the source and destination addresses be 0xFFF8 or less. That is, it doesn't handle address wrapping. If either address is higher than the limit it will do nothing. Also, I've put together the BOM for the two boards. The complete system consists of a small board that plugs into the cartridge port, and the mainboard. A short ribbon cable connects the two. ============================ CARTRIDGE BOARD PARTS LIST ============================ Part Value Close part # Description/important features ------------------------------------------------------------------------------------------- C1 22pF C315C220F3G5TA Ceramic capacitor, 1%, 2.54mm lead spacing C2 33pf C315C330F3G5TA Ceramic capacitor, 1%, 2.54mm lead spacing C3 100nF FG18C0G1H103JNT06 MLCC capacitor, 2.54mm lead spacing C4 33pf C315C330F3G5TA Ceramic capacitor, 1%, 2.54mm lead spacing C5 100nF FG18C0G1H103JNT06 MLCC capacitor, 2.54mm lead spacing C6 100nF FG18C0G1H103JNT06 MLCC capacitor, 2.54mm lead spacing C7 10pF C316C100F3G5TA Ceramic capacitor, 1%, 2.54mm lead spacing D1 1N715 TZX11B-TR Zener diode FB1 2743002112 4211R-11 Through-hole ferrite Bead, 8mm length, 135 ohm IC1 CD74HCT7046A CD74HCT7046AEE4 Phase-Locked Loop with VCO and Lock Detector IC2 AD8031N AD8031ANZ Op-amp IC3 74LS74N SN74HCT74NE4 Dual D type positive edge triggered FLIP FLOP, preset and clear IC4 MAX913CPA MAX913CPA+ Voltage comparator JP1 2x22 70246-4402 2x22 shrouded, keyed male pin header R1 10k MFR-25FRF52-10K Resistor, 1/4W, 1%, 6.3mm length R2 10k MFR-25FRF52-10K Resistor, 1/4W, 1%, 6.3mm length R3 10k MFR-25FRF52-10K Resistor, 1/4W, 1%, 6.3mm length R5 33 MFR-25FRF52-33R Resistor, 1/4W, 1%, 6.3mm length R6 10k MFR-25FRF52-10K Resistor, 1/4W, 1%, 6.3mm length R7 47k MFR-25FBF52-47K Resistor, 1/4W, 1%, 6.3mm length R8 10k MFR-25FRF52-10K Resistor, 1/4W, 1%, 6.3mm length R9 22k MFR-25FTF52-22K Resistor, 1/4W, 1%, 6.3mm length R10 10k MFR-25FRF52-10K Resistor, 1/4W, 1%, 6.3mm length R11 5.6k MFR-25FTE52-5K6 Resistor, 1/4W, 1%, 6.3mm length CABLE 2x22 IDC IDSD-22-D-03.00-T 2x22 IDC ribbon cable connecting the two boards Cartridge board notes ------------------------- 1. My IDC ribbon cable is 3" long and keyed. A 2" cable would probably be ideal but it wasn't available. Bear in mind that a keyed cable requires keyed receptacles. 2. The cartridge board serves a very important function: it quadruples the rate of the Intellivision's MCLK signal while keeping the result phase-locked. It passes the result along to the mainboard via pin 16. The incoming MCLK signal from the Intellivision is highly attenuated, and it's important to use parts that are in spec for this board to do its job. Recommend that all passives have a 1% tolerance. 3. While it might be tempting to use sockets for the IC's, if they are socketed then a plastic shroud will likely not fit around the board. 4. The 100nF capacitors are exactly the same as the ones on the mainboard. Their sole use is noise filtering. 5. The ferrite bead is the same as the ones on the mainboard. See the mainboard notes for more info on the ferrite beads. 6. All capacitors should have 0.1" (2.54mm) lead spacing. 7. The rating of the zener diode is not critical. I used a 1N715 which is rated for 11V. The point of the diode is only to cut down on ringing. ============================ MAINBOARD PARTS LIST ============================ Part Value Close part # Description/important features ------------------------------------------------------------------------------------------- C1..C31 100nF FG18C0G1H103JNT06 MLCC capacitor, 2.54mm lead spacing (total qty. 30: there is no C20) CN1 151-7620E-E DC barrel jack, 2mm I.D., 6.3mm O.D. FB1 2743002112 4211R-11 Through-hole ferrite Bead, 8mm length, 135 ohm FB2 2743002112 4211R-11 Through-hole ferrite Bead, 8mm length, 135 ohm SOCKET Preci-Dip 540-88-032-24-008 PLCC-32 socket for 1k FIFO IC1 7202J 7202LA50JG 1k x 9 Asynchronous FIFO, 5V IC2 74LS04N SN74HCT04NE4 Hex INVERTER IC3 74AS574N SN74HCT574NE4 8-bit D type FLIP FLOP bus driver IC4 74AS574N SN74HCT574NE4 8-bit D type FLIP FLOP bus driver IC5 74LS245N SN74HCT245NE4 Octal BUS TRANSCEIVER, 3-state IC6 74LS245N SN74HCT245NE4 Octal BUS TRANSCEIVER, 3-state IC7 74LS08N SN74LS08NE4 Quad 2-input AND gate, 5V IC8 74LS245N SN74HCT245NE4 Octal BUS TRANSCEIVER, 3-state IC9 CD74HC40103 CD74HC40103EE4 High-Speed CMOS Logic 8-Stage Synchronous Down Counter IC10 74LS08N SN74LS08NE4 Quad 2-input AND gate, 5V IC11 74LS08N SN74LS08NE4 Quad 2-input AND gate, 5V IC12 CD74HC40103 CD74HC40103EE4 High-Speed CMOS Logic 8-Stage Synchronous Down Counter IC13 CD74HC40103 CD74HC40103EE4 High-Speed CMOS Logic 8-Stage Synchronous Down Counter IC14 CD74HC40103 CD74HC40103EE4 High-Speed CMOS Logic 8-Stage Synchronous Down Counter IC15 74ALS73AN SN74LS73AN Dual J-K FLIP FLOP, clear IC16 74LS04N SN74HCT04NE4 Hex INVERTER IC17 74AS574N SN74HCT574NE4 8-bit D type FLIP FLOP bus driver IC18 74ALS73AN SN74LS73AN Dual J-K FLIP FLOP, clear IC19 CD74HCT4520N CD4520BEE4 Dual syncronous binary UP-COUNTER IC20 74LS245N SN74HCT245NE4 Octal BUS TRANSCEIVER, 3-state IC21 74LS04N SN74HCT04NE4 Hex INVERTER IC22 74LS08N SN74LS08NE4 Quad 2-input AND gate, 5V IC23 74LS08N SN74LS08NE4 Quad 2-input AND gate, 5V IC24 74ALS73AN SN74LS73AN Dual J-K FLIP FLOP, clear IC25 74AS574N SN74HCT574NE4 8-bit D type FLIP FLOP bus driver IC26 74LVC245N SN74LVC245ANE4 LOW-VOLTAGE Octal BUS TRANSCEIVER, 3-state IC27 74LVC245N SN74LVC245ANE4 LOW-VOLTAGE Octal BUS TRANSCEIVER, 3-state IC28 74LVC245N SN74LVC245ANE4 LOW-VOLTAGE Octal BUS TRANSCEIVER, 3-state IC29 74LVC245N SN74LVC245ANE4 LOW-VOLTAGE Octal BUS TRANSCEIVER, 3-state IC30 74AS574N SN74HCT574NE4 8-bit D type FLIP FLOP bus driver IC31 74LS00N SN74HCT00N Quad 2-input NAND gate JP1 1x20 929850-01-20-RB 1x20 female pin header JP2 1x20 929850-01-20-RB 1x20 female pin header JP3 2x6 929852-01-06-RA 2x6 female pin header JP4 2x22 70246-4402 2x22 shrouded, keyed male pin header JP5/JP6 2x22 392-044-558-201 Cartridge edge connector JP7 1x2 171856-0102 1X02 male pin header (for optional power LED) PB1 PUSHBUTTON_6MM SKHLABA010 Small 2-contact pushbutton (Adafruit sells them in packets of 20) PWRSUPP SKM10E-05 SKM10E-05 MEAN WELL 5V 2A DC-DC Power Converter Q1 IRF4905 IRF4905PBF TO220BH P-Channel HEXFET® Power MOSFET R1 1M MFR-25FTE52-1M Resistor, 1/4W, 1%, 6.3mm length R2 40k MFR-12FTF52-40K Resistor, 1/6W, 1%, 6.3mm length R3 20k MFR-25FBF52-20K Resistor, 1/4W, 1%, 6.3mm length R4 10k MFR-25FRF52-10K Resistor, 1/4W, 1%, 6.3mm length R5 5k MFR-25FTE52-4K99 Resistor, 1/4W, 1%, 6.3mm length R6 2.5k MFR-25FBF52-2K49 Resistor, 1/4W, 1%, 6.3mm length R7 1.25k MFR-25FBF52-1K24 Resistor, 1/4W, 1%, 6.3mm length R8 625 MFR-25FRF52-620R Resistor, 1/4W, 1%, 6.3mm length R9 312 MFR-25FRF52-309R Resistor, 1/4W, 1%, 6.3mm length R10 3.9k MFR-25FBF52-3K9 Resistor, 1/4W, 1%, 6.3mm length R11 1k MFR-25FRE52-1K Resistor, 1/4W, 1%, 6.3mm length R12 470 MFR-25FTE52-470R Resistor, 1/4W, 1%, 6.3mm length R13 820 MFR-25FBF52-820R Resistor, 1/4W, 1%, 6.3mm length R14 820 MFR-25FBF52-820R Resistor, 1/4W, 1%, 6.3mm length R15 1k MFR-25FRE52-1K Resistor, 1/4W, 1%, 6.3mm length R16 1k MFR-25FRE52-1K Resistor, 1/4W, 1%, 6.3mm length R17 1k MFR-25FRE52-1K Resistor, 1/4W, 1%, 6.3mm length X1 DSUB25-F 09663526611 Female D-Sub-25 right-angle parallel port connector Mainboard notes ------------------------- 1. For resistors, any 1/4W 1% tolerance resistor that's 6.3mm or less will do. It's okay to use a 1/6W resistor for the 40k one as it's only in the resistor ladder for the output video. 2. For the 1M resistor, the board will accommodate a larger 1/2W one but it isn't necessary. 3. All capacitors are the same, 100nF, with 0.1" (2.54mm) lead spacing. 4. For chips, generally speaking, try to remain compatible with TTL logic levels if possible. 5. It is ***CRITICAL*** to use LVC (low-voltage) variants for IC26-IC29. They translate 5V logic levels to 3.3V for the Raspberry Pi Pico. Not using LVC chips absolutely WILL fry either the Pico or IC26-IC29. 6. The MEAN WELL switching power supply has an upper limit of 9 volts input. Recommended DC power supply is 6V 2A. The barrel jack from the wall-wart power supply must be center-positive. 7. The hardest part to acquire by far is the cartridge connector. 8. PB1 is a reset button for the Raspberry Pi Pico. It isn't strictly necessary. 9. JP7 is a locking header for an optional power LED. 10. JP3 is a header for possible expansion. It provides the digital video levels just before they are converted to analog. A potential use is conversion to DVI/HDMI. 11. The ferrite beads I have are Fair-Rite 2743002112 through-hole axial beads, with an approximate length of 8mm and 135-ohm impedance. The impedance value was not specifically chosen, it's just what looked okay and they do a good (and important) job of removing noise from the power rails. Try to use something similar in size and impedance. 12. Recommend using sockets for all chips. It's cheap insurance. 13. You also need a Raspberry Pi Pico and headers for it, of course. It plugs into JP1 and JP2. DO NOT use its castellated holes to solder it directly to the mainboard or (a) its ability to cool itself will suffer, (b) you won't be able to plug your USB cable into it to load the software, and (c) it will probably short against the vias under it. The (almost certainly) final versions of the boards are on their way to me, so once I receive them I'll assemble and validate them. They're only slightly tweaked from what I have now so I don't expect any problems. At that point I should be about ready to release everything. I'm planning on GPL'ing all of the code because of what artrag went through. As for the board designs, my plan is to release them in both Eagle and Gerber formats. Edited January 22, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 22, 2022 Author Share Posted January 22, 2022 (edited) To make it easier, here is the attached BOM: BOM.txt FYI, the image that Mouser shows for the ferrite beads does not match the datasheet. If you open the manufacturer's datasheet, it shows them as through-hole, not surface-mount. Edited January 22, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 23, 2022 Author Share Posted January 23, 2022 (edited) I really hate how Mouser lists capacitors. I accidentally chose 10nF capacitors instead of 100nF ones from their parts list, so the part shown in my BOM is incorrect. Attached is the correct BOM. BOM.txt I'm just about finished with software testing. I can't exhaustively test every single possible opcode but I've tested all of the emulated instructions and I've tested each of the addressing modes many times in the process. I'm glad I did all this testing because it wound up showing many little bugs in the emulator. I think the last part of the software to test is some of the high-level configuration stuff. The boards haven't arrived yet anyway so I have some time. There's been a minor change to the opcode layout. I realized that TSTR and XCHR are symmetric and require only half of the opcodes they were actually using, so I managed to condense them into a smaller layout. This freed up a block of opcodes that I was able to use for a new instruction, AND@@. It takes the form AND@@ RMS, RMD. It reads one word at the addresses referenced by each of two registers, ANDs them together, and writes the result to [RMD]. Its main benefit would be to rapidly AND a mask into a buffer where either or both of the addresses would auto-increment. It doesn't support SDBD: there just isn't enough RAM space left for the code to do it. So the resulting opcode encoding in the affected region now looks like this: INCLR RD 000011 0111 ddd ddd lowbyte(RD)++ AND@@ RMS, RMD 000011 0111 sss ddd [RMD] &= [RMS] TSTR RA, RB 000011 1000 aaa bbb set_flags(RA & RB) DECLR RD 000011 1000 ddd ddd lowbyte(RD)-- XCHGR RA, RB 000011 1000 aaa bbb RA <--> RB - for AND@@, sss is never equal to ddd. - for TSTR, aaa is always less than bbb. - for XCHGR, aaa is always greater than bbb. Edited January 23, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 24, 2022 Author Share Posted January 24, 2022 (edited) Major feature update For a long while there has been a feature that I wanted to add as soon as I put in sprite exclusion. Having the Pico overclocked to 166MHz enabled me to condense some emulated instruction code, which in turn allowed me to free up the RAM space necessary for the code to do it. What feature? When I showed sprite exclusion I mentioned that it would be easy to extend it to blit sprites instead of just masking out areas where sprites were displayed. And now it's reality. The picture below shows what it can do. At the top it's excluding 8 sprites that would represent the STIC's actual sprites. And below that it's blitting an additional 248 sprites of its own. Basically I extended the subsystem to handle up to 256 sprites, where the first 8 are exclusion-only and the rest it will blit on its own with colors that you designate. There are some caveats. Sprites that are flipped or are clipped on the edges of the screen require a tiny bit more processing, and stretched sprites require significantly more CPU time since it has to push many more pixels to the screen. That said, for the normal-size running man sprites shown here, it can handle all 256 sprites in every bitmap-graphics screen mode that allows sprite exclusion. As another example, it can handle 256 horizontally-stretched, non-clipped sprites in 16-color mode. Generally speaking, the number of sprites it can display depends on the screen mode and their size. In general this is only viable in bitmap graphics modes, though you might be able to display a sprite or two in text mode. The reason is that when in text mode, it first has to convert the display to a bitmap which takes a significant amount of time. There is NO sprite collision checking. That would require a Pico that's maybe ten times as fast as this one, with vastly more RAM than it has. That's something you'll have to handle with the CPU, either the real one or the emulated one. The second image shows what happens when you ask it to do too much. It's trying to handle 256 double-width sprites in 16-bit true-color mode. The Pico can't get all that done before it has to output scan lines to the screen, so the output gets delayed. It can handle that in 160x191x16 mode because that requires a lot less data to be moved around. So, who wants to volunteer to code the Robotron port? Edited January 24, 2022 by JohnPCAE 1 Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 24, 2022 Author Share Posted January 24, 2022 (edited) I should point out that the sprites don't have to all be the same size. You can mix and match exactly the way you can with the STIC. Each sprite has an attribute byte that lets you set visibility, X flip, Y flip, X stretch, Y stretch, and Y double-stretch. They get rendered from 255 down to 0, with the final eight sprites being the exclusion ones (think about it -- they have to be on top). There is also no limit on how many sprites can be displayed on a line, since it's rendering to an offscreen buffer before writing scan lines out to the hardware. It doesn't care where sprites are. I should also point out that since you're free to paint a sprite with black, you can use any non-exclusion sprite as an exclusion sprite. So, for instance, if you want some cards that the STIC is displaying to be shown on top, just use a sprite with the color set to black to exclude whatever pixels you like, and use the lowest-numbered sprites as your extra exclusion ones since they get drawn last. Why are the first 8 sprites special in that they are exclusion-only? SPEED. It's faster to only use a sprite for exclusion than to also paint in a color. Since it takes so long to convert a text-mode screen into a bitmap, if you want to exclude *any* sprites in text mode the Pico needs all the help it can get. So for sprites 0-7 the Pico uses special exclusion-only code instead of the full sprite-painting code. Only sprites 8-255 get the full treatment. Edited January 24, 2022 by JohnPCAE 1 Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 25, 2022 Author Share Posted January 25, 2022 Wow. I stand corrected on what this can do in 40-column text mode. Shown is the software excluding all 8 Intellivision sprites at normal size and then displaying 144 sprites of its own (about the most it can handle if none of them are clipped). When the Pico was running at 133MHz it could barely exclude a single sprite, but at 166MHz it can do all this. Nice. As a reminder, sprite exclusion in text mode, as opposed to bitmap graphics mode, involves an extra step of rendering the text to a bitmap before it can perform sprite exclusion. This limits how many sprites it can handle since it has to do all this every frame between when SR1 from the Intellivision pulses low and when it has to output scan lines to the hardware. I received my updated cartridge boards yesterday, but I'm still waiting on the mainboards as well as components. In the meantime I'm polishing the source code. 2 Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 25, 2022 Author Share Posted January 25, 2022 (edited) Some more eye-candy. Running at 166MHz meant that I don't have to go to crazy-extreme measures to display 80-column text. When it was running at 133MHz, I had to have 256 separate code snippets, one for each of the 256 possible dot patterns in a byte. But running at 166MHz means that I can get away with having only 16 code snippets for a four-bit pattern, and incur the overhead of calling it twice. This saved a boatload of RAM, upwards of 20k. So now all of a sudden I have a bunch of RAM available for more code. This in turn allowed me to write code for sprite exclusion in 80-column mode, with two caveats. First, since it has to convert twice as many characters into a bitmap it can't display as many sprites. The screenshot below shows 80 non-clipped sprites, which is about the most it can handle. The second caveat is that it has to convert the text to a 16-color (4bpp) graphics mode. The reason is there isn't enough buffer space in 128k for the text buffer, a separate bitmap buffer, and the sprite info. So it only looks at the low 4 bits of the foreground and background colors when converting. Note that this is only a factor if you enable sprite exclusion: if you don't turn it on, you have the full 256-color palette available for foreground and background colors in 80-column text mode. I suppose there are multiple potential benefits from using sprite exclusion in a text mode, but for me the main benefit is that you can use it for a hardware cursor that isn't just a text block. You can have an actual arrow instead, albeit a blocky one like an Intellivision sprite. In other news, last night I figured out how to wait long enough in a DTB cycle before I can safely stop outputting data onto the Intellivision bus. It means that I don't have to do it in the following NACT cycle. This frees up the NACT following a DTB that I have to service for running the emulated CPU. So now the emulated CPU can run in all NACT cycles, as well as IAB, DW, and INTAK. Its effective speed relative to the physical CPU will therefore range from 2x to 6x, since all emulated instructions execute in a single one of those aforementioned cycles. And that's not counting the extended instructions that can do things with a single instruction that would take the physical CPU far more to accomplish. Edited January 25, 2022 by JohnPCAE 1 Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted January 27, 2022 Author Share Posted January 27, 2022 (edited) My circuit boards are all here now, but I spent the day working on the emulated CPU. In the past few days I've added some instructions that produce 32-bit fixed-point results and perform some fixed-point 32-bit arithmetic: FPLND FPEXPD FPSIND FPCOSD FPDIVD@@ FPIDIVD@@ There's also a new FPSQRTR instruction that gives an 8.8 format square root, and new VSTO@ instruction that fills 16 words of memory with the value in a source register. So you can do really fast memory fills as well as really fast memory copies. How fast? I did some quick timing calculations and it can: - copy 8 words 78% as fast as a 16MHz 80386 - fill 16 words 179% as fast as a 16MHz 80386 But there's even more. With FPDIVD@@, it takes two 16.16 fixed-point values in memory, divides one by the other, and stores the result. It can do this 115% as fast as a 16MHz 80386, and that's not including the additional shifts that are required to go to and from fixed-point format on the 386 or the operations to load one value from memory and store the result. Bear in mind that all emulated instructions always take 2.235 us to run (i.e. two Intellivision clock cycles), so the more an instruction can do, the more efficient it is. There's method to the madness of putting all these instructions in. Wolfenstein 3D required an 80286 to run (which doesn't have 32-bit instructions). From my timing analysis, the most expensive operations run on par with the fastest 80286's ever made and close to the first 80386 CPU's. It makes me wonder if a complete port of Wolfenstein 3D to the Inty will be possible. I've been trying to make it so, at least. Edited January 27, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted February 1, 2022 Author Share Posted February 1, 2022 (edited) I've made a small update to the BOM. The Zener diode should be a 1N751, not a 1N715. It's rated for 5.1V. The rating is probably important. Updated file attached. I just finished building the final version of the cartridge board and it's working correctly. The next step is to build the final version of the mainboard. I'll probably have to order some components first. The software is packed to the gills and I'm not sure that I can add any more to it. I managed to squeeze in basic single-precision floating-point support (add, subtract, multiply, divide, square root, abs, neg, etc. and several conversion opcodes). Floating-point support is really hard to get to run within the time budget but so far so good (for add and subtract I had to split them into two instructions because of the time it takes to renormalize the result, so first you do an FADD/FSUB and then you do an FOUT to normalize and output the result). I've gotten pretty good at Arm Thumb assembly. It just needs some more testing. There are also some goodies for accessing bit-packed arrays, which should be a help since space in the Inty is always at a premium. Those aren't tested yet. BOM.txt Edited February 1, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted February 7, 2022 Author Share Posted February 7, 2022 (edited) I'm still waiting on parts before I can finish building the final mainboard and start testing it. My order from Mouser was supposed to arrive on Friday, but for some reason it didn't leave Dallas until yesterday. And now it's sitting somewhere at their Philly distribution center next to the airport, literally *seven whole miles* from my house, and estimated delivery isn't until Tuesday night. For crying out loud. The software has passed all of my tests so far and I'm about out of ideas as to what to do next to it. There's a tiny bit of available RAM left; maybe I'll see if I can think of a few more emulated instructions to add, or maybe I'll just leave it as-is in case it's needed later. As it stands, the emulated coprocessor has a *lot* of available instructions, far more than when I last posted the opcode list. Porting something like Keyboard Component software to it wouldn't even make it break a sweat. Speaking of which, I've been thinking a lot about its parallel port of late. I was very tempted to pick up an old HP Thinkjet printer on ebay and write some Inty software to print to it, but I've decided on something else. A Raspberry Pi Pico has USB host capability, so a Pico (with appropriate level-shifting IC's and other stuff) plugged into the parallel port could make for an easy way to have an Intellivision talk to various USB devices. So once I release all of the design files and software for this project I think I'll take a stab at it. If nothing else, being able to use modern USB keyboards and mice with an Intellivision could make for some interesting and in-depth games. I also toyed with the idea of breaking out my old parallel port Iomega ZIP drive and trying to talk to that, but I think being able to talk to a USB stick would be a much better solution. I have no idea how far the USB idea can be pushed (maybe a USB wifi device?) but I'll make any software I write public, so any of us will be able to work on it. Edited February 7, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted February 8, 2022 Author Share Posted February 8, 2022 I got my parts today and got to work. The final hardware design has been built and it's working ? I've started working on documentation, but that will be a long process. In the meantime, there's a good chance of a full release sometime tonight for people to start with, so standby. I just want to work on the documentation some more first. It will be incomplete but it will be enough to start with until I can flesh it out more. Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted February 9, 2022 Author Share Posted February 9, 2022 (edited) Okay. For better or for worse, it's ready for the larger community to start playing with it. So I bring to you the Advanced Console Component. It includes full hardware designs and Gerber code for making your own circuit boards, a BOM (bill of materials), full GPL'ed code for the Pi Pico, as well as a prebuilt binary (overlay.uf2). It also includes what documentation I've finished so far as well as an example Inty program that does a simple test. Documentation is far from finished, but it's enough to get people started and the example Inty program will help. Everything is of course subject to change as we play with it, but at this point I don't foresee any changes save documentation. If there are any bugs, I'm unaware of them. Note that this is NTSC-only, and works best with an Intellivision II or an original Inty that has had the System Changer mod. That said, it will also work with an unmodified Intellivision, though the overlaid video will be much dimmer. This isn't anything I can control as it's due to the large resistor in the original Intellivision that attenuates incoming video. A System Changer mod is highly recommended. Also, you won't see any output from this on RGB-modded consoles as it provides composite video over the Intellivision's video overlay pin and an RGB mod won't see or process it. It does provide a header so that a future RGB device can pick off its video in digital form, but building one is an exercise for the people who make RGB mods ? Advanced Console Component 20220208.zip Edited February 9, 2022 by JohnPCAE 2 1 Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted February 10, 2022 Author Share Posted February 10, 2022 Updated release: I've expanded the coprocessor documentation by quite a lot in the past 24 hours, and in the midst of working on it I uncovered a very minor bug in the code (if you ran a JE/JD/JSRE/JSRD instruction, it would enable interrupts when you asked it to disable them, and vice versa). So this update has a new build as well as a much larger document. There's still much more to add to the documentation, but this adds quite a lot. I also made some minor tweaks to a handful of opcode names in the documentation to make them more intuitive. Advanced Console Component 20220209.zip Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted February 10, 2022 Author Share Posted February 10, 2022 (edited) Another update! The documentation now details all coprocessor instructions with the exception of which ones support SDBD. I also fixed some obscure bugs in the coprocessor code relating to division by zero and setting the overflow flag. I also expanded the SHLD and SHRD instructions to support shifts of more than 16 bits. Attachment below. Advanced Console Component 20220210.zip Edited February 10, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
walldog1 Posted February 13, 2022 Share Posted February 13, 2022 On 1/8/2022 at 11:05 PM, JohnPCAE said: I posted about the problem on the Firefox forums, and they pointed me to a solution. I had to go into my Firefox settings and clear the cache. All fixed now! I had the exact same problems around that time using Firefox Windows 10 64x. I had someone else contact a moderator who e-mailed me that I had a problem with Javascript settings. I took a deep dive into Firefox settings and it said enabled and whole lot of other info, some I understood, some I didn't. Sent a copy to moderator. Then 2 days later, I tried Firefox again and it worked! I did not clear cache nor make any changes to Firefox. Glad to know I wasn't the only one who had this problem for about a week or so. Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted February 13, 2022 Author Share Posted February 13, 2022 (edited) Another update. I've added a few more instructions: ADDBCR RS, RD ADDNCR RS, RD CCD2W RD COMS ADDBCR adds a value in a source register to both bytes in the destination register, clamping each byte to the range 0..255 (no rollover). ADDNCR is similar but it adds to each 4-bit nibble in the destination register, clamping them to the range 0..15. CCD2W reads a 32-bit color at an indirect address, downconverts it to a 16-bit color, and writes it to the register that pointed to the color. COMS flips the sign flag. The first two instructions are useful for lighting effects when working in true-color mode. The third instruction enables quick conversion of, say, a 32-bit texture to 16-bit. As for the last instruction, now the instruction set has set, clear, and complement instructions for each of the flags. Advanced Console Component 20220213.zip Edited February 13, 2022 by JohnPCAE Quote Link to comment Share on other sites More sharing options...
+BBWW Posted February 15, 2022 Share Posted February 15, 2022 Sell this to Intellivision Entertainment. It could be the Intellivision we really want AND deliverable! 1 Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted February 15, 2022 Author Share Posted February 15, 2022 2 hours ago, BBWW said: Sell this to Intellivision Entertainment. It could be the Intellivision we really want AND deliverable! I know, right? At least this exists, unlike the Amico. Anyway, I ran across a bug in my handling of the SHLD and SHRD instructions. Here is a small update that fixes it. Advanced Console Component 20220215.zip Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted February 15, 2022 Author Share Posted February 15, 2022 I'm working on a series of assembler macros that will make writing coprocessor code easier. The idea is that you'd write whatever coprocessor routines you need and then have a standard CP-1600 routine copy them to ACC memory. When it's ready I'll bundle it in the ACC zip file and post an update. Quote Link to comment Share on other sites More sharing options...
JohnPCAE Posted February 21, 2022 Author Share Posted February 21, 2022 An update to the software: - Removed some code for SHLD and SHRD that would never be used - Updated the example Intellivision program to show writing some coprocessor instructions - Updated the documentation - Added an AS1600 source file that has macros for all coprocessor instructions - Added a modified version of AS1600 that is required for the macro file (the same one as in the "Bug in AS1600?" thread) Advanced Console Component 20220220.zip Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.