TRS-80 Gebruikers Vereniging

Actief sinds 1 oktober 1978

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:
  • 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:
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.
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.
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
2FFD	C344B2	JP B244
0674	D3FF	OUT 0FF), A
0676	21D206	LD HL,06D2
0679	110040	LD DE,4000
067C	013600	LD BC,0036
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
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	 
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
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