Is it possible to boot your Model I automatically from harddisk? The Model I was capable of using a harddisk although Tandy didn't promote it. Beside the harddisk you needed an Harddisk Interface (26-1001) which is very rare nowadays. Booting from HDD however was not possible, the Model I ROM didn't support this, nor did any of the DOS's.
So we need to change the ROM and the DOS to make this happen. This page describes the modifications that must be made, and the search for a few bytes necessary to squeeze in the extra routines. The modifications for Newdos/80 2.5 can be found here, the hardware modifications to use a new 2716 ROM in the Model I are described in the hardware section.
The specs are:
This wasn't going to be simple a modification with some switches or a print. We had to exchange the ROM chips for some EPROM we programmed (burned) our self. For those with a EPROM-programmer the binary can be found here.
So we need to change the ROM and the DOS to make this happen. This page describes the modifications that must be made, and the search for a few bytes necessary to squeeze in the extra routines. The modifications for Newdos/80 2.5 can be found here, the hardware modifications to use a new 2716 ROM in the Model I are described in the hardware section.
The specs are:
- The TRS-80 should boot from the hard disk in (at least) Newdos2.5
- Using the BREAK-key while booting should put us in BASIC level II with the Memory Size?
- Using any other key while booting should give the possibility to start up with a floppy disk.
- The TRS-80 should not be altered.
This wasn't going to be simple a modification with some switches or a print. We had to exchange the ROM chips for some EPROM we programmed (burned) our self. For those with a EPROM-programmer the binary can be found here.
Current Boot Sequence
The TRS-80 has a Z80 microprocessor instead of an Intel 8088, 80386, Pentium and so on. The PC has Bios chips while the TRS-80 has ROM chips with a bios program and Basic in only 12K. The ROMs in the TRS-80 were programmed by Microsoft and the copyright was sold to Tandy. To switch the ROMs we needed EPROM chips and some rewiring in the Model I. This is how the TRS-80 ROM divides the 64K memory:
With no Disk Basic loaded you have 64- 21=43kbytes left and with Disk Basic 64-26=39K. Note that I have omitted the character H in the next story. I shall explain the working of our EPROM with some insights in Bill Gates (and Allen Paul) their ROM. The ROM chip starts:
To be sure that the control block data is at the right place, the Rom repeats this process 128 times (starting from 0 to 256 in steps of 2 (DEC A DEC A)) As we will need every byte, remember this place where we can win a byte by just slowing down the TRS-80 a bit. Delete DEC A and the TRS-80 will repeat the process 256 times instead of 128 times and while doing this the TRS-80 will be 0.1 of a second slower at starting up. Every byte counts.
This resets 27H bytes at 4036-4062. Now here comes an important part, as we want to intercept the keyboard to test the BREAK-key and other keys as well.
Here we will start with our intercept. The command at 0693 can be replaced. If the BREAK-key has not been pressed then the computer will test if you do have an E.I. connected. If no Expansion Interface can be found a jump is made to 0075 where a clever routine tests all sort of things. It's there to find eleven bytes!!
But here they missed something. Luckily for us, so we can gain two more bytes.
At 0696 we could load HL with 37EC and than perform a LD A,(HL). That's one byte longer, but afterwards we can gain three bytes because HL still contains 37EC. Gained two bytes!
Again we can win a byte here by just LD (HL),8C instead of LD A,8C and than LD (HL),A. Now the last control to see if the data is ready, and if so read it.
As you see, just 256 bytes will be read, regardless of the size of sector 0! These 256 bytes are at 4200-42FF, that is in RAM memory. At last!!
Lets resume: We saw that the ROM lets the Z80 search for the BREAK-key at the keyboard. If no BREAK-key has been found and there is no E.I. (Expansion Interface) attached to your system than sector 0 track 0 is placed byte by byte at 4200-42FF. After this the Z80 jumps to 4200 to boot from floppy.
Booting from HDD
So this is what we have to do. Make a new ROM which searches for the BREAK-key or some other (special?) key. If no key has been pressed the hard disk should restore and read sector 0, head 0 of track 0 and write it to 4200H and further. The controller used is a WD1002-05 (Western Digital). This controller can be programmed to work with ports C8-CF. The hardware parts can be found on this website.
This is the program scheme Rence constructed to start the HDD:
This is the program scheme Rence constructed to start the HDD:
CALL drive_ready is needed to test the HD ready. To do this we read CF (status) in register A. Than we AND C0 to test bit 6 and 7 both on 1. So 1 and 1 is busy and ready . Than we XOR 40 to see if the status says 0 and 1. The WD1002-05 needs this double checking instead of simple testing the busy (bit 7) bit.
With LD A,20 and the CALL_drive command we give the read sector command to the controller. Now we load HL with 4200 to INIR the port C8 for 256 times. INIR will look in reg. C which port to read and in reg. B for how many times to loop and HL where to write to. From the documentation of the WD1002-05 we learned the meaning of the ports C8- CF CF is the status/command port and C8 is the sector data port.
I read a article in TRS-Times Volume 7 no.1 where Roy Beck gave some extra information about all the ports and the details of the WD 1001/1010 HD controllers.
This is what we have so far for the moment. The ROM finds a HDD and reads 256 bytes from head 0 sector 0 cylinder 0 and transfers this bytes to 4200-42FF. Now the program continues at 4200 where the boot sector should be. Format a hard disk, put the boot sector on sector 0 track 0 and start your TRS-80 Model I. The boot sector program should tell the computer to continue to read from the HDD.
With LD A,20 and the CALL_drive command we give the read sector command to the controller. Now we load HL with 4200 to INIR the port C8 for 256 times. INIR will look in reg. C which port to read and in reg. B for how many times to loop and HL where to write to. From the documentation of the WD1002-05 we learned the meaning of the ports C8- CF CF is the status/command port and C8 is the sector data port.
I read a article in TRS-Times Volume 7 no.1 where Roy Beck gave some extra information about all the ports and the details of the WD 1001/1010 HD controllers.
This is what we have so far for the moment. The ROM finds a HDD and reads 256 bytes from head 0 sector 0 cylinder 0 and transfers this bytes to 4200-42FF. Now the program continues at 4200 where the boot sector should be. Format a hard disk, put the boot sector on sector 0 track 0 and start your TRS-80 Model I. The boot sector program should tell the computer to continue to read from the HDD.
From 0000 to 0060 nothing has been changed. As the ROM jumps to 0674, we will jump there also. At 0674 and 0675 we had to take two bytes in advance so our listing is two bytes longer than the original. But at 0682 we regained our first byte so our listing will be only one byte larger then Bill's. The new TRS-80 will start up in 1.2 in stead of 1.1 seconds, that 1 sec extra comes from the waiting loop at CALL 0060. At 0692 we used BIT 2,A instead of AND 04 on 068E (old ROM). Both instructions tests bit 2 in register A. Bit 2 indicates if the BREAK-key is pressed. At that moment address 3840 (decimal 14400) resides in register A. By using AND 04 the other bits in reg. A are set to zero. By just testing bit two the reg. A remains what it is, giving us the opportunity to test the keyboard address 3840 again. This we did with RLA. RLA will test the left bit which represents the SPACE-BAR. We looked for an extra byte in this area several times in many different ways but didn't find one minding the fact that we had to walk in pace again at 06CC. At 0694 we do a jump to Basic Level II if the BREAK-key has been pressed during reset. At 0697 we jump to starting with floppy routine if a SPACE-BAR has been pressed during reset. From 0699 to 069C we do some testing for a hard disk drive. If not found we start with floppy and if there is no floppy than we start with Level II on 06A4.
By now our listing is about eleven bytes larger. You can compare 069F (new ROM) with 0696 (old ROM). But lets get back to 069F (new ROM). This is the starting point for the floppy disk routine while the comparing code in the old ROM starts at 0696. We did the following tide programming. - At 06B0 we did a CALL without putting BC 0000. We know BC is zero already so we gained three bytes. - At 06B7 there is no need to zero A. A is zero already and can be placed in HL directly gaining an other three bytes. - At 06B9 just load B with 42. C still is zero. Another byte profit. - At 06BB we pushed BC so the stack became 4200. Now we can replace the JP 4200 by only a simple RET giving us a byte. - At 06BC we placed 8C directly in (HL). Bingo an other byte. - By loading DE with 37EE and an INC we gained our last byte here. As I stated our listing was one byte larger. But at 069F we use LD HL, 37EC in combination with LD A, (HL). These are four bytes in stead of the correspond ending LD A,(37EC) at 0696. But as we can omit the LD HL, 37EC at 06A4 we gain two bytes to fill our total needs.
If purely inserted, the program scheme to start the HDD would have taken 28 bytes. The text MEMSIZE R/S L2 BASIC occupies 23 bytes. At the end of the ROM there are 6 bytes left. But it can't be done. Replacing the code gives no redundancy in the contrary. We ended to need at least 34 bytes. That's why de code had to be shortened and put at several places. To be sure that register pair BC would ended on C800 Rence did the following. He loaded BC with 06CE. Due to OUT(C),A- DEC C-DJNZ 010B all ports will be loaded with zero, even two ports extra. The bulk of code is placed at 0105 where the Memsize text formerly resided. An other piece of the code is placed at 0066, well to be honest at 006A. The original ROM uses the code starting at 0066 to test whether you have a floppy drive, an E.I. or not. It is the starting point if you press the reset button at the rear of the computer keyboard. This is known as the "warm start". This code has been reduce to 4 bytes (XOR A, DEC A and JR 0000) allowing us to use eleven bytes. This gives some incompatibility with the old ROM. So to run BASIC Level II you now must to do a "cold start" as the routine at 0066 will simply load A with zero, reset the zero flag and jump to 0000 in stead of jumping to Level II (JP 06CC). If you want to go from DOS to Level II Basic for some special reason you have to do a "cold start" or write a "Boot Level II" program (JP 0000) or mount an extra "cold start reset button". I can not imagine a TRS-80 user with a HDD ROM without E.I. or floppy at least. So if you reset I think you want to use at least your floppy drive. Note that the new ROMs always reinitialize the first piece of RAM (4000-4062).
We had to change to more places in the old ROM. At 00B5 and at 00FC the old ROM points to the "MEMSIZE" and "R/S L2 BASIC" text. These two addresses now points to the new places were this texts resides. One last thing. A piece of the new (shortened) text "Mem. R/S L2.." resides at 0471 and following bytes. Originally this was the place were the TRS-80 changed every lowercase letter into a uppercase letter. So with this new ROMs you can work with lowercase even in Basic Level II.
By now our listing is about eleven bytes larger. You can compare 069F (new ROM) with 0696 (old ROM). But lets get back to 069F (new ROM). This is the starting point for the floppy disk routine while the comparing code in the old ROM starts at 0696. We did the following tide programming. - At 06B0 we did a CALL without putting BC 0000. We know BC is zero already so we gained three bytes. - At 06B7 there is no need to zero A. A is zero already and can be placed in HL directly gaining an other three bytes. - At 06B9 just load B with 42. C still is zero. Another byte profit. - At 06BB we pushed BC so the stack became 4200. Now we can replace the JP 4200 by only a simple RET giving us a byte. - At 06BC we placed 8C directly in (HL). Bingo an other byte. - By loading DE with 37EE and an INC we gained our last byte here. As I stated our listing was one byte larger. But at 069F we use LD HL, 37EC in combination with LD A, (HL). These are four bytes in stead of the correspond ending LD A,(37EC) at 0696. But as we can omit the LD HL, 37EC at 06A4 we gain two bytes to fill our total needs.
If purely inserted, the program scheme to start the HDD would have taken 28 bytes. The text MEMSIZE R/S L2 BASIC occupies 23 bytes. At the end of the ROM there are 6 bytes left. But it can't be done. Replacing the code gives no redundancy in the contrary. We ended to need at least 34 bytes. That's why de code had to be shortened and put at several places. To be sure that register pair BC would ended on C800 Rence did the following. He loaded BC with 06CE. Due to OUT(C),A- DEC C-DJNZ 010B all ports will be loaded with zero, even two ports extra. The bulk of code is placed at 0105 where the Memsize text formerly resided. An other piece of the code is placed at 0066, well to be honest at 006A. The original ROM uses the code starting at 0066 to test whether you have a floppy drive, an E.I. or not. It is the starting point if you press the reset button at the rear of the computer keyboard. This is known as the "warm start". This code has been reduce to 4 bytes (XOR A, DEC A and JR 0000) allowing us to use eleven bytes. This gives some incompatibility with the old ROM. So to run BASIC Level II you now must to do a "cold start" as the routine at 0066 will simply load A with zero, reset the zero flag and jump to 0000 in stead of jumping to Level II (JP 06CC). If you want to go from DOS to Level II Basic for some special reason you have to do a "cold start" or write a "Boot Level II" program (JP 0000) or mount an extra "cold start reset button". I can not imagine a TRS-80 user with a HDD ROM without E.I. or floppy at least. So if you reset I think you want to use at least your floppy drive. Note that the new ROMs always reinitialize the first piece of RAM (4000-4062).
We had to change to more places in the old ROM. At 00B5 and at 00FC the old ROM points to the "MEMSIZE" and "R/S L2 BASIC" text. These two addresses now points to the new places were this texts resides. One last thing. A piece of the new (shortened) text "Mem. R/S L2.." resides at 0471 and following bytes. Originally this was the place were the TRS-80 changed every lowercase letter into a uppercase letter. So with this new ROMs you can work with lowercase even in Basic Level II.
Old ROM
0000 F3 DI 0001 AF XOR A 0002 C37406 JP 0674 0060 0B DEC BC 0061 78 LD A,B 0062 B1 OR C 0063 20FB JR NZ,0060 0065 C9 RET 0066 310006 LD SP,0600 0069 3AEC37 LD A,(37EC) 006C 3C INC A 006D FE02 CP 02 006F D20000 JP NC,0000 0072 C3CC06 JP 06CC 0075 118040 LD DE,4080 00B5 210501 LD HL,0105 00FC 210E01 LD HL,0l0E 0105 4D454D DEFM 'MEM' 0108 205349 DEFM ' SI' 010B 5A45 DEFM 'ZE' 0l0D 00 DEFB 00 010E 522F53 DEFM 'R/S' 0111 204C32 DEFM 'L2' 0114 204241 DEFM 'BA' 0117 534943 DEFM 'SIC' 011A 0D DEFB 0D 011B 00 DEFB 00 0471 FE40 CP 40 0473 3808 JR C,04D7 0475 D640 SUB 40 0477 FE20 CP 20 0479 3802 JR C,047D 047B D620 SUB 20 047D CD4105 CALL 0541 2FFB DEC3 SBC C3 2FFD C344B2 JP B244 0674 D3FF OUT 0FF), A 0676 21D206 LD HL,06D2 0679 110040 LD DE,4000 067C 013600 LD BC,0036 067F EDB0 LDIR 0681 3D DEC A 0682 3D DEC A 0683 20F1 JR NZ,0676 0685 0627 LD B,27 0687 12 LD (DE), A 0688 13 INC DE 0689 10FC DJNZ 0687 068B 3A4038 LD A,(3840) 068E E604 AND 04 0690 C27500 JP NZ,0075 0693 317D40 LD SP,407D 0696 3AEC37 LD A,(37EC) 0699 3C INC A 069A FE02 CP 02 069C DA7500 JP C,0075 069F 3E01 LD A,01 06A1 32E137 LD(37E1), A 06A4 21EC37 LD HL,37EC 06A7 llEF37 LD DE,37EF 06AA 3603 LD(HL), 03 06AC 010000 LD BC,0000 06AF CD6000 CALL 0060 06B2 CB46 BIT 0,(HL) 06B4 20FC JR NZ,06B2 06B6 AF XOR A 06B7 32EE37 LD(37EE), A 06BA 010042 LD BC,4200 06BD 3E8C LD A,8C 06BF 77 LD(HL), A 06C0 CB4E BIT 1,(HL) 06C2 28FC JRZ,06C0 06C4 1A LD A,(DE) 06C5 02 LD(BC), A 06C6 0C INC C 06C7 20F7 JR NZ,06C0 06C9 C30042 JP 4200 06CC 01181A LD BC,lA18 06CF C3AEl9 JP l9AE 06D2 Jump Table
New ROM
0000 F3 DI 0001 AF XOR A 0002 C37406 JP 0674 0060 0B DEC BC 0061 78 LD A,B 0062 B1 OR C 0063 20FB JR NZ,0060 0065 C9 RET 0066 AF XOR A 0067 3D DEC A 0068 1898 JR 0000 006A D3CF OUT(0CF),A 006C DBCF IN A,(0CF) 006E E6C0 AND C0 0070 EE40 XOR 40 0072 20F8 JRNZ, 006C 0074 C9 RET 0075 118040 LD DE,4080 00B5 21FB2F LD HL,2FFB 00FC 217304 LD HL,0473 0105 CD6C00 CALL 006C 0108 0lCE06 LD BC, 06CE 010B ED79 OUT (C),A 0l0D 0D DEC C 010E 10FB DJNZ 010B 0110 3E20 LD A, 20 0112 CD6A00 CALL 006A 0115 210042 LD HL,4200 0118 E5 PUSH HL 0119 EDB2 INIR 011B C9 RET 0471 180A JR 047D 0473 522F53 DEFM 'R/S' 0476 204C32 DEFM ' L2' 0479 2E2E DEFM '..' 047B 0D DEFB 0D 047C 00 DEFB 00 047D CD4105 CALL 0541 2FFB 4D656D DEFM 'Mem' 2FFE 2E DEFM '.' 2FFF 00 DEFB 00 0674 08 EX AF, AF' 0675 AF XOR A 0676 D3FF OUT (0FF),A 0678 21D206 LD HL,06D2 067B 110040 LD DE,4000 067E 013600 LD BC, 0036 0681 EDB0 LDIR 0683 3D DEC A 0684 20F2 JR NZ,0678 0686 0627 LD B,27 0688 12 LD (DE), A 0689 13 INC DE 068A 10FC DJNZ 0688 068C 317D40 LD SP, 407D 068F 3A4038 LD A,(3840) 0692 CB57 BIT 2, A 0694 2032 JRNZ, 06C8 0696 17 RLA 0697 3806 JR C,069F 0699 DBCF IN A,(0CF) 069B 3C INC A 069C C20501 JP NZ,0105 069F 21EC37 LD HL,37EC 06A2 7E LD A,(HL) 06A3 3C INC A 06A4 2822 JR Z, 06C8 06A6 3E01 LD A, 01 06A8 32E137 LD(37E1), A 06AB llEE37 LD DE,37EE 06AE 3603 LD (HL),3 06B0 CD6000 CALL 0060 06B3 CB46 BIT 0,(HL) 06B5 20FC JR NZ, 06B3 06B7 12 LD (DE),A 06B8 13 INC DE 06B9 0642 LD B,42 06BB C5 PUSH BC 06BC 368C LD (HL),8C> 06BE CB4E BIT 1, (HL) 06C0 28FC JR Z,06BE 06C2 1A LD A,(DE) 06C3 02 LD (BC), A 06C4 0C INC C 06C5 20F7 JR NZ, 06BE 06C7 C9 RET 06C8 08 EX AF, AF' 06C9 CA7500 JP Z,0075 06CC 01181A LD BC,lA18 06CF C3AEl9 JP l9AE 06D2 Jump Table