12596
UTILITAIRE -> Divers
© _Public_Domain_ (1998)
 
 
 
RAMROM Loader
cpc
 
 

NOTICE / MANUAL

TXT (1)

NOTICE TEXTE n° 1 (32.67 Ko)

ORG &9000 .MC_START_PROGRAM EQU &BD16 .KL_ROM_WALK EQU &BCCB .TXT_WIN_ENABLE EQU &BB66 .TXT_GET_CURSOR EQU &BB78 .TXT_SET_CURSOR EQU &BB75 .TXT_PLACE_CURSOR EQU &BB8A .TXT_REMOVE_CURSOR EQU &BB8D .SCR_SET_MODE EQU &BC0E .KL_PROBE_ROM EQU &B915 .KM_WAIT_KEY EQU &BB18 .KM_RESET EQU &BB03 .CAS_IN_OPEN EQU &BC77 .CAS_IN_DIRECT EQU &BC83 .CAS_IN_CLOSE EQU &BC7A .KL_ROM_SELECT EQU &B90F .SCR_CHAR_POSITION EQU &BC1A .CAS_CATALOG EQU &BC9B .CAS_OUT_OPEN EQU &BC8C .CAS_OUT_DIRECT EQU &BC98 .CAS_OUT_CLOSE EQU &BC8F .CAS_IN_ABANDON EQU &BC7D .CAS_OUT_ABANDON EQU &BC92 .BIOS_GET_STATUS EQU &C048 .TXT_OUTPUT EQU &BB5A .TXT_WR_CHAR EQU &BB5D .TXT_RD_CHAR EQU &BB60 .KM_TEST_KEY EQU &BB1E .INC_HIX EQU &24DD .DEC_HIX EQU &25DD .LD_LIX_A EQU &6FDD .LD_A_HIX EQU &7CDD LD HL,START LD C,&FF JP MC_START_PROGRAM .START LD HL,&ABFF LD DE,&40 CALL KL_ROM_WALK LD A,2 CALL SCR_SET_MODE DI ;Disable the interrupts so the Z80 doesn't try to execute an interrupt LD HL,&3A ;while the jumpblock is being changed. LD DE,INTERRUPT+2 LD BC,3 LDDR ;Used an LDDR so that HL points to the byte below &38. INC HL LD (HL),&C3 ;Alter the interrupt indirection so it jumps to the new routine. INC HL LD (HL),BANNER_MODE MOD 256 INC HL LD (HL),BANNER_MODE/256 EI LD C,0 CALL KL_PROBE_ROM ;Find out what kind of CPC this is by looking at the BASIC LD A,H ;ROM version number. CP 1 JR C,CPC464 JR Z,CPC664 .CPC6128 LD HL,&AE66 LD (REF_ADDR_BAS+2),HL INC HL INC HL LD (REF_ADDR_BAS+6),HL INC HL INC HL LD (REF_ADDR_BAS+10),HL INC HL INC HL LD (REF_ADDR_BAS+14),HL LD HL,&EA78 LD (REF2_ADDR_BAS+1),HL JR CONTINUE .CPC464 LD HL,&AE83 LD (REF_ADDR_BAS+2),HL INC HL INC HL LD (REF_ADDR_BAS+6),HL INC HL INC HL LD (REF_ADDR_BAS+10),HL INC HL INC HL LD (REF_ADDR_BAS+14),HL LD HL,&E9BD LD (REF2_ADDR_BAS+1),HL JR CONTINUE .CPC664 LD HL,&AE83 LD (REF_ADDR_BAS+2),HL INC HL INC HL LD (REF_ADDR_BAS+6),HL INC HL INC HL LD (REF_ADDR_BAS+10),HL INC HL INC HL LD (REF_ADDR_BAS+14),HL LD HL,&EA7D LD (REF2_ADDR_BAS+1),HL .CONTINUE LD BC,STARTMESS LD DE,&C000 ;Address of where the banner will be printed. CALL MESSAGES ;The characters will be like in mode 1 but printed in mode 2. LD HL,2 LD DE,&5019 CALL TXT_WIN_ENABLE ;Set the window so that the banner stays at the top. LD HL,MESS1 CALL TEXTLOOP CALL KM_WAIT_KEY LD A,&FF LD (&BE78),A .FIND_DISC LD A,10 CALL TXT_OUTPUT CALL TXT_GET_CURSOR NEG ;This is like doing a SUB L,A. ADD L ;Have to take the screen roll into account. LD L,A LD (CURSOR_POS),HL ;Store the position of the cursor for future use. CALL DISC_DRIVE LD (DRIVE_NUM+1),A PUSH AF LD B,A INC B LD HL,&C01B .AUTO_DETECT ;Alters HL to point to the address for ùA or ùB. INC L INC L INC L DJNZ AUTO_DETECT DW INC_HIX DW INC_HIX LD A,(IX-&73) LD (BIOS_READ_SECTOR+2),A LD C,A XOR A PUSH IX CALL &1B POP IX POP AF ADD A ADD A ADD A ADD A ADD A ADD A ADD &90 DW DEC_HIX DW LD_LIX_A LD HL,&2000 LD A,(IX+9) LD BC,&8FF .DIRLEN AND A RLA JR NC,DIRCONT INC C .DIRCONT DJNZ DIRLEN LD A,C .LOG2A INC B SRL A JR C,LOG2A LD A,B ADD (IX+2) SUB (IX+&14) LD B,A LD A,1 .TWO_PWR_A ADD A DJNZ TWO_PWR_A SRL A LD B,A LD D,(IX+&D) .DRIVE_NUM LD E,0 LD C,(IX+&F) .READ_DIRECTORY PUSH HL RST 3,BIOS_READ_SECTOR JP NC,BAD_CAT POP HL PUSH DE LD DE,&200 ADD HL,DE POP DE DJNZ INC_SECTOR JR REARRANGE_FILES .INC_SECTOR INC C LD A,(IX+&10) ADD (IX+&F) CP C JR NZ,READ_DIRECTORY INC D LD C,(IX+&F) JR READ_DIRECTORY .REARRANGE_FILES LD (HL),&E5 LD L,(IX+7) ;Find out how many directory entries there are. LD H,(IX+8) LD (NO_ENTRIES),HL CALL BUBBLE_SORT LD A,(&2000) CP &E5 JR NZ,CAT LD HL,MESS15 CALL TEXTLOOP CALL KM_WAIT_KEY JP FIND_DISC .CAT LD HL,&1FE0 ;This loop displays all of the filenames on the disc. PUSH HL .DISPLAY_CAT POP HL LD DE,&20 ADD HL,DE LD A,(HL) CP &E5 JP Z,SELECT_FILES ;If all of the directory entries have been displayed PUSH HL ;jump to the bit to select the files INC HL LD DE,BUFFER LD A," " LD (DE),A INC DE LD BC,8 LDIR LD A,"." LD (DE),A INC DE LD BC,3 LDIR INC HL INC HL INC HL LD IY,0 ;Use IY as a counter for the size of the file LD A,(HL) RLCA JR NC,FIND_SIZE .MULTI_BLOCK LD HL,16 EX DE,HL ADD IY,DE ;Just the same as doing ADD IY,HL. EX DE,HL POP BC PUSH BC LD HL,44 ;Checks whether this entry has another part. ADD HL,BC OR A JR Z,BLOCK_SIZE ;Jumps to BLOCK_SIZE if it doesn't. LD HL,32 ADD HL,BC ;Points HL to the next entry for the filename. LD A,&E5 ;Marks this second part as erased, so that there aren't two entries LD (HL),A ;with the same name. .BLOCK_SIZE LD HL,47 ADD HL,BC ;HL points to the length of this entry. LD A,(HL) PUSH AF PUSH DE CALL NZ,BUBBLE_SORT ;This moves the erased file to the end, if it was erased. POP DE POP AF RLCA JR Z,FIND_SIZE JR C,MULTI_BLOCK ;If this entry is 16K also, look for another entry. .FIND_SIZE RRCA RRCA RRCA RRCA LD H,A AND &1F LD L,A LD A,H AND &E0 JR Z,ROUND_DECIMALS INC L .ROUND_DECIMALS LD H,0 EX DE,HL ADD IY,DE EX DE,HL PUSH IY POP HL XOR A ADD H DAA LD H,A XOR A SRL L ;Divides L by two so that when it is changed to decimal it isn't more JR NC,A0 ;than 199. INC A ;If the number is odd add one on to A. .A0 PUSH AF LD A,L ;Need to find L as a BCD number before adding. AND &F0 RRCA RRCA RRCA RRCA LD B,A INC B XOR A .MULTIPLY ADD &16 DAA DJNZ MULTIPLY SUB &16 DAA LD B,A LD A,L AND &F LD C,A XOR A ADD C DAA ADD B DAA LD L,A POP AF ADD L ;Add the first half to A DAA JR NC,CHECK_CARRY PUSH AF ;If the BCD number overflowed increment H. LD A,H AND A INC A DAA LD H,A POP AF .CHECK_CARRY ADD L ;Add the second half to A. DAA JR NC,PRINT_CHAR PUSH AF ;If the BCD number overflowed increment H. LD A,H AND A INC A DAA LD H,A POP AF .PRINT_CHAR LD L,A ;Store the BCD number in L. .NUMBER_OF_NUMBERS XOR A LD B,A ;This part finds out how many spaces to add so that the number is LD A,4 ;right justified. PUSH AF .TEST_NIBBLES LD A,L AND &F ;Only look at the last nibble of the HL register pair. JR Z,NO_NUM LD C,B ;C holds the highest number of digits so far. .NO_NUM POP AF RR H ;Rotate the HL register pair so that the next nibble is where the RR L ;last one was. RR H RR L RR H RR L RR H RR L PUSH AF INC B CP B ;If B is 4 finish the loop, otherwise increment B and repeat it. JR NZ,TEST_NIBBLES RR H ;Return HL to its previous value. RR L POP AF SUB C LD B,A CALL ADD_SPACES LD A,C ;C is one less than the number of digits. SUB 1 ;Need to do SUB rather than DEC, because DEC doesn't set Carry. JR Z,TWO_DIGITS ;If the number is less than 3 digits skip the next call. JR C,TWO_DIGITS SUB 2 ;If there is an odd number of digits Carry will be set. LD B,H CALL ADD_NUMBERS ;Routine to add the numbers to the string. .TWO_DIGITS LD B,L CALL ADD_NUMBERS LD A,"K" LD (DE),A ;Print the K on the end to show the file size is in Kilobytes. INC DE LD B,1 CALL ADD_SPACES ;Add one space onto the end so that there is exactly 4 columns XOR A ;across the screen. LD (DE),A LD HL,BUFFER CALL TEXTLOOP ;Print the filename and size. JP DISPLAY_CAT ;Repeat the loop. .SELECT_FILES ;This routine allows the files to be selected. LD HL,MESS2 CALL TEXTLOOP LD H,A ;A is always 0 after the TEXTLOOP routine. LD L,A LD (CURRENT_FILE),A LD (FILECOUNT),HL CALL TXT_GET_CURSOR NEG ADD L LD L,A LD (LOCATE+1),HL ;Store the cursor position, for printing messages later. LD HL,SAVENAME LD (SELECT_POINTER),HL ;Point to the files that are stored in the buffer. CALL TXT_GET_CURSOR ;Get the screen roll number in A. LD HL,(CURSOR_POS) ADD L ;Adjust L to allow for the screen scrolling. LD L,A CALL TXT_SET_CURSOR ;Move the text cursor to the top of the file list. LD A,243 CALL TXT_OUTPUT ;Print the pointer (an arrow). .MOVE_POINTER ;This loop checks whether any keys have been pressed. LD HL,&3200 .PAUSE ;Wait for a little while so that the arrow doesn't move too quickly. DEC HL LD A,H OR L JR NZ,PAUSE LD A,8 CALL KM_TEST_KEY ;Test the left arrow key. CALL NZ,MOVE_LEFT XOR A CALL KM_TEST_KEY ;Test the up arrow key. CALL NZ,MOVE_UP LD A,1 CALL KM_TEST_KEY ;Test the right arrow key. CALL NZ,MOVE_RIGHT LD A,2 CALL KM_TEST_KEY ;Test the down arrow key. CALL NZ,MOVE_DOWN LD A,18 CALL KM_TEST_KEY ;Test the return key. CALL NZ,LOAD_EACH_FILE LD A,9 CALL KM_TEST_KEY ;Test the copy key. CALL NZ,SELECT JR MOVE_POINTER .MOVE_LEFT CALL TXT_GET_CURSOR LD HL,(CURSOR_POS) ;Get the cursor position. ADD L LD L,A PUSH HL CALL TXT_SET_CURSOR LD A," " CALL TXT_OUTPUT ;This clears the cursor from its old position. POP HL LD A,H SUB 20 ;Calculate the position for the next column to the left. PUSH AF LD A,(CURRENT_FILE) LD C,A JR NC,LEFT_COLUMN POP AF ADD 80 ;This adds 80 if the result is negative so that the screen wraps around. PUSH AF LD A,C ;This makes sure that the right file number is kept when the screen ADD 4 ;wraps around. LD C,A .LEFT_COLUMN POP AF LD B,A PUSH BC ;Check whether there is actually a filename at the new position. PUSH HL LD H,A INC H CALL TXT_UNWRITE POP HL POP BC CP " " LD A,B JP Z,NO_CHANGE1 LD H,A LD A,C DEC A LD (CURRENT_FILE),A ;This indicates which file the arrow is pointing at. .NO_CHANGE1 PUSH HL CALL TXT_SET_CURSOR CALL TXT_GET_CURSOR POP HL NEG ADD L LD L,A LD (CURSOR_POS),HL ;This stores the new position of the cursor. LD A,243 CALL TXT_OUTPUT ;Print the arrow at its new position. RET .MOVE_RIGHT CALL TXT_GET_CURSOR LD HL,(CURSOR_POS) ;Get the cursor position. ADD L LD L,A PUSH HL CALL TXT_SET_CURSOR LD A," " CALL TXT_OUTPUT ;This clears the cursor from its old position. POP HL LD A,H ADD 20 CP 81 PUSH AF LD A,(CURRENT_FILE) LD C,A JR NZ,RIGHT_COLUMN POP AF SUB 80 ;Move the cursor to the extreme left if it moves off the screen. PUSH AF LD A,C SUB 4 LD C,A .RIGHT_COLUMN POP AF LD B,A PUSH BC PUSH HL LD H,A INC H CALL TXT_UNWRITE POP HL POP BC CP " " LD A,B JP Z,NO_CHANGE2 LD H,A LD A,C INC A LD (CURRENT_FILE),A .NO_CHANGE2 PUSH HL CALL TXT_SET_CURSOR ;Move the text cursor to the new position. CALL TXT_GET_CURSOR POP HL NEG ADD L LD L,A LD (CURSOR_POS),HL ;This stores the new position of the cursor. LD A,243 CALL TXT_OUTPUT RET .MOVE_UP CALL TXT_GET_CURSOR LD HL,(CURSOR_POS) ;Get the cursor position. ADD L LD L,A PUSH HL CALL TXT_SET_CURSOR LD A," " CALL TXT_OUTPUT ;These routines are fairly similar. POP HL LD A,L DEC A PUSH AF PUSH HL LD L,A INC H CALL TXT_UNWRITE POP HL POP BC CP " " LD A,B JP Z,NO_CHANGE3 LD L,A LD A,(CURRENT_FILE) SUB 4 LD (CURRENT_FILE),A .NO_CHANGE3 PUSH HL CALL TXT_SET_CURSOR CALL TXT_GET_CURSOR POP HL NEG ADD L LD L,A LD (CURSOR_POS),HL LD A,243 CALL TXT_OUTPUT RET .MOVE_DOWN CALL TXT_GET_CURSOR LD HL,(CURSOR_POS) ADD L LD L,A PUSH HL CALL TXT_SET_CURSOR LD A," " CALL TXT_OUTPUT POP HL LD A,L INC A PUSH AF PUSH HL LD L,A INC H CALL TXT_UNWRITE POP HL POP BC CP " " LD A,B JP Z,NO_CHANGE4 LD L,A LD A,(CURRENT_FILE) ADD 4 LD (CURRENT_FILE),A .NO_CHANGE4 PUSH HL CALL TXT_SET_CURSOR CALL TXT_GET_CURSOR POP HL NEG ADD L LD L,A LD (CURSOR_POS),HL LD A,243 CALL TXT_OUTPUT RET .SELECT CALL TXT_GET_CURSOR LD HL,(CURSOR_POS) ADD L LD L,A INC L ;INC L because of the banner window at the top. CALL SCR_CHAR_POSITION .REVERSE_CHARACTERS ;Routine to highlight the selected filename. LD C,8 .REVERSE_ROWS LD B,18 PUSH HL .REVERSE_BYTES LD A,(HL) CPL ;Reverse all of the bits in the byte. LD (HL),A INC HL LD D,A DJNZ REVERSE_BYTES POP HL LD A,H ADD 8 ;HL holds the address of the next row (&800 greater than the last). LD H,A DEC C JR NZ,REVERSE_ROWS PUSH DE ;D holds the last byte that was inverted i.e. the bottom right byte. LD HL,(FILECOUNT) INC HL ;Add one to the number of files selected. LD DE,(SELECT_POINTER) LD A,(CURRENT_FILE) LD (DE),A INC DE POP AF ;Puts the value of the last byte which was inverted in A. OR A JR NZ,ADD_FILE ;If the last byte inverted was changed to a 0 then the file must DEC HL ;have been deselected. This means that the counter will have to be DEC HL ;decremented and the pointer decremented also. PUSH HL PUSH DE INC HL LD B,H ;This bit takes out the filename number that has been deselected. LD C,L LD HL,SAVENAME LD A,(CURRENT_FILE) ;Search for the file number to be removed. CPIR JP PO,ONE_BYTE ;If BC is zero don't bother moving any bytes. LD D,H LD E,L DEC DE ;The bytes are moved back one byte. LDIR ;Move other numbers up to close the gap. .ONE_BYTE POP DE POP HL DEC DE ;Decrement the file pointer. DEC DE .ADD_FILE LD (FILECOUNT),HL LD (SELECT_POINTER),DE RET .LOAD_EACH_FILE LD HL,(FILECOUNT) LD A,H OR L RET Z POP HL CALL TXT_GET_CURSOR .LOCATE LD HL,0 ADD L LD L,A CALL TXT_SET_CURSOR CALL KM_RESET ;Clear the key buffer. LD HL,MESS14 CALL TEXTLOOP LD HL,&1000 CALL INPUT_ROUTINE+3 LD C,B LD B,0 LD (&F00),BC LD HL,ROM_HEADER LD DE,&4000 LD BC,NAME_TABLE-ROM_HEADER LDIR EX DE,HL ;HL now points to the beginning of the Jumpblock in the ROM image. LD BC,(FILECOUNT) ;Have to leave some room for the Jumpblock. LD DE,3 .X3BC ;Multiply BC by 3 and add it on to HL. ADD HL,DE DEC BC LD A,B OR C JR NZ,X3BC LD DE,&8000 PUSH HL ADD HL,DE LD (NAMETABLE_ADDR-ROM_HEADER+&4000),HL ;Adds the address of the name table to POP DE ;the ROM image. LD HL,NAME_TABLE ;Add the name of the initialisation command to the name table. LD BC,COMMAND_NAME-NAME_TABLE LDIR LD BC,(FILECOUNT) LD B,C ;Use B as a counter of how many times to go through the loop. LD HL,SAVENAME ;Points HL to the first filename number. .ASSIGN_NAMES ;This loop assigns a name to each file. PUSH BC PUSH DE PUSH HL .INPUT_COMMAND ;If the command name was invalid this bit is repeated. LD HL,MESS4 CALL TEXTLOOP POP HL PUSH HL CALL CREATE_FILENAME ;Finds the filename from the number pointed to by HL. EX DE,HL LD (HL),"?" INC HL LD (HL)," " INC HL LD (HL),13 INC HL LD (HL),10 INC HL LD (HL),0 LD HL,BUFFER CALL TEXTLOOP CALL INPUT_ROUTINE ;Gets input from the keyboard. LD C,B LD B,0 LD (COMMAND_LEN),BC LD A,C CP 17 JR NC,INPUT_COMMAND LD HL,BUFFER ;The command name is stored at BUFFER. .CHECK_COMMAND LD A,(HL) RES 7,A ;Reset bit 7 so BASIC doesn't think it is the end of the name. CP "." JR Z,MAKEUP CP "0" JR C,INPUT_COMMAND CP ":" JR C,MAKEUP CP "A" JR C,INPUT_COMMAND CP "[" JR C,MAKEUP CP "a" JR C,INPUT_COMMAND CP "é" JR NC,INPUT_COMMAND .MAKEUP SUB 97 JR C,UPPER SUB 26 JR NC,UPPER LD A,(HL) SUB 32 LD (HL),A .UPPER INC HL DEC C JR NZ,CHECK_COMMAND DEC HL SET 7,(HL) ;Set bit 7 of the last character of the command. POP HL POP DE PUSH HL LD HL,BUFFER LD BC,(COMMAND_LEN) LDIR POP HL INC HL POP BC DJNZ ASSIGN_NAMES XOR A LD (DE),A INC DE LD HL,INITMESS-ROMINIT+&8000 ;Find out the address of the initialisation ADD HL,DE ;message LD (MESS_ADDRESS+1),HL LD HL,INITMESS-ROMINIT+1 ADD HL,DE PUSH DE LD DE,&1000 EX DE,HL LD BC,(&F00) LDIR EX DE,HL LD (HL),10 INC HL LD (HL),13 INC HL LD (HL),10 INC HL LD (HL),0 INC HL POP DE PUSH HL LD BC,INITMESS-ROMINIT+1 LD HL,&8000 ADD HL,DE PUSH DE EX DE,HL LD HL,INITIALISE_ROM-ROM_HEADER+&4001 LD (HL),E ;Store the address of the initialisation routine, so that the routine INC HL ;is jumped to on initialisation. LD (HL),D INC HL LD (COMMAND_LEN),HL ;Store the address of where all the other JP commands go. LD HL,ROMINIT ;Copy the initialisation code to the ROM image. POP DE LDIR POP DE LD HL,&8000 AND A SBC HL,DE ;Find out how much space there is for programs and store in HL. LD (RAM_REMAINING),HL LD HL,SAVENAME LD BC,(FILECOUNT) LD B,C LD (HEADER_POINTER),DE .LOAD_FILES ;This loop loads each file and fills in the addresses to jump to. PUSH BC PUSH HL CALL CREATE_FILENAME .LOAD LD B,12 LD DE,&8000 LD HL,BUFFER CALL CAS_IN_OPEN JP NC,RETRY CALL FREE_BYTES JP NC,TOO_LONG ;If the file is too big carry is reset. LD (RAM_REMAINING),IX PUSH BC ;Store the length of the program. CP 2 ;This part copies the loader code for each program to its position in the JR NC,BIN ;ROM image. LD HL,(HEADER_POINTER) LD DE,BASRUN-BASIC+&8000 PUSH HL ADD HL,DE LD (BASRUN_PROG+1),HL POP HL PUSH HL LD DE,BASEND-BASIC+&8000 ADD HL,DE LD (BASIC+1),HL LD (BAS_LENGTH+1),BC POP DE PUSH DE LD HL,&8000 ADD HL,DE EX DE,HL LD HL,(COMMAND_LEN) ;Get the address of the next space in the Jumpblock. LD (HL),&C3 ;The opcode for the JP instruction. INC HL LD (HL),E ;Put the execution address of the loader code in the Jumpblock. INC HL LD (HL),D INC HL LD (COMMAND_LEN),HL ;Store the address of the next space in the Jumpblock. POP DE LD HL,BASIC LD BC,BASEND-BASIC LDIR JR LOAD_FILE .BIN PUSH DE LD DE,26 ADD HL,DE LD E,(HL) INC HL LD D,(HL) LD (BIN_EXEC+1),DE LD HL,(HEADER_POINTER) LD DE,BINEND-BINARY+&8000 ADD HL,DE LD (BIN_ADDRESS+1),HL POP DE LD (BIN_DEST+1),DE LD (BIN_LENGTH+1),BC LD DE,(HEADER_POINTER) LD HL,&8000 ADD HL,DE PUSH DE EX DE,HL LD HL,(COMMAND_LEN) LD (HL),&C3 INC HL LD (HL),E INC HL LD (HL),D INC HL LD (COMMAND_LEN),HL POP DE LD HL,BINARY LD BC,BINEND-BINARY LDIR .LOAD_FILE LD H,D LD L,E POP BC ADD HL,BC ;Find where the next program will be stored. LD (HEADER_POINTER),HL ;Store the position of the next program. EX DE,HL ;Get the address of where the program is to be loaded from DE. .IMAGE_LOAD CALL CAS_IN_DIRECT ;Load the program. CALL CAS_IN_CLOSE POP HL POP BC INC HL ;Move on to the next program to load. DEC B JP NZ,LOAD_FILES .RETRY_ROM LD C,16 ;Finds the number of the RAMROM. .FIND_RAMROM DEC C JP Z,NO_RAMROM ;Assumes that the BASIC ROM will be at number 0. PUSH BC CALL KL_ROM_SELECT POP BC LD A,&FE LD (&C000),A LD A,(&C000) ;If it is a RAMROM the byte that was written will be returned. CP &FE ;If it isn't a RAMROM the byte returned will be 0,1,2, &80, or &FF. JR NZ,FIND_RAMROM ;If it isn't a RAMROM loop again. LD A,2 ;Reset the screen offset and clear the cursor to the top. CALL SCR_SET_MODE XOR A LD (DI),A ;Disables the normal firmware interrupts LD BC,&BC06 ;Restrict the vertical size of the screen to 3 lines. OUT (C),C LD BC,&BD03 OUT (C),C LD HL,&40 ;Clear the area from &40 to &3FFF, so the screen appears to be blank. LD DE,&41 LD BC,&3FBF LD (HL),0 LDIR LD BC,&BC0C ;Screen moved to &50 so there aren't any lines across the screen. OUT (C),C ;Select CRTC register 12. INC B OUT (C),A ;Set the screen base to &00. DEC B INC C OUT (C),C ;Select CRTC register 13. LD C,&50 INC B OUT (C),C ;Set the offset to &50, so the Lower Jumpblock isn't overwritten. INC A LD (MODE_NUM),A LD BC,STARTMESS LD DE,&A0 CALL MESSAGES ;Reprints the banner at the new screen location. LD HL,&4000 ;This bit copies the ROM image to the RAMROM. LD BC,&4000 LD DE,&C000 LDIR LD A,2 LD (MODE_NUM),A LD BC,MESS65 LD DE,&140 ;Screen address of the 3rd line down. CALL MESSAGES ;This is a different routine to TEXTLOOP because the firmware LD BC,NUMBERS ;can't be used, otherwise the RAMROM will be corrupted. PUSH DE CALL MESSAGES ;Prints out how long the user has to switch the RAMROM to read LD BC,MESS675 ;only. CALL MESSAGES .COUNTDOWN LD BC,NUMBERS+1 ;Points to the ASCII representation of the countdown numbers. LD A,(NUMBER) ;Finds what the current number is and changes it to ASCII. PUSH AF AND &F ADD 48 LD (BC),A POP AF DEC BC AND &F0 RRCA ;Rotate the top nibble of the A register to the right. RRCA RRCA RRCA ADD 48 LD (BC),A LD BC,NUMBERS POP DE PUSH DE CALL MESSAGES .LOOP_TO_COUNTDOWN JP COUNTDOWN ;This jump will be changed to JP CNT when the time has expired. .CNT POP DE LD HL,&C000 LD DE,&C001 LD BC,&3FFF LD (HL),0 ;Clear the screen. LDIR LD A,48 ;Set the normal screen area. LD BC,&BC0C OUT (C),C INC B OUT (C),A DEC B INC C OUT (C),C INC B XOR A OUT (C),A ;Reset the screen offset. LD BC,&BC06 ;Change the vertical screen size back to 25 lines. OUT (C),C LD BC,&BD19 OUT (C),C LD A,1 LD (MODE_NUM),A LD BC,STARTMESS LD DE,&C000 CALL MESSAGES ;Print the banner in the normal screen area. LD A,&FF LD (DI),A ;Enable the normal firmware interrupts. LD HL,2 LD DE,&5019 CALL TXT_WIN_ENABLE ;Set the window so that the banner stays at the top. LD HL,MESS7 ;Ask whether to save the ROM image. CALL TEXTLOOP CALL KM_WAIT_KEY CP "Y" JR Z,SAVE CP "y" JR Z,SAVE RST 0 .SAVE CALL DISC_DRIVE .CAT_AGAIN LD DE,&8000 ;Area used as a buffer for the firmware disc routines. CALL CAS_CATALOG AND &C0 JP NZ,SAVE_CAT .FILENAME LD HL,MESS8 CALL TEXTLOOP CALL INPUT_ROUTINE LD (COMMAND_LEN),BC .SAVING LD BC,(COMMAND_LEN) PUSH BC LD HL,BUFFER LD DE,SAVENAME LD C,B LD B,0 LDIR LD HL,IMAGE_INIT ;Copy the loader code to just before the ROM image. LD DE,&4000-IMAGE_INIT_END+IMAGE_INIT LD BC,IMAGE_INIT_END-IMAGE_INIT LDIR POP BC LD HL,SAVENAME LD DE,&8000 CALL CAS_OUT_OPEN JR NC,SAVE_RETRY LD HL,&4000-IMAGE_INIT_END+IMAGE_INIT LD DE,&4000+IMAGE_INIT_END-IMAGE_INIT LD B,H ;The execution address is the same as the load address. LD C,L LD A,2 CALL CAS_OUT_DIRECT CALL CAS_OUT_CLOSE JP NC, SAVE_RETRY LD HL,MESS12 CALL TEXTLOOP CALL KM_WAIT_KEY RST 0 .RETRY CALL CAS_IN_ABANDON LD HL,MESS3 CALL TEXTLOOP CALL KM_WAIT_KEY CP "R" JP Z,LOAD CP "r" JP Z,LOAD JP FIND_DISC .TOO_LONG CALL CAS_IN_ABANDON LD HL,MESS5 CALL TEXTLOOP CALL KM_WAIT_KEY POP HL POP HL JP FIND_DISC .BAD_CAT ;If an error occured, while cataloguing, go back to FIND_DISC. LD HL,MESS6 CALL TEXTLOOP CALL KM_WAIT_KEY JP FIND_DISC .SAVE_CAT LD HL,MESS11 CALL TEXTLOOP CALL KM_WAIT_KEY CP "R" JP Z,CAT_AGAIN CP "r" JP Z,CAT_AGAIN JP SAVE .SAVE_RETRY CALL CAS_OUT_ABANDON LD HL,MESS9 CALL TEXTLOOP CALL KM_WAIT_KEY CP "R" JP Z,SAVING ;If R is pressed try saving again. CP "r" JP Z,SAVING CP "F" JP Z,FILENAME ;If F is pressed go to the filename entry routine. CP "f" JP Z,FILENAME JP SAVE .ASCII ;If a file is ASCII the appropriate message is displayed. POP HL POP HL POP HL POP HL CALL CAS_IN_ABANDON LD HL,MESS10 CALL TEXTLOOP CALL KM_WAIT_KEY JP FIND_DISC ;Always goes back to here no matter what is pressed. .DISC_DRIVE ;Tests whether there is a disc in either drive. LD IX,(&BE7D) ;Loads IX with the start of the operating area. DW INC_HIX DW INC_HIX XOR A ;Tests drive 1 first. .TEST_DRIVE XOR 1 ;Toggles between 0 and 1. PUSH AF LD HL,BIOS_GET_STATUS ;BIOS command, which returns the status of the specified LD C,(IX-&73) ;disc drive. C holds the ROM number of the operating system. CALL &1B LD B,A POP AF BIT 5,B ;If bit 5 is set a disc is fitted and ready. JR Z,TEST_DRIVE ;Otherwise keep looping until a disc drive has a disc in it. DW DEC_HIX ;If a disc was found A holds the drive number. DW DEC_HIX LD (IX),A RET .TEXTLOOP ;Simple routine to display text. LD A,(HL) OR A RET Z RES 7,A CALL TXT_OUTPUT INC HL JR TEXTLOOP .CREATE_FILENAME ;Finds the filename that the number corresponds to. LD B,(HL) INC B ;Increments B so that the loop executes once when B is 0. LD HL,&1FE1 ;Subtract 32 from &2001 because B was incremented. LD DE,&20 .POINT_TO_FILE ;Multiplies B by 32 and adds it to &1FE1. ADD HL,DE DJNZ POINT_TO_FILE LD DE,BUFFER ;Copies the filename to the buffer so it can be printed. LD BC,8 LDIR LD A,"." LD (DE),A INC DE LD BC,3 LDIR RET .INPUT_ROUTINE LD HL,BUFFER LD B,0 CALL TXT_PLACE_CURSOR .INPUT CALL KM_WAIT_KEY CP 13 JR NZ,DEL LD A,B OR A JR Z,INPUT CALL TXT_REMOVE_CURSOR LD A,13 CALL TXT_OUTPUT LD A,10 JP TXT_OUTPUT .DEL CP 127 JR NZ,ADD_TO_BUFFER LD A,B OR A JR Z,INPUT CALL TXT_REMOVE_CURSOR XOR A DEC HL LD (HL),A DEC B LD A,8 CALL TXT_OUTPUT LD A,16 CALL TXT_OUTPUT CALL TXT_PLACE_CURSOR JR INPUT .ADD_TO_BUFFER INC B JR NZ,CONT DEC B JR INPUT .CONT LD (HL),A PUSH AF CALL TXT_REMOVE_CURSOR POP AF PUSH HL PUSH BC CALL TXT_WR_CHAR CALL TXT_PLACE_CURSOR POP BC POP HL INC HL JR INPUT .MESSAGES DI ;The interrupts have to be disabled for this routine. The countdown counts PUSH BC ;in 299/300ths of a second, to allow for this routine. LD BC,&7F8A OUT (C),C ;Enable the lower ROM. POP BC LD A,(BC) .SPECIAL_MESS PUSH BC PUSH DE LD L,A LD H,7 ADD HL,HL ADD HL,HL ADD HL,HL LD B,8 .X8_ROWS PUSH BC LD A,(MODE_NUM) RRCA ;If it is one Carry is set. LD A,(HL) PUSH DE JR NC,MODE2 CPL PUSH HL PUSH AF AND &F0 ;Look at the top nibble. LD B,4 .EXPAND_TOP RLA RL H SLA H DJNZ EXPAND_TOP LD A,H RRCA ;Synchronise the 0s with the 1s in the two bytes. OR H ;Add the two bytes together. LD (DE),A ;Store the new byte. POP AF AND &F LD B,4 .EXPAND_BOTTOM RRA RR L SRL L DJNZ EXPAND_BOTTOM INC DE LD A,L RLCA OR L POP HL .MODE2 LD (DE),A POP DE INC HL LD A,D ADD 8 LD D,A POP BC DJNZ X8_ROWS POP DE INC DE LD A,(MODE_NUM) RRCA JR NC,MODE_2 INC DE ;If it is in mode 1 then move two bytes to the right. .MODE_2 POP BC INC BC LD A,(BC) OR A JR NZ,SPECIAL_MESS LD BC,&7F8E ;Turn the lower ROM off and select mode 2. OUT (C),C EI RET .ADD_NUMBERS JR C,NEXT_NIBBLE LD A,B AND &F0 RRCA RRCA RRCA RRCA ADD 48 LD (DE),A INC DE .NEXT_NIBBLE LD A,B AND &F ADD 48 LD (DE),A INC DE RET .TXT_UNWRITE ;Routine to read a character from the screen. PUSH HL ;Store where the character to be read is located. CALL TXT_GET_CURSOR EX (SP),HL ;Stores where the cursor was and gets where it is to be moved to. CALL TXT_SET_CURSOR ;Move the cursor to where the character is to be read from. CALL TXT_RD_CHAR ;Get the character from the screen. POP HL PUSH AF CALL TXT_SET_CURSOR POP AF RET .ADD_SPACES LD A," " LD (DE),A INC DE DJNZ ADD_SPACES RET .FREE_BYTES PUSH DE PUSH AF LD IX,&AA34 LD A,(IX+2) CP &C3 JR NZ,NOT_ROMIMAGE LD A,(IX+1) AND &C0 JR Z,NOT_ROMIMAGE LD A,(IX+4) AND &C0 JR Z,NOT_ROMIMAGE LD A,(IX-4) CP 3 JR C,IS_IMAGE CP &80 JR NZ,NOT_ROMIMAGE .IS_IMAGE POP AF POP DE LD HL,(FILECOUNT) DEC HL LD A,H OR L RET NZ POP AF LD H,&40 JP IMAGE_LOAD .NOT_ROMIMAGE POP AF PUSH AF LD IX,(RAM_REMAINING) CP 2 JR C,BASIC_LOADER CP 16 JR C,BINARY_LOADER POP HL JP ASCII .BASIC_LOADER LD DE,&10000-BASEND+BASIC ADD IX,DE JR ADD_PROG .BINARY_LOADER LD DE,&10000-BINEND+BINARY ADD IX,DE .ADD_PROG LD A,B ;Change BC to -BC and store it in DE. CPL ;To make a number negative all the bits are complemented and 1 is added. LD D,A LD A,C CPL LD E,A INC DE ADD IX,DE ;This is the equivalent of doing a SBC IX,BC. POP AF LD D,A DW LD_A_HIX CP &40 LD A,D POP DE RET .BANNER_MODE DI PUSH AF PUSH HL LD A,(DI) ;Check the state of the DI flag. When it is 0 the countdown starts. OR A JR NZ,FIRMWARE_INTERRUPT LD HL,TIMER ;TIMER holds the 1/300ths of a second counter. DEC (HL) JR NZ,TIMER_END ;If this byte has reached 0, decrement the next byte. INC HL DEC (HL) ;If it isn't 0 return from routine. JR NZ,TIMER_END LD HL,&22B ;This number happens to be 300+&99 in hexadecimal. This is so that, LD (TIMER),HL ;when both bytes are 0, 299 1/300ths of a second have passed. LD A,(NUMBER) ;When a 299/300ths of a second have passed decrement the counter. DEC A DAA ;Change the number to BCD. JR NZ,STORE_SECS ;If the counter isn't zero then store the new number. LD HL,CNT ;If the counter has reached zero the number print routine is ended. LD (LOOP_TO_COUNTDOWN+1),HL ;Alter the program so that the loop terminates. .STORE_SECS LD (NUMBER),A ;Store the new number of seconds. .TIMER_END POP HL POP AF EI RET ;Return from the interrupt. .FIRMWARE_INTERRUPT POP HL POP AF EI .INTERRUPT DS 3 ;Will hold the address of the interrupt handling routine. .NO_RAMROM LD HL,MESS13 CALL TEXTLOOP CALL KM_WAIT_KEY JP RETRY_ROM .BUBBLE_SORT LD HL,(NO_ENTRIES) LD DE,&2000 .START_SORTING PUSH HL PUSH DE LD A,(DE) CP &E5 LD HL,32 ADD HL,DE JR NZ,NEXT_CHAR CP (HL) JR Z,SKIP_IT JR SWAP .NEXT_CHAR LD A,&E5 CP (HL) JR Z,SKIP_IT INC DE LD A,(DE) LD HL,32 ADD HL,DE CP (HL) JR C,SKIP_IT JR Z,NEXT_CHAR .SWAP LD B,32 POP DE PUSH DE LD HL,32 ADD HL,DE .SWAP_LOOP LD C,(HL) LD A,(DE) EX DE,HL ;Swap the contents of the HL and DE registers. LD (HL),C LD (DE),A EX DE,HL INC DE INC HL DJNZ SWAP_LOOP XOR A LD (FLAG),A .SKIP_IT POP DE LD HL,32 ADD HL,DE EX DE,HL POP HL DEC HL LD A,H OR L JR NZ,START_SORTING LD A,(FLAG) OR A LD A,&FF LD (FLAG),A JR Z,BUBBLE_SORT RET .ROM_HEADER DB 1,1,0,0 .NAMETABLE_ADDR DW 0 ;When the name table is constructed this will store its address. .INITIALISE_ROM JP ROMINIT ;All ROMs are initialised at this address. .NAME_TABLE DB "START U","P"+&80;Name of the initialisation routine. .COMMAND_NAME ;Beginning of the command name table. .ROMINIT PUSH HL .MESS_ADDRESS ;This will store the address of the start up message. LD HL,0 .INITTEXT LD A,(HL) OR A JR Z,END_INIT CALL TXT_OUTPUT INC HL JR INITTEXT .END_INIT POP HL SCF RET .INITMESS DB " " .BASIC LD HL,0 ;This will hold the address of the BASIC program when it is copied. LD DE,&170 .BAS_LENGTH LD BC,0 ;This will hold the length of the BASIC program when it is copied. LDIR .REF_ADDR_BAS LD (&AE66),DE LD (&AE68),DE LD (&AE6A),DE LD (&AE6C),DE .BASRUN_PROG LD HL,0 ;This will hold the address of the BASRUN code in the ROM. LD DE,&40 ;The code will be copied to here before it is executed. LD BC,14 LDIR JP &40 .BASRUN ;This code runs the BASIC program and must be copied into RAM before it LD C,0 ;is executed. CALL KL_ROM_SELECT LD HL,&B0 LD (HL),0 .REF2_ADDR_BAS JP &EA78 .BASEND .BINARY ;Beginning of the binary loader code. PUSH HL ;Make sure all of the registers are passed to the destination routine PUSH DE ;unaltered. PUSH BC .BIN_ADDRESS LD HL,0 ;This will hold the address in the ROM of the binary program. .BIN_DEST LD DE,0 ;This will hold the address of where the program would normal load to. .BIN_LENGTH LD BC,0 ;This will hold the length of the binary program. LDIR POP BC POP DE POP HL .BIN_EXEC JP 0 ;This will jump to the execution address of the binary program. .BINEND .IMAGE_INIT LD A,2 CALL SCR_SET_MODE LD C,16 ;Finds the number of the RAMROM. .FIND_RAMROM2 DEC C PUSH BC CALL KL_ROM_SELECT POP BC LD A,&FE LD (&C000),A LD A,(&C000) CP &FE JR NZ,FIND_RAMROM2 LD HL,&4000-IMAGE_INIT_END+IMAGE_INIT+IMAG_MESS-IMAGE_INIT ;Points to message. .PRINT_MESS LD A,(HL) OR A JR Z,PRINT_END CALL TXT_OUTPUT INC HL JR PRINT_MESS .PRINT_END CALL KM_WAIT_KEY DI LD HL,&4000 ;Copies the ROM image to the RAMROM LD DE,&C000 LD BC,&4000 LDIR LD B,10 ;Does nothing for a few seconds so that the RAMROM can be switched to .DELAY1 ;read only. LD HL,0 .DELAY2 DEC HL LD A,H OR L JR NZ,DELAY2 DJNZ DELAY1 RST 0 .IMAG_MESS DB "Switch the RAMROM to read only when the lines across the screen" DB " have stopped.",10,13,"Press a key to load the RAMROM.",0 .IMAGE_INIT_END .COMMAND_LEN DW 0 ;Stores the length of the RSX commands as they are entered. .HEADER_POINTER DW 0 ;Keeps track of where the next program will go in the ROM. .FILECOUNT DW 0 .NO_ENTRIES DW 0 .NUMBER DB &30 .NUMBERS DB "30" DB 0 ;Marks the end of the numbers string. .CURSOR_POS DW 0 .CURRENT_FILE DB 0 .SELECT_POINTER DW 0 .RAM_REMAINING DW &4000 .MODE_NUM DB 1 .TIMER DW &22B .DI DB &FF .FLAG DB &FF .BIOS_READ_SECTOR DW &C03C DB 7 .STARTMESS DB " RAMROM Loader ",&A4," James Hoskisson 1998 ",0 .MESS1 DB "Insert disc, with program for ROM image, in drive and press any DB " key",10,13,0 .MESS2 DB 10,13,10,"Select the files using the cursor keys and COPY. Press" DB " RETURN to continue.",10,10,13,0 .MESS3 DB "There was an error reading a file.",10,13 DB "Press R to retry, F to reselect the files, or D for a different" DB " disc.",10,13,0 .MESS4 DB "What command do you want to use to access the program called ",0 .MESS5 DB "This selection is too big to fit in the ROM.",10,13 DB "Press F to reselect, or D for a different disc.",10,13,0 .MESS6 DB "There was an error cataloguing the disc.",10,13 DB "Press R to retry, or D for a different disc.",10,13,0 .MESS65 DB "You have ",0 .MESS675 DB " seconds to switch the RAMROM to read only.",0 .MESS7 DB "Do you want to save the ROM image before initialising?" DB " (Y/N)",10,13,0 .MESS8 DB "Type in the filename: ",0 .MESS9 DB "There was an error while saving.",10,13 DB "Press R to retry, F to use a different filename, or D for a different" DB " disc.",10,13,0 .MESS10 DB "One of the files is ASCII.",10,13 DB "Press F to reselect, or D for a different disc",10,13,0 .MESS11 DB "There was a disc error.",10,13 DB "Press R to retry, or D to catalogue a different disc",10,13,0 .MESS12 DB "ROM image saved successfully. Press any key to initialise the" DB " RAMROM.",0 .MESS13 DB "Couldn't find a RAMROM. Make sure it is set to read/write.",10,13 DB "Press any key to retry.",10,13,0 .MESS14 DB "What is the start up message for your RAMROM?",10,13,0 .MESS15 DB "There aren't any files on this disc. Press a key to try another" DB " disc.",10,13,0 .BUFFER DS 21 .SAVENAME DS 256 DB 0
 



Goto Top
CPC-POWER/CPCSOFTS, programmation par Kukulcan © 2007-2024 tous droits réservés.
Reproduction sans autorisation interdite. Tous les titres utilisés appartiennent à leurs propriétaires respectifs.
Hébergement Web, Mail et serveurs de jeux haute performance