I have absolutely no idea what you are talking about but I learn a lot watching this video. Small channels like this give me much more knowledge than any big RU-vidr l
Hello, you say at 4:59 that the Spectrum uses half broken RAM chips and that "it wires the working half using twice as many chips", but this doesn't sound quite right. The Z80 memory space is 64k bytes, addressable through a 16-bit bus (pins A0 to A15). On the Spectrum, this memory space is organized as 16k ROM + 16k RAM + 32k RAM, the latter 32k being optional, hence the two versions, 16k and 48k. For the first 16K of RAM, the Spectrum uses 8 x 4116 chips, which you can see on the bottom left corner of the photo at the beginning of the video (0:19). Each of these chips holds 16384 x 1 bit, meaning that when it is addressed it accesses a single bit out of its 16384. The data bus of the Spectrum is 8-bit, corresponding to pins D0 to D7 on the processor, and each one of those 8 chips connects to a single one of these data lines. So, 8 chips for 8 data bits. Simple, inexpensive, fast, cheap. For the upper 32k, it's the same principle. It uses 8 x TMS4532 (which you can also see in the photo to the right of the 16k), each one holding 32768 x 1 bit, and I don't really think it's using "twice as many memory chips" as you say. If what you mean by this is that instead of 16K + 32k RAM it could have used the full 64k with only 8 chips (these would be the 4164 chips, each holding 65536 x 1 bit) instead of 16 chips, please note that this would completely fill the processor address space and, unless you used some clever "costly" electronics, you'd have to throw out the initial 16K because that space is reserved for the ROM. Also, you would not have (easily) an upgrade possibility of a 16k to a 48k Spectrum. And for sure, using 8 x 4164s would also be more expensive than using the 4116 + TMS4532 approach. The TMS4532 is a half broken 4164, meaning that it was found faulty in either the lower 32k or the upper 32k half of the chip. That's why there are two versions of it: The TMS4532-15NL3 and the TMS4532-15NL4, the former having the lower 32k ok, and the latter having the upper 32k ok. You can't mix these types with each other, the 8 chips have to be all NL-3 or all NL-4. The selection of which 32k half is the valid one is performed on the Spectrum board by a wire jumper. Technically, you could use 4164 chips instead and it would always work regardless of how that jumper is set (but it must be there). Hope this clarifies the issue (if I didn't mess up somewhere). Cheers!
there were also OKI 4532s that had the dropout bad section on the other part of the address, one brand had a dud 'column' one a dud 'row' cant remember offhand which was which, so the memory links had 4 possible combinations and of course couldnt mix types when replacing (unless using a 4164 as stated😉)
Excellent information. I'm still really frustrated however that I found it extremely difficult to get access to this kind of knowledge and insight when I was 16 in 1982. Penfolds 'An Introduction to Z80 Machine Code' was about as indepth a book as I could find at the time. There was almost nothing about algorithms, game design and code optimisation. How the world has changed thanks in part to YT and years and years of real world experience.
Quite true, it was very very hard to find specialized information. First because most people wouldn't really care, they wanted to play games, and second because only a few people knew about it, computers were not nearly as prevalent as today. Even today only a few would know about how a cpu works or what are interrupts, maybe they are still wanting to play games I guess, but the information is much, much easier to find nowadays. I think I had that book on Z80 machine code too, also the complete ROM disassembly 😉
R.A. Penfold! Gosh, there's a name I haven't heard in years.. I remember a time when it seemed like every book about my favourite subjects was written by him (and, often, his brother). Good memories.
I feel you. I had 'Programming the Z80' by Zacks, which I pretty much understood but it left me clueless how to draw graphics on my Amstrad. I had no clue I needed such thing as a firmware manual and I probably wouldn't have known where to get one if I did.
I found it was quite easy to get great information from 1977. You just had to look in the right places. Great books include the Spracklen’s Sargon Chess book with source code and Z80 & 8080 Assembly Language programming book. With manual hand assembly just getting code to work was an achievement let alone optimising it.
In my custom rom i removed the interrupt for the keyboard handler. Built the scanning in the keyboard loop. Now you can disable interrupts and no lock up...
I solved this problem in what I think is a more elegant way when designing a keyboard for my Z80 homebrew. I just loaded down the data bus with a network of 8 resistors to ground, so that if no device (like the DART for example) was putting the interrupt vector on the data bus, the processor would just read 0x00 from the data bus, and use that as the interrupt vector.
The problem is that Z80 starts code execution from address 0x0000, so you probably have a ROM at this address, which contains actual code. It means that the programmer has no chance to put any arbitrary vector at this particular address. I think that the idle state of the bus which equals 0xff is a better idea. Or you can just use IM1, and at interrupt vector, you can take an address from RAM, something like LD HL,(address), JP(HL).
@@tmfmikro 0 is not the vector address, just the lower byte of it. The higher byte can be anything. Also, it doesn't actually have to be a zero, can really be anything. I happened to pick zero, but you could hardwire any value.
to be fair it was this genius that made home computing affordable AND many people are very successful for having learned their trade on them the spectrum was far from perfect as was most other "affordable "micros but again the 16k came in at £99 new so at least forty quid cheaper then the vic 20 which was also flawed
Was it my design or by mistake though - originally coder provided the High 8 bits in the I register - the bottom 8 bits were always 255....so vector only took 2 bytes - until the Sinclair Interface 1 came out.. that changed the value of the Low 8 bits when that was plugged in. So, then as you say - you had to waste 257 bytes on a vector table - but someone much after release, not by original hardware design, figured out you could use the 257 unused bytes in ROM. This trick broke with the 128K spectrums however which used that Rom space - and you had to go back to wasting 257 bytes ram. There was another interrupt that wasnt used - the NMI on the expansion port at the back - it could have been intended to let you implement maybe an ESC key or hardware breakpoint tool - ROM code was supposed to read a value from ram (address 23728 -NMIADD) and jump to it - but a bug in the ROM meant it didn't work.
It's not completely true that when the Z80 reads the data bus and nothing is put there, the value is random. When the Z80 reads the bus and there is "nothing", it will read always 255. Also, due to the bus design in the Spectrum, reading from a port without a peripheral attached to it results in getting the value that the ULA is reading in that precise moment from RAM, which explains why sometimes you read "random" values in the bus. But the point is that the ULA generates the interrupt precisely when it begins to paint the upper-left corner of the screen, which is BORDER. That means that, in that instant, it doesn't need to read from the RAM and the bus will be 255, so in a "pure" spectrum you don't need the table; just can assume that the bus will be 255. The problem comes with some cheap interfaces (like the original Kempston), which doesn't decode the RD line, but only the A5 and the IORQ. That means that, if the last data read by the Z80 had the A5 address line set to zero, the kempston interface will put the joystick data in the bus because the Z80 will set low IORQ and M1 to indicate that it is waiting for interrupt data, and that confuses the kempston interface.
@@AlexestpersonneNot any Kempston IF, but only those that don't decode the RD line (well, or any interface that uses the same trick to reduce the number of chips required).
The value is random because the IM2 interrupt handler doesnt know what value is on the data bus and so every possible vector has to point to the same address in order to work.
Its not quite random because the CPU half of the data bus is resistor coupled the Video half, which means you may get $FF during blank periods, but if you read the data when the video is being processed, you may get attribute data. (Note, attribute data because the the ULA does a 2-step read using the CAS signal, which is why the video memory layout is so messed up, and the data present when the CPU actually samples the data is the attribute. This is used in some games to do clever border tricks)
Thanks for the great explanation, I used to write z80 assembler when I first stared coding many years ago working on cpm machines.. Can you clarify, the 48k spectrum presumably has a 16k gap in the ram somewhere. For the vector mapping to work as described it needs ram at both the top end and the bottom end of the address space so where was the 16k gap? also how big and where was the rom located? Looking forward to the DMA video,.
On the 48k spectrum the first 16k of address space from 0000 is used by the ROM. The remainder is the 48k of RAM. The Spectrum ROM uses IM1 for its interrupt instead of IM2. Games and software that didn't use ROM routines would use IM2.
I decided that I don't get it. What was the advantage of using vectored interrupts if they didn't use vectoring? Surely, Mode 1 would have been more appropriate for a system where only one devices generates interrupts?
i thought the same thing. they could just put a jump command at 0x0038 to somewhere in the ram in case the rom was also used like 0c8000 where the programmer could put their own jump command. although it's competitively hilariously over engineered it is more preferable to wasting 257 bytes of 16k of ram.
As I recall, the interrupts on the Spectrum ran in IM1 but they never thought to put any kind of 16 bit vector in their system variables space to be read by their IM1 handler code so we programmers could hang extra code on the existing vertical blanking routines which were all frozen in ROM space. Hence the need to use the IM2 mode. We never trusted that ROM 0xFF hack, believing something else, one day might appear there. EDIT: Switching to IM2 with the vector table was a hack we programmers used, to be able to write custom code running on interrupts. Sinclair themselves did not need IM2.
Ridiculus: 1) The z80 was not a underpowered or slow CPU on the ZX Spectrum era. There were worse cpu's . 2) An interrupt does not make a cpu more capable than it is, even the opposite. Handling an interrupt imposes to the cpu some additional operations like saving the instruction ptr (on z80 called PC, eventually some registers onto the stack etc). This consumes time, that is a non working time. Too much interrupt requests instead slow down the cpu for the 'main job' it was executing. I remember a c64 (based on 6502 cpu) software that handled the movement of a sprites on screen under interrupts. Even if handling hw sprites on c64 is not a so heavy task and can effecively run under interrupt i recall clearly that, when this routine was executing (moving sprites around the screen), the list command was remarcably slower in its output. It was obvious, the CPU ad to do additional work to handle sprite movements fifty times per seconds and this time was subtracted from main task.
I am a bit confused with your explanation on interrupts. @5:32 There are 2 types of interrupts Maskable and nonmaskable. What you did not precise they are implemented over 4 pins of the Z80 PIN Type of Interrupt 1 Maskable IM0 2 Maskable IM1 (the CPU restarts at address 0038h) 3 Maskable IM2 (Interrupt Vector table) 17 NonMaskable NMI (Non Maskable Interrrupt) @6:51 you mention the VBI (Vertical Blank Interval), but you left us in the void, which interrupt is being used to trigger it? (IM2 or NMI). Is the ULA wired to the NMI? Or is it some other clever method?
The z80 doesnt have interrupt levels other then NMI and INT, just interrupt modes which are incompatible, so there are only two interrupt pins, NMI and INT (Well three if you count reset, as that's basically just an NMI that forces a jump to $0000) NMI (Pin 17) always forces a jump to $0066 and is by default unused by the speccy. Snapshot devices like the multiface do use this and a page in of their own ROM to take control of the machine. INT (Pin 16) causes an Maskable interrupt. On the speccy, it is by default triggered by the vertical blank, so 50 times a second. The interrupt mode only controls what happens when you pulse the INT pin. You can only have one mode active at a time. IM0 is basically a hold-over from the 8080 and of no practical use on the speccy. (Basically it expects a peripheral to put one of the 8 RST instructions on the bus, but as these addresses are already used for other things in the speccy, they arent much use. (The instructions are RST 0 RST 8 RST 10h .... RST 38h) IM1 is the simplest one that forces a jump to $0038. This is used by the speccy for keyboard input. IM2 is the complex super one that is more useful in non-Speccy systems, particularly with the proper z80 peripherals, but uses the vector lookup table as described.