diff --git a/CPM-sd-image/cpm-blank.zip b/CPM-sd-image/cpm-blank.zip new file mode 100644 index 0000000..d20754b Binary files /dev/null and b/CPM-sd-image/cpm-blank.zip differ diff --git a/CPM-sd-image/cpm_file_copier.py b/CPM-sd-image/cpm_file_copier.py index 396f2da..6b264da 100644 --- a/CPM-sd-image/cpm_file_copier.py +++ b/CPM-sd-image/cpm_file_copier.py @@ -122,10 +122,10 @@ UNUSED_DIR_MARKER = 0xE5 # Marker for unused directory entries UNUSED_DATA_MARKER = 0x00 # Marker for unused data blocks # Default values -DEFAULT_IMAGE_FILE = "cpm-zeroed.img" +DEFAULT_IMAGE_FILE = "cpm-new.img" DEFAULT_TO_DIR = "to_img" DEFAULT_FROM_DIR = "from_img" -DEFAULT_HEX_PATH = os.path.join("hexFiles") # Base path for hex files +DEFAULT_HEX_PATH = os.path.join("Z80 CPM and bootloader (basmon)/hexFiles") # Base path for hex files DEFAULT_CPM_HEX = os.path.join(DEFAULT_HEX_PATH, "cpm22.hex") DEFAULT_CBIOS_HEX = os.path.join(DEFAULT_HEX_PATH, "cbios128.hex") @@ -414,13 +414,26 @@ def write_track0_image(image_file: str, cpm_hex: str, cbios_hex: str): def create_blank_disk_image(image_file: str, drives: int = 16, cpm_hex=None, cbios_hex=None): """ Create a blank CP/M disk image and write system to track 0. + The image file will be created in the current working directory. + + Args: + image_file (str): Name of the image file to create + drives (int): Number of drives to initialize (1-16) + cpm_hex (str, optional): CP/M hex content + cbios_hex (str, optional): CBIOS hex content """ + # Ensure the image file is created in current directory + image_path = os.path.basename(image_file) + # Calculate total size drive_size = DRIVE_SIZE_MB * 1024 * 1024 # 8MB per drive total_size = drive_size * drives - # Create the file - with open(image_file, 'wb') as f: + print(f"\nCreating disk image '{image_path}' in {os.getcwd()}") + print(f"Total size: {total_size / (1024*1024):.1f} MB") + + # Create the file in current directory + with open(image_path, 'wb') as f: # Write zeros to the entire file buffer_size = 1024 * 1024 # 1MB buffer zeros = bytes([0] * buffer_size) @@ -450,17 +463,19 @@ def create_blank_disk_image(image_file: str, drives: int = 16, cpm_hex=None, cbi # Write CP/M and CBIOS as one block if both are provided if cpm_hex and cbios_hex: print("\nWriting system to track 0...") - write_track0_image(image_file, cpm_hex, cbios_hex) + write_track0_image(image_path, cpm_hex, cbios_hex) else: print("Warning: Both CP/M and CBIOS hex files required for system track") + print(f"\nDisk image created successfully: {image_path}") + def main(): parser = argparse.ArgumentParser(description="CP/M 2.2 disk image manipulation tool") parser.add_argument("--image", default=DEFAULT_IMAGE_FILE, help=f"CP/M disk image file (default: {DEFAULT_IMAGE_FILE})") parser.add_argument("--to", default=DEFAULT_TO_DIR, help=f"Source directory for files to copy to image (default: {DEFAULT_TO_DIR})") parser.add_argument("--from", dest="from_dir", default=DEFAULT_FROM_DIR, help=f"Target directory for extracted files (default: {DEFAULT_FROM_DIR})") parser.add_argument("--copy", action="store_true", help="Copy files to the image (default is to extract)") - parser.add_argument("--init", action="store_true", help="Initialize a new disk image") + parser.add_argument("--init", default=True, action="store_true", help="Initialize a new disk image") parser.add_argument("--drives", type=int, default=16, help="Number of drives for new image (1-16, default 16)") parser.add_argument("--force", action="store_true", help="Force overwrite of existing image") parser.add_argument("--hex-path", default=DEFAULT_HEX_PATH, help=f"Base path for hex files (default: {DEFAULT_HEX_PATH})") diff --git a/MultiComp.sv b/MultiComp.sv index cc965e9..d37b227 100644 --- a/MultiComp.sv +++ b/MultiComp.sv @@ -351,6 +351,7 @@ wire sdss; wire vsdmiso; reg vsd_sel = 0; +// latch vsd_sel if user selects an image file always @(posedge clk_sys) begin if(RESET) begin // Only clear on hard reset vsd_sel <= 0; @@ -365,13 +366,12 @@ end //always @(posedge clk_sys) if(img_mounted) vsd_sel <= |img_size; +// uses the previous sd_card implementation i.e. now in components/sdcard image_card image_card ( .clk_sys(clk_sys), .reset(reset), .sdhc(1), - //.img_mounted(img_mounted), - //.img_size(img_size), .sd_lba(sd_lba[0]), .sd_rd(sd_rd), // New connection @@ -390,6 +390,34 @@ image_card image_card .miso(vsdmiso) ); +// this does not work i.e. with the new sd_card in /sys, not sure why yet +// sd_card sd_card +// ( +// .clk_sys(clk_sys), +// .reset(reset), +// .sdhc(1), + +// .img_mounted(img_mounted), +// .img_size(img_size), + +// .sd_lba(sd_lba[0]), +// .sd_rd(sd_rd), // New connection +// .sd_wr(sd_wr), // New connection +// .sd_ack(sd_ack), // New connection + +// .sd_buff_addr(sd_buff_addr), // New connection +// .sd_buff_dout(sd_buff_dout), // New connection +// .sd_buff_din(sd_buff_din[0]), +// .sd_buff_wr(sd_buff_wr), // New connection + +// .clk_spi(clk_sys), +// .ss(sdss | ~vsd_sel), +// .sck(sdclk), +// .mosi(sdmosi), +// .miso(vsdmiso) +// ); + + assign SD_CS = sdss | vsd_sel; assign SD_SCK = sdclk & ~vsd_sel; assign SD_MOSI = sdmosi & ~vsd_sel; diff --git a/Z80 CPM and bootloader (basmon)/hexFiles/BASMON.HEX b/Z80 CPM and bootloader (basmon)/hexFiles/BASMON.HEX index 7344ae9..5fb6127 100644 --- a/Z80 CPM and bootloader (basmon)/hexFiles/BASMON.HEX +++ b/Z80 CPM and bootloader (basmon)/hexFiles/BASMON.HEX @@ -1,343 +1,343 @@ -:0430040000000000C8 -:18000000F3C3940000000000C332000000000000C31B000000000000CB -:18001800C35C003A0030FE002008CD630028FBDB81C9CD6A0028FBDB74 -:1800300083C9F53A0030FE00200D1801F5CD500028FBF1D381C9F5CDC4 -:18004800560028FBF1D383C9DB800FCB47C9DB820FCB47C93A0030FE23 -:18006000002007DB80E601FE00C9DB82E601FE00C9D7FE0A28FBFE1B32 -:1800780020023E03C9FE0D280AFE0C2804FE203801CFC93E0DCF3E0A80 -:18009000CF3E0DC93128303E95D380D3823E00320030216503CD1B015F -:1800A8003E01320030216503CD1B01CD6300280F3E00320030CD1B003E -:1800C000FE20C2B3001814CD6A0028E73E01320030CD1B00FE20C2B307 -:1800D8000018003E0CCD3C00CD4600CD2201219602CD1B0121EC00E50E -:1800F000CD22013E3ECFCD7100FE2038F9FE3ACA9901CD7D00E65FFE07 -:1801080042CADA01FE47CA9301FE58CAF1013E3FCF18D57EB7C8CF231B -:1801200018F93E0DCF3E0ACFC9CD7100FE03C8FE2038F6C9CD29014762 -:18013800CD29014FCD73014F7B915F79C9210000CD8C01FE0D200E3741 -:18015000C9210000CD8C01FE0DC8FE2CC8FE0328EE29292929D630FECF -:180168000A3802D607E60F856F18E178D630FE0A3802D60707070707C3 -:180180004779D630FE0A3802D60780C9CD7100CD7D00C9CD4501D8E518 -:18019800C91E00CD340157CD340167CD34016FCD3401FE012009CD340A -:1801B000017BA7281E18157AA7280BCD340177233E2ECF1518F1CD3457 -:1801C800017BA7C8215403CD1B01C9218A03CD1B01C9214203CD1B015B -:1801E000CD2901C8E65FFE43CA9503FE57CA9803C9210302CD1B01CD01 -:1801F8002901C8E65FFE59CA2402C90D0A426F6F742043502F4D3F008F -:180210000D0A4C6F6164696E672043502F4D2E2E2E0D0A00211002CD31 -:180228001B0106183E003204303205303206303207302100D022023063 -:18024000CD6E021100022A0230192202303A04303C32043010EA3A0049 -:1802580030F52AFEFFE93A0630D38C3A0530D38B3A0430D38AC9F5C56F -:18027000E5DB89FE8020FACD5E023E00D3890E040680DB89FEE020FADA -:18028800DB8877230520F30D20EEE1C1F1C943502F4D20426F6F7420EF -:1802A000524F4D20322E3020627920472E20536561726C650D0A0D0A6E -:1802B8004243206F72204257202D20524F4D20424153494320436F6CD4 -:1802D000642F5761726D0D0A5820202020202020202D20426F6F74207C -:1802E80043502F4D20286C6F61642024443030302D2446464646290D50 -:180300000A3A6E6E6E6E2E2E2E202D204C6F616420496E74656C2D48E1 -:1803180065782066696C65207265636F72640D0A476E6E6E6E2020201B -:18033000202D2052756E206C6F63206E6E6E6E0D0A000D0A436F6C642D -:18034800206F72207761726D3F0D0A00436865636B73756D20657272D3 -:180360006F720D0A000C5072657373205B53504143455D20746F2061AC -:180378006374697661746520636F6E736F6C650D0A00436F6D706C65F3 -:1803900074650D0A00C39B03C33904DD210000C3A6034C0CC21321B09C -:1803A80030F9C3E11F117306066321B0301A77231305C2B503F9CD74DD -:1803C00008CD420E325A3132A931218804CDE014CD9108CD9A0BB7C278 -:1803D800EF03210D32237CB5CA01047E472F77BE70CADD03C30104CDC0 -:1803F000660CB7C24207EB2B3ED94677BE70C2CA032B110C32CD0A0ABF -:18040800DACA0311CEFF225F3119220A31CD4F082A0A3111EFFF19117D -:18042000A9317D936F7C9A67E5215104CDE014E1CD831B214204CDE072 -:1804380014311631CD7408C38D0720427974657320667265650D0A0080 -:18045000005A38302042415349432056657220342E37620D0A436F70AF -:18046800797269676874202843292031393738206279204D6963726F23 -:18048000736F66740D0A00004D656D6F727920746F7000F819BC1A0EB0 -:180498001AB330A0132517CE13821C611D9D18D01CD61DDC1D3D1E5229 -:1804B0001E7917BD1E013152166A14EC1661167216DF1E721F8216B2BA -:1804C80016BC16C54E44C64F52CE455854C4415441C94E505554C44900 -:1804E0004DD2454144CC4554C74F544FD2554EC946D24553544F5245D5 -:1804F800C74F535542D2455455524ED2454DD3544F50CF5554CF4ECEFF -:18051000554C4CD7414954C44546D04F4B45C44F4B45D3435245454E50 -:18052800CC494E4553C34C53D749445448CD4F4E49544F52D34554D278 -:1805400045534554D052494E54C34F4E54CC495354C34C454152C34CFF -:180558004F4144C353415645CE4557D4414228D44FC64ED3504328D443 -:1805700048454ECE4F54D3544550ABADAAAFDEC14E44CF52BEBDBCD35E -:18058800474EC94E54C14253D55352C65245C94E50D04F53D35152D20D -:1805A0004E44CC4F47C55850C34F53D3494ED4414EC1544ED045454BA8 -:1805B800C445454BD04F494E54CC454ED3545224D6414CC15343C348C7 -:1805D0005224C8455824C2494E24CC45465424D24947485424CD49444C -:1805E8002480E40BE10ABC0F310DC30EF811F20E480DEE0CD10CC00DA1 -:18060000AA0BDD0C0C0D330DE20B3117A20D230C3717D6138017C81E24 -:18061800330DAE1EA11EA61EDE1F04310731E40D100C560A8B0C330D8D -:18063000330D4E08796A1B799E177CDC187C3D197F8B1C505111465040 -:18064800114E46534E52474F4446434F564F4D554C425344442F3049F8 -:1806600044544D4F534C535354434E55464D4F4858424EC33904C36199 -:180678000CD300C9D6006F7CDE006778DE00473E00C9000000354ACACF -:1806900099391C76982295B3980ADD479853D199990A1A9F9865BCCDEF -:1806A80098D6773E9852C74F80DB00C901FF1C000014001400000000AF -:1806C00000C38709C30000C30000C300000D32FEFFAA31204572726FB7 -:1806D800720020696E20004F6B0D0A0000427265616B00210400397EEF -:1806F00023FE81C04E234623E569607AB3EBCA0507EBCD0A0A010D0040 -:18070800E1C809C3EF06CD2807C5E3C1CD0A0A7E02C80B2BC31407E5E8 -:180720002A8A31060009093EE53ED0956F3EFF9CDA37076739E1D81E27 -:180738000CC356072A7931220C311E02011E14011E00011E12011E2266 -:18075000011E0A011E18CD740832F530CD350E214906573E3FCD1B0A4B -:18076800197ECD1B0ACD9A0BCD1B0A21D306CDE0142A0C3111FEFFCD8F -:180780000A0ACAA6037CA53CC47B1B3EC1AF32F530CD350E21DF06CD3B -:18079800E01421FFFF220C31CD8709DA9A07CD9A0B3C3DCA9A07F5CDE7 -:1807B000660CD5CD9E0847D1F1D27A0BD5C5AF327C31CD9A0BB7F5CD04 -:1807C8002E08DAD307F1F5CA070DB7C5D2EA07EB2A86311A020313CD61 -:1807E0000A0AC2DB076069228631D1F1CA11082A8631E3C109E5CD0EB4 -:1807F80007E1228631EB74D12323732372231111311A772313B7C209EB -:1808100008CD5A0823EB626B7E23B6CA9A07232323AFBE23C22208EB2C -:18082800732372C316082A0E31444D7E23B62BC823237E23666FCD0AF8 -:180840000A60697E23666F3FC83FD0C33108C02A0E31AF772377232217 -:1808580086312A0E312B227E312A5F31227331AFCDAA0B2A8631228830 -:1808700031228A31C12A0A31F9216331226131AF6F67228431327B31A0 -:18088800228E31E5C52A7E31C93E3FCD1B0A3E20CD1B0AC3FE30AF329A -:1808A0005E310E051111317EFE20CA260947FE22CA4609B7CA4D093A25 -:1808B8005E31B77EC22609FE3F3E9ECA26097EFE30DAD108FE3CDA26C8 -:1808D00009D511CA04C5012209C5067F7EFE61DAEA08FE7BD2EA08E64C -:1808E8005F774EEB23B6F2EC08047EE67FC8B9C2EC08EBE5131AB7FA5E -:180900001E094F78FE88C20D09CD9A0B2B237EFE61DA1609E65FB9CA35 -:18091800FC08E1C3EA0848F1EBC9EB79C1D12312130CD63ACA3409FEE1 -:1809300049C23709325E31D654C2A708477EB7CA4D09B8CA2609231286 -:180948000C13C33D092110311213121312C93AF430B73E0032F430C27D -:180960006A0905CA8709CD1B0A3E052BCA7E097ECD1B0AC39009052B00 -:18097800CD1B0AC29009CD1B0ACD420EC387092111310601AF32F43049 -:18099000CD450A4FFE7FCA56093AF430B7CAA9093E00CD1B0AAF32F4A8 -:1809A8003079FE07CAED09FE03CC420E37C8FE0DCA3D0EFE15CA810926 -:1809C000FE40CA7E09FE5FCA7609FE08CA7609FE12C2E809C5D5E53623 -:1809D80000CDF21F211131CDE014E1D1C1C39009FE20DA900978FE49E6 -:1809F0003E07D2020A7971327C312304CD1B0AC39009CD1B0A3E08C393 -:180A0800FC097C92C07D93C97EE3BE23E3CA9A0BC34207F53AF530B77F -:180A2000C21515F1C5F5FE20DA3F0A3AF230473A5B3104CA3B0A05B8AD -:180A3800CC420E3C325B31F1C1CDDB1FC9CD9F1EE67FFE0FC03AF53033 -:180A50002F32F530AFC9CD660CC0C1CD2E08C5CDAC0AE14E2346237852 -:180A6800B1CA8D07CDB50ACDC50BC5CD420E5E235623E5EBCD831B3EE9 -:180A800020E1CD1B0A7EB723CA620AF2820AD67F4F11CB041A13B7F205 -:180A9800940A0DC2940AE67FCD1B0A1A13B7F29E0AC3850AE52AF830DD -:180AB00022F630E1C9E5D52AF63011FFFFED5A22F630D1E1F0E52AF8EB -:180AC8003022F630CD9F1EFE03CAD80AE1C3B50A2AF83022F630C33C6B -:180AE000043E64327B31CD480DC1E5CD310D22773121020039CDEF06BF -:180AF800D1C2110B09D52B562B5E2323E52A7731CD0A0AE1C2F50AD1FE -:180B1000F9EB0E08CD1F07E52A7731E3E52A0C31E3CD0A10CD100AA6A3 -:180B2800CD0710E5CD351AE1C5D5010081515A7EFEAB3E01C24D0BCDDB -:180B40009A0BCD0710E5CD351ACDE919E1C5D5F533E52A7E31E3068179 -:180B5800C533CDC50B227E317EFE3ACA7A0BB7C24207237E23B6CAEC28 -:180B70000B235E2356EB220C31EBCD9A0B115A0BD5C8D680DA480DFE2B -:180B880025D24207074F0600EB21EA05094E2346C5EB237EFE3AD0FEA7 -:180BA00020CA9A0BFE303F3C3DC9EB2A0E31CABF0BEBCD660CE5CD2E0D -:180BB800086069D1D2070D2B228C31EBC9DFC8D7FE1B2811FE03280DD9 -:180BD000FE13C0D7FE11C8FE03280718F63EFF32FD30C0F6C0227E316D -:180BE80021F6FFC12A0C31F57DA43CCAFF0B2282312A7E31228431AF5D -:180C000032F530CD350EF121E506C27607C38D072A84317CB51E20CACA -:180C18005607EB2A8231220C31EBC9CD6817C032F130C9E52AFA300625 -:180C3000004F0922FA30E1C97EFE41D8FE5B3FC9CD9A0BCD0710CDE95C -:180C480019FA610C3A9731FE90DA911A018090110000E5CD641AE1517B -:180C6000C81E08C356072B110000CD9A0BD0E5F5219819CD0A0ADA4247 -:180C780007626B19291929F1D6305F160019EBE1C36A0CCA5E08CD4342 -:180C90000C2BCD9A0BE52A5F31CAAE0CE1CD100A2CD5CD430C2BCD9A09 -:180CA8000BC24207E3EB7D935F7C9A57DA3707E52A863101280009CD97 -:180CC0000A0AD23707EB220A31E1225F31E1C35E08CA5A08CD5E0801B3 -:180CD8005A0BC3ED0C0E03CD1F07C1E5E52A0C31E33E8CF533C5CD6620 -:180CF0000CCD330DE52A0C31CD0A0AE123DC3108D42E0860692BD81E99 -:180D08000EC35607C016FFCDEB06F9FE8C1E04C25607E1220C31237C6F -:180D2000B5C22B0D3A7C31B7C28C07215A0BE33EE1013A0E00060079C9 -:180D380048477EB7C8B8C823FE22CA370DC33A0DCDFD11CD100AB4D5F1 -:180D50003A5D31F5CD1910F1E3227E311FCD0C10CA9B0DE52A9431E500 -:180D680023235E23562A0E31CD0A0AD28A0D2A0A31CD0A0AD1D2920D1B -:180D8000216F31CD0A0AD2920D3ED1CD4116EBCD7A14CD4116E1CD44B9 -:180D98001AE1C9E5CD411AD1E1C9CD68177E47FE8CCAB10DCD100A8865 -:180DB0002B4B0D78CA820BCD670CFE2CC0C3B20DCD19107EFE88CACE9B -:180DC8000DCD100AA92BCD0A10CDE919CA330DCD9A0BDAEE0CC3810BF6 -:180DE0002BCD9A0BCA420EC8FEA5CA750EFEA8CA750EE5FE2CCA5E0E54 -:180DF800FE3BCA980EC1CD1910E53A5D31B7C22E0ECD8E1BCD9E1436F6 -:180E1000202A9431342A94313AF2304704CA2A0E043A5B31863DB8D4D6 -:180E2800420ECDE314AFC4E314E1C3E00D3A5B31B7C8C3420E360021F4 -:180E400010313E0DCD1B0A3E0ACD1B0AAF325B313AF1303DC8F5AFCDA4 -:180E58001B0AF1C3530E3AF330473A5B31B8D4420ED2980ED60ED26C68 -:180E70000E2FC38D0EF5CD6517CD100A292BF1D6A8E5CA880E3A5B31DC -:180E88002F83D2980E3C473E20CD1B0A05C2910EE1CD9A0BC3E70D3FA6 -:180EA0005265646F2066726F6D2073746172740D0A003A7D31B7C23CDA -:180EB80007C1219F0ECDE014C38D08CD4B147EFE223E0032F530C2DD75 -:180ED0000ECD9F14CD100A3BE5CDE3143EE5CD9108C1DAE90B237EB741 -:180EE8002BC5CA300D362CC3F70EE52A8C31F6AF327D31E3C3030FCDFB -:180F0000100A2CCDFD11E3D57EFE2CCA2B0F3A7D31B7C2980F3E3FCD02 -:180F18001B0ACD9108D1C1DAE90B237EB72BC5CA300DD53A5D31B7CA69 -:180F3000550FCD9A0B5747FE22CA490F3A7D31B757CA460F163A062C5C -:180F48002BCDA214EB21600FE3D5C3630DCD9A0BCDF01AE3CD411AE148 -:180F60002BCD9A0BCA6C0FFE2CC2B20EE32BCD9A0BC2FF0ED13A7D31E3 -:180F7800B7EBC2C00BD5B621870FC4E014E1C93F45787472612069675B -:180F90006E6F7265640D0A00CD310DB7C2B10F237E23B61E06CA560711 -:180FA800235E2356EB227931EBCD9A0BFE83C2980FC32B0F110000C467 -:180FC000FD11227E31CDEB06C24807F9D57E23F5D5CD271AE3E5CD94FB -:180FD80017E1CD411AE1CD381AE5CD641AE1C190CD381ACAF70FEB2283 -:180FF0000C316960C3560BF92A7E317EFE2CC25A0BCD9A0BCDBF0FCD44 -:181008001910F6373A5D318FB7E8C35407CD100A282B1600D50E01CD65 -:181020001F07CD90102280312A8031C178FE78D40A107E1600D6B3DAE3 -:181038005110FE03D25110FE0117AABA57DA4207227531CD9A0BC335E5 -:18105000107AB7C278117E227531D6ACD8FE07D05F3A5D313DB37BCA2B -:18106800D61507835F213406197856BAD023CD0A10C5012810C5434A76 -:18108000CD1A1A58514E234623C52A7531C31C10AF325D31CD9A0B1E51 -:1810980024CA5607DAF01ACD380CD2F710FE262012CD9A0BFE48CA341B -:1810B0001FFE42CAA41F1E02CA5607FEACCA9010FE2ECAF01AFEADCA6C -:1810C800E610FE22CA9F14FEAACAD811FEA7CA0314D6B6D20811CD1543 -:1810E00010CD100A29C9167DCD1C102A8031E5CD121ACD0A10E1C9CD6C -:1810F800FD11E5EB2294313A5D31B7CC271AE1C90600074FC5CD9A0B52 -:1811100079FE31DA2F11CD1510CD100A2CCD0B10EB2A9431E3E5EBCDBE -:181128006817EBE3C33711CDDE10E311F210D5019304094E236669E907 -:1811400015FEADC8FE2DC814FE2BC8FEACC82BC9F6AFF5CD0A10CD4C17 -:181158000CF1EBC1E3EBCD2A1AF5CD4C0CF1C17921C113C27311A34F85 -:1811700078A2E9B34F78B2E9218A113A5D311F7A175F166478BAD0C37D -:1811880079108C1179B71FC1D1F5CD0C1021CE11E5CA641AAF325D31CE -:1811A000D5CD23167E23234E2346D1C5F5CD2716CD381AF157E17BB2D7 -:1811B800C87AD601D8AFBB3CD0151D0ABE2303CAB6113FC3F4193C8F2D -:1811D000C1A0C6FF9FC3FB19165ACD1C10CD0A10CD4C0C7B2F4F7A2F54 -:1811E800CDC113C1C328102BCD9A0BC8CD100A2C01EF11C5F6AF325C21 -:181200003146CD380CDA4207AF4F325D31CD9A0BDA1912CD380CDA26E5 -:18121800124FCD9A0BDA1A12CD380CD21A12D624C235123C325D310FC8 -:18123000814FCD9A0B3A7B313DCAE212F245127ED628CABA12AF327BCC -:1812480031E550592A8E31CD0A0A119031CA2A192A8831EB2A8631CDAA -:181260000A0ACA7812799623C26D12789623CAAC1223232323C35F1222 -:18127800E1E3D511FA10CD0A0AD1CAAF12E3E5C50106002A8A31E50906 -:18129000C1E5CD0E07E1228A3160692288312B3600CD0A0AC29E12D1D7 -:1812A80073237223EBE1C932973121DE06229431E1C9E52A5C31E35708 -:1812C000D5C5CD400CC1F1EBE3E5EB3C577EFE2CCAC012CD100A29220A -:1812D8008031E1225C311E00D511E5F52A88313E19EB2A8A31EBCD0A13 -:1812F0000ACA1A137EB923C2FC127EB8235E235623C2E8123A5C31B72E -:18130800C24B07F1444DCA2A1996CA78131E10C35607110400F1CA61C0 -:181320000C712370234FCD1F07232322753171233A5C311779010B003B -:18133800D23D13C10371237023F5E5CDD51AEBE1F13DC23513F5424B74 -:18135000EB19DA3707CD2807228A312B3600CD0A0AC25B1303572A7525 -:18136800315EEB2909EB2B2B73237223F1DA9C13474F7E2316E15E232C -:181380005623E3F5CD0A0AD21513E5CDD51AD119F13D444DC27D132964 -:1813980029C109EB2A8031C92A8A31EB210000393A5D31B7CABC13CDAC -:1813B0002316CD23152A0A31EB2A73317D934F7C9A41501E00215D31F6 -:1813C800730690C3001A3A5B3147AFC3C213CD5914CD4B1401310DC569 -:1813E000D5CD100A28CDFD11E5EB2B562B5EE1CD0A10CD100A29CD10A7 -:1813F8000AB4444DE3712370C39814CD5914D5CDDE10CD0A10E35E2323 -:1814100056237AB3CA4E077E23666FE52A8E31E3228E312A9231E52AFB -:181428009031E5219031D5CD411AE1CD07102BCD9A0BC24207E1229027 -:1814400031E1229231E1228E31E1C9E52A0C31237CB5E1C01E16C356A3 -:1814580007CD100AA73E80327B31B647CD0212C30A10CD0A10CD8E1B33 -:18147000CD9E14CD2316017E16C57E2323E5CDF914E14E2346CD9214F7 -:18148800E56FCD1616D1C9CDF914216F31E5772323732372E1C92B0645 -:1814A0002250E50EFF237E0CB7CAB414BACAB414B8C2A514FE22CC9AD5 -:1814B8000BE323EB79CD9214116F312A61312294313E01325D31CD44D0 -:1814D0001ACD0A0A226131E17EC01E1EC3560723CD9E14CD2316CD382D -:1814E8001A1C1DC80ACD1B0AFE0DCC4C0E03C3EA14B70EF1F52A0A31D0 -:18150000EB2A73312F4F06FF0923CD0A0ADA171522733123EBF1C9F105 -:181518001E1ACA5607BFF501FB14C52A5F31227331210000E52A0A31E8 -:18153000E5216331EB2A6131EBCD0A0A013415C288152A8631EB2A886F -:1815480031EBCD0A0ACA5B157E2323B7CD8B15C34515C1EB2A8A31EBD3 -:18156000CD0A0ACAB115CD381A7BE509B7F25A15227531E14E0600095C -:181578000923EB2A7531EBCD0A0ACA5B15017A15C5F6807E23235E235E -:181590005623F0B7C8444D2A7331CD0A0A6069D8E1E3CD0A0AE3E560AD -:1815A80069D0C1F1F1E5D5C5C9D1E17DB4C82B462B4EE52B2B6E2600A3 -:1815C0000950592B444D2A7331CD1107E171237069602BC32615C5E571 -:1815D8002A9431E3CD9010E3CD0B107EE52A9431E5861E1CDA5607CDF6 -:1815F0008F14D1CD2716E3CD2616E52A7131EBCD0D16CD0D16212510A7 -:18160800E3E5C3C014E1E37E23234E23466F2C2DC80A120313C317167A -:18162000CD0B102A9431EBCD4116EBC0D550591B4E2A7331CD0A0AC2C9 -:181638003F164709227331E1C92A61312B462B4E2B2BCD0A0AC0226165 -:1816500031C901D113C5CD2016AF57325D317EB7C901D113C5CD561634 -:18166800CA610C23235E23561AC93E01CD8F14CD6B172A713173C1C372 -:18168000C014CD1B17AFE34FE57EB8DA901678110E00C5CDF914C1E12B -:18169800E5232346236668060009444DCD92146FCD1616D1CD2716C3BF -:1816B000C014CD1B17D1D51A90C38616EB7ECD20170405CA610CC51E10 -:1816C800FFFE29CAD516CD100A2CCD6817CD100A29F1E3018816C53D4B -:1816E000BE0600D04F7E91BB47D843C9CD5616CA09185F23237E23664A -:1816F8006FE5194672E3C57EFE24C20A17CD341F180DFE25C21417CD68 -:18171000A41F1803CDF01AC1E170C9EBCD100A29C1D1C543C9CD6B1784 -:1817280032EF30CDEE30C3D113CD5517C3B630CD5517F51E002BCD9A06 -:181740000BCA4B17CD100A2CCD6817C1CDEE30ABA0CA4C17C9CD6817C2 -:1817580032EF3032B730CD100A2CC36817CD9A0BCD0710CD460C7AB714 -:18177000C2610C2BCD9A0B7BC9CD4C0C1AC3D113CD0710CD4C0CD5CDC0 -:18178800100A2CCD6817D112C921671CCD381AC3A317CD381A21C1D1F9 -:1817A000CD121A78B7C83A9731B7CA2A1A90D2BD172F3CEBCD1A1AEB02 -:1817B800CD2A1AC1D1FE19D0F5CD4F1A67F1CD6818B4219431F2E31739 -:1817D000CD4818D229182334CA51072E01CD7E18C32918AF90477E9B13 -:1817E8005F237E9A57237E994FDC54186863AF4779B7C216184A546543 -:181800006F78D608FEE0C2F717AF329731C905297A1757798F4FF20E7E -:1818180018785C45B7CA29182197318677D20918C878219731B7FC3BD5 -:181830001846237EE680A94FC32A1A1CC014C00CC00E8034C0C3510723 -:181848007E835F237E8A57237E894FC92198317E2F77AF6F90477D9B49 -:181860005F7D9A577D994FC90600D608DA7718435A510E00C36A18C621 -:18187800096FAF2DC8791F4F7A1F577B1F5F781F47C37A1800000081B8 -:1818900003AA561980F122768045AA3882CDE919B7EA610C2197317EAE -:1818A80001358011F30490F570D5C5CDA317C1D104CD3F19218C18CD07 -:1818C0009A17219018CD311D018080110000CDA317F1CD641B013180F3 -:1818D80011187221C1D1CDE919C82E00CDA7197932A631EB22A73101F0 -:1818F0000000505821F417E5210019E5E52194317E23B7CA2C19E52EC3 -:18190800081F6779D21A19E52AA73119EBE13AA631891F4F7A1F577B7C -:181920001F5F781F472D7CC20919E1C9435A514FC9CD1A1A012084115F -:181938000000CD2A1AC1D1CDE919CA45072EFFCDA71934342B7E32C250 -:18195000302B7E32BE302B7E32BA3041EBAF4F575F32C530E5C57DCDC6 -:18196800B930DE003FD2771932C530F1F137D2C1E1793C3D1FFA2A18FE -:18198000177B175F7A175779174F297817473AC5301732C53079B2B336 -:18199800C26419E521973135E1C26419C3510778B7CACB197D21973177 -:1819B000AE80471FA878F2CA19C68077CA2A19CD4F1A772BC9CDE9195C -:1819C8002FE1B7E1F20918C35107CD351A78B7C8C602DA510747CDA36D -:1819E0001721973134C0C351073A9731B7C83A9631FE2F179FC03CC9B6 -:1819F800CDE91906881100002197314F70060023368017C3F117CDE94A -:181A100019F02196317EEE8077C9EB2A9431E3E52A9631E3E5EBC9CDC5 -:181A2800381AEB2294316069229631EBC92194315E2356234E23462362 -:181A4000C911943106041A77132305C2461AC92196317E07371F773FB5 -:181A58001F2323777907371F4F1FAEC978B7CAE91921F219E5CDE91904 -:181A700079C8219631AE79F8CD7E1A1FA9C92378BEC02B79BEC02B7A40 -:181A8800BEC02B7B96C0E1E1C9474F575FB7C8E5CD351ACD4F1AAE672A -:181AA000FCB51A3E9890CD68187C17DC3B180600DC5418E1C91B7AA3BE -:181AB8003CC00BC92197317EFE983A9431D07ECD911A36987BF57917B6 -:181AD000CDF117F1C921000078B1C83E1029DA1513EB29EBD2EB1A0905 -:181AE800DA15133DC2DD1AC9FE2DF5CAFC1AFE2BCAFC1A2BCD091847BC -:181B0000575F2F4FCD9A0BDA4D1BFE2ECA281BFE45C22C1BCD9A0BCD21 -:181B18004011CD9A0BDA6F1B14C22C1BAF935F0C0CCA041BE57B90F4EB -:181B3000451BF23B1BF5CD3119F13CC22F1BD1F1CC121AEBC9C8F5CDB8 -:181B4800D219F13DC9D557788947C5E5D5CDD219F1D630CD641BE1C113 -:181B6000D1C3041BCD1A1ACDFB19C1D1C3A3177B0707830786D6305FCB -:181B7800C31A1BE521DA06CDE014E1EBAF0698CD001A21DF14E5219903 -:181B900031E5CDE9193620F29C1B362D233630CA521CE5FC121AAFF584 -:181BA800CD581C01439111F84FCD641AB7E2C91BF1CD461BF5C3AB1B52 -:181BC000CD3119F13CF5CD581CCD91173CCD911ACD2A1A010603F181DD -:181BD8003CFAE51BFE08D2E51B3C473E023D3DE1F5116B1C05C2F61B64 -:181BF000362E2336302305362ECC3F1AC5E5D5CD351AE1062F047B9679 -:181C08005F237A9E5723799E4F2B2BD2051CCD481823CD2A1AEBE17064 -:181C200023C10DC2F61B05CA361C2B7EFE30CA2A1CFE2EC43F1AF1CADC -:181C3800551C364523362BF2461C362D2F3C062F04D60AD2481CC63AB3 -:181C5000237023772371E1C901749411F723CD641AB7E1E2C01BE90054 -:181C6800000080A08601102700E803006400000A000001000021121ADF -:181C8000E3E9CD1A1A21671CCD271AC1D1CDE91978CAD01CF29B1CB7DE -:181C9800CA4507B7CA0A18D5C579F67FCD351AF2B81CD5C5CDBC1AC113 -:181CB000D1F5CD641AE17C1FE1229631E1229431DC7D1CCC121AD5C5F6 -:181CC800CD9D18C1D1CDDE18CD1A1A013881113BAACDDE183A9731FEB9 -:181CE00088D2C519CDBC1AC680C602DAC519F5218C18CD9417CDD5185F -:181CF800F1C1D1F5CDA017CD121A21101DCD401D110000C14AC3DE1892 -:181D100008402E9474704F2E776E02887AE6A02A7C50AAAA7EFFFF7F9C -:181D28007F0000808100000081CD1A1A11DC18D5E5CD351ACDDE18E122 -:181D4000CD1A1A7E23CD271A06F1C1D13DC8D5C5F5E5CDDE18E1CD3830 -:181D58001AE5CDA317E1C3491DCDE91921C930FAC21D21EA30CD271AD8 -:181D700021C930C886E6070600772387874F09CD381ACDDE183AC830EC -:181D88003CE6030600FE018832C83021C61D87874F09CD9417CD351A69 -:181DA0007B59EE4F4F36802B46368021C730347ED6ABC2B91D770C1573 -:181DB8001CCDF41721EA30C3411A772B772B77C39D1D68B1466899E945 -:181DD000926910D1756821201ECD9417CD1A1A01498311DB0FCD2A1A91 -:181DE800C1D1CD3F19CD1A1ACDBC1AC1D1CDA01721241ECD9A17CDE9DB -:181E00001937F20C1ECD9117CDE919B7F5F4121A21241ECD9417F1D4AE -:181E1800121A21281EC3311DDB0F49810000007F05BAD71E866426997E -:181E30008758342387E05DA586DA0F4983CD1A1ACDDC1DC1E1CD1A1A56 -:181E4800EBCD2A1ACDD61DC33D19CDE919FC7D1CFC121A3A9731FE81A0 -:181E6000DA6F1E0100815159CD3F19219A17E521791ECD311D21201EC9 -:181E7800C9094AD73B78026E847BFEC12F7C74319A7D843D5A7DC87F38 -:181E9000917EE4BB4C7E6CAAAA7F00000081C9D7C93E0CC3DB1FCD685D -:181EA800177B32F230C9CD0710CD4C0CED53F630ED53F830C9CD4C0CAE -:181EC000D5E146237EC3C213CD0710CD4C0CD5CD100A2CCD0710CD4CE7 -:181ED8000CE3732372E1C9CD0A10CD4C0CC52199317AFE00280CCD1705 -:181EF0001F78FE302802702371237BCD171F7AFE00200578FE302802D9 -:181F080070237123AF772377C1219931C3701447E60FFE0A3802C6079C -:181F2000C6304F780F0F0F0FE60FFE0A3802C607C63047C9EB2100009A -:181F3800CD4D1FDA6D1F1805CD4D1F381F29292929B56F18F3131AFE47 -:181F500020CA4D1FD630D8FE0A3805D607FE0AD8FE103FC9EB7A4BE598 -:181F6800CDC113E1C91E26C35607CD0A10CD4C0CC52199310611057862 -:181F8000FE012808CB13CB1230F41804CB13CB123E30CE007723052069 -:181F9800F3AF772377C1219931C37014EB210000CDC11FDACF1FD63004 -:181FB00029B56FCDC11F30F6EB7A4BE5CDC113E1C9131AFE20CAC11F24 -:181FC800FE30D8FE323FC91E28C35607DD21FFFFC3A603C30800C30067 -:181FE000003E0032FD30C3AD03ED45F5A0C1B83E00C9CD1B0AC3420E8D -:00000001FF +:0430040000000000C8 +:18000000F3C3940000000000C332000000000000C31B000000000000CB +:18001800C35C003A0030FE002008CD630028FBDB81C9CD6A0028FBDB74 +:1800300083C9F53A0030FE00200D1801F5CD500028FBF1D381C9F5CDC4 +:18004800560028FBF1D383C9DB800FCB47C9DB820FCB47C93A0030FE23 +:18006000002007DB80E601FE00C9DB82E601FE00C9D7FE0A28FBFE1B32 +:1800780020023E03C9FE0D280AFE0C2804FE203801CFC93E0DCF3E0A80 +:18009000CF3E0DC93128303E95D380D3823E00320030216503CD1B015F +:1800A8003E01320030216503CD1B01CD6300280F3E00320030CD1B003E +:1800C000FE20C2B3001814CD6A0028E73E01320030CD1B00FE20C2B307 +:1800D8000018003E0CCD3C00CD4600CD2201219602CD1B0121EC00E50E +:1800F000CD22013E3ECFCD7100FE2038F9FE3ACA9901CD7D00E65FFE07 +:1801080042CADA01FE47CA9301FE58CAF1013E3FCF18D57EB7C8CF231B +:1801200018F93E0DCF3E0ACFC9CD7100FE03C8FE2038F6C9CD29014762 +:18013800CD29014FCD73014F7B915F79C9210000CD8C01FE0D200E3741 +:18015000C9210000CD8C01FE0DC8FE2CC8FE0328EE29292929D630FECF +:180168000A3802D607E60F856F18E178D630FE0A3802D60707070707C3 +:180180004779D630FE0A3802D60780C9CD7100CD7D00C9CD4501D8E518 +:18019800C91E00CD340157CD340167CD34016FCD3401FE012009CD340A +:1801B000017BA7281E18157AA7280BCD340177233E2ECF1518F1CD3457 +:1801C800017BA7C8215403CD1B01C9218A03CD1B01C9214203CD1B015B +:1801E000CD2901C8E65FFE43CA9503FE57CA9803C9210302CD1B01CD01 +:1801F8002901C8E65FFE59CA2402C90D0A426F6F742043502F4D3F008F +:180210000D0A4C6F6164696E672043502F4D2E2E2E0D0A00211002CD31 +:180228001B0106183E003204303205303206303207302100D022023063 +:18024000CD6E021100022A0230192202303A04303C32043010EA3A0049 +:1802580030F52AFEFFE93A0630D38C3A0530D38B3A0430D38AC9F5C56F +:18027000E5DB89FE8020FACD5E023E00D3890E040680DB89FEE020FADA +:18028800DB8877230520F30D20EEE1C1F1C943502F4D20426F6F7420EF +:1802A000524F4D20322E3020627920472E20536561726C650D0A0D0A6E +:1802B8004243206F72204257202D20524F4D20424153494320436F6CD4 +:1802D000642F5761726D0D0A5820202020202020202D20426F6F74207C +:1802E80043502F4D20286C6F61642024443030302D2446464646290D50 +:180300000A3A6E6E6E6E2E2E2E202D204C6F616420496E74656C2D48E1 +:1803180065782066696C65207265636F72640D0A476E6E6E6E2020201B +:18033000202D2052756E206C6F63206E6E6E6E0D0A000D0A436F6C642D +:18034800206F72207761726D3F0D0A00436865636B73756D20657272D3 +:180360006F720D0A000C5072657373205B53504143455D20746F2061AC +:180378006374697661746520636F6E736F6C650D0A00436F6D706C65F3 +:1803900074650D0A00C39B03C33904DD210000C3A6034C0CC21321B09C +:1803A80030F9C3E11F117306066321B0301A77231305C2B503F9CD74DD +:1803C00008CD420E325A3132A931218804CDE014CD9108CD9A0BB7C278 +:1803D800EF03210D32237CB5CA01047E472F77BE70CADD03C30104CDC0 +:1803F000660CB7C24207EB2B3ED94677BE70C2CA032B110C32CD0A0ABF +:18040800DACA0311CEFF225F3119220A31CD4F082A0A3111EFFF19117D +:18042000A9317D936F7C9A67E5215104CDE014E1CD831B214204CDE072 +:1804380014311631CD7408C38D0720427974657320667265650D0A0080 +:18045000005A38302042415349432056657220342E37620D0A436F70AF +:18046800797269676874202843292031393738206279204D6963726F23 +:18048000736F66740D0A00004D656D6F727920746F7000F819BC1A0EB0 +:180498001AB330A0132517CE13821C611D9D18D01CD61DDC1D3D1E5229 +:1804B0001E7917BD1E013152166A14EC1661167216DF1E721F8216B2BA +:1804C80016BC16C54E44C64F52CE455854C4415441C94E505554C44900 +:1804E0004DD2454144CC4554C74F544FD2554EC946D24553544F5245D5 +:1804F800C74F535542D2455455524ED2454DD3544F50CF5554CF4ECEFF +:18051000554C4CD7414954C44546D04F4B45C44F4B45D3435245454E50 +:18052800CC494E4553C34C53D749445448CD4F4E49544F52D34554D278 +:1805400045534554D052494E54C34F4E54CC495354C34C454152C34CFF +:180558004F4144C353415645CE4557D4414228D44FC64ED3504328D443 +:1805700048454ECE4F54D3544550ABADAAAFDEC14E44CF52BEBDBCD35E +:18058800474EC94E54C14253D55352C65245C94E50D04F53D35152D20D +:1805A0004E44CC4F47C55850C34F53D3494ED4414EC1544ED045454BA8 +:1805B800C445454BD04F494E54CC454ED3545224D6414CC15343C348C7 +:1805D0005224C8455824C2494E24CC45465424D24947485424CD49444C +:1805E8002480E40BE10ABC0F310DC30EF811F20E480DEE0CD10CC00DA1 +:18060000AA0BDD0C0C0D330DE20B3117A20D230C3717D6138017C81E24 +:18061800330DAE1EA11EA61EDE1F04310731E40D100C560A8B0C330D8D +:18063000330D4E08796A1B799E177CDC187C3D197F8B1C505111465040 +:18064800114E46534E52474F4446434F564F4D554C425344442F3049F8 +:1806600044544D4F534C535354434E55464D4F4858424EC33904C36199 +:180678000CD300C9D6006F7CDE006778DE00473E00C9000000354ACACF +:1806900099391C76982295B3980ADD479853D199990A1A9F9865BCCDEF +:1806A80098D6773E9852C74F80DB00C901FF1C000014001400000000AF +:1806C00000C38709C30000C30000C300000D32FEFFAA31204572726FB7 +:1806D800720020696E20004F6B0D0A0000427265616B00210400397EEF +:1806F00023FE81C04E234623E569607AB3EBCA0507EBCD0A0A010D0040 +:18070800E1C809C3EF06CD2807C5E3C1CD0A0A7E02C80B2BC31407E5E8 +:180720002A8A31060009093EE53ED0956F3EFF9CDA37076739E1D81E27 +:180738000CC356072A7931220C311E02011E14011E00011E12011E2266 +:18075000011E0A011E18CD740832F530CD350E214906573E3FCD1B0A4B +:18076800197ECD1B0ACD9A0BCD1B0A21D306CDE0142A0C3111FEFFCD8F +:180780000A0ACAA6037CA53CC47B1B3EC1AF32F530CD350E21DF06CD3B +:18079800E01421FFFF220C31CD8709DA9A07CD9A0B3C3DCA9A07F5CDE7 +:1807B000660CD5CD9E0847D1F1D27A0BD5C5AF327C31CD9A0BB7F5CD04 +:1807C8002E08DAD307F1F5CA070DB7C5D2EA07EB2A86311A020313CD61 +:1807E0000A0AC2DB076069228631D1F1CA11082A8631E3C109E5CD0EB4 +:1807F80007E1228631EB74D12323732372231111311A772313B7C209EB +:1808100008CD5A0823EB626B7E23B6CA9A07232323AFBE23C22208EB2C +:18082800732372C316082A0E31444D7E23B62BC823237E23666FCD0AF8 +:180840000A60697E23666F3FC83FD0C33108C02A0E31AF772377232217 +:1808580086312A0E312B227E312A5F31227331AFCDAA0B2A8631228830 +:1808700031228A31C12A0A31F9216331226131AF6F67228431327B31A0 +:18088800228E31E5C52A7E31C93E3FCD1B0A3E20CD1B0AC3FE30AF329A +:1808A0005E310E051111317EFE20CA260947FE22CA4609B7CA4D093A25 +:1808B8005E31B77EC22609FE3F3E9ECA26097EFE30DAD108FE3CDA26C8 +:1808D00009D511CA04C5012209C5067F7EFE61DAEA08FE7BD2EA08E64C +:1808E8005F774EEB23B6F2EC08047EE67FC8B9C2EC08EBE5131AB7FA5E +:180900001E094F78FE88C20D09CD9A0B2B237EFE61DA1609E65FB9CA35 +:18091800FC08E1C3EA0848F1EBC9EB79C1D12312130CD63ACA3409FEE1 +:1809300049C23709325E31D654C2A708477EB7CA4D09B8CA2609231286 +:180948000C13C33D092110311213121312C93AF430B73E0032F430C27D +:180960006A0905CA8709CD1B0A3E052BCA7E097ECD1B0AC39009052B00 +:18097800CD1B0AC29009CD1B0ACD420EC387092111310601AF32F43049 +:18099000CD450A4FFE7FCA56093AF430B7CAA9093E00CD1B0AAF32F4A8 +:1809A8003079FE07CAED09FE03CC420E37C8FE0DCA3D0EFE15CA810926 +:1809C000FE40CA7E09FE5FCA7609FE08CA7609FE12C2E809C5D5E53623 +:1809D80000CDF21F211131CDE014E1D1C1C39009FE20DA900978FE49E6 +:1809F0003E07D2020A7971327C312304CD1B0AC39009CD1B0A3E08C393 +:180A0800FC097C92C07D93C97EE3BE23E3CA9A0BC34207F53AF530B77F +:180A2000C21515F1C5F5FE20DA3F0A3AF230473A5B3104CA3B0A05B8AD +:180A3800CC420E3C325B31F1C1CDDB1FC9CD9F1EE67FFE0FC03AF53033 +:180A50002F32F530AFC9CD660CC0C1CD2E08C5CDAC0AE14E2346237852 +:180A6800B1CA8D07CDB50ACDC50BC5CD420E5E235623E5EBCD831B3EE9 +:180A800020E1CD1B0A7EB723CA620AF2820AD67F4F11CB041A13B7F205 +:180A9800940A0DC2940AE67FCD1B0A1A13B7F29E0AC3850AE52AF830DD +:180AB00022F630E1C9E5D52AF63011FFFFED5A22F630D1E1F0E52AF8EB +:180AC8003022F630CD9F1EFE03CAD80AE1C3B50A2AF83022F630C33C6B +:180AE000043E64327B31CD480DC1E5CD310D22773121020039CDEF06BF +:180AF800D1C2110B09D52B562B5E2323E52A7731CD0A0AE1C2F50AD1FE +:180B1000F9EB0E08CD1F07E52A7731E3E52A0C31E3CD0A10CD100AA6A3 +:180B2800CD0710E5CD351AE1C5D5010081515A7EFEAB3E01C24D0BCDDB +:180B40009A0BCD0710E5CD351ACDE919E1C5D5F533E52A7E31E3068179 +:180B5800C533CDC50B227E317EFE3ACA7A0BB7C24207237E23B6CAEC28 +:180B70000B235E2356EB220C31EBCD9A0B115A0BD5C8D680DA480DFE2B +:180B880025D24207074F0600EB21EA05094E2346C5EB237EFE3AD0FEA7 +:180BA00020CA9A0BFE303F3C3DC9EB2A0E31CABF0BEBCD660CE5CD2E0D +:180BB800086069D1D2070D2B228C31EBC9DFC8D7FE1B2811FE03280DD9 +:180BD000FE13C0D7FE11C8FE03280718F63EFF32FD30C0F6C0227E316D +:180BE80021F6FFC12A0C31F57DA43CCAFF0B2282312A7E31228431AF5D +:180C000032F530CD350EF121E506C27607C38D072A84317CB51E20CACA +:180C18005607EB2A8231220C31EBC9CD6817C032F130C9E52AFA300625 +:180C3000004F0922FA30E1C97EFE41D8FE5B3FC9CD9A0BCD0710CDE95C +:180C480019FA610C3A9731FE90DA911A018090110000E5CD641AE1517B +:180C6000C81E08C356072B110000CD9A0BD0E5F5219819CD0A0ADA4247 +:180C780007626B19291929F1D6305F160019EBE1C36A0CCA5E08CD4342 +:180C90000C2BCD9A0BE52A5F31CAAE0CE1CD100A2CD5CD430C2BCD9A09 +:180CA8000BC24207E3EB7D935F7C9A57DA3707E52A863101280009CD97 +:180CC0000A0AD23707EB220A31E1225F31E1C35E08CA5A08CD5E0801B3 +:180CD8005A0BC3ED0C0E03CD1F07C1E5E52A0C31E33E8CF533C5CD6620 +:180CF0000CCD330DE52A0C31CD0A0AE123DC3108D42E0860692BD81E99 +:180D08000EC35607C016FFCDEB06F9FE8C1E04C25607E1220C31237C6F +:180D2000B5C22B0D3A7C31B7C28C07215A0BE33EE1013A0E00060079C9 +:180D380048477EB7C8B8C823FE22CA370DC33A0DCDFD11CD100AB4D5F1 +:180D50003A5D31F5CD1910F1E3227E311FCD0C10CA9B0DE52A9431E500 +:180D680023235E23562A0E31CD0A0AD28A0D2A0A31CD0A0AD1D2920D1B +:180D8000216F31CD0A0AD2920D3ED1CD4116EBCD7A14CD4116E1CD44B9 +:180D98001AE1C9E5CD411AD1E1C9CD68177E47FE8CCAB10DCD100A8865 +:180DB0002B4B0D78CA820BCD670CFE2CC0C3B20DCD19107EFE88CACE9B +:180DC8000DCD100AA92BCD0A10CDE919CA330DCD9A0BDAEE0CC3810BF6 +:180DE0002BCD9A0BCA420EC8FEA5CA750EFEA8CA750EE5FE2CCA5E0E54 +:180DF800FE3BCA980EC1CD1910E53A5D31B7C22E0ECD8E1BCD9E1436F6 +:180E1000202A9431342A94313AF2304704CA2A0E043A5B31863DB8D4D6 +:180E2800420ECDE314AFC4E314E1C3E00D3A5B31B7C8C3420E360021F4 +:180E400010313E0DCD1B0A3E0ACD1B0AAF325B313AF1303DC8F5AFCDA4 +:180E58001B0AF1C3530E3AF330473A5B31B8D4420ED2980ED60ED26C68 +:180E70000E2FC38D0EF5CD6517CD100A292BF1D6A8E5CA880E3A5B31DC +:180E88002F83D2980E3C473E20CD1B0A05C2910EE1CD9A0BC3E70D3FA6 +:180EA0005265646F2066726F6D2073746172740D0A003A7D31B7C23CDA +:180EB80007C1219F0ECDE014C38D08CD4B147EFE223E0032F530C2DD75 +:180ED0000ECD9F14CD100A3BE5CDE3143EE5CD9108C1DAE90B237EB741 +:180EE8002BC5CA300D362CC3F70EE52A8C31F6AF327D31E3C3030FCDFB +:180F0000100A2CCDFD11E3D57EFE2CCA2B0F3A7D31B7C2980F3E3FCD02 +:180F18001B0ACD9108D1C1DAE90B237EB72BC5CA300DD53A5D31B7CA69 +:180F3000550FCD9A0B5747FE22CA490F3A7D31B757CA460F163A062C5C +:180F48002BCDA214EB21600FE3D5C3630DCD9A0BCDF01AE3CD411AE148 +:180F60002BCD9A0BCA6C0FFE2CC2B20EE32BCD9A0BC2FF0ED13A7D31E3 +:180F7800B7EBC2C00BD5B621870FC4E014E1C93F45787472612069675B +:180F90006E6F7265640D0A00CD310DB7C2B10F237E23B61E06CA560711 +:180FA800235E2356EB227931EBCD9A0BFE83C2980FC32B0F110000C467 +:180FC000FD11227E31CDEB06C24807F9D57E23F5D5CD271AE3E5CD94FB +:180FD80017E1CD411AE1CD381AE5CD641AE1C190CD381ACAF70FEB2283 +:180FF0000C316960C3560BF92A7E317EFE2CC25A0BCD9A0BCDBF0FCD44 +:181008001910F6373A5D318FB7E8C35407CD100A282B1600D50E01CD65 +:181020001F07CD90102280312A8031C178FE78D40A107E1600D6B3DAE3 +:181038005110FE03D25110FE0117AABA57DA4207227531CD9A0BC335E5 +:18105000107AB7C278117E227531D6ACD8FE07D05F3A5D313DB37BCA2B +:18106800D61507835F213406197856BAD023CD0A10C5012810C5434A76 +:18108000CD1A1A58514E234623C52A7531C31C10AF325D31CD9A0B1E51 +:1810980024CA5607DAF01ACD380CD2F710FE262012CD9A0BFE48CA341B +:1810B0001FFE42CAA41F1E02CA5607FEACCA9010FE2ECAF01AFEADCA6C +:1810C800E610FE22CA9F14FEAACAD811FEA7CA0314D6B6D20811CD1543 +:1810E00010CD100A29C9167DCD1C102A8031E5CD121ACD0A10E1C9CD6C +:1810F800FD11E5EB2294313A5D31B7CC271AE1C90600074FC5CD9A0B52 +:1811100079FE31DA2F11CD1510CD100A2CCD0B10EB2A9431E3E5EBCDBE +:181128006817EBE3C33711CDDE10E311F210D5019304094E236669E907 +:1811400015FEADC8FE2DC814FE2BC8FEACC82BC9F6AFF5CD0A10CD4C17 +:181158000CF1EBC1E3EBCD2A1AF5CD4C0CF1C17921C113C27311A34F85 +:1811700078A2E9B34F78B2E9218A113A5D311F7A175F166478BAD0C37D +:1811880079108C1179B71FC1D1F5CD0C1021CE11E5CA641AAF325D31CE +:1811A000D5CD23167E23234E2346D1C5F5CD2716CD381AF157E17BB2D7 +:1811B800C87AD601D8AFBB3CD0151D0ABE2303CAB6113FC3F4193C8F2D +:1811D000C1A0C6FF9FC3FB19165ACD1C10CD0A10CD4C0C7B2F4F7A2F54 +:1811E800CDC113C1C328102BCD9A0BC8CD100A2C01EF11C5F6AF325C21 +:181200003146CD380CDA4207AF4F325D31CD9A0BDA1912CD380CDA26E5 +:18121800124FCD9A0BDA1A12CD380CD21A12D624C235123C325D310FC8 +:18123000814FCD9A0B3A7B313DCAE212F245127ED628CABA12AF327BCC +:1812480031E550592A8E31CD0A0A119031CA2A192A8831EB2A8631CDAA +:181260000A0ACA7812799623C26D12789623CAAC1223232323C35F1222 +:18127800E1E3D511FA10CD0A0AD1CAAF12E3E5C50106002A8A31E50906 +:18129000C1E5CD0E07E1228A3160692288312B3600CD0A0AC29E12D1D7 +:1812A80073237223EBE1C932973121DE06229431E1C9E52A5C31E35708 +:1812C000D5C5CD400CC1F1EBE3E5EB3C577EFE2CCAC012CD100A29220A +:1812D8008031E1225C311E00D511E5F52A88313E19EB2A8A31EBCD0A13 +:1812F0000ACA1A137EB923C2FC127EB8235E235623C2E8123A5C31B72E +:18130800C24B07F1444DCA2A1996CA78131E10C35607110400F1CA61C0 +:181320000C712370234FCD1F07232322753171233A5C311779010B003B +:18133800D23D13C10371237023F5E5CDD51AEBE1F13DC23513F5424B74 +:18135000EB19DA3707CD2807228A312B3600CD0A0AC25B1303572A7525 +:18136800315EEB2909EB2B2B73237223F1DA9C13474F7E2316E15E232C +:181380005623E3F5CD0A0AD21513E5CDD51AD119F13D444DC27D132964 +:1813980029C109EB2A8031C92A8A31EB210000393A5D31B7CABC13CDAC +:1813B0002316CD23152A0A31EB2A73317D934F7C9A41501E00215D31F6 +:1813C800730690C3001A3A5B3147AFC3C213CD5914CD4B1401310DC569 +:1813E000D5CD100A28CDFD11E5EB2B562B5EE1CD0A10CD100A29CD10A7 +:1813F8000AB4444DE3712370C39814CD5914D5CDDE10CD0A10E35E2323 +:1814100056237AB3CA4E077E23666FE52A8E31E3228E312A9231E52AFB +:181428009031E5219031D5CD411AE1CD07102BCD9A0BC24207E1229027 +:1814400031E1229231E1228E31E1C9E52A0C31237CB5E1C01E16C356A3 +:1814580007CD100AA73E80327B31B647CD0212C30A10CD0A10CD8E1B33 +:18147000CD9E14CD2316017E16C57E2323E5CDF914E14E2346CD9214F7 +:18148800E56FCD1616D1C9CDF914216F31E5772323732372E1C92B0645 +:1814A0002250E50EFF237E0CB7CAB414BACAB414B8C2A514FE22CC9AD5 +:1814B8000BE323EB79CD9214116F312A61312294313E01325D31CD44D0 +:1814D0001ACD0A0A226131E17EC01E1EC3560723CD9E14CD2316CD382D +:1814E8001A1C1DC80ACD1B0AFE0DCC4C0E03C3EA14B70EF1F52A0A31D0 +:18150000EB2A73312F4F06FF0923CD0A0ADA171522733123EBF1C9F105 +:181518001E1ACA5607BFF501FB14C52A5F31227331210000E52A0A31E8 +:18153000E5216331EB2A6131EBCD0A0A013415C288152A8631EB2A886F +:1815480031EBCD0A0ACA5B157E2323B7CD8B15C34515C1EB2A8A31EBD3 +:18156000CD0A0ACAB115CD381A7BE509B7F25A15227531E14E0600095C +:181578000923EB2A7531EBCD0A0ACA5B15017A15C5F6807E23235E235E +:181590005623F0B7C8444D2A7331CD0A0A6069D8E1E3CD0A0AE3E560AD +:1815A80069D0C1F1F1E5D5C5C9D1E17DB4C82B462B4EE52B2B6E2600A3 +:1815C0000950592B444D2A7331CD1107E171237069602BC32615C5E571 +:1815D8002A9431E3CD9010E3CD0B107EE52A9431E5861E1CDA5607CDF6 +:1815F0008F14D1CD2716E3CD2616E52A7131EBCD0D16CD0D16212510A7 +:18160800E3E5C3C014E1E37E23234E23466F2C2DC80A120313C317167A +:18162000CD0B102A9431EBCD4116EBC0D550591B4E2A7331CD0A0AC2C9 +:181638003F164709227331E1C92A61312B462B4E2B2BCD0A0AC0226165 +:1816500031C901D113C5CD2016AF57325D317EB7C901D113C5CD561634 +:18166800CA610C23235E23561AC93E01CD8F14CD6B172A713173C1C372 +:18168000C014CD1B17AFE34FE57EB8DA901678110E00C5CDF914C1E12B +:18169800E5232346236668060009444DCD92146FCD1616D1CD2716C3BF +:1816B000C014CD1B17D1D51A90C38616EB7ECD20170405CA610CC51E10 +:1816C800FFFE29CAD516CD100A2CCD6817CD100A29F1E3018816C53D4B +:1816E000BE0600D04F7E91BB47D843C9CD5616CA09185F23237E23664A +:1816F8006FE5194672E3C57EFE24C20A17CD341F180DFE25C21417CD68 +:18171000A41F1803CDF01AC1E170C9EBCD100A29C1D1C543C9CD6B1784 +:1817280032EF30CDEE30C3D113CD5517C3B630CD5517F51E002BCD9A06 +:181740000BCA4B17CD100A2CCD6817C1CDEE30ABA0CA4C17C9CD6817C2 +:1817580032EF3032B730CD100A2CC36817CD9A0BCD0710CD460C7AB714 +:18177000C2610C2BCD9A0B7BC9CD4C0C1AC3D113CD0710CD4C0CD5CDC0 +:18178800100A2CCD6817D112C921671CCD381AC3A317CD381A21C1D1F9 +:1817A000CD121A78B7C83A9731B7CA2A1A90D2BD172F3CEBCD1A1AEB02 +:1817B800CD2A1AC1D1FE19D0F5CD4F1A67F1CD6818B4219431F2E31739 +:1817D000CD4818D229182334CA51072E01CD7E18C32918AF90477E9B13 +:1817E8005F237E9A57237E994FDC54186863AF4779B7C216184A546543 +:181800006F78D608FEE0C2F717AF329731C905297A1757798F4FF20E7E +:1818180018785C45B7CA29182197318677D20918C878219731B7FC3BD5 +:181830001846237EE680A94FC32A1A1CC014C00CC00E8034C0C3510723 +:181848007E835F237E8A57237E894FC92198317E2F77AF6F90477D9B49 +:181860005F7D9A577D994FC90600D608DA7718435A510E00C36A18C621 +:18187800096FAF2DC8791F4F7A1F577B1F5F781F47C37A1800000081B8 +:1818900003AA561980F122768045AA3882CDE919B7EA610C2197317EAE +:1818A80001358011F30490F570D5C5CDA317C1D104CD3F19218C18CD07 +:1818C0009A17219018CD311D018080110000CDA317F1CD641B013180F3 +:1818D80011187221C1D1CDE919C82E00CDA7197932A631EB22A73101F0 +:1818F0000000505821F417E5210019E5E52194317E23B7CA2C19E52EC3 +:18190800081F6779D21A19E52AA73119EBE13AA631891F4F7A1F577B7C +:181920001F5F781F472D7CC20919E1C9435A514FC9CD1A1A012084115F +:181938000000CD2A1AC1D1CDE919CA45072EFFCDA71934342B7E32C250 +:18195000302B7E32BE302B7E32BA3041EBAF4F575F32C530E5C57DCDC6 +:18196800B930DE003FD2771932C530F1F137D2C1E1793C3D1FFA2A18FE +:18198000177B175F7A175779174F297817473AC5301732C53079B2B336 +:18199800C26419E521973135E1C26419C3510778B7CACB197D21973177 +:1819B000AE80471FA878F2CA19C68077CA2A19CD4F1A772BC9CDE9195C +:1819C8002FE1B7E1F20918C35107CD351A78B7C8C602DA510747CDA36D +:1819E0001721973134C0C351073A9731B7C83A9631FE2F179FC03CC9B6 +:1819F800CDE91906881100002197314F70060023368017C3F117CDE94A +:181A100019F02196317EEE8077C9EB2A9431E3E52A9631E3E5EBC9CDC5 +:181A2800381AEB2294316069229631EBC92194315E2356234E23462362 +:181A4000C911943106041A77132305C2461AC92196317E07371F773FB5 +:181A58001F2323777907371F4F1FAEC978B7CAE91921F219E5CDE91904 +:181A700079C8219631AE79F8CD7E1A1FA9C92378BEC02B79BEC02B7A40 +:181A8800BEC02B7B96C0E1E1C9474F575FB7C8E5CD351ACD4F1AAE672A +:181AA000FCB51A3E9890CD68187C17DC3B180600DC5418E1C91B7AA3BE +:181AB8003CC00BC92197317EFE983A9431D07ECD911A36987BF57917B6 +:181AD000CDF117F1C921000078B1C83E1029DA1513EB29EBD2EB1A0905 +:181AE800DA15133DC2DD1AC9FE2DF5CAFC1AFE2BCAFC1A2BCD091847BC +:181B0000575F2F4FCD9A0BDA4D1BFE2ECA281BFE45C22C1BCD9A0BCD21 +:181B18004011CD9A0BDA6F1B14C22C1BAF935F0C0CCA041BE57B90F4EB +:181B3000451BF23B1BF5CD3119F13CC22F1BD1F1CC121AEBC9C8F5CDB8 +:181B4800D219F13DC9D557788947C5E5D5CDD219F1D630CD641BE1C113 +:181B6000D1C3041BCD1A1ACDFB19C1D1C3A3177B0707830786D6305FCB +:181B7800C31A1BE521DA06CDE014E1EBAF0698CD001A21DF14E5219903 +:181B900031E5CDE9193620F29C1B362D233630CA521CE5FC121AAFF584 +:181BA800CD581C01439111F84FCD641AB7E2C91BF1CD461BF5C3AB1B52 +:181BC000CD3119F13CF5CD581CCD91173CCD911ACD2A1A010603F181DD +:181BD8003CFAE51BFE08D2E51B3C473E023D3DE1F5116B1C05C2F61B64 +:181BF000362E2336302305362ECC3F1AC5E5D5CD351AE1062F047B9679 +:181C08005F237A9E5723799E4F2B2BD2051CCD481823CD2A1AEBE17064 +:181C200023C10DC2F61B05CA361C2B7EFE30CA2A1CFE2EC43F1AF1CADC +:181C3800551C364523362BF2461C362D2F3C062F04D60AD2481CC63AB3 +:181C5000237023772371E1C901749411F723CD641AB7E1E2C01BE90054 +:181C6800000080A08601102700E803006400000A000001000021121ADF +:181C8000E3E9CD1A1A21671CCD271AC1D1CDE91978CAD01CF29B1CB7DE +:181C9800CA4507B7CA0A18D5C579F67FCD351AF2B81CD5C5CDBC1AC113 +:181CB000D1F5CD641AE17C1FE1229631E1229431DC7D1CCC121AD5C5F6 +:181CC800CD9D18C1D1CDDE18CD1A1A013881113BAACDDE183A9731FEB9 +:181CE00088D2C519CDBC1AC680C602DAC519F5218C18CD9417CDD5185F +:181CF800F1C1D1F5CDA017CD121A21101DCD401D110000C14AC3DE1892 +:181D100008402E9474704F2E776E02887AE6A02A7C50AAAA7EFFFF7F9C +:181D28007F0000808100000081CD1A1A11DC18D5E5CD351ACDDE18E122 +:181D4000CD1A1A7E23CD271A06F1C1D13DC8D5C5F5E5CDDE18E1CD3830 +:181D58001AE5CDA317E1C3491DCDE91921C930FAC21D21EA30CD271AD8 +:181D700021C930C886E6070600772387874F09CD381ACDDE183AC830EC +:181D88003CE6030600FE018832C83021C61D87874F09CD9417CD351A69 +:181DA0007B59EE4F4F36802B46368021C730347ED6ABC2B91D770C1573 +:181DB8001CCDF41721EA30C3411A772B772B77C39D1D68B1466899E945 +:181DD000926910D1756821201ECD9417CD1A1A01498311DB0FCD2A1A91 +:181DE800C1D1CD3F19CD1A1ACDBC1AC1D1CDA01721241ECD9A17CDE9DB +:181E00001937F20C1ECD9117CDE919B7F5F4121A21241ECD9417F1D4AE +:181E1800121A21281EC3311DDB0F49810000007F05BAD71E866426997E +:181E30008758342387E05DA586DA0F4983CD1A1ACDDC1DC1E1CD1A1A56 +:181E4800EBCD2A1ACDD61DC33D19CDE919FC7D1CFC121A3A9731FE81A0 +:181E6000DA6F1E0100815159CD3F19219A17E521791ECD311D21201EC9 +:181E7800C9094AD73B78026E847BFEC12F7C74319A7D843D5A7DC87F38 +:181E9000917EE4BB4C7E6CAAAA7F00000081C9D7C93E0CC3DB1FCD685D +:181EA800177B32F230C9CD0710CD4C0CED53F630ED53F830C9CD4C0CAE +:181EC000D5E146237EC3C213CD0710CD4C0CD5CD100A2CCD0710CD4CE7 +:181ED8000CE3732372E1C9CD0A10CD4C0CC52199317AFE00280CCD1705 +:181EF0001F78FE302802702371237BCD171F7AFE00200578FE302802D9 +:181F080070237123AF772377C1219931C3701447E60FFE0A3802C6079C +:181F2000C6304F780F0F0F0FE60FFE0A3802C607C63047C9EB2100009A +:181F3800CD4D1FDA6D1F1805CD4D1F381F29292929B56F18F3131AFE47 +:181F500020CA4D1FD630D8FE0A3805D607FE0AD8FE103FC9EB7A4BE598 +:181F6800CDC113E1C91E26C35607CD0A10CD4C0CC52199310611057862 +:181F8000FE012808CB13CB1230F41804CB13CB123E30CE007723052069 +:181F9800F3AF772377C1219931C37014EB210000CDC11FDACF1FD63004 +:181FB00029B56FCDC11F30F6EB7A4BE5CDC113E1C9131AFE20CAC11F24 +:181FC800FE30D8FE323FC91E28C35607DD21FFFFC3A603C30800C30067 +:181FE000003E0032FD30C3AD03ED45F5A0C1B83E00C9CD1B0AC3420E8D +:00000001FF diff --git a/Z80 CPM and bootloader (basmon)/hexFiles/CBIOS128.HEX b/Z80 CPM and bootloader (basmon)/hexFiles/CBIOS128.HEX index 6cefd8c..9e21522 100644 --- a/Z80 CPM and bootloader (basmon)/hexFiles/CBIOS128.HEX +++ b/Z80 CPM and bootloader (basmon)/hexFiles/CBIOS128.HEX @@ -1,59 +1,62 @@ -:18E60000C351E7C3B5E7C31DE8C358E8C396E8C37EE8C38AE8C34CE847 -:18E61800C3EFE8C3C7E8C3FBE8C300E9C305E9C30DE9C321E9C3C4E8E6 -:18E63000C30AE900000000000000000DEB33E700008DEB000000000092 -:18E648000000000DEB42E700008EEC00000000000000000DEB42E700FE -:18E66000008FED00000000000000000DEB42E7000090EE000000000087 -:18E678000000000DEB42E7000091EF00000000000000000DEB42E700C8 -:18E690000092F000000000000000000DEB42E7000093F100000000004B -:18E6A8000000000DEB42E7000094F200000000000000000DEB42E70092 -:18E6C0000095F300000000000000000DEB42E7000096F400000000000F -:18E6D8000000000DEB42E7000097F500000000000000000DEB42E7005C -:18E6F0000098F600000000000000000DEB42E7000099F70000000000D3 -:18E708000000000DEB42E700009AF800000000000000000DEB42E70025 -:18E72000009BF900000000000000000DEB42E700009CFA8000051F01F1 -:18E73800FB07FF01F000000001008000051F01FF07FF01F0000000003B -:18E7500000F331C1FB3E01D3383E95D380D382CDF9EA0C43502F4D2021 -:18E7680042494F5320322E3020627920472E20536561726C652032302E -:18E7800031330D0A0D0A43502F4D20322E322028632920313937392040 -:18E798006279204469676974616C2052657365617263680D0A00AF326B -:18E7B0000400C3F5E7F331C1FB060B3E0032C9FBD38CD38B2100D0DB00 -:18E7C80089FE8020FA3AC9FBD38A3E00D389C50E040680DB89FEE02064 -:18E7E000FADB8877230520F30D20EE3AC9FB3C32C9FBC110D2AF32CB78 -:18E7F800FB32CDFB21800022D6FB3EC33200002103E6220100320500E9 -:18E810002106D82206003A04004FC300D03A0300E60BFE0A280AFE0241 -:18E828002814E603FE01200EDB80E601FE0028033EFFC93E00C9DB82B1 -:18E84000E601FE0028033EFFC93E00C9F53A0300E608FE08201C180E1B -:18E85800F53A0300E603FE0228EBFE01200CF1DB80E601FE0028F8DB23 -:18E8700081C9F1DB82E601FE0028F8DB83C9F53A0300E6C0FE40202670 -:18E88800181AF53A0300E620FE20201A180EF53A0300E603FE0228DF6E -:18E8A000FE01200ACDB8E828FB79D381F1C9CDBEE828FB79D383F1C901 -:18E8B800DB800FCB47C9DB820FCB47C93EFFC921000079FE10380D3A8F -:18E8D0000400B9C0AF32040032C1FBC932C1FBCB07CB07CB07CB0721C0 -:18E8E80033E606004F09C93ACCFBB7200332CBFB010000ED43C2FBC94E -:18E90000ED43C4FBC9ED43D6FBC9C5E1C9AF32CDFB3E0132D4FB32D320 -:18E91800FB3E0232D5FBC388E9AF32D4FB7932D5FBFE0220173E203284 -:18E93000CDFB3AC1FB32CEFB2AC2FB22CFFB3AC4FB32D1FB3ACDFBB793 -:18E9480028363D32CDFB3AC1FB21CEFBBEC280E921CFFBCD1FEAC28056 -:18E96000E93AC4FB21D1FBBEC280E9347EFE80380936002ACFFB232207 -:18E97800CFFBAF32D3FB1808AF32CDFB3C32D3FBAF32D2FB3AC4FBB7AB -:18E990001FB71F32CAFB21CBFB7E3601B728213AC1FB21C6FBBE201120 -:18E9A80021C7FBCD1FEA20093ACAFB21C9FBBE28243ACCFBB7C4C4EA5D -:18E9C0003AC1FB32C6FB2AC2FB22C7FB3ACAFB32C9FB3AD3FBB7C4957E -:18E9D800EAAF32CCFB3AC4FBE6036F26002929292929292911D8FB1902 -:18E9F000EB2AD6FB0E803AD4FBB720063E0132CCFBEB1A1377230D209E -:18EA0800F93AD5FBFE013AD2FBC0B7C0AF32CCFBCDC4EA3AD2FBC9EBD8 -:18EA200021C2FB1ABEC013231ABEC92AC7FBCB05CB05CB05CB05CB0595 -:18EA38007DE6E06F3AC9FB85329DFB2AC7FBCB0DCB0DCB0D7DE61F6F62 -:18EA5000CB04CB04CB04CB04CB047CE620673AC6FBCB07CB07CB07CB7E -:18EA680007CB07CB07E6C08485329EFB3AC6FBCB0FCB0FE603329FFB0D -:18EA80003E0032A0FB3A9FFBD38C3A9EFBD38B3A9DFBD38AC9F5C5E578 -:18EA9800DB89FE8020FACD2BEA3E00D3890E0421D8FB0680DB89FEE020 -:18EAB00020FADB8877230520F30D20EEE1C1F1AF32D2FBC9F5C5E5DB80 -:18EAC80089FE8020FACD2BEA3E01D3890E0421D8FB0680DB89FEA020EA -:18EAE000FAC5063210FEC17ED388230520ED0D20E8E1C1F1AF32D2FBF4 -:15EAF800C9E3F5C57EFE0028074FCD96E82318F423C1F1E3C9AE -:04FB9D000000000064 -:15FDD8003E01D338F1FE0128043E0118023E00320300C300E63B -:12FFE8003E01D33821004111000101008FEDB0C300E673 -:02FFFE00D8FD2C -:00000001FF +:18E60000C351E7C3B5E7C31DE8C358E8C396E8C37EE8C38AE8C34CE847 +:18E61800C3EFE8C3C7E8C3FBE8C300E9C305E9C30DE9C321E9C3C4E8E6 +:18E63000C30AE9000000000000000043EB33E70000C3EB000000000026 +:18E6480000000043EB42E70000C4EC000000000000000043EB42E7005C +:18E6600000C5ED000000000000000043EB42E70000C6EE0000000000E5 +:18E6780000000043EB42E70000C7EF000000000000000043EB42E70026 +:18E6900000C8F0000000000000000043EB42E70000C9F10000000000A9 +:18E6A80000000043EB42E70000CAF2000000000000000043EB42E700F0 +:18E6C00000CBF3000000000000000043EB42E70000CCF400000000006D +:18E6D80000000043EB42E70000CDF5000000000000000043EB42E700BA +:18E6F00000CEF6000000000000000043EB42E70000CFF7000000000031 +:18E7080000000043EB42E70000D0F8000000000000000043EB42E70083 +:18E7200000D1F9000000000000000043EB42E70000D2FA8000051F014F +:18E73800FB07FF01F000000001008000051F01FF07FF01F0000000003B +:18E7500000F331F7FB3E01D3383E95D380D382CD2FEB0C43502F4D20B4 +:18E7680042494F5320322E3020627920472E20536561726C652032302E +:18E7800031330D0A0D0A43502F4D20322E322028632920313937392040 +:18E798006279204469676974616C2052657365617263680D0A00AF326B +:18E7B0000400C3F5E7F331F7FB060B3E0032FFFBD38CD38B2100D0DB94 +:18E7C80089FE8020FA3AFFFBD38A3E00D389C50E040680DB89FEE0202E +:18E7E000FADB8877230520F30D20EE3AFFFB3C32FFFBC110D2AF3201D6 +:18E7F800FC3203FC218000220CFC3EC33200002103E62201003205007A +:18E810002106D82206003A04004FC300D03A0300E60BFE0A280AFE0241 +:18E828002814E603FE01200EDB80E601FE0028033EFFC93E00C9DB82B1 +:18E84000E601FE0028033EFFC93E00C9F53A0300E608FE08201C180E1B +:18E85800F53A0300E603FE0228EBFE01200CF1DB80E601FE0028F8DB23 +:18E8700081C9F1DB82E601FE0028F8DB83C9F53A0300E6C0FE40202670 +:18E88800181AF53A0300E620FE20201A180EF53A0300E603FE0228DF6E +:18E8A000FE01200ACDB8E828FB79D381F1C9CDBEE828FB79D383F1C901 +:18E8B800DB800FCB47C9DB820FCB47C93EFFC921000079FE10380D3A8F +:18E8D0000400B9C0AF32040032F7FBC932F7FBCB07CB07CB07CB072154 +:18E8E80033E606004F09C93A02FCB720033201FC010000ED43F8FBC9AA +:18E90000ED43FAFBC9ED430CFCC9C5E1C9AF3203FC3E01320AFC32090F +:18E91800FC3E02320BFCC388E9AF320AFC79320BFCFE0220173E2032DE +:18E9300003FC3AF7FB3204FC2AF8FB2205FC3AFAFB3207FC3A03FCB7DE +:18E9480028363D3203FC3AF7FB2104FCBEC280E92105FCCD1FEAC2807B +:18E96000E93AFAFB2107FCBEC280E9347EFE80380936002A05FC232263 +:18E9780005FCAF3209FC1808AF3203FC3C3209FCAF3208FC3AFAFBB762 +:18E990001FB71F3200FC2101FC7E3601B728213AF7FB21FCFBBE201146 +:18E9A80021FDFBCD1FEA20093A00FC21FFFBBE28243A02FCB7C4EAEA5D +:18E9C0003AF7FB32FCFB2AF8FB22FDFB3A00FC32FFFB3A09FCB7C49502 +:18E9D800EAAF3202FC3AFAFBE6036F260029292929292929110EFC195E +:18E9F000EB2A0CFC0E803A0AFCB720063E013202FCEB1A1377230D20F9 +:18EA0800F93A0BFCFE013A08FCC0B7C0AF3202FCCDEAEA3A08FCC9EBD6 +:18EA200021F8FB1ABEC013231ABEC92AFDFBCB05CB05CB05CB05CB0529 +:18EA38007DE6E06F3AFFFB8532D3FB2AFDFBCB0DCB0DCB0D7DE61F6FC0 +:18EA5000CB04CB04CB04CB04CB047CE620673AFCFBCB07CB07CB07CB48 +:18EA680007CB07CB07E6C0848532D4FB3AFCFBCB0FCB0FE60332D5FB6B +:18EA80003E0032D6FB3AD5FBD38C3AD4FBD38B3AD3FBD38AC9F5C5E5A0 +:18EA9800DB89FE8020FA0603DB89FE8020FA10F8CD2BEA3E00D3890ED3 +:18EAB00004210EFC0680DB89FEE020FAC50602DB89FEE020FA10F8C14B +:18EAC800DB88C5060A10FEC177230520E10D20DC0600DB89FE8020FA84 +:18EAE00010F8E1C1F1AF3208FCC9F5C5E5DB89FE8020FACD2BEA3E0119 +:18EAF800D3890E04210EFC0680DB89FEA020FAC50603DB89FEA020FAE1 +:18EB100010F8C17ED388230520E70D20E20600DB89FE8020FA10F8E122 +:18EB2800C1F1AF3208FCC9E3F5C57EFE0028074FCD96E82318F423C180 +:03EB4000F1E3C935 +:04FBD300000000002E +:15FE0E003E01D338F1FE0128043E0118023E00320300C300E604 +:12FFE8003E01D33821004111000101008FEDB0C300E673 +:02FFFE000EFEF5 +:00000001FF diff --git a/Z80 CPM and bootloader (basmon)/hexFiles/CPM22.HEX b/Z80 CPM and bootloader (basmon)/hexFiles/CPM22.HEX index 773954a..58a3096 100644 --- a/Z80 CPM and bootloader (basmon)/hexFiles/CPM22.HEX +++ b/Z80 CPM and bootloader (basmon)/hexFiles/CPM22.HEX @@ -1,238 +1,238 @@ -:18D00000C35CD3C358D37F00436F7079726967687420313937392028BE -:18D018006329206279204469676974616C20526573656172636820200E -:18D0300020202020000000000000000000000000000000000000000068 -:18D04800000000000000000000000000000000000000000000000000D0 -:18D06000000000000000000000000000000000000000000000000000B8 -:18D078000000000000000000000000000000000008D000005F0E02C396 -:18D090000500C5CD8CD0C1C93E0DCD92D03E0AC392D03E20C392D0C5DC -:18D0A800CD98D0E17EB7C823E5CD8CD0E1C3ACD00E0DC305005F0E0EAE -:18D0C000C30500CD050032EED73CC90E0FC3C3D0AF32EDD711CDD7C332 -:18D0D800CBD00E10C3C3D00E11C3C3D00E12C3C3D011CDD7C3DFD00E11 -:18D0F00013C30500CD0500B7C90E14C3F4D011CDD7C3F9D00E15C3F437 -:18D10800D00E16C3C3D00E17C305001EFF0E20C30500CD13D18787877F -:18D120008721EFD7B6320400C93AEFD7320400C9FE61D8FE7BD0E65F10 -:18D13800C93AABD7B7CA96D13AEFD7B73E00C4BDD011ACD7CDCBD0CA66 -:18D1500096D13ABBD73D32CCD711ACD7CDF9D0C296D11107D0218000A6 -:18D168000680CD42D421BAD73600233511ACD7CDDAD0CA96D13AEFD7CA -:18D18000B7C4BDD02108D0CDACD0CDC2D1CAA7D1CDDDD1C382D3CDDD6E -:18D19800D1CD1AD10E0A1106D0CD0500CD29D12107D0462378B7CABA4A -:18D1B000D17ECD30D17705C3ABD1772108D02288D0C90E0BCD0500B73A -:18D1C800C80E01CD0500B7C90E19C305001180000E1AC3050021ABD713 -:18D1E0007EB7C83600AFCDBDD011ACD7CDEFD03AEFD7C3BDD01128D37F -:18D1F8002100D806061ABEC2CFD3132305C2FDD1C9CD98D02A8AD07E13 -:18D21000FE20CA22D2B7CA22D2E5CD8CD0E123C30FD23E3FCD8CD0CD8C -:18D2280098D0CDDDD1C382D31AB7C8FE20DA09D2C8FE3DC8FE5FC8FE99 -:18D240002EC8FE3AC8FE3BC8FE3CC8FE3EC8C91AB7C8FE20C013C34F74 -:18D25800D2856FD024C93E0021CDD7CD59D2E5E5AF32F0D72A88D0EB61 -:18D27000CD4FD2EB228AD0EBE11AB7CA89D2DE4047131AFE3ACA90D299 -:18D288001B3AEFD777C396D27832F0D770130608CD30D2CAB9D223FE8A -:18D2A0002AC2A9D2363FC3ABD2771305C298D2CD30D2CAC0D213C3AFEF -:18D2B800D223362005C2B9D20603FE2EC2E9D213CD30D2CAE9D223FE87 -:18D2D0002AC2D9D2363FC3DBD2771305C2C8D2CD30D2CAF0D213C3DFCF -:18D2E800D223362005C2E9D2060323360005C2F2D2EB2288D0E1010B22 -:18D3000000237EFE3FC209D3040DC201D378B7C9444952204552412003 -:18D31800545950455341564552454E2055534552001600000000211001 -:18D33000D30E0079FE06D011CED706041ABEC24FD3132305C23CD31A15 -:18D34800FE20C254D379C92305C24FD30CC333D3AF3207D031ABD7C573 -:18D36000791F1F1F1FE60F5FCD15D1CDB8D032ABD7C179E60F32EFD789 -:18D37800CDBDD03A07D0B7C298D331ABD7CD98D0CDD0D1C641CD8CD0C8 -:18D390003E3ECD8CD0CD39D1118000CDD8D1CDD0D132EFD7CD5ED2C4DB -:18D3A80009D23AF0D7B7C2A5D6CD2ED321C1D35F160019197E23666FFD -:18D3C000E977D41FD55DD5ADD510D68ED6A5D621F3762200D02100D047 -:18D3D800E901DFD3C3A7D052656164206572726F720001F0D3C3A7D0A3 -:18D3F0004E6F2066696C6500CD5ED23AF0D7B7C209D221CED7010B0084 -:18D408007EFE20CA33D423D630FE0AD209D25778E6E0C209D278070709 -:18D420000780DA09D280DA09D282DA09D2470DC208D4C97EFE20C2092A -:18D43800D2230DC233D478C906037E12231305C242D4C921800081CD6C -:18D4500059D27EC9AF32CDD73AF0D7B7C83D21EFD7BEC8C3BDD03AF029 -:18D46800D7B7C83D21EFD7BEC83AEFD7C3BDD0CD5ED2CD54D421CED7A4 -:18D480007EFE20C28FD4060B363F2305C288D41E00D5CDE9D0CCEAD305 -:18D49800CA1BD53AEED70F0F0FE6604F3E0ACD4BD417DA0FD5D17B1C90 -:18D4B000D5E603F5C2CCD4CD98D0C5CDD0D1C1C641CD92D03E3ACD9219 -:18D4C800D0C3D4D4CDA2D03E3ACD92D0CDA2D0060178CD4BD4E67FFE1E -:18D4E00020C2F9D4F1F5FE03C2F7D43E09CD4BD4E67FFE20CA0ED53E70 -:18D4F80020CD92D00478FE0CD20ED5FE09C2D9D4CDA2D0C3D9D4F1CDAF -:18D51000C2D1C21BD5CDE4D0C398D4D1C386D7CD5ED2FE0BC242D5013D -:18D5280052D5CDA7D0CD39D12107D035C282D3237EFE59C282D3232211 -:18D5400088D0CD54D411CDD7CDEFD03CCCEAD3C386D7416C6C20287986 -:18D558002F6E293F00CD5ED2C209D2CD54D4CDD0D0CAA7D5CD98D0211E -:18D57000F1D736FF21F1D77EFE80DA87D5E5CDFED0E1C2A0D5AF773499 -:18D58800218000CD59D27EFE1ACA86D7CD8CD0CDC2D1C286D7C374D581 -:18D5A0003DCA86D7CDD9D3CD66D4C309D2CDF8D3F5CD5ED2C209D2CDFD -:18D5B80054D411CDD7D5CDEFD0D1CD09D1CAFBD5AF32EDD7F16F2600E0 -:18D5D000291100017CB5CAF1D52BE521800019E5CDD8D111CDD7CD049C -:18D5E800D1D1E1C2FBD5C3D4D511CDD7CDDAD03CC201D60107D6CDA757 -:18D60000D0CDD5D1C386D74E6F20737061636500CD5ED2C209D23AF002 -:18D61800D7F5CD54D4CDE9D0C279D621CDD711DDD70610CD42D42A886D -:18D63000D0EBCD4FD2FE3DCA3FD6FE5FC273D6EB232288D0CD5ED2C270 -:18D6480073D6F14721F0D77EB7CA59D6B870C273D670AF32CDD7CDE955 -:18D66000D0CA6DD611CDD7CD0ED1C386D7CDEAD3C386D7CD66D4C309D7 -:18D67800D20182D6CDA7D0C386D746696C652065786973747300CDF806 -:18D69000D3FE10D209D25F3ACED7FE20CA09D2CD15D1C389D7CDF5D18A -:18D6A8003ACED7FE20C2C4D63AF0D7B7CA89D73D32EFD7CD29D1CDBDA9 -:18D6C000D0C389D711D6D71AFE20C209D2D5CD54D4D12183D7CD40D4D5 -:18D6D800CDD0D0CA6BD7210001E5EBCDD8D111CDD7CDF9D0C201D7E193 -:18D6F000118000191100D07D937C9AD271D7C3E1D6E13DC271D7CD6682 -:18D70800D4CD5ED221F0D7E57E32CDD73E10CD60D2E17E32DDD7AF32A4 -:18D72000EDD7115C0021CDD70621CD42D42108D07EB7CA3ED7FE20CAFC -:18D738003ED723C330D706001181007E12B7CA4FD7042313C343D77879 -:18D75000328000CD98D0CDD5D1CD1AD1CD000131ABD7CD29D1CDBDD00D -:18D76800C382D3CD66D4C309D2017AD7CDA7D0C386D7426164206C6F34 -:18D78000616400434F4DCD66D4CD5ED23ACED7D62021F0D7B6C209D2D9 -:18D79800C382D3000000000000000000000000000000000000242424F5 -:18D7B000202020202053554200000000000000000000000000000000D7 -:18D7C800000000000000202020202020202020202000000000002020A9 -:18D7E00020202020202020202000000000000000000000000000000011 -:18D7F8000000000000000000001600000000C311D899D8A5D8ABD8B135 -:18D81000D8EB2243DBEB7B32D6E52100002245DB39220FDB3141DBAF06 -:18D8280032E0E532DEE52174E5E579FE29D04B2147D85F160019195E9D -:18D8400023562A43DBEBE903E6C8DA90D9CEDA12E60FE6D4DAEDDAF34A -:18D85800DAF8DAE1D9FEDA7EE483E445E49CE4A5E4ABE4C8E4D7E4E0A9 -:18D87000E4E6E4ECE4F5E4FEE404E50AE511E52CDD17E51DE526E52D5A -:18D88800E541E547E54DE50EE453E504DB04DB9BE521CAD8CDE5D8FE6C -:18D8A00003CA0000C921D5D8C3B4D821E1D8C3B4D821DCD8CDE5D8C372 -:18D8B800000042646F7320457272204F6E20203A20244261642053650D -:18D8D00063746F722453656C6563742446696C6520522F4F24E5CDC9D1 -:18D8E800D93A42DBC64132C6D801BAD8CDD3D9C1CDD3D9210EDB7E361D -:18D9000000B7C0C309E6CDFBD8CD14D9D8F54FCD90D9F1C9FE0DC8FEAF -:18D918000AC8FE09C8FE08C8FE20C93A0EDBB7C245D9CD06E6E601C87F -:18D93000CD09E6FE13C242D9CD09E6FE03CA0000AFC9320EDB3E01C913 -:18D948003A0ADBB7C262D9C5CD23D9C1C5CD0CE6C1C53A0DDBB7C40FEF -:18D96000E6C179210CDBFE7FC834FE20D0357EB7C879FE08C279D93526 -:18D97800C9FE0AC03600C979CD14D9D290D9F50E5ECD48D9F1F6404FD4 -:18D9900079FE09C248D90E20CD48D93A0CDBE607C296D9C9CDACD90E98 -:18D9A80020CD0CE60E08C30CE60E23CD48D9CDC9D93A0CDB210BDBBE49 -:18D9C000D00E20CD48D9C3B9D90E0DCD48D90E0AC348D90AFE24C80312 -:18D9D800C54FCD90D9C1C3D3D93A0CDB320BDB2A43DB4E23E50600C51B -:18D9F000E5CDFBD8E67FE1C1FE0DCAC1DAFE0ACAC1DAFE08C216DA7886 -:18DA0800B7CAEFD9053A0CDB320ADBC370DAFE7FC226DA78B7CAEFD973 -:18DA20007E052BC3A9DAFE05C237DAC5E5CDC9D9AF320BDBC3F1D9FEB9 -:18DA380010C248DAE5210DDB3E019677E1C3EFD9FE18C25FDAE13A0B05 -:18DA5000DB210CDBBED2E1D935CDA4D9C34EDAFE15C26BDACDB1D9E1D5 -:18DA6800C3E1D9FE12C2A6DAC5CDB1D9C1E1E5C578B7CA8ADA234E059C -:18DA8000C5E5CD7FD9E1C1C378DAE53A0ADBB7CAF1D9210CDB96320ADF -:18DA9800DBCDA4D9210ADB35C299DAC3F1D9237704C5E54FCD7FD9E1B7 -:18DAB000C17EFE0378C2BDDAFE01CA0000B9DAEFD9E1700E0DC348D9D9 -:18DAC800CD06D9C301DBCD15E6C301DB793CCAE0DA3CCA06E6C30CE6B4 -:18DAE000CD06E6B7CA91E5CD09E6C301DB3A0300C301DB21030071C9E9 -:18DAF800EB4D44C3D3D9CD23D93245DBC93E01C301DB00020000000067 -:18DB1000000000000000000000000000000000000000000000000000FD -:18DB2800000000000000000000000000000000000000000000000000E5 -:18DB400000000000000000210BD85E2356EBE90C0DC81A771323C35063 -:18DB5800DB3A42DB4FCD1BE67CB5C85E23562322B3E5232322B5E52394 -:18DB70002322B7E52323EB22D0E521B9E50E08CD4FDB2ABBE5EB21C151 -:18DB8800E50E0FCD4FDB2AC6E57C21DDE536FFB7CA9DDB36003EFFB700 -:18DBA000C9CD18E6AF2AB5E57723772AB7E5772377C9CD27E6C3BBDB82 -:18DBB800CD2AE6B7C82109D8C34ADB2AEAE50E02CDEADC22E5E522EC79 -:18DBD000E521E5E54E23462AB7E55E23562AB5E57E23666F7993789AC1 -:18DBE800D2FADBE52AC1E57B955F7A9C57E12BC3E4DBE52AC1E519DAB7 -:18DC00000FDC7995789CDA0FDCEBE123C3FADBE1C5D5E5EB2ACEE51972 -:18DC1800444DCD1EE6D12AB5E5732372D12AB7E5732372C179934F78C2 -:18DC30009A472AD0E5EBCD30E64D44C321E621C3E54E3AE3E5B71F0DF7 -:18DC4800C245DC473E08964F3AE2E50DCA5CDCB717C353DC80C92A43E9 -:18DC6000DB11100019093ADDE5B7CA71DC6E2600C9095E2356EBC9CD06 -:18DC78003EDC4F0600CD5EDC22E5E5C92AE5E57DB4C93AC3E52AE5E5A5 -:18DC9000293DC290DC22E7E53AC4E54F3AE3E5A1B56F22E5E5C92A43DF -:18DCA800DB110C0019C92A43DB110F0019EB21110019C9CDAEDC7E3203 -:18DCC000E3E5EB7E32E1E5CDA6DC3AC5E5A632E2E5C9CDAEDC3AD5E53D -:18DCD800FE02C2DEDCAF4F3AE3E58177EB3AE1E577C90C0DC87CB71F62 -:18DCF000677D1F6FC3EBDC0E802AB9E5AF86230DC2FDDCC90C0DC829F7 -:18DD0800C305DDC53A42DB4F210100CD04DDC179B56F78B467C92AAD92 -:18DD2000E53A42DB4FCDEADC7DE601C921ADE54E2346CD0BDD22ADE5CD -:18DD38002AC8E523EB2AB3E5732372C9CD5EDD110900197E17D0210F8B -:18DD5000D8C34ADBCD1EDDC8210DD8C34ADB2AB9E53AE9E5856FD024C5 -:18DD6800C92A43DB110E00197EC9CD69DD3600C9CD69DDF68077C92A0E -:18DD8000EAE5EB2AB3E57B96237A9EC9CD7FDDD813722B73C97B956F8E -:18DD98007A9C67C90EFF2AECE5EB2ACCE5CD95DDD0C5CDF7DC2ABDE51F -:18DDB000EB2AECE519C10CCAC4DDBEC8CD7FDDD0CD2CDDC977C9CD9C5D -:18DDC800DDCDE0DD0E01CDB8DBC3DADDCDE0DDCDB2DB21B1E5C3E3DDD5 -:18DDE00021B9E54E2346C324E62AB9E5EB2AB1E50E80C34FDB21EAE50A -:18DDF8007E23BEC03CC921FFFF22EAE5C92AC8E5EB2AEAE52322EAE547 -:18DE1000CD95DDD219DEC3FEDD3AEAE5E60306058705C220DE32E9E50B -:18DE2800B7C0C5CDC3DBCDD4DDC1C39EDD79E6073C5F57790F0F0FE6DA -:18DE40001F4F788787878787B14F780F0F0FE61F472ABFE5097E071DD7 -:18DE5800C256DEC9D5CD35DEE6FEC1B10F15C264DE77C9CD5EDD111057 -:18DE70000019C50E11D10DC8D53ADDE5B7CA88DEC5E54E0600C38EDE12 -:18DE88000DC54E2346E579B0CA9DDE2AC6E57D917C98D45CDEE123C1DC -:18DEA000C375DE2AC6E50E03CDEADC23444D2ABFE53600230B78B1C20A -:18DEB800B1DE2ACAE5EB2ABFE5732372CDA1DB2AB3E53603233600CDBF -:18DED000FEDD0EFFCD05DECDF5DDC8CD5EDD3EE5BECAD2DE3A41DBBEC4 -:18DEE800C2F6DE237ED624C2F6DE3D3245DB0E01CD6BDECD8CDDC3D2DC -:18DF0000DE3AD4E5C301DBC5F53AC5E52F4779A04FF1A091E61FC1C96C -:18DF18003EFF32D4E521D8E5712A43DB22D9E5CDFEDDCDA1DB0E00CD86 -:18DF300005DECDF5DDCA94DF2AD9E5EB1AFEE5CA4ADFD5CD7FDDD1D2B6 -:18DF480094DFCD5EDD3AD8E54F060079B7CA83DF1AFE3FCA7CDF78FEAC -:18DF60000DCA7CDFFE0C1ACA73DF96E67FC22DDFC37CDFC54ECD07DF8A -:18DF7800C1C22DDF1323040DC353DF3AEAE5E6033245DB21D4E57E1713 -:18DF9000D0AF77C9CDFEDD3EFFC301DBCD54DD0E0CCD18DFCDF5DDC8F3 -:18DFA800CD44DDCD5EDD36E50E00CD6BDECDC6DDCD2DDFC3A4DF5059F4 -:18DFC00079B0CAD1DF0BD5C5CD35DE1FD2ECDFC1D12AC6E57B957A9CD8 -:18DFD800D2F4DF13C5D5424BCD35DE1FD2ECDFD1C1C3C0DF173CCD643E -:18DFF000DEE1D1C979B0C2C0DF210000C90E001E20D506002A43DB09D4 -:18E00800EBCD5EDDC1CD4FDBCDC3DBC3C6DDCD54DD0E0CCD18DF2A433B -:18E02000DB7E1110001977CDF5DDC8CD44DD0E101E0CCD01E0CD2DDFBA -:18E03800C327E00E0CCD18DFCDF5DDC80E001E0CCD01E0CD2DDFC340FF -:18E05000E00E0FCD18DFCDF5DDC8CDA6DC7EF5E5CD5EDDEB2A43DB0EA0 -:18E0680020D5CD4FDBCD78DDD1210C00194E210F001946E1F17779BE1E -:18E0800078CA8BE03E00DA8BE03E802A43DB110F001977C97E23B62B57 -:18E09800C01A7713231A771B2BC9AF3245DB32EAE532EBE5CD1EDDC0BD -:18E0B000CD69DDE680C00E0FCD18DFCDF5DDC8011000CD5EDD09EB2AA0 -:18E0C80043DB090E103ADDE5B7CAE8E07EB71AC2DBE077B7C2E1E07EBB -:18E0E00012BEC21FE1C3FDE0CD94E0EBCD94E0EB1ABEC21FE113231AB4 -:18E0F800BEC21FE10D13230DC2CDE001ECFF09EB091ABEDA17E17701C6 -:18E11000030009EB097E123EFF32D2E5C310E02145DB35C9CD54DD2A27 -:18E1280043DBE521ACE52243DB0E01CD18DFCDF5DDE12243DBC8EB2183 -:18E140000F00190E11AF77230DC246E1210D001977CD8CDDCDFDDFC3E1 -:18E1580078DDAF32D2E5CDA2E0CDF5DDC82A43DB010C00097E3CE61FEF -:18E1700077CA83E1473AC5E5A021D2E5A6CA8EE1C3ACE10102000934E0 -:18E188007EE60FCAB6E10E0FCD18DFCDF5DDC2ACE13AD3E53CCAB6E14D -:18E1A000CD24E1CDF5DDCAB6E1C3AFE1CD5AE0CDBBDCAFC301DBCD05B7 -:18E1B800DBC378DD3E0132D5E53EFF32D3E5CDBBDC3AE3E521E1E5BEFF -:18E1D000DAE6E1FE80C2FBE1CD5AE1AF32E3E53A45DBB7C2FBE1CD77D6 -:18E1E800DCCD84DCCAFBE1CD8ADCCDD1DBCDB2DBC3D2DCC305DB3E0117 -:18E2000032D5E53E0032D3E5CD54DD2A43DBCD47DDCDBBDC3AE3E5FE57 -:18E2180080D205DBCD77DCCD84DC0E00C26EE2CD3EDC32D7E501000079 -:18E23000B7CA3BE24F0BCD5EDC444DCDBEDF7DB4C248E23E02C301DBE0 -:18E2480022E5E5EB2A43DB011000093ADDE5B73AD7E5CA64E2CD64DDBE -:18E2600073C36CE24F060009097323720E023A45DBB7C0C5CD8ADC3AA0 -:18E27800D5E53D3DC2BBE2C1C5793D3DC2BBE2E52AB9E557772314F27F -:18E290008CE2CDE0DD2AE7E50E0222E5E5C5CDD1DBC1CDB8DB2AE5E539 -:18E2A8000E003AC4E547A5B823C29AE2E122E5E5CDDADDCDD1DBC1C518 -:18E2C000CDB8DBC13AE3E521E1E5BEDAD2E277340E020000210000F51F -:18E2D800CD69DDE67F77F1FE7FC200E33AD5E5FE01C200E3CDD2DCCD4C -:18E2F0005AE12145DB7EB7C2FEE23D32E3E53600C3D2DCAF32D5E5C585 -:18E308002A43DBEB212100197EE67FF57E17237E17E61F4F7E1F1F1F1B -:18E320001FE60F47F1236E2C2D2E06C28BE32120001977210C001979BB -:18E3380096C247E3210E00197896E67FCA7FE3C5D5CDA2E0D1C12E03B8 -:18E350003A45DB3CCA84E3210C001971210E001970CD51E03A45DB3CEB -:18E36800C27FE3C1C52E040CCA84E3CD24E12E053A45DB3CCA84E3C1F7 -:18E38000AFC301DBE5CD69DD36C0E1C17D3245DBC378DD0EFFCD03E300 -:18E39800CCC1E1C90E00CD03E3CC03E2C9EB194E0600210C00197E0FD0 -:18E3B000E680814F3E0088477E0FE60F8047210E00197E87878787F5F2 -:18E3C8008047F5E17DE1B5E601C90E0CCD18DF2A43DB11210019E57215 -:18E3E00023722372CDF5DDCA0CE4CD5EDD110F00CDA5E3E1E55F7996F1 -:18E3F80023789E237B9EDA06E4732B702B71CD2DDFC3E4E3E1C92A43B0 -:18E41000DB112000CDA5E3212100197123702377C92AAFE53A42DB4F6D -:18E42800CDEADCE5EBCD59DBE1CC47DB7D1FD82AAFE54D44CD0BDD220F -:18E44000AFE5C3A3DE3AD6E52142DBBEC877C321E43EFF32DEE52A4355 -:18E45800DB7EE61F3D32D6E5FE1ED275E43A42DB32DFE57E32E0E5E635 -:18E47000E077CD45E43A41DB2A43DBB677C93E22C301DB21000022ADC4 -:18E48800E522AFE5AF3242DB21800022B1E5CDDADDC321E4CD72DDCD55 -:18E4A00051E4C351E0CD51E4C3A2E00E00EB7EFE3FCAC2E4CDA6DC7E03 -:18E4B800FE3FC472DDCD51E40E0FCD18DFC3E9DD2AD9E52243DBCD514A -:18E4D000E4CD2DDFC3E9DDCD51E4CD9CDFC301DFCD51E4C3BCE1CD5181 -:18E4E800E4C3FEE1CD72DDCD51E4C324E1CD51E4CD16E0C301DF2AAF6F -:18E50000E5C329E53A42DBC301DBEB22B1E5C3DADD2ABFE5C329E52A71 -:18E51800ADE5C329E5CD51E4CD3BE0C301DF2ABBE52245DBC93AD6E531 -:18E53000FEFFC23BE53A41DBC301DBE61F3241DBC9CD51E4C393E3CDDB -:18E5480051E4C39CE3CD51E4C3D2E32A43DB7D2F5F7C2F2AAFE5A45713 -:18E560007DA35F2AADE5EB22AFE57DA36F7CA26722ADE5C93ADEE5B782 -:18E57800CA91E52A43DB36003AE0E5B7CA91E5773ADFE532D6E5CD4563 -:18E59000E42A0FDBF92A45DB7D44C9CD51E43E0232D5E50E00CD07E3BB -:18E5A800CC03E2C9E5000000008000000000000000000000000000007C -:18E5C00000000000000000000000000000000000000000000000000043 -:18E5D8000000000000000000000000000000000000000000000000002B -:18E5F00000000000000000000000000000000000C30000C30000C300CA -:18E6080000C30000C30000C30000C30000C30000C30000C30000C300E2 -:13E6200000C30000C30000C30000C30000C30000C3000055 -:00000001FF +:18D00000C35CD3C358D37F00436F7079726967687420313937392028BE +:18D018006329206279204469676974616C20526573656172636820200E +:18D0300020202020000000000000000000000000000000000000000068 +:18D04800000000000000000000000000000000000000000000000000D0 +:18D06000000000000000000000000000000000000000000000000000B8 +:18D078000000000000000000000000000000000008D000005F0E02C396 +:18D090000500C5CD8CD0C1C93E0DCD92D03E0AC392D03E20C392D0C5DC +:18D0A800CD98D0E17EB7C823E5CD8CD0E1C3ACD00E0DC305005F0E0EAE +:18D0C000C30500CD050032EED73CC90E0FC3C3D0AF32EDD711CDD7C332 +:18D0D800CBD00E10C3C3D00E11C3C3D00E12C3C3D011CDD7C3DFD00E11 +:18D0F00013C30500CD0500B7C90E14C3F4D011CDD7C3F9D00E15C3F437 +:18D10800D00E16C3C3D00E17C305001EFF0E20C30500CD13D18787877F +:18D120008721EFD7B6320400C93AEFD7320400C9FE61D8FE7BD0E65F10 +:18D13800C93AABD7B7CA96D13AEFD7B73E00C4BDD011ACD7CDCBD0CA66 +:18D1500096D13ABBD73D32CCD711ACD7CDF9D0C296D11107D0218000A6 +:18D168000680CD42D421BAD73600233511ACD7CDDAD0CA96D13AEFD7CA +:18D18000B7C4BDD02108D0CDACD0CDC2D1CAA7D1CDDDD1C382D3CDDD6E +:18D19800D1CD1AD10E0A1106D0CD0500CD29D12107D0462378B7CABA4A +:18D1B000D17ECD30D17705C3ABD1772108D02288D0C90E0BCD0500B73A +:18D1C800C80E01CD0500B7C90E19C305001180000E1AC3050021ABD713 +:18D1E0007EB7C83600AFCDBDD011ACD7CDEFD03AEFD7C3BDD01128D37F +:18D1F8002100D806061ABEC2CFD3132305C2FDD1C9CD98D02A8AD07E13 +:18D21000FE20CA22D2B7CA22D2E5CD8CD0E123C30FD23E3FCD8CD0CD8C +:18D2280098D0CDDDD1C382D31AB7C8FE20DA09D2C8FE3DC8FE5FC8FE99 +:18D240002EC8FE3AC8FE3BC8FE3CC8FE3EC8C91AB7C8FE20C013C34F74 +:18D25800D2856FD024C93E0021CDD7CD59D2E5E5AF32F0D72A88D0EB61 +:18D27000CD4FD2EB228AD0EBE11AB7CA89D2DE4047131AFE3ACA90D299 +:18D288001B3AEFD777C396D27832F0D770130608CD30D2CAB9D223FE8A +:18D2A0002AC2A9D2363FC3ABD2771305C298D2CD30D2CAC0D213C3AFEF +:18D2B800D223362005C2B9D20603FE2EC2E9D213CD30D2CAE9D223FE87 +:18D2D0002AC2D9D2363FC3DBD2771305C2C8D2CD30D2CAF0D213C3DFCF +:18D2E800D223362005C2E9D2060323360005C2F2D2EB2288D0E1010B22 +:18D3000000237EFE3FC209D3040DC201D378B7C9444952204552412003 +:18D31800545950455341564552454E2055534552001600000000211001 +:18D33000D30E0079FE06D011CED706041ABEC24FD3132305C23CD31A15 +:18D34800FE20C254D379C92305C24FD30CC333D3AF3207D031ABD7C573 +:18D36000791F1F1F1FE60F5FCD15D1CDB8D032ABD7C179E60F32EFD789 +:18D37800CDBDD03A07D0B7C298D331ABD7CD98D0CDD0D1C641CD8CD0C8 +:18D390003E3ECD8CD0CD39D1118000CDD8D1CDD0D132EFD7CD5ED2C4DB +:18D3A80009D23AF0D7B7C2A5D6CD2ED321C1D35F160019197E23666FFD +:18D3C000E977D41FD55DD5ADD510D68ED6A5D621F3762200D02100D047 +:18D3D800E901DFD3C3A7D052656164206572726F720001F0D3C3A7D0A3 +:18D3F0004E6F2066696C6500CD5ED23AF0D7B7C209D221CED7010B0084 +:18D408007EFE20CA33D423D630FE0AD209D25778E6E0C209D278070709 +:18D420000780DA09D280DA09D282DA09D2470DC208D4C97EFE20C2092A +:18D43800D2230DC233D478C906037E12231305C242D4C921800081CD6C +:18D4500059D27EC9AF32CDD73AF0D7B7C83D21EFD7BEC8C3BDD03AF029 +:18D46800D7B7C83D21EFD7BEC83AEFD7C3BDD0CD5ED2CD54D421CED7A4 +:18D480007EFE20C28FD4060B363F2305C288D41E00D5CDE9D0CCEAD305 +:18D49800CA1BD53AEED70F0F0FE6604F3E0ACD4BD417DA0FD5D17B1C90 +:18D4B000D5E603F5C2CCD4CD98D0C5CDD0D1C1C641CD92D03E3ACD9219 +:18D4C800D0C3D4D4CDA2D03E3ACD92D0CDA2D0060178CD4BD4E67FFE1E +:18D4E00020C2F9D4F1F5FE03C2F7D43E09CD4BD4E67FFE20CA0ED53E70 +:18D4F80020CD92D00478FE0CD20ED5FE09C2D9D4CDA2D0C3D9D4F1CDAF +:18D51000C2D1C21BD5CDE4D0C398D4D1C386D7CD5ED2FE0BC242D5013D +:18D5280052D5CDA7D0CD39D12107D035C282D3237EFE59C282D3232211 +:18D5400088D0CD54D411CDD7CDEFD03CCCEAD3C386D7416C6C20287986 +:18D558002F6E293F00CD5ED2C209D2CD54D4CDD0D0CAA7D5CD98D0211E +:18D57000F1D736FF21F1D77EFE80DA87D5E5CDFED0E1C2A0D5AF773499 +:18D58800218000CD59D27EFE1ACA86D7CD8CD0CDC2D1C286D7C374D581 +:18D5A0003DCA86D7CDD9D3CD66D4C309D2CDF8D3F5CD5ED2C209D2CDFD +:18D5B80054D411CDD7D5CDEFD0D1CD09D1CAFBD5AF32EDD7F16F2600E0 +:18D5D000291100017CB5CAF1D52BE521800019E5CDD8D111CDD7CD049C +:18D5E800D1D1E1C2FBD5C3D4D511CDD7CDDAD03CC201D60107D6CDA757 +:18D60000D0CDD5D1C386D74E6F20737061636500CD5ED2C209D23AF002 +:18D61800D7F5CD54D4CDE9D0C279D621CDD711DDD70610CD42D42A886D +:18D63000D0EBCD4FD2FE3DCA3FD6FE5FC273D6EB232288D0CD5ED2C270 +:18D6480073D6F14721F0D77EB7CA59D6B870C273D670AF32CDD7CDE955 +:18D66000D0CA6DD611CDD7CD0ED1C386D7CDEAD3C386D7CD66D4C309D7 +:18D67800D20182D6CDA7D0C386D746696C652065786973747300CDF806 +:18D69000D3FE10D209D25F3ACED7FE20CA09D2CD15D1C389D7CDF5D18A +:18D6A8003ACED7FE20C2C4D63AF0D7B7CA89D73D32EFD7CD29D1CDBDA9 +:18D6C000D0C389D711D6D71AFE20C209D2D5CD54D4D12183D7CD40D4D5 +:18D6D800CDD0D0CA6BD7210001E5EBCDD8D111CDD7CDF9D0C201D7E193 +:18D6F000118000191100D07D937C9AD271D7C3E1D6E13DC271D7CD6682 +:18D70800D4CD5ED221F0D7E57E32CDD73E10CD60D2E17E32DDD7AF32A4 +:18D72000EDD7115C0021CDD70621CD42D42108D07EB7CA3ED7FE20CAFC +:18D738003ED723C330D706001181007E12B7CA4FD7042313C343D77879 +:18D75000328000CD98D0CDD5D1CD1AD1CD000131ABD7CD29D1CDBDD00D +:18D76800C382D3CD66D4C309D2017AD7CDA7D0C386D7426164206C6F34 +:18D78000616400434F4DCD66D4CD5ED23ACED7D62021F0D7B6C209D2D9 +:18D79800C382D3000000000000000000000000000000000000242424F5 +:18D7B000202020202053554200000000000000000000000000000000D7 +:18D7C800000000000000202020202020202020202000000000002020A9 +:18D7E00020202020202020202000000000000000000000000000000011 +:18D7F8000000000000000000001600000000C311D899D8A5D8ABD8B135 +:18D81000D8EB2243DBEB7B32D6E52100002245DB39220FDB3141DBAF06 +:18D8280032E0E532DEE52174E5E579FE29D04B2147D85F160019195E9D +:18D8400023562A43DBEBE903E6C8DA90D9CEDA12E60FE6D4DAEDDAF34A +:18D85800DAF8DAE1D9FEDA7EE483E445E49CE4A5E4ABE4C8E4D7E4E0A9 +:18D87000E4E6E4ECE4F5E4FEE404E50AE511E52CDD17E51DE526E52D5A +:18D88800E541E547E54DE50EE453E504DB04DB9BE521CAD8CDE5D8FE6C +:18D8A00003CA0000C921D5D8C3B4D821E1D8C3B4D821DCD8CDE5D8C372 +:18D8B800000042646F7320457272204F6E20203A20244261642053650D +:18D8D00063746F722453656C6563742446696C6520522F4F24E5CDC9D1 +:18D8E800D93A42DBC64132C6D801BAD8CDD3D9C1CDD3D9210EDB7E361D +:18D9000000B7C0C309E6CDFBD8CD14D9D8F54FCD90D9F1C9FE0DC8FEAF +:18D918000AC8FE09C8FE08C8FE20C93A0EDBB7C245D9CD06E6E601C87F +:18D93000CD09E6FE13C242D9CD09E6FE03CA0000AFC9320EDB3E01C913 +:18D948003A0ADBB7C262D9C5CD23D9C1C5CD0CE6C1C53A0DDBB7C40FEF +:18D96000E6C179210CDBFE7FC834FE20D0357EB7C879FE08C279D93526 +:18D97800C9FE0AC03600C979CD14D9D290D9F50E5ECD48D9F1F6404FD4 +:18D9900079FE09C248D90E20CD48D93A0CDBE607C296D9C9CDACD90E98 +:18D9A80020CD0CE60E08C30CE60E23CD48D9CDC9D93A0CDB210BDBBE49 +:18D9C000D00E20CD48D9C3B9D90E0DCD48D90E0AC348D90AFE24C80312 +:18D9D800C54FCD90D9C1C3D3D93A0CDB320BDB2A43DB4E23E50600C51B +:18D9F000E5CDFBD8E67FE1C1FE0DCAC1DAFE0ACAC1DAFE08C216DA7886 +:18DA0800B7CAEFD9053A0CDB320ADBC370DAFE7FC226DA78B7CAEFD973 +:18DA20007E052BC3A9DAFE05C237DAC5E5CDC9D9AF320BDBC3F1D9FEB9 +:18DA380010C248DAE5210DDB3E019677E1C3EFD9FE18C25FDAE13A0B05 +:18DA5000DB210CDBBED2E1D935CDA4D9C34EDAFE15C26BDACDB1D9E1D5 +:18DA6800C3E1D9FE12C2A6DAC5CDB1D9C1E1E5C578B7CA8ADA234E059C +:18DA8000C5E5CD7FD9E1C1C378DAE53A0ADBB7CAF1D9210CDB96320ADF +:18DA9800DBCDA4D9210ADB35C299DAC3F1D9237704C5E54FCD7FD9E1B7 +:18DAB000C17EFE0378C2BDDAFE01CA0000B9DAEFD9E1700E0DC348D9D9 +:18DAC800CD06D9C301DBCD15E6C301DB793CCAE0DA3CCA06E6C30CE6B4 +:18DAE000CD06E6B7CA91E5CD09E6C301DB3A0300C301DB21030071C9E9 +:18DAF800EB4D44C3D3D9CD23D93245DBC93E01C301DB00020000000067 +:18DB1000000000000000000000000000000000000000000000000000FD +:18DB2800000000000000000000000000000000000000000000000000E5 +:18DB400000000000000000210BD85E2356EBE90C0DC81A771323C35063 +:18DB5800DB3A42DB4FCD1BE67CB5C85E23562322B3E5232322B5E52394 +:18DB70002322B7E52323EB22D0E521B9E50E08CD4FDB2ABBE5EB21C151 +:18DB8800E50E0FCD4FDB2AC6E57C21DDE536FFB7CA9DDB36003EFFB700 +:18DBA000C9CD18E6AF2AB5E57723772AB7E5772377C9CD27E6C3BBDB82 +:18DBB800CD2AE6B7C82109D8C34ADB2AEAE50E02CDEADC22E5E522EC79 +:18DBD000E521E5E54E23462AB7E55E23562AB5E57E23666F7993789AC1 +:18DBE800D2FADBE52AC1E57B955F7A9C57E12BC3E4DBE52AC1E519DAB7 +:18DC00000FDC7995789CDA0FDCEBE123C3FADBE1C5D5E5EB2ACEE51972 +:18DC1800444DCD1EE6D12AB5E5732372D12AB7E5732372C179934F78C2 +:18DC30009A472AD0E5EBCD30E64D44C321E621C3E54E3AE3E5B71F0DF7 +:18DC4800C245DC473E08964F3AE2E50DCA5CDCB717C353DC80C92A43E9 +:18DC6000DB11100019093ADDE5B7CA71DC6E2600C9095E2356EBC9CD06 +:18DC78003EDC4F0600CD5EDC22E5E5C92AE5E57DB4C93AC3E52AE5E5A5 +:18DC9000293DC290DC22E7E53AC4E54F3AE3E5A1B56F22E5E5C92A43DF +:18DCA800DB110C0019C92A43DB110F0019EB21110019C9CDAEDC7E3203 +:18DCC000E3E5EB7E32E1E5CDA6DC3AC5E5A632E2E5C9CDAEDC3AD5E53D +:18DCD800FE02C2DEDCAF4F3AE3E58177EB3AE1E577C90C0DC87CB71F62 +:18DCF000677D1F6FC3EBDC0E802AB9E5AF86230DC2FDDCC90C0DC829F7 +:18DD0800C305DDC53A42DB4F210100CD04DDC179B56F78B467C92AAD92 +:18DD2000E53A42DB4FCDEADC7DE601C921ADE54E2346CD0BDD22ADE5CD +:18DD38002AC8E523EB2AB3E5732372C9CD5EDD110900197E17D0210F8B +:18DD5000D8C34ADBCD1EDDC8210DD8C34ADB2AB9E53AE9E5856FD024C5 +:18DD6800C92A43DB110E00197EC9CD69DD3600C9CD69DDF68077C92A0E +:18DD8000EAE5EB2AB3E57B96237A9EC9CD7FDDD813722B73C97B956F8E +:18DD98007A9C67C90EFF2AECE5EB2ACCE5CD95DDD0C5CDF7DC2ABDE51F +:18DDB000EB2AECE519C10CCAC4DDBEC8CD7FDDD0CD2CDDC977C9CD9C5D +:18DDC800DDCDE0DD0E01CDB8DBC3DADDCDE0DDCDB2DB21B1E5C3E3DDD5 +:18DDE00021B9E54E2346C324E62AB9E5EB2AB1E50E80C34FDB21EAE50A +:18DDF8007E23BEC03CC921FFFF22EAE5C92AC8E5EB2AEAE52322EAE547 +:18DE1000CD95DDD219DEC3FEDD3AEAE5E60306058705C220DE32E9E50B +:18DE2800B7C0C5CDC3DBCDD4DDC1C39EDD79E6073C5F57790F0F0FE6DA +:18DE40001F4F788787878787B14F780F0F0FE61F472ABFE5097E071DD7 +:18DE5800C256DEC9D5CD35DEE6FEC1B10F15C264DE77C9CD5EDD111057 +:18DE70000019C50E11D10DC8D53ADDE5B7CA88DEC5E54E0600C38EDE12 +:18DE88000DC54E2346E579B0CA9DDE2AC6E57D917C98D45CDEE123C1DC +:18DEA000C375DE2AC6E50E03CDEADC23444D2ABFE53600230B78B1C20A +:18DEB800B1DE2ACAE5EB2ABFE5732372CDA1DB2AB3E53603233600CDBF +:18DED000FEDD0EFFCD05DECDF5DDC8CD5EDD3EE5BECAD2DE3A41DBBEC4 +:18DEE800C2F6DE237ED624C2F6DE3D3245DB0E01CD6BDECD8CDDC3D2DC +:18DF0000DE3AD4E5C301DBC5F53AC5E52F4779A04FF1A091E61FC1C96C +:18DF18003EFF32D4E521D8E5712A43DB22D9E5CDFEDDCDA1DB0E00CD86 +:18DF300005DECDF5DDCA94DF2AD9E5EB1AFEE5CA4ADFD5CD7FDDD1D2B6 +:18DF480094DFCD5EDD3AD8E54F060079B7CA83DF1AFE3FCA7CDF78FEAC +:18DF60000DCA7CDFFE0C1ACA73DF96E67FC22DDFC37CDFC54ECD07DF8A +:18DF7800C1C22DDF1323040DC353DF3AEAE5E6033245DB21D4E57E1713 +:18DF9000D0AF77C9CDFEDD3EFFC301DBCD54DD0E0CCD18DFCDF5DDC8F3 +:18DFA800CD44DDCD5EDD36E50E00CD6BDECDC6DDCD2DDFC3A4DF5059F4 +:18DFC00079B0CAD1DF0BD5C5CD35DE1FD2ECDFC1D12AC6E57B957A9CD8 +:18DFD800D2F4DF13C5D5424BCD35DE1FD2ECDFD1C1C3C0DF173CCD643E +:18DFF000DEE1D1C979B0C2C0DF210000C90E001E20D506002A43DB09D4 +:18E00800EBCD5EDDC1CD4FDBCDC3DBC3C6DDCD54DD0E0CCD18DF2A433B +:18E02000DB7E1110001977CDF5DDC8CD44DD0E101E0CCD01E0CD2DDFBA +:18E03800C327E00E0CCD18DFCDF5DDC80E001E0CCD01E0CD2DDFC340FF +:18E05000E00E0FCD18DFCDF5DDC8CDA6DC7EF5E5CD5EDDEB2A43DB0EA0 +:18E0680020D5CD4FDBCD78DDD1210C00194E210F001946E1F17779BE1E +:18E0800078CA8BE03E00DA8BE03E802A43DB110F001977C97E23B62B57 +:18E09800C01A7713231A771B2BC9AF3245DB32EAE532EBE5CD1EDDC0BD +:18E0B000CD69DDE680C00E0FCD18DFCDF5DDC8011000CD5EDD09EB2AA0 +:18E0C80043DB090E103ADDE5B7CAE8E07EB71AC2DBE077B7C2E1E07EBB +:18E0E00012BEC21FE1C3FDE0CD94E0EBCD94E0EB1ABEC21FE113231AB4 +:18E0F800BEC21FE10D13230DC2CDE001ECFF09EB091ABEDA17E17701C6 +:18E11000030009EB097E123EFF32D2E5C310E02145DB35C9CD54DD2A27 +:18E1280043DBE521ACE52243DB0E01CD18DFCDF5DDE12243DBC8EB2183 +:18E140000F00190E11AF77230DC246E1210D001977CD8CDDCDFDDFC3E1 +:18E1580078DDAF32D2E5CDA2E0CDF5DDC82A43DB010C00097E3CE61FEF +:18E1700077CA83E1473AC5E5A021D2E5A6CA8EE1C3ACE10102000934E0 +:18E188007EE60FCAB6E10E0FCD18DFCDF5DDC2ACE13AD3E53CCAB6E14D +:18E1A000CD24E1CDF5DDCAB6E1C3AFE1CD5AE0CDBBDCAFC301DBCD05B7 +:18E1B800DBC378DD3E0132D5E53EFF32D3E5CDBBDC3AE3E521E1E5BEFF +:18E1D000DAE6E1FE80C2FBE1CD5AE1AF32E3E53A45DBB7C2FBE1CD77D6 +:18E1E800DCCD84DCCAFBE1CD8ADCCDD1DBCDB2DBC3D2DCC305DB3E0117 +:18E2000032D5E53E0032D3E5CD54DD2A43DBCD47DDCDBBDC3AE3E5FE57 +:18E2180080D205DBCD77DCCD84DC0E00C26EE2CD3EDC32D7E501000079 +:18E23000B7CA3BE24F0BCD5EDC444DCDBEDF7DB4C248E23E02C301DBE0 +:18E2480022E5E5EB2A43DB011000093ADDE5B73AD7E5CA64E2CD64DDBE +:18E2600073C36CE24F060009097323720E023A45DBB7C0C5CD8ADC3AA0 +:18E27800D5E53D3DC2BBE2C1C5793D3DC2BBE2E52AB9E557772314F27F +:18E290008CE2CDE0DD2AE7E50E0222E5E5C5CDD1DBC1CDB8DB2AE5E539 +:18E2A8000E003AC4E547A5B823C29AE2E122E5E5CDDADDCDD1DBC1C518 +:18E2C000CDB8DBC13AE3E521E1E5BEDAD2E277340E020000210000F51F +:18E2D800CD69DDE67F77F1FE7FC200E33AD5E5FE01C200E3CDD2DCCD4C +:18E2F0005AE12145DB7EB7C2FEE23D32E3E53600C3D2DCAF32D5E5C585 +:18E308002A43DBEB212100197EE67FF57E17237E17E61F4F7E1F1F1F1B +:18E320001FE60F47F1236E2C2D2E06C28BE32120001977210C001979BB +:18E3380096C247E3210E00197896E67FCA7FE3C5D5CDA2E0D1C12E03B8 +:18E350003A45DB3CCA84E3210C001971210E001970CD51E03A45DB3CEB +:18E36800C27FE3C1C52E040CCA84E3CD24E12E053A45DB3CCA84E3C1F7 +:18E38000AFC301DBE5CD69DD36C0E1C17D3245DBC378DD0EFFCD03E300 +:18E39800CCC1E1C90E00CD03E3CC03E2C9EB194E0600210C00197E0FD0 +:18E3B000E680814F3E0088477E0FE60F8047210E00197E87878787F5F2 +:18E3C8008047F5E17DE1B5E601C90E0CCD18DF2A43DB11210019E57215 +:18E3E00023722372CDF5DDCA0CE4CD5EDD110F00CDA5E3E1E55F7996F1 +:18E3F80023789E237B9EDA06E4732B702B71CD2DDFC3E4E3E1C92A43B0 +:18E41000DB112000CDA5E3212100197123702377C92AAFE53A42DB4F6D +:18E42800CDEADCE5EBCD59DBE1CC47DB7D1FD82AAFE54D44CD0BDD220F +:18E44000AFE5C3A3DE3AD6E52142DBBEC877C321E43EFF32DEE52A4355 +:18E45800DB7EE61F3D32D6E5FE1ED275E43A42DB32DFE57E32E0E5E635 +:18E47000E077CD45E43A41DB2A43DBB677C93E22C301DB21000022ADC4 +:18E48800E522AFE5AF3242DB21800022B1E5CDDADDC321E4CD72DDCD55 +:18E4A00051E4C351E0CD51E4C3A2E00E00EB7EFE3FCAC2E4CDA6DC7E03 +:18E4B800FE3FC472DDCD51E40E0FCD18DFC3E9DD2AD9E52243DBCD514A +:18E4D000E4CD2DDFC3E9DDCD51E4CD9CDFC301DFCD51E4C3BCE1CD5181 +:18E4E800E4C3FEE1CD72DDCD51E4C324E1CD51E4CD16E0C301DF2AAF6F +:18E50000E5C329E53A42DBC301DBEB22B1E5C3DADD2ABFE5C329E52A71 +:18E51800ADE5C329E5CD51E4CD3BE0C301DF2ABBE52245DBC93AD6E531 +:18E53000FEFFC23BE53A41DBC301DBE61F3241DBC9CD51E4C393E3CDDB +:18E5480051E4C39CE3CD51E4C3D2E32A43DB7D2F5F7C2F2AAFE5A45713 +:18E560007DA35F2AADE5EB22AFE57DA36F7CA26722ADE5C93ADEE5B782 +:18E57800CA91E52A43DB36003AE0E5B7CA91E5773ADFE532D6E5CD4563 +:18E59000E42A0FDBF92A45DB7D44C9CD51E43E0232D5E50E00CD07E3BB +:18E5A800CC03E2C9E5000000008000000000000000000000000000007C +:18E5C00000000000000000000000000000000000000000000000000043 +:18E5D8000000000000000000000000000000000000000000000000002B +:18E5F00000000000000000000000000000000000C30000C30000C300CA +:18E6080000C30000C30000C30000C30000C30000C30000C30000C300E2 +:13E6200000C30000C30000C30000C30000C30000C3000055 +:00000001FF diff --git a/Z80 CPM and bootloader (basmon)/hexFiles/DOWNLOAD.HEX b/Z80 CPM and bootloader (basmon)/hexFiles/DOWNLOAD.HEX index 643dffe..085a094 100644 --- a/Z80 CPM and bootloader (basmon)/hexFiles/DOWNLOAD.HEX +++ b/Z80 CPM and bootloader (basmon)/hexFiles/DOWNLOAD.HEX @@ -1,19 +1,19 @@ -:180100003E00326D02327102327202327002218000226E02CD3902FEE0 -:1801180055CA2A02FE3A20F40E13115C00CD05000E16115C00CD050075 -:18013000CD3902FE3E286147C5CD3902C14FCD4C02473A710280327194 -:18014800023A72023C327202782A6E027723226E023A6D023C326D0249 -:18016000FE8020320E15115C00CD05003E2ECD45023A70023CFE40208F -:180178000F3270023E0DCD45023E0ACD45023E00327002218000226EEE -:18019000023E00326D0218983A6D02FE00280D0E15115C00CD05003E4A -:1801A8002ECD45020E10115C00CD0500CD390247C5CD3902C14FCD4C5B -:1801C00002473A720290FE00281A3E0DCD45023E0ACD45021191020EF3 -:1801D80009CD0500CD3902CD3902183CCD390247C5CD3902C14FCD4C8B -:1801F00002473A710290FE0028143E0DCD45023E0ACD45021176020EE5 -:1802080009CD050018123E0DCD45023E0ACD45021173020E09CD0500AF -:180220000E201E00CD0500C30000CD3902CD65025F0E20CD0500C31473 -:18023800011EFF0E06CD0500FE0028F5C90E025FCD0500C978D630FE40 -:180250000A3802D607070707074779D630FE0A3802D60780C9D630FE27 -:180268000AD8D607C90000000000004F4B243D3D3D3D3D3D4368656357 -:180280006B73756D204572726F723D3D3D3D3D3D243D3D3D3D3D3D4636 -:17029800696C65204C656E677468204572726F723D3D3D3D3D3D24D7 -:00000001FF +:180100003E00326D02327102327202327002218000226E02CD3902FEE0 +:1801180055CA2A02FE3A20F40E13115C00CD05000E16115C00CD050075 +:18013000CD3902FE3E286147C5CD3902C14FCD4C02473A710280327194 +:18014800023A72023C327202782A6E027723226E023A6D023C326D0249 +:18016000FE8020320E15115C00CD05003E2ECD45023A70023CFE40208F +:180178000F3270023E0DCD45023E0ACD45023E00327002218000226EEE +:18019000023E00326D0218983A6D02FE00280D0E15115C00CD05003E4A +:1801A8002ECD45020E10115C00CD0500CD390247C5CD3902C14FCD4C5B +:1801C00002473A720290FE00281A3E0DCD45023E0ACD45021191020EF3 +:1801D80009CD0500CD3902CD3902183CCD390247C5CD3902C14FCD4C8B +:1801F00002473A710290FE0028143E0DCD45023E0ACD45021176020EE5 +:1802080009CD050018123E0DCD45023E0ACD45021173020E09CD0500AF +:180220000E201E00CD0500C30000CD3902CD65025F0E20CD0500C31473 +:18023800011EFF0E06CD0500FE0028F5C90E025FCD0500C978D630FE40 +:180250000A3802D607070707074779D630FE0A3802D60780C9D630FE27 +:180268000AD8D607C90000000000004F4B243D3D3D3D3D3D4368656357 +:180280006B73756D204572726F723D3D3D3D3D3D243D3D3D3D3D3D4636 +:17029800696C65204C656E677468204572726F723D3D3D3D3D3D24D7 +:00000001FF diff --git a/Z80 CPM and bootloader (basmon)/hexFiles/FORM128.HEX b/Z80 CPM and bootloader (basmon)/hexFiles/FORM128.HEX index e9198f5..b2a8782 100644 --- a/Z80 CPM and bootloader (basmon)/hexFiles/FORM128.HEX +++ b/Z80 CPM and bootloader (basmon)/hexFiles/FORM128.HEX @@ -1,16 +1,16 @@ -:18500000CDD55043502F4D20466F726D617474657220322E3020627918 -:1850180020472E20536561726C6520323031330D0A003E4132E7503A50 -:18503000E750CF3C32E7503E2032E6503AE650D38A3E00D38B3E00D37D -:185048008C3EE0CDA7503AE6503C32E650FE4020E311400021400006D5 -:185060000F3AE750CF3C32E7503E0032E6503AE650D38A7DD38B7CD3A7 -:185078008CCDA7503AE6503C32E650FE2020E7190520D6CDD5500D0A7A -:18509000466F726D617474696E6720636F6D706C6574650D0A00C9F59F -:1850A800C5E5DB89FE8020FA3E01D3890E0421E8500680DB89FEA0209C -:1850C000FAC5063210FEC17ED388230520ED0D20E5E1C1F1C9E3F5C5F9 -:1850D8007EFE002804CF2318F723C1F1E3C90000E520202020202020D1 -:1850F00020202020000000000000000000000000000000000000000028 -:18510800E520202020202020202020200000000000000000000000004A -:185120000000000000000000E520202020202020202020200000000032 -:1851380000000000000000000000000000000000E5202020202020209A -:18515000202020200000000000000000000000000000000000000000C7 -:00000001FF +:18500000CDD55043502F4D20466F726D617474657220322E3020627918 +:1850180020472E20536561726C6520323031330D0A003E4132E7503A50 +:18503000E750CF3C32E7503E2032E6503AE650D38A3E00D38B3E00D37D +:185048008C3EE0CDA7503AE6503C32E650FE4020E311400021400006D5 +:185060000F3AE750CF3C32E7503E0032E6503AE650D38A7DD38B7CD3A7 +:185078008CCDA7503AE6503C32E650FE2020E7190520D6CDD5500D0A7A +:18509000466F726D617474696E6720636F6D706C6574650D0A00C9F59F +:1850A800C5E5DB89FE8020FA3E01D3890E0421E8500680DB89FEA0209C +:1850C000FAC5063210FEC17ED388230520ED0D20E5E1C1F1C9E3F5C5F9 +:1850D8007EFE002804CF2318F723C1F1E3C90000E520202020202020D1 +:1850F00020202020000000000000000000000000000000000000000028 +:18510800E520202020202020202020200000000000000000000000004A +:185120000000000000000000E520202020202020202020200000000032 +:1851380000000000000000000000000000000000E5202020202020209A +:18515000202020200000000000000000000000000000000000000000C7 +:00000001FF diff --git a/Z80 CPM and bootloader (basmon)/hexFiles/PUTSYS.HEX b/Z80 CPM and bootloader (basmon)/hexFiles/PUTSYS.HEX index 5edbe37..1fdb09b 100644 --- a/Z80 CPM and bootloader (basmon)/hexFiles/PUTSYS.HEX +++ b/Z80 CPM and bootloader (basmon)/hexFiles/PUTSYS.HEX @@ -1,10 +1,10 @@ -:18500000CDBA5043502F4D2053797374656D205472616E736665722088 -:18501800627920472E20536561726C6520323031322D31330D0A000601 -:18503000183E0032CB5032CC5032CD5032CE502100D022CF50CD8C50FD -:185048001100022ACF501922CF503ACB503C32CB5010EACDBA500D0AD4 -:1850600053797374656D207472616E7366657220636F6D706C657465B5 -:185078000D0A00C93ACD50D38C3ACC50D38B3ACB50D38AC9F5C5E5DBE1 -:1850900089FE8020FACD7C503E01D3890E040680DB89FEA020FAC50634 -:1850A8003210FEC17ED388230520ED0D20E8E1C1F1C9E3F5C57EFE0057 -:1150C0002804CF2318F723C1F1E3C900000000000031 -:00000001FF +:18500000CDBA5043502F4D2053797374656D205472616E736665722088 +:18501800627920472E20536561726C6520323031322D31330D0A000601 +:18503000183E0032CB5032CC5032CD5032CE502100D022CF50CD8C50FD +:185048001100022ACF501922CF503ACB503C32CB5010EACDBA500D0AD4 +:1850600053797374656D207472616E7366657220636F6D706C657465B5 +:185078000D0A00C93ACD50D38C3ACC50D38B3ACB50D38AC9F5C5E5DBE1 +:1850900089FE8020FACD7C503E01D3890E040680DB89FEA020FAC50634 +:1850A8003210FEC17ED388230520ED0D20E8E1C1F1C9E3F5C57EFE0057 +:1150C0002804CF2318F723C1F1E3C900000000000031 +:00000001FF diff --git a/Z80 CPM and bootloader (basmon)/hexFiles/intMon.hex b/Z80 CPM and bootloader (basmon)/hexFiles/intMon.hex index dc90ff2..06e8245 100644 --- a/Z80 CPM and bootloader (basmon)/hexFiles/intMon.hex +++ b/Z80 CPM and bootloader (basmon)/hexFiles/intMon.hex @@ -6,10 +6,10 @@ :18006000DB800FCB47C9DB820FCB47C93A0030FE002007DB80E601FE2D :1800780000C9DB82E601FE00C9D7FE0A28FBFE1B20023E03C9FE0D2822 :180090000AFE0C2804FE203801CFC93E0DCF3E0ACF3E0DC9312A303E1B -:1800A80095D380D3823E00320030210E03CD3701210E032204302A0476 +:1800A80095D380D3823E00320030213403CD37012134032204302A042A :1800C000307EB7280CCD5000280723220430C3BE00CD7300280F3E0094 :1800D800320030CD1B00FE20C2D1001812CD7A0028D43E01320030CD3A -:1800F0001B00FE20C2BE003E0CCD3C00CD5000CD3E01219C02CD3701FF +:1800F0001B00FE20C2BE003E0CCD3C00CD5000CD3E0121C202CD3701D9 :18010800210801E5CD3E013E3ECFCD8100FE2038F9FE3ACAB501CD8DCA :1801200000E65FFE49CAF601FE47CAAF01FE58CAFA013E3FCF18D57EE9 :18013800B7C8CF2318F93E0DCF3E0ACFC9CD8100FE03C8FE2038F6C907 @@ -19,323 +19,324 @@ :18019800070707074779D630FE0A3802D60780C9CD8100CD8D00C9CDC7 :1801B0006101D8E5C91E00CD500157CD500167CD50016FCD5001FE018D :1801C8002009CD50017BA7281E18157AA7280BCD500177233E2ECF15E7 -:1801E00018F1CD50017BA7C821FD02CD3701C9213403CD3701C9C33FE0 +:1801E00018F1CD50017BA7C8212303CD3701C9215A03CD3701C9C3656D :1801F80003C9210C02CD3701CD4501C8E65FFE59CA2A02C90D0A426FF1 :180210006F742043502F4D3F000D0A4C6F6164696E672043502F4D0D74 :180228000A00211902CD370106183E0032063032073032083032093071 :180240002100D0220230CD74021100022A0230192202303A06303C3264 :18025800063010EA3A0030F52AFEFFE93A0830D38C3A0730D38B3A060F -:1802700030D38AC9F5C5E5DB89FE8020FACD64023E00D3890E04068020 -:18028800DB89FEE020FADB8877230520F30D20EEE1C1F1C943502F4D67 -:1802A00020426F6F7420524F4D20322E300D0A492D5374727420496EC3 -:1802B8007472700D0A582D426F6F742043502F4D0D0A3A6E6E6E6E2D43 -:1802D0004C6F6164204920726372640D0A476E6E6E6E2D52206C6F636F -:1802E8000D0A000D0A436F6C64206F72207761726D3F0D0A0043686510 -:18030000636B73756D206572726F720D0A000C5072657373205B7370EA -:180318006163655D20746F20616374697661746520636F6E736F6C65C0 -:180330002E0D0A00436F6D706C6574650D0A0021EB02CD3701CD4501FA -:18034800C8E65FFE43CA5603FE57CA5903C9C35C03C3FA03DD21000008 -:18036000C367030D0C831321B030F9C3A21F113406066321B0301A77E5 -:18037800231305C27603F9CD3508CD030E325A3132A931214904CDA171 -:1803900014CD5208CD5B0BB7C2B003210D32237CB5CAC2037E472F770D -:1803A800BE70CA9E03C3C203CD270CB7C20307EB2B3ED94677BE70C2BF -:1803C0008B032B110C32CDCB09DA8B0311CEFF225F3119220A31CD1031 -:1803D800082A0A3111EFFF1911A9317D936F7C9A67E5211204CDA11403 -:1803F000E1CD441B210304CDA114311631CD3508C34E072042797465F0 -:180408007320667265650D0A00005A38302042415349432056657220DF -:18042000342E37620D0A436F707972696768742028432920313937384C -:18043800206279204D6963726F736F66740D0A00004D656D6F7279202B -:18045000746F7000B9197D1ACF19B3306113E6168F13431C221D5E18E7 -:18046800911C971D9D1DFE1D131E3A177E1E013113162B14AD16221693 -:180480003316A01E331F431673167D16C54E44C64F52CE455854C44114 -:180498005441C94E505554C4494DD2454144CC4554C74F544FD2554E1E -:1804B000C946D24553544F5245C74F535542D2455455524ED2454DD3EA -:1804C800544F50CF5554CF4ECE554C4CD7414954C44546D04F4B45C462 -:1804E0004F4B45D3435245454ECC494E4553C34C53D749445448CD4F6C -:1804F8004E49544F52D34554D245534554D052494E54C34F4E54CC491B -:180510005354C34C454152C34C4F4144C353415645CE4557D441422887 -:18052800D44FC64ED3504328D448454ECE4F54D3544550ABADAAAFDE8B -:18054000C14E44CF52BEBDBCD3474EC94E54C14253D55352C65245C92F -:180558004E50D04F53D35152D24E44CC4F47C55850C34F53D3494ED42F -:18057000414EC1544ED045454BC445454BD04F494E54CC454ED3545261 -:1805880024D6414CC15343C3485224C8455824C2494E24CC4546542427 -:1805A000D24947485424CD49442480A50BA20A7D0FF20C840EB911B32E -:1805B8000E090DAF0C920C810D6B0B9E0CCD0CF40CA30BF216630DE41D -:1805D0000BF81697134117891EF40C6F1E621E671E9F1F04310731A5EF -:1805E8000DD10B170A4C0CF40CF40C0F08792B1B795F177C9D187CFE29 -:18060000187F4C1C5012114611114E46534E52474F4446434F564F4DDD -:18061800554C425344442F304944544D4F534C535354434E55464D4FCF -:180630004858424EC3FA03C3220CD300C9D6006F7CDE006778DE004792 -:180648003E00C9000000354ACA99391C76982295B3980ADD479853D162 -:1806600099990A1A9F9865BCCD98D6773E9852C74F80DB00C901FF1CA4 -:1806780000001400140000000000C34809C30000C30000C300000D32A6 -:18069000FEFFAA31204572726F720020696E20004F6B0D0A00004272B4 -:1806A80065616B00210400397E23FE81C04E234623E569607AB3EBCA61 -:1806C000C606EBCDCB09010D00E1C809C3B006CDE906C5E3C1CDCB09CB -:1806D8007E02C80B2BC3D506E52A8A31060009093EE53ED0956F3EFF9A -:1806F0009CDAF8066739E1D81E0CC317072A7931220C311E02011E1494 -:18070800011E00011E12011E22011E0A011E18CD350832F530CDF60DB7 -:18072000210A06573E3FCDDC09197ECDDC09CD5B0BCDDC09219406CD54 -:18073800A1142A0C3111FEFFCDCB09CA67037CA53CC43C1B3EC1AF3252 -:18075000F530CDF60D21A006CDA11421FFFF220C31CD4809DA5B07CDAE -:180768005B0B3C3DCA5B07F5CD270CD5CD5F0847D1F1D23B0BD5C5AF06 -:18078000327C31CD5B0BB7F5CDEF07DA9407F1F5CAC80CB7C5D2AB07E7 -:18079800EB2A86311A020313CDCB09C29C076069228631D1F1CAD2073E -:1807B0002A8631E3C109E5CDCF06E1228631EB74D123237323722311B0 -:1807C80011311A772313B7C2CA07CD1B0823EB626B7E23B6CA5B072355 -:1807E0002323AFBE23C2E307EB732372C3D7072A0E31444D7E23B62B6F -:1807F800C823237E23666FCDCB0960697E23666F3FC83FD0C3F207C0F3 -:180810002A0E31AF772377232286312A0E312B227E312A5F31227331C6 -:18082800AFCD6B0B2A8631228831228A31C12A0A31F9216331226131A5 -:18084000AF6F67228431327B31228E31E5C52A7E31C93E3FCDDC093ECC -:1808580020CDDC09C3FE30AF325E310E051111317EFE20CAE70847FE55 -:1808700022CA0709B7CA0E093A5E31B77EC2E708FE3F3E9ECAE7087EDD -:18088800FE30DA9208FE3CDAE708D5118B04C501E308C5067F7EFE6166 -:1808A000DAAB08FE7BD2AB08E65F774EEB23B6F2AD08047EE67FC8B9D8 -:1808B800C2AD08EBE5131AB7FADF084F78FE88C2CE08CD5B0B2B237E38 -:1808D000FE61DAD708E65FB9CABD08E1C3AB0848F1EBC9EB79C1D1230E -:1808E80012130CD63ACAF508FE49C2F808325E31D654C26808477EB74E -:18090000CA0E09B8CAE70823120C13C3FE082110311213121312C93AAF -:18091800F430B73E0032F430C22B0905CA4809CDDC093E052BCA3F0910 -:180930007ECDDC09C35109052BCDDC09C25109CDDC09CD030EC34809C0 -:180948002111310601AF32F430CD060A4FFE7FCA17093AF430B7CA6A4C -:18096000093E00CDDC09AF32F43079FE07CAAE09FE03CC030E37C8FEA7 -:180978000DCAFE0DFE15CA4209FE40CA3F09FE5FCA3709FE08CA370996 -:18099000FE12C2A909C5D5E53600CDB31F211131CDA114E1D1C1C3510B -:1809A80009FE20DA510978FE493E07D2C3097971327C312304CDDC0998 -:1809C000C35109CDDC093E08C3BD097C92C07D93C97EE3BE23E3CA5B90 -:1809D8000BC30307F53AF530B7C2D614F1C5F5FE20DA000A3AF2304728 -:1809F0003A5B3104CAFC0905B8CC030E3C325B31F1C1CD9C1FC9CD6092 -:180A08001EE67FFE0FC03AF5302F32F530AFC9CD270CC0C1CDEF07C520 -:180A2000CD6D0AE14E23462378B1CA4E07CD760ACD860BC5CD030E5ECB -:180A3800235623E5EBCD441B3E20E1CDDC097EB723CA230AF2430AD6B9 -:180A50007F4F118C041A13B7F2550A0DC2550AE67FCDDC091A13B7F2CF -:180A68005F0AC3460AE52AF83022F630E1C9E5D52AF63011FFFFED5A71 -:180A800022F630D1E1F0E52AF83022F630CD601EFE03CA990AE1C37622 -:180A98000A2AF83022F630C3FD033E64327B31CD090DC1E5CDF20C22E9 -:180AB000773121020039CDB006D1C2D20A09D52B562B5E2323E52A7784 -:180AC80031CDCB09E1C2B60AD1F9EB0E08CDE006E52A7731E3E52A0CAE -:180AE00031E3CDCB0FCDD109A6CDC80FE5CDF619E1C5D5010081515AE9 -:180AF8007EFEAB3E01C20E0BCD5B0BCDC80FE5CDF619CDAA19E1C5D502 -:180B1000F533E52A7E31E30681C533CD860B227E317EFE3ACA3B0BB7D9 -:180B2800C20307237E23B6CAAD0B235E2356EB220C31EBCD5B0B111B5F -:180B40000BD5C8D680DA090DFE25D20307074F0600EB21AB05094E231E -:180B580046C5EB237EFE3AD0FE20CA5B0BFE303F3C3DC9EB2A0E31CACB -:180B7000800BEBCD270CE5CDEF076069D1D2C80C2B228C31EBC9DFC8AA -:180B8800D7FE1B2811FE03280DFE13C0D7FE11C8FE03280718F63EFFFC -:180BA00032FD30C0F6C0227E3121F6FFC12A0C31F57DA43CCAC00B2250 -:180BB80082312A7E31228431AF32F530CDF60DF121A606C23707C34E1D -:180BD000072A84317CB51E20CA1707EB2A8231220C31EBC9CD2917C028 -:180BE80032F130C9E52AFA3006004F0922FA30E1C97EFE41D8FE5B3F1F -:180C0000C9CD5B0BCDC80FCDAA19FA220C3A9731FE90DA521A0180909D -:180C1800110000E5CD251AE151C81E08C317072B110000CD5B0BD0E59D -:180C3000F5219819CDCB09DA0307626B19291929F1D6305F160019EB9F -:180C4800E1C32B0CCA1F08CD040C2BCD5B0BE52A5F31CA6F0CE1CDD12A -:180C6000092CD5CD040C2BCD5B0BC20307E3EB7D935F7C9A57DAF806E9 -:180C7800E52A863101280009CDCB09D2F806EB220A31E1225F31E1C37C -:180C90001F08CA1B08CD1F08011B0BC3AE0C0E03CDE006C1E5E52A0C1B -:180CA80031E33E8CF533C5CD270CCDF40CE52A0C31CDCB09E123DCF2DD -:180CC00007D4EF0760692BD81E0EC31707C016FFCDAC06F9FE8C1E0479 -:180CD800C21707E1220C31237CB5C2EC0C3A7C31B7C24D07211B0BE3F8 -:180CF0003EE1013A0E0006007948477EB7C8B8C823FE22CAF80CC3FB2A -:180D08000CCDBE11CDD109B4D53A5D31F5CDDA0FF1E3227E311FCDCD2A -:180D20000FCA5C0DE52A9431E523235E23562A0E31CDCB09D24B0D2A45 -:180D38000A31CDCB09D1D2530D216F31CDCB09D2530D3ED1CD0216EB51 -:180D5000CD3B14CD0216E1CD051AE1C9E5CD021AD1E1C9CD29177E47F8 -:180D6800FE8CCA720DCDD109882B4B0D78CA430BCD280CFE2CC0C3733D -:180D80000DCDDA0F7EFE88CA8F0DCDD109A92BCDCB0FCDAA19CAF40CB2 -:180D9800CD5B0BDAAF0CC3420B2BCD5B0BCA030EC8FEA5CA360EFEA813 -:180DB000CA360EE5FE2CCA1F0EFE3BCA590EC1CDDA0FE53A5D31B7C210 -:180DC800EF0DCD4F1BCD5F1436202A9431342A94313AF2304704CAEBDC -:180DE0000D043A5B31863DB8D4030ECDA414AFC4A414E1C3A10D3A5B2D -:180DF80031B7C8C3030E36002110313E0DCDDC093E0ACDDC09AF325B94 -:180E1000313AF1303DC8F5AFCDDC09F1C3140E3AF330473A5B31B8D417 -:180E2800030ED2590ED60ED22D0E2FC34E0EF5CD2617CDD109292BF13E -:180E4000D6A8E5CA490E3A5B312F83D2590E3C473E20CDDC0905C252B9 -:180E58000EE1CD5B0BC3A80D3F5265646F2066726F6D207374617274FD -:180E70000D0A003A7D31B7C2FD06C121600ECDA114C34E08CD0C147E99 -:180E8800FE223E0032F530C29E0ECD6014CDD1093BE5CDA4143EE5CDB2 -:180EA0005208C1DAAA0B237EB72BC5CAF10C362CC3B80EE52A8C31F6D4 -:180EB800AF327D31E3C3C40ECDD1092CCDBE11E3D57EFE2CCAEC0E3A4E -:180ED0007D31B7C2590F3E3FCDDC09CD5208D1C1DAAA0B237EB72BC5BC -:180EE800CAF10CD53A5D31B7CA160FCD5B0B5747FE22CA0A0F3A7D312C -:180F0000B757CA070F163A062C2BCD6314EB21210FE3D5C3240DCD5BEA -:180F18000BCDB11AE3CD021AE12BCD5B0BCA2D0FFE2CC2730EE32BCDC5 -:180F30005B0BC2C00ED13A7D31B7EBC2810BD5B621480FC4A114E1C9E4 -:180F48003F45787472612069676E6F7265640D0A00CDF20CB7C2720F6A -:180F6000237E23B61E06CA1707235E2356EB227931EBCD5B0BFE83C2E1 -:180F7800590FC3EC0E110000C4BE11227E31CDAC06C20907F9D57E2307 -:180F9000F5D5CDE819E3E5CD5517E1CD021AE1CDF919E5CD251AE1C193 -:180FA80090CDF919CAB80FEB220C316960C3170BF92A7E317EFE2CC2FD -:180FC0001B0BCD5B0BCD800FCDDA0FF6373A5D318FB7E8C31507CDD10E -:180FD80009282B1600D50E01CDE006CD51102280312A8031C178FE786D -:180FF000D4CB0F7E1600D6B3DA1210FE03D21210FE0117AABA57DA037F -:1810080007227531CD5B0BC3F60F7AB7C239117E227531D6ACD8FE0724 -:18102000D05F3A5D313DB37BCA971507835F21F505197856BAD023CD7B -:18103800CB0FC501E90FC5434ACDDB1958514E234623C52A7531C3DD3D -:181050000FAF325D31CD5B0B1E24CA1707DAB11ACDF90BD2B810FE2679 -:181068002012CD5B0BFE48CAF51EFE42CA651F1E02CA1707FEACCA518D -:1810800010FE2ECAB11AFEADCAA710FE22CA6014FEAACA9911FEA7CA72 -:18109800C413D6B6D2C910CDD60FCDD10929C9167DCDDD0F2A8031E5DB -:1810B000CDD319CDCB0FE1C9CDBE11E5EB2294313A5D31B7CCE819E19E -:1810C800C90600074FC5CD5B0B79FE31DAF010CDD60FCDD1092CCDCC53 -:1810E0000FEB2A9431E3E5EBCD2917EBE3C3F810CD9F10E311B310D5AE -:1810F800015404094E236669E915FEADC8FE2DC814FE2BC8FEACC82B38 -:18111000C9F6AFF5CDCB0FCD0D0CF1EBC1E3EBCDEB19F5CD0D0CF1C10E -:1811280079218213C23411A34F78A2E9B34F78B2E9214B113A5D311F0B -:181140007A175F166478BAD0C33A104D1179B71FC1D1F5CDCD0F218F91 -:1811580011E5CA251AAF325D31D5CDE4157E23234E2346D1C5F5CDE8BB -:1811700015CDF919F157E17BB2C87AD601D8AFBB3CD0151D0ABE230396 -:18118800CA77113FC3B5193C8FC1A0C6FF9FC3BC19165ACDDD0FCDCB44 -:1811A0000FCD0D0C7B2F4F7A2FCD8213C1C3E90F2BCD5B0BC8CDD109F5 -:1811B8002C01B011C5F6AF325C3146CDF90BDA0307AF4F325D31CD5B27 -:1811D0000BDADA11CDF90BDAE7114FCD5B0BDADB11CDF90BD2DB11D6E7 -:1811E80024C2F6113C325D310F814FCD5B0B3A7B313DCAA312F2061248 -:181200007ED628CA7B12AF327B31E550592A8E31CDCB09119031CAEBD7 -:18121800182A8831EB2A8631CDCB09CA3912799623C22E12789623CA12 -:181230006D1223232323C32012E1E3D511BB10CDCB09D1CA7012E3E5AB -:18124800C50106002A8A31E509C1E5CDCF06E1228A3160692288312B1A -:181260003600CDCB09C25F12D173237223EBE1C9329731219F06229465 -:1812780031E1C9E52A5C31E357D5C5CD010CC1F1EBE3E5EB3C577EFEDA -:181290002CCA8112CDD10929228031E1225C311E00D511E5F52A8831C9 -:1812A8003E19EB2A8A31EBCDCB09CADB127EB923C2BD127EB8235E23FF -:1812C0005623C2A9123A5C31B7C20C07F1444DCAEB1896CA39131E10A4 -:1812D800C31707110400F1CA220C712370234FCDE00623232275317177 -:1812F000233A5C311779010B00D2FE12C10371237023F5E5CD961AEB51 -:18130800E1F13DC2F612F5424BEB19DAF806CDE906228A312B3600CDCF -:18132000CB09C21C1303572A75315EEB2909EB2B2B73237223F1DA5DB7 -:1813380013474F7E2316E15E235623E3F5CDCB09D2D612E5CD961AD1FC -:1813500019F13D444DC23E132929C109EB2A8031C92A8A31EB210000FE -:18136800393A5D31B7CA7D13CDE415CDE4142A0A31EB2A73317D934F53 -:181380007C9A41501E00215D31730690C3C1193A5B3147AFC38313CD59 -:181398001A14CD0C1401F20CC5D5CDD10928CDBE11E5EB2B562B5EE163 -:1813B000CDCB0FCDD10929CDD109B4444DE3712370C35914CD1A14D5DB -:1813C800CD9F10CDCB0FE35E2356237AB3CA0F077E23666FE52A8E31BC -:1813E000E3228E312A9231E52A9031E5219031D5CD021AE1CDC80F2B3F -:1813F800CD5B0BC20307E1229031E1229231E1228E31E1C9E52A0C319C -:18141000237CB5E1C01E16C31707CDD109A73E80327B31B647CDC31132 -:18142800C3CB0FCDCB0FCD4F1BCD5F14CDE415013F16C57E2323E5CD9A -:18144000BA14E14E2346CD5314E56FCDD715D1C9CDBA14216F31E5779B -:181458002323732372E1C92B062250E50EFF237E0CB7CA7514BACA753F -:1814700014B8C26614FE22CC5B0BE323EB79CD5314116F312A613122DD -:1814880094313E01325D31CD051ACDCB09226131E17EC01E1EC317070B -:1814A00023CD5F14CDE415CDF9191C1DC80ACDDC09FE0DCC0D0E03C3B7 -:1814B800AB14B70EF1F52A0A31EB2A73312F4F06FF0923CDCB09DAD892 -:1814D0001422733123EBF1C9F11E1ACA1707BFF501BC14C52A5F31222B -:1814E8007331210000E52A0A31E5216331EB2A6131EBCDCB0901F51406 -:18150000C249152A8631EB2A8831EBCDCB09CA1C157E2323B7CD4C15D4 -:18151800C30615C1EB2A8A31EBCDCB09CA7215CDF9197BE509B7F21B63 -:1815300015227531E14E0600090923EB2A7531EBCDCB09CA1C15013BDE -:1815480015C5F6807E23235E235623F0B7C8444D2A7331CDCB09606945 -:18156000D8E1E3CDCB09E3E56069D0C1F1F1E5D5C5C9D1E17DB4C82B14 -:18157800462B4EE52B2B6E26000950592B444D2A7331CDD206E1712377 -:181590007069602BC3E714C5E52A9431E3CD5110E3CDCC0F7EE52A94CB -:1815A80031E5861E1CDA1707CD5014D1CDE815E3CDE715E52A7131EB49 -:1815C000CDCE15CDCE1521E60FE3E5C38114E1E37E23234E23466F2CA3 -:1815D8002DC80A120313C3D815CDCC0F2A9431EBCD0216EBC0D5505994 -:1815F0001B4E2A7331CDCB09C200164709227331E1C92A61312B462B1B -:181608004E2B2BCDCB09C0226131C9019213C5CDE115AF57325D317ED6 -:18162000B7C9019213C5CD1716CA220C23235E23561AC93E01CD501465 -:18163800CD2C172A713173C1C38114CDDC16AFE34FE57EB8DA511678BE -:18165000110E00C5CDBA14C1E1E5232346236668060009444DCD53142B -:181668006FCDD715D1CDE815C38114CDDC16D1D51A90C34716EB7ECDEA -:18168000E1160405CA220CC51EFFFE29CA9616CDD1092CCD2917CDD15D -:181698000929F1E3014916C53DBE0600D04F7E91BB47D843C9CD171600 -:1816B000CACA175F23237E23666FE5194672E3C57EFE24C2CB16CDF5F9 -:1816C8001E180DFE25C2D516CD651F1803CDB11AC1E170C9EBCDD10986 -:1816E00029C1D1C543C9CD2C1732EF30CDEE30C39213CD1617C3B6300F -:1816F800CD1617F51E002BCD5B0BCA0C17CDD1092CCD2917C1CDEE30F6 -:18171000ABA0CA0D17C9CD291732EF3032B730CDD1092CC32917CD5B4A -:181728000BCDC80FCD070C7AB7C2220C2BCD5B0B7BC9CD0D0C1AC39202 -:1817400013CDC80FCD0D0CD5CDD1092CCD2917D112C921281CCDF9194F -:18175800C36417CDF91921C1D1CDD31978B7C83A9731B7CAEB1990D210 -:181770007E172F3CEBCDDB19EBCDEB19C1D1FE19D0F5CD101A67F1CD6F -:181788002918B4219431F2A417CD0918D2EA172334CA12072E01CD3F8B -:1817A00018C3EA17AF90477E9B5F237E9A57237E994FDC15186863AFB9 -:1817B8004779B7C2D7174A54656F78D608FEE0C2B817AF329731C90544 -:1817D000297A1757798F4FF2CF17785C45B7CAEA172197318677D2CAA4 -:1817E80017C878219731B7FCFC1746237EE680A94FC3EB191CC014C027 -:181800000CC00E8034C0C312077E835F237E8A57237E894FC921983198 -:181818007E2F77AF6F90477D9B5F7D9A577D994FC90600D608DA38187E -:18183000435A510E00C32B18C6096FAF2DC8791F4F7A1F577B1F5F7874 -:181848001F47C33B180000008103AA561980F122768045AA3882CDAAC6 -:1818600019B7EA220C2197317E01358011F30490F570D5C5CD6417C1CB -:18187800D104CD0019214D18CD5B17215118CDF21C018080110000CD94 -:181890006417F1CD251B01318011187221C1D1CDAA19C82E00CD6819F3 -:1818A8007932A631EB22A731010000505821B517E521C118E5E52194CD -:1818C000317E23B7CAED18E52E081F6779D2DB18E52AA73119EBE13AD3 -:1818D800A631891F4F7A1F577B1F5F781F472D7CC2CA18E1C9435A517E -:1818F0004FC9CDDB19012084110000CDEB19C1D1CDAA19CA06072EFF5A -:18190800CD681934342B7E32C2302B7E32BE302B7E32BA3041EBAF4F8C -:18192000575F32C530E5C57DCDB930DE003FD2381932C530F1F137D2A3 -:18193800C1E1793C3D1FFAEB17177B175F7A175779174F297817473AE0 -:18195000C5301732C53079B2B3C22519E521973135E1C22519C31207AE -:1819680078B7CA8C197D219731AE80471FA878F28B19C68077CAEB188F -:18198000CD101A772BC9CDAA192FE1B7E1F2CA17C31207CDF61978B7FB -:18199800C8C602DA120747CD641721973134C0C312073A9731B7C83AB1 -:1819B0009631FE2F179FC03CC9CDAA1906881100002197314F700600D3 -:1819C80023368017C3B217CDAA19F02196317EEE8077C9EB2A9431E33A -:1819E000E52A9631E3E5EBC9CDF919EB2294316069229631EBC92194D1 -:1819F800315E2356234E234623C911943106041A77132305C2071AC9B1 -:181A10002196317E07371F773F1F2323777907371F4F1FAEC978B7CAB5 -:181A2800AA1921B319E5CDAA1979C8219631AE79F8CD3F1A1FA9C9235F -:181A400078BEC02B79BEC02B7ABEC02B7B96C0E1E1C9474F575FB7C801 -:181A5800E5CDF619CD101AAE67FC761A3E9890CD29187C17DCFC170621 -:181A700000DC1518E1C91B7AA33CC00BC92197317EFE983A9431D07E59 -:181A8800CD521A36987BF57917CDB217F1C921000078B1C83E1029DA8C -:181AA000D612EB29EBD2AC1A09DAD6123DC29E1AC9FE2DF5CABD1AFEA5 -:181AB8002BCABD1A2BCDCA1747575F2F4FCD5B0BDA0E1BFE2ECAE91AC7 -:181AD000FE45C2ED1ACD5B0BCD0111CD5B0BDA301B14C2ED1AAF935F0A -:181AE8000C0CCAC51AE57B90F4061BF2FC1AF5CDF218F13CC2F01AD182 -:181B0000F1CCD319EBC9C8F5CD9319F13DC9D557788947C5E5D5CD93F0 -:181B180019F1D630CD251BE1C1D1C3C51ACDDB19CDBC19C1D1C3641750 -:181B30007B0707830786D6305FC3DB1AE5219B06CDA114E1EBAF0698A5 -:181B4800CDC11921A014E5219931E5CDAA193620F25D1B362D23363018 -:181B6000CA131CE5FCD319AFF5CD191C01439111F84FCD251AB7E28AA5 -:181B78001BF1CD071BF5C36C1BCDF218F13CF5CD191CCD52173CCD528F -:181B90001ACDEB19010603F1813CFAA61BFE08D2A61B3C473E023D3D09 -:181BA800E1F5112C1C05C2B71B362E2336302305362ECC001AC5E5D57F -:181BC000CDF619E1062F047B965F237A9E5723799E4F2B2BD2C61BCDB6 -:181BD800091823CDEB19EBE17023C10DC2B71B05CAF71B2B7EFE30CA9D -:181BF000EB1BFE2EC4001AF1CA161C364523362BF2071C362D2F3C06F8 -:181C08002F04D60AD2091CC63A237023772371E1C901749411F723CD4E -:181C2000251AB7E1E2811BE900000080A08601102700E8030064000041 -:181C38000A000001000021D319E3E9CDDB1921281CCDE819C1D1CDAAB3 -:181C50001978CA911CF25C1CB7CA0607B7CACB17D5C579F67FCDF619B5 -:181C6800F2791CD5C5CD7D1AC1D1F5CD251AE17C1FE1229631E122946F -:181C800031DC3E1CCCD319D5C5CD5E18C1D1CD9F18CDDB1901388111AE -:181C98003BAACD9F183A9731FE88D28619CD7D1AC680C602DA8619F5F2 -:181CB000214D18CD5517CD9618F1C1D1F5CD6117CDD31921D11CCD0190 -:181CC8001D110000C14AC39F1808402E9474704F2E776E02887AE6A077 -:181CE0002A7C50AAAA7EFFFF7F7F0000808100000081CDDB19119D181F -:181CF800D5E5CDF619CD9F18E1CDDB197E23CDE81906F1C1D13DC8D546 -:181D1000C5F5E5CD9F18E1CDF919E5CD6417E1C30A1DCDAA1921C93036 -:181D2800FA831D21EA30CDE81921C930C886E6070600772387874F09A5 -:181D4000CDF919CD9F183AC8303CE6030600FE018832C83021871D87CE -:181D5800874F09CD5517CDF6197B59EE4F4F36802B46368021C73034F6 -:181D70007ED6ABC27A1D770C151CCDB51721EA30C3021A772B772B77E1 -:181D8800C35E1D68B1466899E9926910D1756821E11DCD5517CDDB19EA -:181DA00001498311DB0FCDEB19C1D1CD0019CDDB19CD7D1AC1D1CD6135 -:181DB8001721E51DCD5B17CDAA1937F2CD1DCD5217CDAA19B7F5F4D3BE -:181DD0001921E51DCD5517F1D4D31921E91DC3F21CDB0F498100000029 -:181DE8007F05BAD71E866426998758342387E05DA586DA0F4983CDDB85 -:181E000019CD9D1DC1E1CDDB19EBCDEB19CD971DC3FE18CDAA19FC3EE7 -:181E18001CFCD3193A9731FE81DA301E0100815159CD0019215B17E57B -:181E3000213A1ECDF21C21E11DC9094AD73B78026E847BFEC12F7C7434 -:181E4800319A7D843D5A7DC87F917EE4BB4C7E6CAAAA7F00000081C95A -:181E6000D7C93E0CC39C1FCD29177B32F230C9CDC80FCD0D0CED53F69D -:181E780030ED53F830C9CD0D0CD5E146237EC38313CDC80FCD0D0CD5B6 -:181E9000CDD1092CCDC80FCD0D0CE3732372E1C9CDCB0FCD0D0CC521D5 -:181EA80099317AFE00280CCDD81E78FE302802702371237BCDD81E7A3A -:181EC000FE00200578FE30280270237123AF772377C1219931C331147C -:181ED80047E60FFE0A3802C607C6304F780F0F0F0FE60FFE0A3802C6B1 -:181EF00007C63047C9EB210000CD0E1FDA2E1F1805CD0E1F381F2929E0 -:181F08002929B56F18F3131AFE20CA0E1FD630D8FE0A3805D607FE0AF6 -:181F2000D8FE103FC9EB7A4BE5CD8213E1C91E26C31707CDCB0FCD0D74 -:181F38000CC521993106110578FE012808CB13CB1230F41804CB13CB6E -:181F5000123E30CE0077230520F3AF772377C1219931C33114EB2100F9 -:181F680000CD821FDA901FD63029B56FCD821F30F6EB7A4BE5CD82138C -:181F8000E1C9131AFE20CA821FFE30D8FE323FC91E28C31707DD21FF87 -:181F9800FFC36703C30800C300003E0032FD30C36E03ED45F5A0C1B866 -:091FB0003E00C9CDDC09C3030E9B +:1802700030D38AC9F5C5E5DB89FE8020FA0603DB89FE8020FA10F8CDAB +:1802880064023E00D3890E040680DB89FEE020FAC50602DB89FEE0203B +:1802A000FA10F8C1DB88C5060A10FEC177230520E10D20DC0600DB8969 +:1802B800FE8020FA10F8E1C1F1C943502F4D20426F6F7420524F4D2041 +:1802D000322E300D0A492D5374727420496E7472700D0A582D426F6F63 +:1802E800742043502F4D0D0A3A6E6E6E6E2D4C6F6164204920726372D5 +:18030000640D0A476E6E6E6E2D52206C6F630D0A000D0A436F6C6420BE +:180318006F72207761726D3F0D0A00436865636B73756D206572726FB4 +:18033000720D0A000C5072657373205B73706163655D20746F20616348 +:1803480074697661746520636F6E736F6C652E0D0A00436F6D706C6558 +:1803600074650D0A00211103CD3701CD4501C8E65FFE43CA7C03FE575C +:18037800CA7F03C9C38203C32004DD210000C38D03330CA91321B030DC +:18039000F9C3C81F115A06066321B0301A77231305C29C03F9CD5B0881 +:1803A800CD290E325A3132A931216F04CDC714CD7808CD810BB7C2D63F +:1803C00003210D32237CB5CAE8037E472F77BE70CAC403C3E803CD4DC7 +:1803D8000CB7C22907EB2B3ED94677BE70C2B1032B110C32CDF109DAAF +:1803F000B10311CEFF225F3119220A31CD36082A0A3111EFFF1911A9F9 +:18040800317D936F7C9A67E5213804CDC714E1CD6A1B212904CDC7149C +:18042000311631CD5B08C3740720427974657320667265650D0A0000DE +:180438005A38302042415349432056657220342E37620D0A436F70794E +:180450007269676874202843292031393738206279204D6963726F7341 +:180468006F66740D0A00004D656D6F727920746F7000DF19A31AF5196D +:18048000B33087130C17B513691C481D8418B71CBD1DC31D241E391E50 +:180498006017A41E013139165114D31648165916C61E591F69169916ED +:1804B000A316C54E44C64F52CE455854C4415441C94E505554C4494DFA +:1804C800D2454144CC4554C74F544FD2554EC946D24553544F5245C773 +:1804E0004F535542D2455455524ED2454DD3544F50CF5554CF4ECE5589 +:1804F8004C4CD7414954C44546D04F4B45C44F4B45D3435245454ECCF2 +:18051000494E4553C34C53D749445448CD4F4E49544F52D34554D24517 +:18052800534554D052494E54C34F4E54CC495354C34C454152C34C4F0D +:180540004144C353415645CE4557D4414228D44FC64ED3504328D44862 +:18055800454ECE4F54D3544550ABADAAAFDEC14E44CF52BEBDBCD34777 +:180570004EC94E54C14253D55352C65245C94E50D04F53D35152D24E1E +:1805880044CC4F47C55850C34F53D3494ED4414EC1544ED045454BC44A +:1805A00045454BD04F494E54CC454ED3545224D6414CC15343C3485251 +:1805B80024C8455824C2494E24CC45465424D24947485424CD49442492 +:1805D00080CB0BC80AA30F180DAA0EDF11D90E2F0DD50CB80CA70D915F +:1805E8000BC40CF30C1A0DC90B1817890D0A0C1E17BD136717AF1E1AE1 +:180600000D951E881E8D1EC51F04310731CB0DF70B3D0A720C1A0D1AA0 +:180618000D350879511B7985177CC3187C24197F721C50381146371142 +:180630004E46534E52474F4446434F564F4D554C425344442F304944DD +:18064800544D4F534C535354434E55464D4F4858424EC32004C3480C1B +:18066000D300C9D6006F7CDE006778DE00473E00C9000000354ACA995A +:18067800391C76982295B3980ADD479853D199990A1A9F9865BCCD9808 +:18069000D6773E9852C74F80DB00C901FF1C000014001400000000005F +:1806A800C36E09C30000C30000C300000D32FEFFAA31204572726F7276 +:1806C0000020696E20004F6B0D0A0000427265616B00210400397E2356 +:1806D800FE81C04E234623E569607AB3EBCAEC06EBCDF109010D00E1CE +:1806F000C809C3D606CD0F07C5E3C1CDF1097E02C80B2BC3FB06E52A1E +:180708008A31060009093EE53ED0956F3EFF9CDA1E076739E1D81E0C76 +:18072000C33D072A7931220C311E02011E14011E00011E12011E2201A2 +:180738001E0A011E18CD5B0832F530CD1C0E213006573E3FCD020A19AF +:180750007ECD020ACD810BCD020A21BA06CDC7142A0C3111FEFFCDF14C +:1807680009CA8D037CA53CC4621B3EC1AF32F530CD1C0E21C606CDC7FB +:180780001421FFFF220C31CD6E09DA8107CD810B3C3DCA8107F5CD4DF6 +:180798000CD5CD850847D1F1D2610BD5C5AF327C31CD810BB7F5CD15B8 +:1807B00008DABA07F1F5CAEE0CB7C5D2D107EB2A86311A020313CDF102 +:1807C80009C2C2076069228631D1F1CAF8072A8631E3C109E5CDF5061D +:1807E000E1228631EB74D12323732372231111311A772313B7C2F0071C +:1807F800CD410823EB626B7E23B6CA8107232323AFBE23C20908EB7325 +:180810002372C3FD072A0E31444D7E23B62BC823237E23666FCDF109AD +:1808280060697E23666F3FC83FD0C31808C02A0E31AF772377232286CC +:18084000312A0E312B227E312A5F31227331AFCD910B2A8631228831B6 +:18085800228A31C12A0A31F9216331226131AF6F67228431327B3122C7 +:180870008E31E5C52A7E31C93E3FCD020A3E20CD020AC3FE30AF325EA8 +:18088800310E051111317EFE20CA0D0947FE22CA2D09B7CA34093A5E88 +:1808A00031B77EC20D09FE3F3E9ECA0D097EFE30DAB808FE3CDA0D0999 +:1808B800D511B104C5010909C5067F7EFE61DAD108FE7BD2D108E65F72 +:1808D000774EEB23B6F2D308047EE67FC8B9C2D308EBE5131AB7FA0502 +:1808E800094F78FE88C2F408CD810B2B237EFE61DAFD08E65FB9CAE3D6 +:1809000008E1C3D10848F1EBC9EB79C1D12312130CD63ACA1B09FE49DE +:18091800C21E09325E31D654C28E08477EB7CA3409B8CA0D0923120C3F +:1809300013C324092110311213121312C93AF430B73E0032F430C25169 +:180948000905CA6E09CD020A3E052BCA65097ECD020AC37709052BCD32 +:18096000020AC27709CD020ACD290EC36E092111310601AF32F430CDDE +:180978002C0A4FFE7FCA3D093AF430B7CA90093E00CD020AAF32F430C1 +:1809900079FE07CAD409FE03CC290E37C8FE0DCA240EFE15CA6809FED4 +:1809A80040CA6509FE5FCA5D09FE08CA5D09FE12C2CF09C5D5E536009D +:1809C000CDD91F211131CDC714E1D1C1C37709FE20DA770978FE493E24 +:1809D80007D2E9097971327C312304CD020AC37709CD020A3E08C3E36B +:1809F000097C92C07D93C97EE3BE23E3CA810BC32907F53AF530B7C204 +:180A0800FC14F1C5F5FE20DA260A3AF230473A5B3104CA220A05B8CC07 +:180A2000290E3C325B31F1C1CDC21FC9CD861EE67FFE0FC03AF5302F33 +:180A380032F530AFC9CD4D0CC0C1CD1508C5CD930AE14E23462378B133 +:180A5000CA7407CD9C0ACDAC0BC5CD290E5E235623E5EBCD6A1B3E200F +:180A6800E1CD020A7EB723CA490AF2690AD67F4F11B2041A13B7F27B26 +:180A80000A0DC27B0AE67FCD020A1A13B7F2850AC36C0AE52AF83022CB +:180A9800F630E1C9E5D52AF63011FFFFED5A22F630D1E1F0E52AF830F5 +:180AB00022F630CD861EFE03CABF0AE1C39C0A2AF83022F630C3230413 +:180AC8003E64327B31CD2F0DC1E5CD180D22773121020039CDD606D155 +:180AE000C2F80A09D52B562B5E2323E52A7731CDF109E1C2DC0AD1F93B +:180AF800EB0E08CD0607E52A7731E3E52A0C31E3CDF10FCDF709A6CD35 +:180B1000EE0FE5CD1C1AE1C5D5010081515A7EFEAB3E01C2340BCD818B +:180B28000BCDEE0FE5CD1C1ACDD019E1C5D5F533E52A7E31E30681C5B2 +:180B400033CDAC0B227E317EFE3ACA610BB7C22907237E23B6CAD30B5E +:180B5800235E2356EB220C31EBCD810B11410BD5C8D680DA2F0DFE2574 +:180B7000D22907074F0600EB21D105094E2346C5EB237EFE3AD0FE20F6 +:180B8800CA810BFE303F3C3DC9EB2A0E31CAA60BEBCD4D0CE5CD1508A1 +:180BA0006069D1D2EE0C2B228C31EBC9DFC8D7FE1B2811FE03280DFE15 +:180BB80013C0D7FE11C8FE03280718F63EFF32FD30C0F6C0227E312162 +:180BD000F6FFC12A0C31F57DA43CCAE60B2282312A7E31228431AF327D +:180BE800F530CD1C0EF121CC06C25D07C374072A84317CB51E20CA3D3C +:180C000007EB2A8231220C31EBC9CD4F17C032F130C9E52AFA300600AC +:180C18004F0922FA30E1C97EFE41D8FE5B3FC9CD810BCDEE0FCDD019A7 +:180C3000FA480C3A9731FE90DA781A018090110000E5CD4B1AE151C82F +:180C48001E08C33D072B110000CD810BD0E5F5219819CDF109DA290785 +:180C6000626B19291929F1D6305F160019EBE1C3510CCA4508CD2A0CA0 +:180C78002BCD810BE52A5F31CA950CE1CDF7092CD5CD2A0C2BCD810BA0 +:180C9000C22907E3EB7D935F7C9A57DA1E07E52A863101280009CDF1FB +:180CA80009D21E07EB220A31E1225F31E1C34508CA4108CD45080141F9 +:180CC0000BC3D40C0E03CD0607C1E5E52A0C31E33E8CF533C5CD4D0CD1 +:180CD800CD1A0DE52A0C31CDF109E123DC1808D4150860692BD81E0E14 +:180CF000C33D07C016FFCDD206F9FE8C1E04C23D07E1220C31237CB52C +:180D0800C2120D3A7C31B7C2730721410BE33EE1013A0E000600794899 +:180D2000477EB7C8B8C823FE22CA1E0DC3210DCDE411CDF709B4D53A7C +:180D38005D31F5CD0010F1E3227E311FCDF30FCA820DE52A9431E5237B +:180D5000235E23562A0E31CDF109D2710D2A0A31CDF109D1D2790D219B +:180D68006F31CDF109D2790D3ED1CD2816EBCD6114CD2816E1CD2B1A6F +:180D8000E1C9E5CD281AD1E1C9CD4F177E47FE8CCA980DCDF709882BD1 +:180D98004B0D78CA690BCD4E0CFE2CC0C3990DCD00107EFE88CAB50D4E +:180DB000CDF709A92BCDF10FCDD019CA1A0DCD810BDAD50CC3680B2BA1 +:180DC800CD810BCA290EC8FEA5CA5C0EFEA8CA5C0EE5FE2CCA450EFE16 +:180DE0003BCA7F0EC1CD0010E53A5D31B7C2150ECD751BCD8514362069 +:180DF8002A9431342A94313AF2304704CA110E043A5B31863DB8D429FF +:180E10000ECDCA14AFC4CA14E1C3C70D3A5B31B7C8C3290E36002110A2 +:180E2800313E0DCD020A3E0ACD020AAF325B313AF1303DC8F5AFCD02FC +:180E40000AF1C33A0E3AF330473A5B31B8D4290ED27F0ED60ED2530EF1 +:180E58002FC3740EF5CD4C17CDF709292BF1D6A8E5CA6F0E3A5B312F38 +:180E700083D27F0E3C473E20CD020A05C2780EE1CD810BC3CE0D3F5218 +:180E880065646F2066726F6D2073746172740D0A003A7D31B7C2230756 +:180EA000C121860ECDC714C37408CD32147EFE223E0032F530C2C40E03 +:180EB800CD8614CDF7093BE5CDCA143EE5CD7808C1DAD00B237EB72BBA +:180ED000C5CA170D362CC3DE0EE52A8C31F6AF327D31E3C3EA0ECDF793 +:180EE800092CCDE411E3D57EFE2CCA120F3A7D31B7C27F0F3E3FCD0275 +:180F00000ACD7808D1C1DAD00B237EB72BC5CA170DD53A5D31B7CA3CAB +:180F18000FCD810B5747FE22CA300F3A7D31B757CA2D0F163A062C2BE9 +:180F3000CD8914EB21470FE3D5C34A0DCD810BCDD71AE3CD281AE12BF6 +:180F4800CD810BCA530FFE2CC2990EE32BCD810BC2E60ED13A7D31B7EC +:180F6000EBC2A70BD5B6216E0FC4C714E1C93F45787472612069676E07 +:180F78006F7265640D0A00CD180DB7C2980F237E23B61E06CA3D0723BF +:180F90005E2356EB227931EBCD810BFE83C27F0FC3120F110000C4E409 +:180FA80011227E31CDD206C22F07F9D57E23F5D5CD0E1AE3E5CD7B175D +:180FC000E1CD281AE1CD1F1AE5CD4B1AE1C190CD1F1ACADE0FEB220C23 +:180FD800316960C33D0BF92A7E317EFE2CC2410BCD810BCDA60FCD00CC +:180FF00010F6373A5D318FB7E8C33B07CDF709282B1600D50E01CD06C4 +:1810080007CD77102280312A8031C178FE78D4F10F7E1600D6B3DA3815 +:1810200010FE03D23810FE0117AABA57DA2907227531CD810BC31C10A2 +:181038007AB7C25F117E227531D6ACD8FE07D05F3A5D313DB37BCABDAF +:181050001507835F211B06197856BAD023CDF10FC5010F10C5434ACDE3 +:18106800011A58514E234623C52A7531C30310AF325D31CD810B1E245D +:18108000CA3D07DAD71ACD1F0CD2DE10FE262012CD810BFE48CA1B1FCE +:18109800FE42CA8B1F1E02CA3D07FEACCA7710FE2ECAD71AFEADCACD3A +:1810B00010FE22CA8614FEAACABF11FEA7CAEA13D6B6D2EF10CDFC0FB1 +:1810C800CDF70929C9167DCD03102A8031E5CDF919CDF10FE1C9CDE417 +:1810E00011E5EB2294313A5D31B7CC0E1AE1C90600074FC5CD810B7920 +:1810F800FE31DA1611CDFC0FCDF7092CCDF20FEB2A9431E3E5EBCD4F68 +:1811100017EBE3C31E11CDC510E311D910D5017A04094E236669E915D6 +:18112800FEADC8FE2DC814FE2BC8FEACC82BC9F6AFF5CDF10FCD330C6B +:18114000F1EBC1E3EBCD111AF5CD330CF1C17921A813C25A11A34F7895 +:18115800A2E9B34F78B2E92171113A5D311F7A175F166478BAD0C360C6 +:1811700010731179B71FC1D1F5CDF30F21B511E5CA4B1AAF325D31D5EF +:18118800CD0A167E23234E2346D1C5F5CD0E16CD1F1AF157E17BB2C847 +:1811A0007AD601D8AFBB3CD0151D0ABE2303CA9D113FC3DB193C8FC17E +:1811B800A0C6FF9FC3E219165ACD0310CDF10FCD330C7B2F4F7A2FCDC5 +:1811D000A813C1C30F102BCD810BC8CDF7092C01D611C5F6AF325C3153 +:1811E80046CD1F0CDA2907AF4F325D31CD810BDA0012CD1F0CDA0D12B3 +:181200004FCD810BDA0112CD1F0CD20112D624C21C123C325D310F81EE +:181218004FCD810B3A7B313DCAC912F22C127ED628CAA112AF327B3198 +:18123000E550592A8E31CDF109119031CA11192A8831EB2A8631CDF135 +:1812480009CA5F12799623C25412789623CA931223232323C34612E1C8 +:18126000E3D511E110CDF109D1CA9612E3E5C50106002A8A31E509C18A +:18127800E5CDF506E1228A3160692288312B3600CDF109C28512D1738A +:18129000237223EBE1C932973121C506229431E1C9E52A5C31E357D5D7 +:1812A800C5CD270CC1F1EBE3E5EB3C577EFE2CCAA712CDF709292280C3 +:1812C00031E1225C311E00D511E5F52A88313E19EB2A8A31EBCDF109BB +:1812D800CA01137EB923C2E3127EB8235E235623C2CF123A5C31B7C2D9 +:1812F0003207F1444DCA111996CA5F131E10C33D07110400F1CA480C0C +:18130800712370234FCD0607232322753171233A5C311779010B00D2A6 +:181320002413C10371237023F5E5CDBC1AEBE1F13DC21C13F5424BEBBE +:1813380019DA1E07CD0F07228A312B3600CDF109C2421303572A75315C +:181350005EEB2909EB2B2B73237223F1DA8313474F7E2316E15E235638 +:1813680023E3F5CDF109D2FC12E5CDBC1AD119F13D444DC2641329290F +:18138000C109EB2A8031C92A8A31EB210000393A5D31B7CAA313CD0AFC +:1813980016CD0A152A0A31EB2A73317D934F7C9A41501E00215D3173D7 +:1813B0000690C3E7193A5B3147AFC3A913CD4014CD321401180DC5D59D +:1813C800CDF70928CDE411E5EB2B562B5EE1CDF10FCDF70929CDF7090B +:1813E000B4444DE3712370C37F14CD4014D5CDC510CDF10FE35E235654 +:1813F800237AB3CA35077E23666FE52A8E31E3228E312A9231E52A90F3 +:1814100031E5219031D5CD281AE1CDEE0F2BCD810BC22907E122903103 +:18142800E1229231E1228E31E1C9E52A0C31237CB5E1C01E16C33D07FE +:18144000CDF709A73E80327B31B647CDE911C3F10FCDF10FCD751BCD06 +:181458008514CD0A16016516C57E2323E5CDE014E14E2346CD7914E574 +:181470006FCDFD15D1C9CDE014216F31E5772323732372E1C92B062253 +:1814880050E50EFF237E0CB7CA9B14BACA9B14B8C28C14FE22CC810B68 +:1814A000E323EB79CD7914116F312A61312294313E01325D31CD2B1A0B +:1814B800CDF109226131E17EC01E1EC33D0723CD8514CD0A16CD1F1AC3 +:1814D0001C1DC80ACD020AFE0DCC330E03C3D114B70EF1F52A0A31EB62 +:1814E8002A73312F4F06FF0923CDF109DAFE1422733123EBF1C9F11E1F +:181500001ACA3D07BFF501E214C52A5F31227331210000E52A0A31E56B +:18151800216331EB2A6131EBCDF109011B15C26F152A8631EB2A883187 +:18153000EBCDF109CA42157E2323B7CD7215C32C15C1EB2A8A31EBCDB4 +:18154800F109CA9815CD1F1A7BE509B7F24115227531E14E060009099D +:1815600023EB2A7531EBCDF109CA4215016115C5F6807E23235E235675 +:1815780023F0B7C8444D2A7331CDF1096069D8E1E3CDF109E3E56069E6 +:18159000D0C1F1F1E5D5C5C9D1E17DB4C82B462B4EE52B2B6E2600091B +:1815A80050592B444D2A7331CDF806E171237069602BC30D15C5E52A9B +:1815C0009431E3CD7710E3CDF20F7EE52A9431E5861E1CDA3D07CD760E +:1815D80014D1CD0E16E3CD0D16E52A7131EBCDF415CDF415210C10E3EA +:1815F000E5C3A714E1E37E23234E23466F2C2DC80A120313C3FE15CDDC +:18160800F20F2A9431EBCD2816EBC0D550591B4E2A7331CDF109C226D5 +:18162000164709227331E1C92A61312B462B4E2B2BCDF109C0226131A5 +:18163800C901B813C5CD0716AF57325D317EB7C901B813C5CD3D16CA17 +:18165000480C23235E23561AC93E01CD7614CD52172A713173C1C3A7F8 +:1816680014CD0217AFE34FE57EB8DA771678110E00C5CDE014C1E1E569 +:18168000232346236668060009444DCD79146FCDFD15D1CD0E16C3A761 +:1816980014CD0217D1D51A90C36D16EB7ECD07170405CA480CC51EFF4D +:1816B000FE29CABC16CDF7092CCD4F17CDF70929F1E3016F16C53DBE23 +:1816C8000600D04F7E91BB47D843C9CD3D16CAF0175F23237E23666FE4 +:1816E000E5194672E3C57EFE24C2F116CD1B1F180DFE25C2FB16CD8BB1 +:1816F8001F1803CDD71AC1E170C9EBCDF70929C1D1C543C9CD5217325B +:18171000EF30CDEE30C3B813CD3C17C3B630CD3C17F51E002BCD810BA9 +:18172800CA3217CDF7092CCD4F17C1CDEE30ABA0CA3317C9CD4F173231 +:18174000EF3032B730CDF7092CC34F17CD810BCDEE0FCD2D0C7AB7C21B +:18175800480C2BCD810B7BC9CD330C1AC3B813CDEE0FCD330CD5CDF73A +:18177000092CCD4F17D112C9214E1CCD1F1AC38A17CD1F1A21C1D1CDD2 +:18178800F91978B7C83A9731B7CA111A90D2A4172F3CEBCD011AEBCD7F +:1817A000111AC1D1FE19D0F5CD361A67F1CD4F18B4219431F2CA17CDB5 +:1817B8002F18D210182334CA38072E01CD6518C31018AF90477E9B5F16 +:1817D000237E9A57237E994FDC3B186863AF4779B7C2FD174A54656F7E +:1817E80078D608FEE0C2DE17AF329731C905297A1757798F4FF2F51721 +:18180000785C45B7CA10182197318677D2F017C878219731B7FC221839 +:1818180046237EE680A94FC3111A1CC014C00CC00E8034C0C338077E07 +:18183000835F237E8A57237E894FC92198317E2F77AF6F90477D9B5F80 +:181848007D9A577D994FC90600D608DA5E18435A510E00C35118C609C1 +:181860006FAF2DC8791F4F7A1F577B1F5F781F47C361180000008103EF +:18187800AA561980F122768045AA3882CDD019B7EA480C2197317E01FA +:18189000358011F30490F570D5C5CD8A17C1D104CD2619217318CD81EA +:1818A80017217718CD181D018080110000CD8A17F1CD4B1B01318011F8 +:1818C000187221C1D1CDD019C82E00CD8E197932A631EB22A73101004B +:1818D80000505821DB17E521E718E5E52194317E23B7CA1319E52E081F +:1818F0001F6779D20119E52AA73119EBE13AA631891F4F7A1F577B1F97 +:181908005F781F472D7CC2F018E1C9435A514FC9CD011A0120841100C9 +:1819200000CD111AC1D1CDD019CA2C072EFFCD8E1934342B7E32C2309C +:181938002B7E32BE302B7E32BA3041EBAF4F575F32C530E5C57DCDB955 +:1819500030DE003FD25E1932C530F1F137D2C1E1793C3D1FFA111817EA +:181968007B175F7A175779174F297817473AC5301732C53079B2B3C2A3 +:181980004B19E521973135E1C24B19C3380778B7CAB2197D219731AE07 +:1819980080471FA878F2B119C68077CA1119CD361A772BC9CDD0192F57 +:1819B000E1B7E1F2F017C33807CD1C1A78B7C8C602DA380747CD8A171B +:1819C80021973134C0C338073A9731B7C83A9631FE2F179FC03CC9CD31 +:1819E000D01906881100002197314F70060023368017C3D817CDD01961 +:1819F800F02196317EEE8077C9EB2A9431E3E52A9631E3E5EBC9CD1FD8 +:181A10001AEB2294316069229631EBC92194315E2356234E234623C9E9 +:181A280011943106041A77132305C22D1AC92196317E07371F773F1F90 +:181A40002323777907371F4F1FAEC978B7CAD01921D919E5CDD019790D +:181A5800C8219631AE79F8CD651A1FA9C92378BEC02B79BEC02B7ABE2C +:181A7000C02B7B96C0E1E1C9474F575FB7C8E5CD1C1ACD361AAE67FC36 +:181A88009C1A3E9890CD4F187C17DC22180600DC3B18E1C91B7AA33CFA +:181AA000C00BC92197317EFE983A9431D07ECD781A36987BF57917CD56 +:181AB800D817F1C921000078B1C83E1029DAFC12EB29EBD2D21A09DA5C +:181AD000FC123DC2C41AC9FE2DF5CAE31AFE2BCAE31A2BCDF0174757D6 +:181AE8005F2F4FCD810BDA341BFE2ECA0F1BFE45C2131BCD810BCD27E7 +:181B000011CD810BDA561B14C2131BAF935F0C0CCAEB1AE57B90F42C7C +:181B18001BF2221BF5CD1819F13CC2161BD1F1CCF919EBC9C8F5CDB9C1 +:181B300019F13DC9D557788947C5E5D5CDB919F1D630CD4B1BE1C1D15E +:181B4800C3EB1ACD011ACDE219C1D1C38A177B0707830786D6305FC356 +:181B6000011BE521C106CDC714E1EBAF0698CDE71921C614E52199312B +:181B7800E5CDD0193620F2831B362D233630CA391CE5FCF919AFF5CD65 +:181B90003F1C01439111F84FCD4B1AB7E2B01BF1CD2D1BF5C3921BCDE7 +:181BA8001819F13CF5CD3F1CCD78173CCD781ACD111A010603F1813C03 +:181BC000FACC1BFE08D2CC1B3C473E023D3DE1F511521C05C2DD1B36E6 +:181BD8002E2336302305362ECC261AC5E5D5CD1C1AE1062F047B965F9A +:181BF000237A9E5723799E4F2B2BD2EC1BCD2F1823CD111AEBE1702305 +:181C0800C10DC2DD1B05CA1D1C2B7EFE30CA111CFE2EC4261AF1CA3C3F +:181C20001C364523362BF22D1C362D2F3C062F04D60AD22F1CC63A232F +:181C38007023772371E1C901749411F723CD4B1AB7E1E2A71BE90000C1 +:181C50000080A08601102700E803006400000A000001000021F919E32E +:181C6800E9CD011A214E1CCD0E1AC1D1CDD01978CAB71CF2821CB7CAA5 +:181C80002C07B7CAF117D5C579F67FCD1C1AF29F1CD5C5CDA31AC1D1A2 +:181C9800F5CD4B1AE17C1FE1229631E1229431DC641CCCF919D5C5CD5E +:181CB0008418C1D1CDC518CD011A013881113BAACDC5183A9731FE887A +:181CC800D2AC19CDA31AC680C602DAAC19F5217318CD7B17CDBC18F1A4 +:181CE000C1D1F5CD8717CDF91921F71CCD271D110000C14AC3C5180812 +:181CF800402E9474704F2E776E02887AE6A02A7C50AAAA7EFFFF7F7F3E +:181D10000000808100000081CD011A11C318D5E5CD1C1ACDC518E1CD50 +:181D2800011A7E23CD0E1A06F1C1D13DC8D5C5F5E5CDC518E1CD1F1A5F +:181D4000E5CD8A17E1C3301DCDD01921C930FAA91D21EA30CD0E1A2166 +:181D5800C930C886E6070600772387874F09CD1F1ACDC5183AC8303C1B +:181D7000E6030600FE018832C83021AD1D87874F09CD7B17CD1C1A7B8D +:181D880059EE4F4F36802B46368021C730347ED6ABC2A01D770C151C03 +:181DA000CDDB1721EA30C3281A772B772B77C3841D68B1466899E99232 +:181DB8006910D1756821071ECD7B17CD011A01498311DB0FCD111AC1DE +:181DD000D1CD2619CD011ACDA31AC1D1CD8717210B1ECD8117CDD0194A +:181DE80037F2F31DCD7817CDD019B7F5F4F919210B1ECD7B17F1D4F97F +:181E000019210F1EC3181DDB0F49810000007F05BAD71E866426998754 +:181E180058342387E05DA586DA0F4983CD011ACDC31DC1E1CD011AEB55 +:181E3000CD111ACDBD1DC32419CDD019FC641CFCF9193A9731FE81DA60 +:181E4800561E0100815159CD2619218117E521601ECD181D21071EC988 +:181E6000094AD73B78026E847BFEC12F7C74319A7D843D5A7DC87F9188 +:181E78007EE4BB4C7E6CAAAA7F00000081C9D7C93E0CC3C21FCD4F1721 +:181E90007B32F230C9CDEE0FCD330CED53F630ED53F830C9CD330CD554 +:181EA800E146237EC3A913CDEE0FCD330CD5CDF7092CCDEE0FCD330C61 +:181EC000E3732372E1C9CDF10FCD330CC52199317AFE00280CCDFE1E57 +:181ED80078FE302802702371237BCDFE1E7AFE00200578FE30280270BA +:181EF000237123AF772377C1219931C3571447E60FFE0A3802C607C678 +:181F0800304F780F0F0F0FE60FFE0A3802C607C63047C9EB210000CDAB +:181F2000341FDA541F1805CD341F381F29292929B56F18F3131AFE2057 +:181F3800CA341FD630D8FE0A3805D607FE0AD8FE103FC9EB7A4BE5CD1C +:181F5000A813E1C91E26C33D07CDF10FCD330CC521993106110578FEAE +:181F6800012808CB13CB1230F41804CB13CB123E30CE0077230520F38C +:181F8000AF772377C1219931C35714EB210000CDA81FDAB61FD6302931 +:181F9800B56FCDA81F30F6EB7A4BE5CDA813E1C9131AFE20CAA81FFEB2 +:181FB00030D8FE323FC91E28C33D07DD21FFFFC38D03C30800C30000AF +:171FC8003E0032FD30C39403ED45F5A0C1B83E00C9CD020AC3290EF1 :00000001FF diff --git a/Z80 CPM and bootloader (basmon)/source/BASMON.LST b/Z80 CPM and bootloader (basmon)/source/BASMON.LST index 75b4060..e9d219c 100644 --- a/Z80 CPM and bootloader (basmon)/source/BASMON.LST +++ b/Z80 CPM and bootloader (basmon)/source/BASMON.LST @@ -1,5015 +1,5095 @@ -0001 0000 ;================================================================================== -0002 0000 ; The updates to the original BASIC within this file are copyright Grant Searle -0003 0000 ; -0004 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY -0005 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. -0006 0000 ; -0007 0000 ; http://searle.hostei.com/grant/index.html -0008 0000 ; -0009 0000 ; eMail: home.micros01@btinternet.com -0010 0000 ; -0011 0000 ; If the above don't work, please perform an Internet search to see if I have -0012 0000 ; updated the web page hosting service. -0013 0000 ; -0014 0000 ;================================================================================== -0015 0000 -0016 0000 -0017 0000 ;================================================================================== -0018 0000 ; Contents of this file are copyright Grant Searle -0019 0000 ; HEX routines from Joel Owens. -0020 0000 ; -0021 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY -0022 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. -0023 0000 ; -0024 0000 ; http://searle.hostei.com/grant/index.html -0025 0000 ; -0026 0000 ; eMail: home.micros01@btinternet.com -0027 0000 ; -0028 0000 ; If the above don't work, please perform an Internet search to see if I have -0029 0000 ; updated the web page hosting service. -0030 0000 ; -0031 0000 ;================================================================================== -0032 0000 -0033 0000 ;------------------------------------------------------------------------------ -0034 0000 ; -0035 0000 ; Z80 Monitor Rom -0036 0000 ; -0037 0000 ;------------------------------------------------------------------------------ -0038 0000 ; General Equates -0039 0000 ;------------------------------------------------------------------------------ -0040 0000 -0041 0000 ;CR .EQU 0DH -0042 0000 ;LF .EQU 0AH -0043 0000 ;ESC .EQU 1BH -0044 0000 ;CTRLC .EQU 03H -0045 0000 M_CLS .EQU 0CH -0046 0000 -0047 0000 -0048 0000 loadAddr .EQU 0D000h ; CP/M load address -0049 0000 numSecs .EQU 24 ; Number of 512 sectors to be loaded -0050 0000 -0051 0000 -0052 0000 RTS_HIGH .EQU 0D5H -0053 0000 RTS_LOW .EQU 095H -0054 0000 -0055 0000 ACIA0_D .EQU $81 -0056 0000 ACIA0_C .EQU $80 -0057 0000 ACIA1_D .EQU $83 -0058 0000 ACIA1_C .EQU $82 -0059 0000 -0060 0000 SD_DATA .EQU 088H -0061 0000 SD_CONTROL .EQU 089H -0062 0000 SD_STATUS .EQU 089H -0063 0000 SD_LBA0 .EQU 08AH -0064 0000 SD_LBA1 .EQU 08BH -0065 0000 SD_LBA2 .EQU 08CH -0066 0000 -0067 3000 .ORG $3000 -0068 3000 -0069 3000 primaryIO .ds 1 -0070 3001 secNo .ds 1 -0071 3002 dmaAddr .ds 2 -0072 3004 -0073 3004 00 lba0 .DB 00h -0074 3005 00 lba1 .DB 00h -0075 3006 00 lba2 .DB 00h -0076 3007 00 lba3 .DB 00h -0077 3008 -0078 3008 stackSpace .ds 32 -0079 3028 M_STACK .EQU $ ; Stack top -0080 3028 -0081 3028 -0082 3028 ;------------------------------------------------------------------------------ -0083 3028 ; START OF MONITOR ROM -0084 3028 ;------------------------------------------------------------------------------ -0085 3028 -0086 0000 MON .ORG $0000 ; MONITOR ROM RESET VECTOR -0087 0000 ;------------------------------------------------------------------------------ -0088 0000 ; Reset -0089 0000 ;------------------------------------------------------------------------------ -0090 0000 F3 RST00 DI ;Disable INTerrupts -0091 0001 C3 94 00 JP M_INIT ;Initialize Hardware and go -0092 0004 00 NOP -0093 0005 00 NOP -0094 0006 00 NOP -0095 0007 00 NOP -0096 0008 ;------------------------------------------------------------------------------ -0097 0008 ; TX a character over RS232 wait for TXDONE first. -0098 0008 ;------------------------------------------------------------------------------ -0099 0008 C3 32 00 RST08 JP conout -0100 000B 00 NOP -0101 000C 00 NOP -0102 000D 00 NOP -0103 000E 00 NOP -0104 000F 00 NOP -0105 0010 ;------------------------------------------------------------------------------ -0106 0010 ; RX a character from buffer wait until char ready. -0107 0010 ;------------------------------------------------------------------------------ -0108 0010 C3 1B 00 RST10 JP conin -0109 0013 00 NOP -0110 0014 00 NOP -0111 0015 00 NOP -0112 0016 00 NOP -0113 0017 00 NOP -0114 0018 ;------------------------------------------------------------------------------ -0115 0018 ; Check input buffer status -0116 0018 ;------------------------------------------------------------------------------ -0117 0018 C3 5C 00 RST18 JP CKINCHAR -0118 001B -0119 001B -0120 001B ;------------------------------------------------------------------------------ -0121 001B ; Console input routine -0122 001B ; Use the "primaryIO" flag to determine which input port to monitor. -0123 001B ;------------------------------------------------------------------------------ -0124 001B conin: -0125 001B 3A 00 30 LD A,(primaryIO) -0126 001E FE 00 CP 0 -0127 0020 20 08 JR NZ,coninB -0128 0022 coninA: -0129 0022 -0130 0022 waitForCharA: -0131 0022 CD 63 00 call ckincharA -0132 0025 28 FB JR Z, waitForCharA -0133 0027 DB 81 IN A,(ACIA0_D) -0134 0029 C9 RET ; Char ready in A -0135 002A -0136 002A coninB: -0137 002A -0138 002A waitForCharB: -0139 002A CD 6A 00 call ckincharB -0140 002D 28 FB JR Z, waitForCharB -0141 002F DB 83 IN A,(ACIA1_D) -0142 0031 C9 RET ; Char ready in A -0143 0032 -0144 0032 ;------------------------------------------------------------------------------ -0145 0032 ; Console output routine -0146 0032 ; Use the "primaryIO" flag to determine which output port to send a character. -0147 0032 ;------------------------------------------------------------------------------ -0148 0032 F5 conout: PUSH AF ; Store character -0149 0033 3A 00 30 LD A,(primaryIO) -0150 0036 FE 00 CP 0 -0151 0038 20 0D JR NZ,conoutB1 -0152 003A 18 01 JR conoutA1 -0153 003C conoutA: -0154 003C F5 PUSH AF -0155 003D -0156 003D CD 50 00 conoutA1: CALL CKACIA0 ; See if ACIA channel A is finished transmitting -0157 0040 28 FB JR Z,conoutA1 ; Loop until ACIA flag signals ready -0158 0042 F1 POP AF ; RETrieve character -0159 0043 D3 81 OUT (ACIA0_D),A ; OUTput the character -0160 0045 C9 RET -0161 0046 -0162 0046 conoutB: -0163 0046 F5 PUSH AF -0164 0047 -0165 0047 CD 56 00 conoutB1: CALL CKACIA1 ; See if ACIA channel B is finished transmitting -0166 004A 28 FB JR Z,conoutB1 ; Loop until ACIA flag signals ready -0167 004C F1 POP AF ; RETrieve character -0168 004D D3 83 OUT (ACIA1_D),A ; OUTput the character -0169 004F C9 RET -0170 0050 -0171 0050 ;------------------------------------------------------------------------------ -0172 0050 ; I/O status check routine -0173 0050 ; Use the "primaryIO" flag to determine which port to check. -0174 0050 ;------------------------------------------------------------------------------ -0175 0050 CKACIA0 -0176 0050 DB 80 IN A,(ACIA0_C) ; Status byte D1=TX Buff Empty, D0=RX char ready -0177 0052 0F RRCA ; Rotates RX status into Carry Flag, -0178 0053 CB 47 BIT 0,A ; Set Zero flag if still transmitting character -0179 0055 C9 RET -0180 0056 -0181 0056 CKACIA1 -0182 0056 DB 82 IN A,(ACIA1_C) ; Status byte D1=TX Buff Empty, D0=RX char ready -0183 0058 0F RRCA ; Rotates RX status into Carry Flag, -0184 0059 CB 47 BIT 0,A ; Set Zero flag if still transmitting character -0185 005B C9 RET -0186 005C -0187 005C ;------------------------------------------------------------------------------ -0188 005C ; Check if there is a character in the input buffer -0189 005C ; Use the "primaryIO" flag to determine which port to check. -0190 005C ;------------------------------------------------------------------------------ -0191 005C CKINCHAR -0192 005C 3A 00 30 LD A,(primaryIO) -0193 005F FE 00 CP 0 -0194 0061 20 07 JR NZ,ckincharB -0195 0063 -0196 0063 ckincharA: -0197 0063 -0198 0063 DB 80 IN A,(ACIA0_C) ; Status byte -0199 0065 E6 01 AND $01 -0200 0067 FE 00 CP $0 ; Z flag set if no char -0201 0069 C9 RET -0202 006A -0203 006A ckincharB: -0204 006A -0205 006A DB 82 IN A,(ACIA1_C) ; Status byte -0206 006C E6 01 AND $01 -0207 006E FE 00 CP $0 ; Z flag set if no char -0208 0070 C9 RET -0209 0071 -0210 0071 ;------------------------------------------------------------------------------ -0211 0071 ; Filtered Character I/O -0212 0071 ;------------------------------------------------------------------------------ -0213 0071 -0214 0071 D7 RDCHR RST 10H -0215 0072 FE 0A CP LF -0216 0074 28 FB JR Z,RDCHR ; Ignore LF -0217 0076 FE 1B CP ESC -0218 0078 20 02 JR NZ,RDCHR1 -0219 007A 3E 03 LD A,CTRLC ; Change ESC to CTRL-C -0220 007C C9 RDCHR1 RET -0221 007D -0222 007D FE 0D WRCHR CP CR -0223 007F 28 0A JR Z,WRCRLF ; When CR, write CRLF -0224 0081 FE 0C CP M_CLS -0225 0083 28 04 JR Z,WR ; Allow write of "CLS" -0226 0085 FE 20 CP ' ' ; Don't write out any other control codes -0227 0087 38 01 JR C,NOWR ; ie. < space -0228 0089 CF WR RST 08H -0229 008A C9 NOWR RET -0230 008B -0231 008B 3E 0D WRCRLF LD A,CR -0232 008D CF RST 08H -0233 008E 3E 0A LD A,LF -0234 0090 CF RST 08H -0235 0091 3E 0D LD A,CR -0236 0093 C9 RET -0237 0094 -0238 0094 -0239 0094 ;------------------------------------------------------------------------------ -0240 0094 ; Initialise hardware and start main loop -0241 0094 ;------------------------------------------------------------------------------ -0242 0094 31 28 30 M_INIT LD SP,M_STACK ; Set the Stack Pointer -0243 0097 -0244 0097 3E 95 LD A,RTS_LOW -0245 0099 D3 80 OUT (ACIA0_C),A ; Initialise ACIA0 -0246 009B D3 82 OUT (ACIA1_C),A ; Initialise ACIA1 -0247 009D ; Display the "Press space to start" message on both consoles -0248 009D 3E 00 LD A,$00 -0249 009F 32 00 30 LD (primaryIO),A -0250 00A2 21 65 03 LD HL,INITTXT -0251 00A5 CD 1B 01 CALL M_PRINT -0252 00A8 3E 01 LD A,$01 -0253 00AA 32 00 30 LD (primaryIO),A -0254 00AD 21 65 03 LD HL,INITTXT -0255 00B0 CD 1B 01 CALL M_PRINT -0256 00B3 -0257 00B3 ; Wait until space is in one of the buffers to determine the active console -0258 00B3 -0259 00B3 waitForSpace: -0260 00B3 -0261 00B3 CD 63 00 CALL ckincharA -0262 00B6 28 0F jr Z,notInA -0263 00B8 3E 00 LD A,$00 -0264 00BA 32 00 30 LD (primaryIO),A -0265 00BD CD 1B 00 CALL conin -0266 00C0 FE 20 CP ' ' -0267 00C2 C2 B3 00 JP NZ, waitForSpace -0268 00C5 18 14 JR spacePressed -0269 00C7 -0270 00C7 notInA: -0271 00C7 CD 6A 00 CALL ckincharB -0272 00CA 28 E7 JR Z,waitForSpace -0273 00CC 3E 01 LD A,$01 -0274 00CE 32 00 30 LD (primaryIO),A -0275 00D1 CD 1B 00 CALL conin -0276 00D4 FE 20 CP ' ' -0277 00D6 C2 B3 00 JP NZ, waitForSpace -0278 00D9 18 00 JR spacePressed -0279 00DB -0280 00DB spacePressed: -0281 00DB -0282 00DB ; Clear message on both consoles -0283 00DB 3E 0C LD A,$0C -0284 00DD CD 3C 00 CALL conoutA -0285 00E0 CD 46 00 CALL conoutB -0286 00E3 -0287 00E3 ; primaryIO is now set to the channel where SPACE was pressed -0288 00E3 -0289 00E3 -0290 00E3 CD 22 01 CALL TXCRLF ; TXCRLF -0291 00E6 21 96 02 LD HL,M_SIGNON ; Print SIGNON message -0292 00E9 CD 1B 01 CALL M_PRINT -0293 00EC -0294 00EC ;------------------------------------------------------------------------------ -0295 00EC ; Monitor command loop -0296 00EC ;------------------------------------------------------------------------------ -0297 00EC 21 EC 00 MAIN LD HL,MAIN ; Save entry point for Monitor -0298 00EF E5 PUSH HL ; This is the return address -0299 00F0 CD 22 01 MAIN0 CALL TXCRLF ; Entry point for Monitor, Normal -0300 00F3 3E 3E LD A,'>' ; Get a ">" -0301 00F5 CF RST 08H ; print it -0302 00F6 -0303 00F6 CD 71 00 MAIN1 CALL RDCHR ; Get a character from the input port -0304 00F9 FE 20 CP ' ' ; or less? -0305 00FB 38 F9 JR C,MAIN1 ; Go back -0306 00FD -0307 00FD FE 3A CP ':' ; ":"? -0308 00FF CA 99 01 JP Z,LOAD ; First character of a HEX load -0309 0102 -0310 0102 CD 7D 00 CALL WRCHR ; Print char on console -0311 0105 -0312 0105 E6 5F AND $5F ; Make character uppercase -0313 0107 -0314 0107 FE 42 CP 'B' -0315 0109 CA DA 01 JP Z,BASIC -0316 010C -0317 010C FE 47 CP 'G' -0318 010E CA 93 01 JP Z,M_GOTO -0319 0111 -0320 0111 FE 58 CP 'X' -0321 0113 CA F1 01 JP Z,CPMLOAD -0322 0116 -0323 0116 3E 3F LD A,'?' ; Get a "?" -0324 0118 CF RST 08H ; Print it -0325 0119 18 D5 JR MAIN0 -0326 011B -0327 011B ;------------------------------------------------------------------------------ -0328 011B ; Print string of characters to Serial A until byte=$00, WITH CR, LF -0329 011B ;------------------------------------------------------------------------------ -0330 011B 7E M_PRINT LD A,(HL) ; Get character -0331 011C B7 OR A ; Is it $00 ? -0332 011D C8 RET Z ; Then RETurn on terminator -0333 011E CF RST 08H ; Print it -0334 011F 23 INC HL ; Next Character -0335 0120 18 F9 JR M_PRINT ; Continue until $00 -0336 0122 -0337 0122 -0338 0122 3E 0D TXCRLF LD A,$0D ; -0339 0124 CF RST 08H ; Print character -0340 0125 3E 0A LD A,$0A ; -0341 0127 CF RST 08H ; Print character -0342 0128 C9 RET -0343 0129 -0344 0129 ;------------------------------------------------------------------------------ -0345 0129 ; Get a character from the console, must be $20-$7F to be valid (no control characters) -0346 0129 ; and breaks with the Zero Flag set -0347 0129 ;------------------------------------------------------------------------------ -0348 0129 CD 71 00 M_GETCHR CALL RDCHR ; RX a Character -0349 012C FE 03 CP $03 ; User break? -0350 012E C8 RET Z -0351 012F FE 20 CP $20 ; or better? -0352 0131 38 F6 JR C,M_GETCHR ; Do it again until we get something usable -0353 0133 C9 RET -0354 0134 ;------------------------------------------------------------------------------ -0355 0134 ; Gets two ASCII characters from the console (assuming them to be HEX 0-9 A-F) -0356 0134 ; Moves them into B and C, converts them into a byte value in A and updates a -0357 0134 ; Checksum value in E -0358 0134 ;------------------------------------------------------------------------------ -0359 0134 CD 29 01 GET2 CALL M_GETCHR ; Get us a valid character to work with -0360 0137 47 LD B,A ; Load it in B -0361 0138 CD 29 01 CALL M_GETCHR ; Get us another character -0362 013B 4F LD C,A ; load it in C -0363 013C CD 73 01 CALL BCTOA ; Convert ASCII to byte -0364 013F 4F LD C,A ; Build the checksum -0365 0140 7B LD A,E -0366 0141 91 SUB C ; The checksum should always equal zero when checked -0367 0142 5F LD E,A ; Save the checksum back where it came from -0368 0143 79 LD A,C ; Retrieve the byte and go back -0369 0144 C9 RET -0370 0145 ;------------------------------------------------------------------------------ -0371 0145 ; Gets four Hex characters from the console, converts them to values in HL -0372 0145 ;------------------------------------------------------------------------------ -0373 0145 21 00 00 GETHL LD HL,$0000 ; Gets xxxx but sets Carry Flag on any Terminator -0374 0148 CD 8C 01 CALL ECHO ; RX a Character -0375 014B FE 0D CP $0D ; ? -0376 014D 20 0E JR NZ,GETX2 ; other key -0377 014F 37 SETCY SCF ; Set Carry Flag -0378 0150 C9 RET ; and Return to main program -0379 0151 ;------------------------------------------------------------------------------ -0380 0151 ; This routine converts last four hex characters (0-9 A-F) user types into a value in HL -0381 0151 ; Rotates the old out and replaces with the new until the user hits a terminating character -0382 0151 ;------------------------------------------------------------------------------ -0383 0151 21 00 00 GETX LD HL,$0000 ; CLEAR HL -0384 0154 CD 8C 01 GETX1 CALL ECHO ; RX a character from the console -0385 0157 FE 0D CP $0D ; -0386 0159 C8 RET Z ; quit -0387 015A FE 2C CP $2C ; <,> can be used to safely quit for multiple entries -0388 015C C8 RET Z ; (Like filling both DE and HL from the user) -0389 015D FE 03 GETX2 CP $03 ; Likewise, a will terminate clean, too, but -0390 015F 28 EE JR Z,SETCY ; It also sets the Carry Flag for testing later. -0391 0161 29 ADD HL,HL ; Otherwise, rotate the previous low nibble to high -0392 0162 29 ADD HL,HL ; rather slowly -0393 0163 29 ADD HL,HL ; until we get to the top -0394 0164 29 ADD HL,HL ; and then we can continue on. -0395 0165 D6 30 SUB $30 ; Convert ASCII to byte value -0396 0167 FE 0A CP $0A ; Are we in the 0-9 range? -0397 0169 38 02 JR C,GETX3 ; Then we just need to sub $30, but if it is A-F -0398 016B D6 07 SUB $07 ; We need to take off 7 more to get the value down to -0399 016D E6 0F GETX3 AND $0F ; to the right hex value -0400 016F 85 ADD A,L ; Add the high nibble to the low -0401 0170 6F LD L,A ; Move the byte back to A -0402 0171 18 E1 JR GETX1 ; and go back for next character until he terminates -0403 0173 ;------------------------------------------------------------------------------ -0404 0173 ; Convert ASCII characters in B C registers to a byte value in A -0405 0173 ;------------------------------------------------------------------------------ -0406 0173 78 BCTOA LD A,B ; Move the hi order byte to A -0407 0174 D6 30 SUB $30 ; Take it down from Ascii -0408 0176 FE 0A CP $0A ; Are we in the 0-9 range here? -0409 0178 38 02 JR C,BCTOA1 ; If so, get the next nybble -0410 017A D6 07 SUB $07 ; But if A-F, take it down some more -0411 017C 07 BCTOA1 RLCA ; Rotate the nybble from low to high -0412 017D 07 RLCA ; One bit at a time -0413 017E 07 RLCA ; Until we -0414 017F 07 RLCA ; Get there with it -0415 0180 47 LD B,A ; Save the converted high nybble -0416 0181 79 LD A,C ; Now get the low order byte -0417 0182 D6 30 SUB $30 ; Convert it down from Ascii -0418 0184 FE 0A CP $0A ; 0-9 at this point? -0419 0186 38 02 JR C,BCTOA2 ; Good enough then, but -0420 0188 D6 07 SUB $07 ; Take off 7 more if it's A-F -0421 018A 80 BCTOA2 ADD A,B ; Add in the high order nybble -0422 018B C9 RET -0423 018C -0424 018C ;------------------------------------------------------------------------------ -0425 018C ; Get a character and echo it back to the user -0426 018C ;------------------------------------------------------------------------------ -0427 018C CD 71 00 ECHO CALL RDCHR -0428 018F CD 7D 00 CALL WRCHR -0429 0192 C9 RET -0430 0193 -0431 0193 ;------------------------------------------------------------------------------ -0432 0193 ; GOTO command -0433 0193 ;------------------------------------------------------------------------------ -0434 0193 CD 45 01 M_GOTO CALL GETHL ; ENTRY POINT FOR oto addr. Get XXXX from user. -0435 0196 D8 RET C ; Return if invalid -0436 0197 E5 PUSH HL -0437 0198 C9 RET ; Jump to HL address value -0438 0199 -0439 0199 ;------------------------------------------------------------------------------ -0440 0199 ; LOAD Intel Hex format file from the console. -0441 0199 ; [Intel Hex Format is: -0442 0199 ; 1) Colon (Frame 0) -0443 0199 ; 2) Record Length Field (Frames 1 and 2) -0444 0199 ; 3) Load Address Field (Frames 3,4,5,6) -0445 0199 ; 4) Record Type Field (Frames 7 and 8) -0446 0199 ; 5) Data Field (Frames 9 to 9+2*(Record Length)-1 -0447 0199 ; 6) Checksum Field - Sum of all byte values from Record Length to and -0448 0199 ; including Checksum Field = 0 ] -0449 0199 ;------------------------------------------------------------------------------ -0450 0199 1E 00 LOAD LD E,0 ; First two Characters is the Record Length Field -0451 019B CD 34 01 CALL GET2 ; Get us two characters into BC, convert it to a byte -0452 019E 57 LD D,A ; Load Record Length count into D -0453 019F CD 34 01 CALL GET2 ; Get next two characters, Memory Load Address -0454 01A2 67 LD H,A ; put value in H register. -0455 01A3 CD 34 01 CALL GET2 ; Get next two characters, Memory Load Address -0456 01A6 6F LD L,A ; put value in L register. -0457 01A7 CD 34 01 CALL GET2 ; Get next two characters, Record Field Type -0458 01AA FE 01 CP $01 ; Record Field Type 00 is Data, 01 is End of File -0459 01AC 20 09 JR NZ,LOAD2 ; Must be the end of that file -0460 01AE CD 34 01 CALL GET2 ; Get next two characters, assemble into byte -0461 01B1 7B LD A,E ; Recall the Checksum byte -0462 01B2 A7 AND A ; Is it Zero? -0463 01B3 28 1E JR Z,LOAD00 ; Print footer reached message -0464 01B5 18 15 JR LOADERR ; Checksums don't add up, Error out -0465 01B7 -0466 01B7 7A LOAD2 LD A,D ; Retrieve line character counter -0467 01B8 A7 AND A ; Are we done with this line? -0468 01B9 28 0B JR Z,LOAD3 ; Get two more ascii characters, build a byte and checksum -0469 01BB CD 34 01 CALL GET2 ; Get next two chars, convert to byte in A, checksum it -0470 01BE 77 LD (HL),A ; Move converted byte in A to memory location -0471 01BF 23 INC HL ; Increment pointer to next memory location -0472 01C0 3E 2E LD A,'.' ; Print out a "." for every byte loaded -0473 01C2 CF RST 08H ; -0474 01C3 15 DEC D ; Decrement line character counter -0475 01C4 18 F1 JR LOAD2 ; and keep loading into memory until line is complete -0476 01C6 -0477 01C6 CD 34 01 LOAD3 CALL GET2 ; Get two chars, build byte and checksum -0478 01C9 7B LD A,E ; Check the checksum value -0479 01CA A7 AND A ; Is it zero? -0480 01CB C8 RET Z -0481 01CC -0482 01CC 21 54 03 LOADERR LD HL,CKSUMERR ; Get "Checksum Error" message -0483 01CF CD 1B 01 CALL M_PRINT ; Print Message from (HL) and terminate the load -0484 01D2 C9 RET -0485 01D3 -0486 01D3 21 8A 03 LOAD00 LD HL,LDETXT ; Print load complete message -0487 01D6 CD 1B 01 CALL M_PRINT -0488 01D9 C9 RET -0489 01DA -0490 01DA ;------------------------------------------------------------------------------ -0491 01DA ; Start BASIC command -0492 01DA ;------------------------------------------------------------------------------ -0493 01DA BASIC -0494 01DA 21 42 03 LD HL,M_BASTXT -0495 01DD CD 1B 01 CALL M_PRINT -0496 01E0 CD 29 01 CALL M_GETCHR -0497 01E3 C8 RET Z ; Cancel if CTRL-C -0498 01E4 E6 5F AND $5F ; uppercase -0499 01E6 FE 43 CP 'C' -0500 01E8 CA 95 03 JP Z,COLD -0501 01EB FE 57 CP 'W' -0502 01ED CA 98 03 JP Z,WARM -0503 01F0 C9 RET -0504 01F1 -0505 01F1 ;------------------------------------------------------------------------------ -0506 01F1 ; CP/M load command -0507 01F1 ;------------------------------------------------------------------------------ -0508 01F1 CPMLOAD -0509 01F1 -0510 01F1 21 03 02 LD HL,CPMTXT -0511 01F4 CD 1B 01 CALL M_PRINT -0512 01F7 CD 29 01 CALL M_GETCHR -0513 01FA C8 RET Z ; Cancel if CTRL-C -0514 01FB E6 5F AND $5F ; uppercase -0515 01FD FE 59 CP 'Y' -0516 01FF CA 24 02 JP Z,CPMLOAD2 -0517 0202 C9 RET -0518 0203 CPMTXT -0519 0203 0D 0A .BYTE $0D,$0A -0520 0205 426F6F742043 .TEXT "Boot CP/M?" -0520 020B 502F4D3F -0521 020F 00 .BYTE $00 -0522 0210 -0523 0210 CPMTXT2 -0524 0210 0D 0A .BYTE $0D,$0A -0525 0212 4C6F6164696E .TEXT "Loading CP/M..." -0525 0218 672043502F4D2E2E2E -0526 0221 0D 0A 00 .BYTE $0D,$0A,$00 -0527 0224 -0528 0224 CPMLOAD2 -0529 0224 21 10 02 LD HL,CPMTXT2 -0530 0227 CD 1B 01 CALL M_PRINT -0531 022A -0532 022A 06 18 LD B,numSecs -0533 022C -0534 022C 3E 00 LD A,0 -0535 022E 32 04 30 LD (lba0),A -0536 0231 32 05 30 ld (lba1),A -0537 0234 32 06 30 ld (lba2),A -0538 0237 32 07 30 ld (lba3),A -0539 023A -0540 023A 21 00 D0 LD HL,loadAddr -0541 023D 22 02 30 LD (dmaAddr),HL -0542 0240 processSectors: -0543 0240 -0544 0240 CD 6E 02 call readhst -0545 0243 -0546 0243 11 00 02 LD DE,0200H -0547 0246 2A 02 30 LD HL,(dmaAddr) -0548 0249 19 ADD HL,DE -0549 024A 22 02 30 LD (dmaAddr),HL -0550 024D 3A 04 30 LD A,(lba0) -0551 0250 3C INC A -0552 0251 32 04 30 LD (lba0),A -0553 0254 -0554 0254 10 EA djnz processSectors -0555 0256 -0556 0256 ; Start CP/M using entry at top of BIOS -0557 0256 ; The current active console stream ID is pushed onto the stack -0558 0256 ; to allow the CBIOS to pick it up -0559 0256 ; 0 = ACIA0, 1 = ACIA1 -0560 0256 -0561 0256 3A 00 30 ld A,(primaryIO) -0562 0259 F5 PUSH AF -0563 025A 2A FE FF ld HL,($FFFE) -0564 025D E9 jp (HL) -0565 025E -0566 025E -0567 025E ;------------------------------------------------------------------------------ -0568 025E ; ROUTINES AS USED IN BIOS -0569 025E ;------------------------------------------------------------------------------ -0570 025E -0571 025E ;================================================================================================ -0572 025E ; Convert track/head/sector into LBA for physical access to the disk -0573 025E ;================================================================================================ -0574 025E setLBAaddr: -0575 025E ; Transfer LBA to disk (LBA3 not used on SD card) -0576 025E 3A 06 30 LD A,(lba2) -0577 0261 D3 8C OUT (SD_LBA2),A -0578 0263 3A 05 30 LD A,(lba1) -0579 0266 D3 8B OUT (SD_LBA1),A -0580 0268 3A 04 30 LD A,(lba0) -0581 026B D3 8A OUT (SD_LBA0),A -0582 026D C9 RET -0583 026E -0584 026E ;================================================================================================ -0585 026E ; Read physical sector from host -0586 026E ;================================================================================================ -0587 026E -0588 026E readhst: -0589 026E F5 PUSH AF -0590 026F C5 PUSH BC -0591 0270 E5 PUSH HL -0592 0271 -0593 0271 DB 89 rdWait1: IN A,(SD_STATUS) -0594 0273 FE 80 CP 128 -0595 0275 20 FA JR NZ,rdWait1 -0596 0277 -0597 0277 CD 5E 02 CALL setLBAaddr -0598 027A -0599 027A 3E 00 LD A,$00 ; 00 = Read block -0600 027C D3 89 OUT (SD_CONTROL),A -0601 027E -0602 027E 0E 04 LD c,4 -0603 0280 ; LD HL,hstbuf -0604 0280 rd4secs: -0605 0280 06 80 LD b,128 -0606 0282 rdByte: -0607 0282 -0608 0282 DB 89 rdWait2: IN A,(SD_STATUS) -0609 0284 FE E0 CP 224 ; Read byte waiting -0610 0286 20 FA JR NZ,rdWait2 -0611 0288 -0612 0288 DB 88 IN A,(SD_DATA) -0613 028A -0614 028A 77 LD (HL),A -0615 028B 23 INC HL -0616 028C 05 dec b -0617 028D 20 F3 JR NZ, rdByte -0618 028F 0D dec c -0619 0290 20 EE JR NZ,rd4secs -0620 0292 -0621 0292 E1 POP HL -0622 0293 C1 POP BC -0623 0294 F1 POP AF -0624 0295 -0625 0295 ; XOR a -0626 0295 ; ld (erflag),a -0627 0295 C9 RET -0628 0296 -0629 0296 ;------------------------------------------------------------------------------ -0630 0296 ; END OF ROUTINES AS USED IN BIOS -0631 0296 ;------------------------------------------------------------------------------ -0632 0296 -0633 0296 -0634 0296 43502F4D2042M_SIGNON .BYTE "CP/M Boot ROM 2.0" -0634 029C 6F6F7420524F4D20322E30 -0635 02A7 20627920472E .BYTE " by G. Searle" -0635 02AD 20536561726C65 -0636 02B4 0D 0A .BYTE $0D,$0A -0637 02B6 0D 0A .BYTE $0D,$0A -0638 02B8 4243206F7220 .TEXT "BC or BW - ROM BASIC Cold/Warm" -0638 02BE 4257202D20524F4D20424153494320436F6C642F5761726D -0639 02D6 0D 0A .BYTE $0D,$0A -0640 02D8 582020202020 .TEXT "X - Boot CP/M (load $D000-$FFFF)" -0640 02DE 2020202D20426F6F742043502F4D20286C6F61642024443030302D244646464629 -0641 02FF 0D 0A .BYTE $0D,$0A -0642 0301 3A6E6E6E6E2E .TEXT ":nnnn... - Load Intel-Hex file record" -0642 0307 2E2E202D204C6F616420496E74656C2D4865782066696C65207265636F7264 -0643 0326 0D 0A .BYTE $0D,$0A -0644 0328 476E6E6E6E20 .TEXT "Gnnnn - Run loc nnnn" -0644 032E 2020202D2052756E206C6F63206E6E6E6E -0645 033F 0D 0A .BYTE $0D,$0A -0646 0341 00 .BYTE $00 -0647 0342 -0648 0342 M_BASTXT -0649 0342 0D 0A .BYTE $0D,$0A -0650 0344 436F6C64206F .TEXT "Cold or warm?" -0650 034A 72207761726D3F -0651 0351 0D 0A 00 .BYTE $0D,$0A,$00 -0652 0354 -0653 0354 436865636B73CKSUMERR .BYTE "Checksum error" -0653 035A 756D206572726F72 -0654 0362 0D 0A 00 .BYTE $0D,$0A,$00 -0655 0365 -0656 0365 INITTXT -0657 0365 0C .BYTE $0C -0658 0366 507265737320 .TEXT "Press [SPACE] to activate console" -0658 036C 5B53504143455D20746F20616374697661746520636F6E736F6C65 -0659 0387 0D 0A 00 .BYTE $0D,$0A, $00 -0660 038A -0661 038A LDETXT -0662 038A 436F6D706C65 .TEXT "Complete" -0662 0390 7465 -0663 0392 0D 0A 00 .BYTE $0D,$0A, $00 -0664 0395 -0665 0395 ;=========================================================================================================================== -0666 0395 -0667 0395 ; NASCOM ROM BASIC Ver 4.7, (C) 1978 Microsoft -0668 0395 ; Scanned from source published in 80-BUS NEWS from Vol 2, Issue 3 -0669 0395 ; (May-June 1983) to Vol 3, Issue 3 (May-June 1984) -0670 0395 ; Adapted for the freeware Zilog Macro Assembler 2.10 to produce -0671 0395 ; the original ROM code (checksum A934H). PA -0672 0395 -0673 0395 ; GENERAL EQUATES -0674 0395 -0675 0395 CTRLC .EQU 03H ; Control "C" -0676 0395 CTRLG .EQU 07H ; Control "G" -0677 0395 BKSP .EQU 08H ; Back space -0678 0395 LF .EQU 0AH ; Line feed -0679 0395 CS .EQU 0CH ; Clear screen -0680 0395 CR .EQU 0DH ; Carriage return -0681 0395 CTRLO .EQU 0FH ; Control "O" -0682 0395 CTRLQ .EQU 11H ; Control "Q" -0683 0395 CTRLR .EQU 12H ; Control "R" -0684 0395 CTRLS .EQU 13H ; Control "S" -0685 0395 CTRLU .EQU 15H ; Control "U" -0686 0395 ESC .EQU 1BH ; Escape -0687 0395 DEL .EQU 7FH ; Delete -0688 0395 -0689 0395 ; BASIC WORK SPACE LOCATIONS -0690 0395 -0691 0395 WRKSPC .EQU 30B0H ; BASIC Work space -0692 0395 USR .EQU WRKSPC+3H ; "USR (x)" jump -0693 0395 OUTSUB .EQU WRKSPC+6H ; "OUT p,n" -0694 0395 OTPORT .EQU WRKSPC+7H ; Port (p) -0695 0395 DIVSUP .EQU WRKSPC+9H ; Division support routine -0696 0395 DIV1 .EQU WRKSPC+0AH ; <- Values -0697 0395 DIV2 .EQU WRKSPC+0EH ; <- to -0698 0395 DIV3 .EQU WRKSPC+12H ; <- be -0699 0395 DIV4 .EQU WRKSPC+15H ; <-inserted -0700 0395 SEED .EQU WRKSPC+17H ; Random number seed -0701 0395 LSTRND .EQU WRKSPC+3AH ; Last random number -0702 0395 INPSUB .EQU WRKSPC+3EH ; #INP (x)" Routine -0703 0395 INPORT .EQU WRKSPC+3FH ; PORT (x) -0704 0395 NULLS .EQU WRKSPC+41H ; Number of nulls -0705 0395 LWIDTH .EQU WRKSPC+42H ; Terminal width -0706 0395 COMMAN .EQU WRKSPC+43H ; Width for commas -0707 0395 NULFLG .EQU WRKSPC+44H ; Null after input byte flag -0708 0395 CTLOFG .EQU WRKSPC+45H ; Control "O" flag -0709 0395 LINESC .EQU WRKSPC+46H ; Lines counter -0710 0395 LINESN .EQU WRKSPC+48H ; Lines number -0711 0395 CHKSUM .EQU WRKSPC+4AH ; Array load/save check sum -0712 0395 NMIFLG .EQU WRKSPC+4CH ; Flag for NMI break routine -0713 0395 BRKFLG .EQU WRKSPC+4DH ; Break flag -0714 0395 RINPUT .EQU WRKSPC+4EH ; Input reflection -0715 0395 POINT .EQU WRKSPC+51H ; "POINT" reflection (unused) -0716 0395 PSET .EQU WRKSPC+54H ; "SET" reflection -0717 0395 RESET .EQU WRKSPC+57H ; "RESET" reflection -0718 0395 STRSPC .EQU WRKSPC+5AH ; Bottom of string space -0719 0395 LINEAT .EQU WRKSPC+5CH ; Current line number -0720 0395 BASTXT .EQU WRKSPC+5EH ; Pointer to start of program -0721 0395 BUFFER .EQU WRKSPC+61H ; Input buffer -0722 0395 STACK .EQU WRKSPC+66H ; Initial stack -0723 0395 CURPOS .EQU WRKSPC+0ABH ; Character position on line -0724 0395 LCRFLG .EQU WRKSPC+0ACH ; Locate/Create flag -0725 0395 TYPE .EQU WRKSPC+0ADH ; Data type flag -0726 0395 DATFLG .EQU WRKSPC+0AEH ; Literal statement flag -0727 0395 LSTRAM .EQU WRKSPC+0AFH ; Last available RAM -0728 0395 TMSTPT .EQU WRKSPC+0B1H ; Temporary string pointer -0729 0395 TMSTPL .EQU WRKSPC+0B3H ; Temporary string pool -0730 0395 TMPSTR .EQU WRKSPC+0BFH ; Temporary string -0731 0395 STRBOT .EQU WRKSPC+0C3H ; Bottom of string space -0732 0395 CUROPR .EQU WRKSPC+0C5H ; Current operator in EVAL -0733 0395 LOOPST .EQU WRKSPC+0C7H ; First statement of loop -0734 0395 DATLIN .EQU WRKSPC+0C9H ; Line of current DATA item -0735 0395 FORFLG .EQU WRKSPC+0CBH ; "FOR" loop flag -0736 0395 LSTBIN .EQU WRKSPC+0CCH ; Last byte entered -0737 0395 READFG .EQU WRKSPC+0CDH ; Read/Input flag -0738 0395 BRKLIN .EQU WRKSPC+0CEH ; Line of break -0739 0395 NXTOPR .EQU WRKSPC+0D0H ; Next operator in EVAL -0740 0395 ERRLIN .EQU WRKSPC+0D2H ; Line of error -0741 0395 CONTAD .EQU WRKSPC+0D4H ; Where to CONTinue -0742 0395 PROGND .EQU WRKSPC+0D6H ; End of program -0743 0395 VAREND .EQU WRKSPC+0D8H ; End of variables -0744 0395 ARREND .EQU WRKSPC+0DAH ; End of arrays -0745 0395 NXTDAT .EQU WRKSPC+0DCH ; Next data item -0746 0395 FNRGNM .EQU WRKSPC+0DEH ; Name of FN argument -0747 0395 FNARG .EQU WRKSPC+0E0H ; FN argument value -0748 0395 FPREG .EQU WRKSPC+0E4H ; Floating point register -0749 0395 FPEXP .EQU FPREG+3 ; Floating point exponent -0750 0395 SGNRES .EQU WRKSPC+0E8H ; Sign of result -0751 0395 PBUFF .EQU WRKSPC+0E9H ; Number print buffer -0752 0395 MULVAL .EQU WRKSPC+0F6H ; Multiplier -0753 0395 PROGST .EQU WRKSPC+0F9H ; Start of program text area -0754 0395 STLOOK .EQU WRKSPC+15DH ; Start of memory test -0755 0395 -0756 0395 ; BASIC ERROR CODE VALUES -0757 0395 -0758 0395 NF .EQU 00H ; NEXT without FOR -0759 0395 SN .EQU 02H ; Syntax error -0760 0395 RG .EQU 04H ; RETURN without GOSUB -0761 0395 OD .EQU 06H ; Out of DATA -0762 0395 FC .EQU 08H ; Function call error -0763 0395 OV .EQU 0AH ; Overflow -0764 0395 OM .EQU 0CH ; Out of memory -0765 0395 UL .EQU 0EH ; Undefined line number -0766 0395 BS .EQU 10H ; Bad subscript -0767 0395 DD .EQU 12H ; Re-DIMensioned array -0768 0395 DZ .EQU 14H ; Division by zero (/0) -0769 0395 ID .EQU 16H ; Illegal direct -0770 0395 TM .EQU 18H ; Type miss-match -0771 0395 OS .EQU 1AH ; Out of string space -0772 0395 LS .EQU 1CH ; String too long -0773 0395 ST .EQU 1EH ; String formula too complex -0774 0395 CN .EQU 20H ; Can't CONTinue -0775 0395 UF .EQU 22H ; UnDEFined FN function -0776 0395 MO .EQU 24H ; Missing operand -0777 0395 HX .EQU 26H ; HEX error -0778 0395 BN .EQU 28H ; BIN error -0779 0395 -0780 0395 ; .ORG 00396H -0781 0395 -0782 0395 C3 9B 03 COLD: JP STARTB ; Jump for cold start -0783 0398 C3 39 04 WARM: JP WARMST ; Jump for warm start -0784 039B STARTB: -0785 039B DD 21 00 00 LD IX,0 ; Flag cold start -0786 039F C3 A6 03 JP CSTART ; Jump to initialise -0787 03A2 -0788 03A2 4C 0C .WORD DEINT ; Get integer -32768 to 32767 -0789 03A4 C2 13 .WORD ABPASS ; Return integer in AB -0790 03A6 -0791 03A6 -0792 03A6 21 B0 30 CSTART: LD HL,WRKSPC ; Start of workspace RAM -0793 03A9 F9 LD SP,HL ; Set up a temporary stack -0794 03AA C3 E1 1F JP INITST ; Go to initialise -0795 03AD -0796 03AD 11 73 06 INIT: LD DE,INITAB ; Initialise workspace -0797 03B0 06 63 LD B,INITBE-INITAB+3; Bytes to copy -0798 03B2 21 B0 30 LD HL,WRKSPC ; Into workspace RAM -0799 03B5 1A COPY: LD A,(DE) ; Get source -0800 03B6 77 LD (HL),A ; To destination -0801 03B7 23 INC HL ; Next destination -0802 03B8 13 INC DE ; Next source -0803 03B9 05 DEC B ; Count bytes -0804 03BA C2 B5 03 JP NZ,COPY ; More to move -0805 03BD F9 LD SP,HL ; Temporary stack -0806 03BE CD 74 08 CALL CLREG ; Clear registers and stack -0807 03C1 CD 42 0E CALL PRNTCRLF ; Output CRLF -0808 03C4 32 5A 31 LD (BUFFER+72+1),A ; Mark end of buffer -0809 03C7 32 A9 31 LD (PROGST),A ; Initialise program area -0810 03CA 21 88 04 MSIZE: LD HL,MEMMSG ; Point to message -0811 03CD CD E0 14 CALL PRS ; Output "Memory size" -0812 03D0 CD 91 08 CALL PROMPT ; Get input with '?' -0813 03D3 CD 9A 0B CALL GETCHR ; Get next character -0814 03D6 B7 OR A ; Set flags -0815 03D7 C2 EF 03 JP NZ,TSTMEM ; If number - Test if RAM there -0816 03DA 21 0D 32 LD HL,STLOOK ; Point to start of RAM -0817 03DD 23 MLOOP: INC HL ; Next byte -0818 03DE 7C LD A,H ; Above address FFFF ? -0819 03DF B5 OR L -0820 03E0 CA 01 04 JP Z,SETTOP ; Yes - 64K RAM -0821 03E3 7E LD A,(HL) ; Get contents -0822 03E4 47 LD B,A ; Save it -0823 03E5 2F CPL ; Flip all bits -0824 03E6 77 LD (HL),A ; Put it back -0825 03E7 BE CP (HL) ; RAM there if same -0826 03E8 70 LD (HL),B ; Restore old contents -0827 03E9 CA DD 03 JP Z,MLOOP ; If RAM - test next byte -0828 03EC C3 01 04 JP SETTOP ; Top of RAM found -0829 03EF -0830 03EF CD 66 0C TSTMEM: CALL ATOH ; Get high memory into DE -0831 03F2 B7 OR A ; Set flags on last byte -0832 03F3 C2 42 07 JP NZ,SNERR ; ?SN Error if bad character -0833 03F6 EB EX DE,HL ; Address into HL -0834 03F7 2B DEC HL ; Back one byte -0835 03F8 3E D9 LD A,11011001B ; Test byte -0836 03FA 46 LD B,(HL) ; Get old contents -0837 03FB 77 LD (HL),A ; Load test byte -0838 03FC BE CP (HL) ; RAM there if same -0839 03FD 70 LD (HL),B ; Restore old contents -0840 03FE C2 CA 03 JP NZ,MSIZE ; Ask again if no RAM -0841 0401 -0842 0401 2B SETTOP: DEC HL ; Back one byte -0843 0402 11 0C 32 LD DE,STLOOK-1 ; See if enough RAM -0844 0405 CD 0A 0A CALL CPDEHL ; Compare DE with HL -0845 0408 DA CA 03 JP C,MSIZE ; Ask again if not enough RAM -0846 040B 11 CE FF LD DE,0-50 ; 50 Bytes string space -0847 040E 22 5F 31 LD (LSTRAM),HL ; Save last available RAM -0848 0411 19 ADD HL,DE ; Allocate string space -0849 0412 22 0A 31 LD (STRSPC),HL ; Save string space -0850 0415 CD 4F 08 CALL CLRPTR ; Clear program area -0851 0418 2A 0A 31 LD HL,(STRSPC) ; Get end of memory -0852 041B 11 EF FF LD DE,0-17 ; Offset for free bytes -0853 041E 19 ADD HL,DE ; Adjust HL -0854 041F 11 A9 31 LD DE,PROGST ; Start of program text -0855 0422 7D LD A,L ; Get LSB -0856 0423 93 SUB E ; Adjust it -0857 0424 6F LD L,A ; Re-save -0858 0425 7C LD A,H ; Get MSB -0859 0426 9A SBC A,D ; Adjust it -0860 0427 67 LD H,A ; Re-save -0861 0428 E5 PUSH HL ; Save bytes free -0862 0429 21 51 04 LD HL,SIGNON ; Sign-on message -0863 042C CD E0 14 CALL PRS ; Output string -0864 042F E1 POP HL ; Get bytes free back -0865 0430 CD 83 1B CALL PRNTHL ; Output amount of free memory -0866 0433 21 42 04 LD HL,BFREE ; " Bytes free" message -0867 0436 CD E0 14 CALL PRS ; Output string -0868 0439 -0869 0439 31 16 31 WARMST: LD SP,STACK ; Temporary stack -0870 043C CD 74 08 BRKRET: CALL CLREG ; Clear registers and stack -0871 043F C3 8D 07 JP PRNTOK ; Go to get command line -0872 0442 -0873 0442 204279746573BFREE: .BYTE " Bytes free",CR,LF,0,0 -0873 0448 20667265650D0A0000 -0874 0451 -0875 0451 5A3830204241SIGNON: .BYTE "Z80 BASIC Ver 4.7b",CR,LF -0875 0457 5349432056657220342E37620D0A -0876 0465 436F70797269 .BYTE "Copyright ",40,"C",41 -0876 046B 67687420284329 -0877 0472 203139373820 .BYTE " 1978 by Microsoft",CR,LF,0,0 -0877 0478 6279204D6963726F736F66740D0A0000 -0878 0488 -0879 0488 4D656D6F7279MEMMSG: .BYTE "Memory top",0 -0879 048E 20746F7000 -0880 0493 -0881 0493 ; FUNCTION ADDRESS TABLE -0882 0493 -0883 0493 F8 19 FNCTAB: .WORD SGN -0884 0495 BC 1A .WORD INT -0885 0497 0E 1A .WORD ABS -0886 0499 B3 30 .WORD USR -0887 049B A0 13 .WORD FRE -0888 049D 25 17 .WORD INP -0889 049F CE 13 .WORD POS -0890 04A1 82 1C .WORD SQR -0891 04A3 61 1D .WORD RND -0892 04A5 9D 18 .WORD LOG -0893 04A7 D0 1C .WORD EXP -0894 04A9 D6 1D .WORD COS -0895 04AB DC 1D .WORD SIN -0896 04AD 3D 1E .WORD TAN -0897 04AF 52 1E .WORD ATN -0898 04B1 79 17 .WORD PEEK -0899 04B3 BD 1E .WORD DEEK -0900 04B5 01 31 .WORD POINT -0901 04B7 52 16 .WORD LEN -0902 04B9 6A 14 .WORD STR -0903 04BB EC 16 .WORD VAL -0904 04BD 61 16 .WORD ASC -0905 04BF 72 16 .WORD CHR -0906 04C1 DF 1E .WORD HEX -0907 04C3 72 1F .WORD BIN -0908 04C5 82 16 .WORD LEFT -0909 04C7 B2 16 .WORD RIGHT -0910 04C9 BC 16 .WORD MID -0911 04CB -0912 04CB ; RESERVED WORD LIST -0913 04CB -0914 04CB C5 4E 44 WORDS: .BYTE 'E'+80H,"ND" -0915 04CE C6 4F 52 .BYTE 'F'+80H,"OR" -0916 04D1 CE 45 58 54 .BYTE 'N'+80H,"EXT" -0917 04D5 C4 41 54 41 .BYTE 'D'+80H,"ATA" -0918 04D9 C94E505554 .BYTE 'I'+80H,"NPUT" -0919 04DE C4 49 4D .BYTE 'D'+80H,"IM" -0920 04E1 D2 45 41 44 .BYTE 'R'+80H,"EAD" -0921 04E5 CC 45 54 .BYTE 'L'+80H,"ET" -0922 04E8 C7 4F 54 4F .BYTE 'G'+80H,"OTO" -0923 04EC D2 55 4E .BYTE 'R'+80H,"UN" -0924 04EF C9 46 .BYTE 'I'+80H,"F" -0925 04F1 D24553544F52 .BYTE 'R'+80H,"ESTORE" -0925 04F7 45 -0926 04F8 C74F535542 .BYTE 'G'+80H,"OSUB" -0927 04FD D2455455524E .BYTE 'R'+80H,"ETURN" -0928 0503 D2 45 4D .BYTE 'R'+80H,"EM" -0929 0506 D3 54 4F 50 .BYTE 'S'+80H,"TOP" -0930 050A CF 55 54 .BYTE 'O'+80H,"UT" -0931 050D CF 4E .BYTE 'O'+80H,"N" -0932 050F CE 55 4C 4C .BYTE 'N'+80H,"ULL" -0933 0513 D7 41 49 54 .BYTE 'W'+80H,"AIT" -0934 0517 C4 45 46 .BYTE 'D'+80H,"EF" -0935 051A D0 4F 4B 45 .BYTE 'P'+80H,"OKE" -0936 051E C4 4F 4B 45 .BYTE 'D'+80H,"OKE" -0937 0522 D3435245454E .BYTE 'S'+80H,"CREEN" -0938 0528 CC494E4553 .BYTE 'L'+80H,"INES" -0939 052D C3 4C 53 .BYTE 'C'+80H,"LS" -0940 0530 D749445448 .BYTE 'W'+80H,"IDTH" -0941 0535 CD4F4E49544F .BYTE 'M'+80H,"ONITOR" -0941 053B 52 -0942 053C D3 45 54 .BYTE 'S'+80H,"ET" -0943 053F D245534554 .BYTE 'R'+80H,"ESET" -0944 0544 D052494E54 .BYTE 'P'+80H,"RINT" -0945 0549 C3 4F 4E 54 .BYTE 'C'+80H,"ONT" -0946 054D CC 49 53 54 .BYTE 'L'+80H,"IST" -0947 0551 C34C454152 .BYTE 'C'+80H,"LEAR" -0948 0556 C34C4F4144 .BYTE 'C'+80H,"LOAD" -0949 055B C353415645 .BYTE 'C'+80H,"SAVE" -0950 0560 CE 45 57 .BYTE 'N'+80H,"EW" -0951 0563 -0952 0563 D4 41 42 28 .BYTE 'T'+80H,"AB(" -0953 0567 D4 4F .BYTE 'T'+80H,"O" -0954 0569 C6 4E .BYTE 'F'+80H,"N" -0955 056B D3 50 43 28 .BYTE 'S'+80H,"PC(" -0956 056F D4 48 45 4E .BYTE 'T'+80H,"HEN" -0957 0573 CE 4F 54 .BYTE 'N'+80H,"OT" -0958 0576 D3 54 45 50 .BYTE 'S'+80H,"TEP" -0959 057A -0960 057A AB .BYTE '+'+80H -0961 057B AD .BYTE '-'+80H -0962 057C AA .BYTE '*'+80H -0963 057D AF .BYTE '/'+80H -0964 057E DE .BYTE '^'+80H -0965 057F C1 4E 44 .BYTE 'A'+80H,"ND" -0966 0582 CF 52 .BYTE 'O'+80H,"R" -0967 0584 BE .BYTE '>'+80H -0968 0585 BD .BYTE '='+80H -0969 0586 BC .BYTE '<'+80H -0970 0587 -0971 0587 D3 47 4E .BYTE 'S'+80H,"GN" -0972 058A C9 4E 54 .BYTE 'I'+80H,"NT" -0973 058D C1 42 53 .BYTE 'A'+80H,"BS" -0974 0590 D5 53 52 .BYTE 'U'+80H,"SR" -0975 0593 C6 52 45 .BYTE 'F'+80H,"RE" -0976 0596 C9 4E 50 .BYTE 'I'+80H,"NP" -0977 0599 D0 4F 53 .BYTE 'P'+80H,"OS" -0978 059C D3 51 52 .BYTE 'S'+80H,"QR" -0979 059F D2 4E 44 .BYTE 'R'+80H,"ND" -0980 05A2 CC 4F 47 .BYTE 'L'+80H,"OG" -0981 05A5 C5 58 50 .BYTE 'E'+80H,"XP" -0982 05A8 C3 4F 53 .BYTE 'C'+80H,"OS" -0983 05AB D3 49 4E .BYTE 'S'+80H,"IN" -0984 05AE D4 41 4E .BYTE 'T'+80H,"AN" -0985 05B1 C1 54 4E .BYTE 'A'+80H,"TN" -0986 05B4 D0 45 45 4B .BYTE 'P'+80H,"EEK" -0987 05B8 C4 45 45 4B .BYTE 'D'+80H,"EEK" -0988 05BC D04F494E54 .BYTE 'P'+80H,"OINT" -0989 05C1 CC 45 4E .BYTE 'L'+80H,"EN" -0990 05C4 D3 54 52 24 .BYTE 'S'+80H,"TR$" -0991 05C8 D6 41 4C .BYTE 'V'+80H,"AL" -0992 05CB C1 53 43 .BYTE 'A'+80H,"SC" -0993 05CE C3 48 52 24 .BYTE 'C'+80H,"HR$" -0994 05D2 C8 45 58 24 .BYTE 'H'+80H,"EX$" -0995 05D6 C2 49 4E 24 .BYTE 'B'+80H,"IN$" -0996 05DA CC45465424 .BYTE 'L'+80H,"EFT$" -0997 05DF D24947485424 .BYTE 'R'+80H,"IGHT$" -0998 05E5 CD 49 44 24 .BYTE 'M'+80H,"ID$" -0999 05E9 80 .BYTE 80H ; End of list marker -1000 05EA -1001 05EA ; KEYWORD ADDRESS TABLE -1002 05EA -1003 05EA E4 0B WORDTB: .WORD PEND -1004 05EC E1 0A .WORD FOR -1005 05EE BC 0F .WORD NEXT -1006 05F0 31 0D .WORD DATA -1007 05F2 C3 0E .WORD INPUT -1008 05F4 F8 11 .WORD DIM -1009 05F6 F2 0E .WORD READ -1010 05F8 48 0D .WORD LET -1011 05FA EE 0C .WORD GOTO -1012 05FC D1 0C .WORD RUN -1013 05FE C0 0D .WORD IF -1014 0600 AA 0B .WORD RESTOR -1015 0602 DD 0C .WORD GOSUB -1016 0604 0C 0D .WORD RETURN -1017 0606 33 0D .WORD REM -1018 0608 E2 0B .WORD STOP -1019 060A 31 17 .WORD POUT -1020 060C A2 0D .WORD ON -1021 060E 23 0C .WORD NULL -1022 0610 37 17 .WORD WAIT -1023 0612 D6 13 .WORD DEF -1024 0614 80 17 .WORD POKE -1025 0616 C8 1E .WORD DOKE -1026 0618 33 0D .WORD REM -1027 061A AE 1E .WORD LINES -1028 061C A1 1E .WORD CLS -1029 061E A6 1E .WORD WIDTH -1030 0620 DE 1F .WORD MONITR -1031 0622 04 31 .WORD PSET -1032 0624 07 31 .WORD RESET -1033 0626 E4 0D .WORD PRINT -1034 0628 10 0C .WORD CONT -1035 062A 56 0A .WORD LIST -1036 062C 8B 0C .WORD CLEAR -1037 062E 33 0D .WORD REM -1038 0630 33 0D .WORD REM -1039 0632 4E 08 .WORD NEW -1040 0634 -1041 0634 ; RESERVED WORD TOKEN VALUES -1042 0634 -1043 0634 ZEND .EQU 080H ; END -1044 0634 ZFOR .EQU 081H ; FOR -1045 0634 ZDATA .EQU 083H ; DATA -1046 0634 ZGOTO .EQU 088H ; GOTO -1047 0634 ZGOSUB .EQU 08CH ; GOSUB -1048 0634 ZREM .EQU 08EH ; REM -1049 0634 ZPRINT .EQU 09EH ; PRINT -1050 0634 ZNEW .EQU 0A4H ; NEW -1051 0634 -1052 0634 ZTAB .EQU 0A5H ; TAB -1053 0634 ZTO .EQU 0A6H ; TO -1054 0634 ZFN .EQU 0A7H ; FN -1055 0634 ZSPC .EQU 0A8H ; SPC -1056 0634 ZTHEN .EQU 0A9H ; THEN -1057 0634 ZNOT .EQU 0AAH ; NOT -1058 0634 ZSTEP .EQU 0ABH ; STEP -1059 0634 -1060 0634 ZPLUS .EQU 0ACH ; + -1061 0634 ZMINUS .EQU 0ADH ; - -1062 0634 ZTIMES .EQU 0AEH ; * -1063 0634 ZDIV .EQU 0AFH ; / -1064 0634 ZOR .EQU 0B2H ; OR -1065 0634 ZGTR .EQU 0B3H ; > -1066 0634 ZEQUAL .EQU 0B4H ; M -1067 0634 ZLTH .EQU 0B5H ; < -1068 0634 ZSGN .EQU 0B6H ; SGN -1069 0634 ZPOINT .EQU 0C7H ; POINT -1070 0634 ZLEFT .EQU 0CDH +2 ; LEFT$ -1071 0634 -1072 0634 ; ARITHMETIC PRECEDENCE TABLE -1073 0634 -1074 0634 79 PRITAB: .BYTE 79H ; Precedence value -1075 0635 6A 1B .WORD PADD ; FPREG = + FPREG -1076 0637 -1077 0637 79 .BYTE 79H ; Precedence value -1078 0638 9E 17 .WORD PSUB ; FPREG = - FPREG -1079 063A -1080 063A 7C .BYTE 7CH ; Precedence value -1081 063B DC 18 .WORD MULT ; PPREG = * FPREG -1082 063D -1083 063D 7C .BYTE 7CH ; Precedence value -1084 063E 3D 19 .WORD DIV ; FPREG = / FPREG -1085 0640 -1086 0640 7F .BYTE 7FH ; Precedence value -1087 0641 8B 1C .WORD POWER ; FPREG = ^ FPREG -1088 0643 -1089 0643 50 .BYTE 50H ; Precedence value -1090 0644 51 11 .WORD PAND ; FPREG = AND FPREG -1091 0646 -1092 0646 46 .BYTE 46H ; Precedence value -1093 0647 50 11 .WORD POR ; FPREG = OR FPREG -1094 0649 -1095 0649 ; BASIC ERROR CODE LIST -1096 0649 -1097 0649 4E 46 ERRORS: .BYTE "NF" ; NEXT without FOR -1098 064B 53 4E .BYTE "SN" ; Syntax error -1099 064D 52 47 .BYTE "RG" ; RETURN without GOSUB -1100 064F 4F 44 .BYTE "OD" ; Out of DATA -1101 0651 46 43 .BYTE "FC" ; Illegal function call -1102 0653 4F 56 .BYTE "OV" ; Overflow error -1103 0655 4F 4D .BYTE "OM" ; Out of memory -1104 0657 55 4C .BYTE "UL" ; Undefined line -1105 0659 42 53 .BYTE "BS" ; Bad subscript -1106 065B 44 44 .BYTE "DD" ; Re-DIMensioned array -1107 065D 2F 30 .BYTE "/0" ; Division by zero -1108 065F 49 44 .BYTE "ID" ; Illegal direct -1109 0661 54 4D .BYTE "TM" ; Type mis-match -1110 0663 4F 53 .BYTE "OS" ; Out of string space -1111 0665 4C 53 .BYTE "LS" ; String too long -1112 0667 53 54 .BYTE "ST" ; String formula too complex -1113 0669 43 4E .BYTE "CN" ; Can't CONTinue -1114 066B 55 46 .BYTE "UF" ; Undefined FN function -1115 066D 4D 4F .BYTE "MO" ; Missing operand -1116 066F 48 58 .BYTE "HX" ; HEX error -1117 0671 42 4E .BYTE "BN" ; BIN error -1118 0673 -1119 0673 ; INITIALISATION TABLE ------------------------------------------------------- -1120 0673 -1121 0673 C3 39 04 INITAB: JP WARMST ; Warm start jump -1122 0676 C3 61 0C JP FCERR ; "USR (X)" jump (Set to Error) -1123 0679 D3 00 OUT (0),A ; "OUT p,n" skeleton -1124 067B C9 RET -1125 067C D6 00 SUB 0 ; Division support routine -1126 067E 6F LD L,A -1127 067F 7C LD A,H -1128 0680 DE 00 SBC A,0 -1129 0682 67 LD H,A -1130 0683 78 LD A,B -1131 0684 DE 00 SBC A,0 -1132 0686 47 LD B,A -1133 0687 3E 00 LD A,0 -1134 0689 C9 RET -1135 068A 00 00 00 .BYTE 0,0,0 ; Random number seed table used by RND -1136 068D 35 4A CA 99 .BYTE 035H,04AH,0CAH,099H ;-2.65145E+07 -1137 0691 39 1C 76 98 .BYTE 039H,01CH,076H,098H ; 1.61291E+07 -1138 0695 22 95 B3 98 .BYTE 022H,095H,0B3H,098H ;-1.17691E+07 -1139 0699 0A DD 47 98 .BYTE 00AH,0DDH,047H,098H ; 1.30983E+07 -1140 069D 53 D1 99 99 .BYTE 053H,0D1H,099H,099H ;-2-01612E+07 -1141 06A1 0A 1A 9F 98 .BYTE 00AH,01AH,09FH,098H ;-1.04269E+07 -1142 06A5 65 BC CD 98 .BYTE 065H,0BCH,0CDH,098H ;-1.34831E+07 -1143 06A9 D6 77 3E 98 .BYTE 0D6H,077H,03EH,098H ; 1.24825E+07 -1144 06AD 52 C7 4F 80 .BYTE 052H,0C7H,04FH,080H ; Last random number -1145 06B1 DB 00 IN A,(0) ; INP (x) skeleton -1146 06B3 C9 RET -1147 06B4 01 .BYTE 1 ; POS (x) number (1) -1148 06B5 FF .BYTE 255 ; Terminal width (255 = no auto CRLF) -1149 06B6 1C .BYTE 28 ; Width for commas (3 columns) -1150 06B7 00 .BYTE 0 ; No nulls after input bytes -1151 06B8 00 .BYTE 0 ; Output enabled (^O off) -1152 06B9 14 00 .WORD 20 ; Initial lines counter -1153 06BB 14 00 .WORD 20 ; Initial lines number -1154 06BD 00 00 .WORD 0 ; Array load/save check sum -1155 06BF 00 .BYTE 0 ; Break not by NMI -1156 06C0 00 .BYTE 0 ; Break flag -1157 06C1 C3 87 09 JP TTYLIN ; Input reflection (set to TTY) -1158 06C4 C3 00 00 JP $0000 ; POINT reflection unused -1159 06C7 C3 00 00 JP $0000 ; SET reflection -1160 06CA C3 00 00 JP $0000 ; RESET reflection -1161 06CD 0D 32 .WORD STLOOK ; Temp string space -1162 06CF FE FF .WORD -2 ; Current line number (cold) -1163 06D1 AA 31 .WORD PROGST+1 ; Start of program text -1164 06D3 INITBE: -1165 06D3 -1166 06D3 ; END OF INITIALISATION TABLE --------------------------------------------------- -1167 06D3 -1168 06D3 204572726F72ERRMSG: .BYTE " Error",0 -1168 06D9 00 -1169 06DA 20696E2000 INMSG: .BYTE " in ",0 -1170 06DF ZERBYT .EQU $-1 ; A zero byte -1171 06DF 4F6B0D0A0000OKMSG: .BYTE "Ok",CR,LF,0,0 -1172 06E5 427265616B00BRKMSG: .BYTE "Break",0 -1173 06EB -1174 06EB 21 04 00 BAKSTK: LD HL,4 ; Look for "FOR" block with -1175 06EE 39 ADD HL,SP ; same index as specified -1176 06EF 7E LOKFOR: LD A,(HL) ; Get block ID -1177 06F0 23 INC HL ; Point to index address -1178 06F1 FE 81 CP ZFOR ; Is it a "FOR" token -1179 06F3 C0 RET NZ ; No - exit -1180 06F4 4E LD C,(HL) ; BC = Address of "FOR" index -1181 06F5 23 INC HL -1182 06F6 46 LD B,(HL) -1183 06F7 23 INC HL ; Point to sign of STEP -1184 06F8 E5 PUSH HL ; Save pointer to sign -1185 06F9 69 LD L,C ; HL = address of "FOR" index -1186 06FA 60 LD H,B -1187 06FB 7A LD A,D ; See if an index was specified -1188 06FC B3 OR E ; DE = 0 if no index specified -1189 06FD EB EX DE,HL ; Specified index into HL -1190 06FE CA 05 07 JP Z,INDFND ; Skip if no index given -1191 0701 EB EX DE,HL ; Index back into DE -1192 0702 CD 0A 0A CALL CPDEHL ; Compare index with one given -1193 0705 01 0D 00 INDFND: LD BC,16-3 ; Offset to next block -1194 0708 E1 POP HL ; Restore pointer to sign -1195 0709 C8 RET Z ; Return if block found -1196 070A 09 ADD HL,BC ; Point to next block -1197 070B C3 EF 06 JP LOKFOR ; Keep on looking -1198 070E -1199 070E CD 28 07 MOVUP: CALL ENFMEM ; See if enough memory -1200 0711 C5 MOVSTR: PUSH BC ; Save end of source -1201 0712 E3 EX (SP),HL ; Swap source and dest" end -1202 0713 C1 POP BC ; Get end of destination -1203 0714 CD 0A 0A MOVLP: CALL CPDEHL ; See if list moved -1204 0717 7E LD A,(HL) ; Get byte -1205 0718 02 LD (BC),A ; Move it -1206 0719 C8 RET Z ; Exit if all done -1207 071A 0B DEC BC ; Next byte to move to -1208 071B 2B DEC HL ; Next byte to move -1209 071C C3 14 07 JP MOVLP ; Loop until all bytes moved -1210 071F -1211 071F E5 CHKSTK: PUSH HL ; Save code string address -1212 0720 2A 8A 31 LD HL,(ARREND) ; Lowest free memory -1213 0723 06 00 LD B,0 ; BC = Number of levels to test -1214 0725 09 ADD HL,BC ; 2 Bytes for each level -1215 0726 09 ADD HL,BC -1216 0727 3E .BYTE 3EH ; Skip "PUSH HL" -1217 0728 E5 ENFMEM: PUSH HL ; Save code string address -1218 0729 3E D0 LD A,0D0H ;LOW -48 ; 48 Bytes minimum RAM -1219 072B 95 SUB L -1220 072C 6F LD L,A -1221 072D 3E FF LD A,0FFH; HIGH (-48) ; 48 Bytes minimum RAM -1222 072F 9C SBC A,H -1223 0730 DA 37 07 JP C,OMERR ; Not enough - ?OM Error -1224 0733 67 LD H,A -1225 0734 39 ADD HL,SP ; Test if stack is overflowed -1226 0735 E1 POP HL ; Restore code string address -1227 0736 D8 RET C ; Return if enough mmory -1228 0737 1E 0C OMERR: LD E,OM ; ?OM Error -1229 0739 C3 56 07 JP ERROR -1230 073C -1231 073C 2A 79 31 DATSNR: LD HL,(DATLIN) ; Get line of current DATA item -1232 073F 22 0C 31 LD (LINEAT),HL ; Save as current line -1233 0742 1E 02 SNERR: LD E,SN ; ?SN Error -1234 0744 01 .BYTE 01H ; Skip "LD E,DZ" -1235 0745 1E 14 DZERR: LD E,DZ ; ?/0 Error -1236 0747 01 .BYTE 01H ; Skip "LD E,NF" -1237 0748 1E 00 NFERR: LD E,NF ; ?NF Error -1238 074A 01 .BYTE 01H ; Skip "LD E,DD" -1239 074B 1E 12 DDERR: LD E,DD ; ?DD Error -1240 074D 01 .BYTE 01H ; Skip "LD E,UF" -1241 074E 1E 22 UFERR: LD E,UF ; ?UF Error -1242 0750 01 .BYTE 01H ; Skip "LD E,OV -1243 0751 1E 0A OVERR: LD E,OV ; ?OV Error -1244 0753 01 .BYTE 01H ; Skip "LD E,TM" -1245 0754 1E 18 TMERR: LD E,TM ; ?TM Error -1246 0756 -1247 0756 CD 74 08 ERROR: CALL CLREG ; Clear registers and stack -1248 0759 32 F5 30 LD (CTLOFG),A ; Enable output (A is 0) -1249 075C CD 35 0E CALL STTLIN ; Start new line -1250 075F 21 49 06 LD HL,ERRORS ; Point to error codes -1251 0762 57 LD D,A ; D = 0 (A is 0) -1252 0763 3E 3F LD A,'?' -1253 0765 CD 1B 0A CALL OUTC ; Output '?' -1254 0768 19 ADD HL,DE ; Offset to correct error code -1255 0769 7E LD A,(HL) ; First character -1256 076A CD 1B 0A CALL OUTC ; Output it -1257 076D CD 9A 0B CALL GETCHR ; Get next character -1258 0770 CD 1B 0A CALL OUTC ; Output it -1259 0773 21 D3 06 LD HL,ERRMSG ; "Error" message -1260 0776 CD E0 14 ERRIN: CALL PRS ; Output message -1261 0779 2A 0C 31 LD HL,(LINEAT) ; Get line of error -1262 077C 11 FE FF LD DE,-2 ; Cold start error if -2 -1263 077F CD 0A 0A CALL CPDEHL ; See if cold start error -1264 0782 CA A6 03 JP Z,CSTART ; Cold start error - Restart -1265 0785 7C LD A,H ; Was it a direct error? -1266 0786 A5 AND L ; Line = -1 if direct error -1267 0787 3C INC A -1268 0788 C4 7B 1B CALL NZ,LINEIN ; No - output line of error -1269 078B 3E .BYTE 3EH ; Skip "POP BC" -1270 078C C1 POPNOK: POP BC ; Drop address in input buffer -1271 078D -1272 078D AF PRNTOK: XOR A ; Output "Ok" and get command -1273 078E 32 F5 30 LD (CTLOFG),A ; Enable output -1274 0791 CD 35 0E CALL STTLIN ; Start new line -1275 0794 21 DF 06 LD HL,OKMSG ; "Ok" message -1276 0797 CD E0 14 CALL PRS ; Output "Ok" -1277 079A 21 FF FF GETCMD: LD HL,-1 ; Flag direct mode -1278 079D 22 0C 31 LD (LINEAT),HL ; Save as current line -1279 07A0 CD 87 09 CALL GETLIN ; Get an input line -1280 07A3 DA 9A 07 JP C,GETCMD ; Get line again if break -1281 07A6 CD 9A 0B CALL GETCHR ; Get first character -1282 07A9 3C INC A ; Test if end of line -1283 07AA 3D DEC A ; Without affecting Carry -1284 07AB CA 9A 07 JP Z,GETCMD ; Nothing entered - Get another -1285 07AE F5 PUSH AF ; Save Carry status -1286 07AF CD 66 0C CALL ATOH ; Get line number into DE -1287 07B2 D5 PUSH DE ; Save line number -1288 07B3 CD 9E 08 CALL CRUNCH ; Tokenise rest of line -1289 07B6 47 LD B,A ; Length of tokenised line -1290 07B7 D1 POP DE ; Restore line number -1291 07B8 F1 POP AF ; Restore Carry -1292 07B9 D2 7A 0B JP NC,EXCUTE ; No line number - Direct mode -1293 07BC D5 PUSH DE ; Save line number -1294 07BD C5 PUSH BC ; Save length of tokenised line -1295 07BE AF XOR A -1296 07BF 32 7C 31 LD (LSTBIN),A ; Clear last byte input -1297 07C2 CD 9A 0B CALL GETCHR ; Get next character -1298 07C5 B7 OR A ; Set flags -1299 07C6 F5 PUSH AF ; And save them -1300 07C7 CD 2E 08 CALL SRCHLN ; Search for line number in DE -1301 07CA DA D3 07 JP C,LINFND ; Jump if line found -1302 07CD F1 POP AF ; Get status -1303 07CE F5 PUSH AF ; And re-save -1304 07CF CA 07 0D JP Z,ULERR ; Nothing after number - Error -1305 07D2 B7 OR A ; Clear Carry -1306 07D3 C5 LINFND: PUSH BC ; Save address of line in prog -1307 07D4 D2 EA 07 JP NC,INEWLN ; Line not found - Insert new -1308 07D7 EB EX DE,HL ; Next line address in DE -1309 07D8 2A 86 31 LD HL,(PROGND) ; End of program -1310 07DB 1A SFTPRG: LD A,(DE) ; Shift rest of program down -1311 07DC 02 LD (BC),A -1312 07DD 03 INC BC ; Next destination -1313 07DE 13 INC DE ; Next source -1314 07DF CD 0A 0A CALL CPDEHL ; All done? -1315 07E2 C2 DB 07 JP NZ,SFTPRG ; More to do -1316 07E5 60 LD H,B ; HL - New end of program -1317 07E6 69 LD L,C -1318 07E7 22 86 31 LD (PROGND),HL ; Update end of program -1319 07EA -1320 07EA D1 INEWLN: POP DE ; Get address of line, -1321 07EB F1 POP AF ; Get status -1322 07EC CA 11 08 JP Z,SETPTR ; No text - Set up pointers -1323 07EF 2A 86 31 LD HL,(PROGND) ; Get end of program -1324 07F2 E3 EX (SP),HL ; Get length of input line -1325 07F3 C1 POP BC ; End of program to BC -1326 07F4 09 ADD HL,BC ; Find new end -1327 07F5 E5 PUSH HL ; Save new end -1328 07F6 CD 0E 07 CALL MOVUP ; Make space for line -1329 07F9 E1 POP HL ; Restore new end -1330 07FA 22 86 31 LD (PROGND),HL ; Update end of program pointer -1331 07FD EB EX DE,HL ; Get line to move up in HL -1332 07FE 74 LD (HL),H ; Save MSB -1333 07FF D1 POP DE ; Get new line number -1334 0800 23 INC HL ; Skip pointer -1335 0801 23 INC HL -1336 0802 73 LD (HL),E ; Save LSB of line number -1337 0803 23 INC HL -1338 0804 72 LD (HL),D ; Save MSB of line number -1339 0805 23 INC HL ; To first byte in line -1340 0806 11 11 31 LD DE,BUFFER ; Copy buffer to program -1341 0809 1A MOVBUF: LD A,(DE) ; Get source -1342 080A 77 LD (HL),A ; Save destinations -1343 080B 23 INC HL ; Next source -1344 080C 13 INC DE ; Next destination -1345 080D B7 OR A ; Done? -1346 080E C2 09 08 JP NZ,MOVBUF ; No - Repeat -1347 0811 CD 5A 08 SETPTR: CALL RUNFST ; Set line pointers -1348 0814 23 INC HL ; To LSB of pointer -1349 0815 EB EX DE,HL ; Address to DE -1350 0816 62 PTRLP: LD H,D ; Address to HL -1351 0817 6B LD L,E -1352 0818 7E LD A,(HL) ; Get LSB of pointer -1353 0819 23 INC HL ; To MSB of pointer -1354 081A B6 OR (HL) ; Compare with MSB pointer -1355 081B CA 9A 07 JP Z,GETCMD ; Get command line if end -1356 081E 23 INC HL ; To LSB of line number -1357 081F 23 INC HL ; Skip line number -1358 0820 23 INC HL ; Point to first byte in line -1359 0821 AF XOR A ; Looking for 00 byte -1360 0822 BE FNDEND: CP (HL) ; Found end of line? -1361 0823 23 INC HL ; Move to next byte -1362 0824 C2 22 08 JP NZ,FNDEND ; No - Keep looking -1363 0827 EB EX DE,HL ; Next line address to HL -1364 0828 73 LD (HL),E ; Save LSB of pointer -1365 0829 23 INC HL -1366 082A 72 LD (HL),D ; Save MSB of pointer -1367 082B C3 16 08 JP PTRLP ; Do next line -1368 082E -1369 082E 2A 0E 31 SRCHLN: LD HL,(BASTXT) ; Start of program text -1370 0831 44 SRCHLP: LD B,H ; BC = Address to look at -1371 0832 4D LD C,L -1372 0833 7E LD A,(HL) ; Get address of next line -1373 0834 23 INC HL -1374 0835 B6 OR (HL) ; End of program found? -1375 0836 2B DEC HL -1376 0837 C8 RET Z ; Yes - Line not found -1377 0838 23 INC HL -1378 0839 23 INC HL -1379 083A 7E LD A,(HL) ; Get LSB of line number -1380 083B 23 INC HL -1381 083C 66 LD H,(HL) ; Get MSB of line number -1382 083D 6F LD L,A -1383 083E CD 0A 0A CALL CPDEHL ; Compare with line in DE -1384 0841 60 LD H,B ; HL = Start of this line -1385 0842 69 LD L,C -1386 0843 7E LD A,(HL) ; Get LSB of next line address -1387 0844 23 INC HL -1388 0845 66 LD H,(HL) ; Get MSB of next line address -1389 0846 6F LD L,A ; Next line to HL -1390 0847 3F CCF -1391 0848 C8 RET Z ; Lines found - Exit -1392 0849 3F CCF -1393 084A D0 RET NC ; Line not found,at line after -1394 084B C3 31 08 JP SRCHLP ; Keep looking -1395 084E -1396 084E C0 NEW: RET NZ ; Return if any more on line -1397 084F 2A 0E 31 CLRPTR: LD HL,(BASTXT) ; Point to start of program -1398 0852 AF XOR A ; Set program area to empty -1399 0853 77 LD (HL),A ; Save LSB = 00 -1400 0854 23 INC HL -1401 0855 77 LD (HL),A ; Save MSB = 00 -1402 0856 23 INC HL -1403 0857 22 86 31 LD (PROGND),HL ; Set program end -1404 085A -1405 085A 2A 0E 31 RUNFST: LD HL,(BASTXT) ; Clear all variables -1406 085D 2B DEC HL -1407 085E -1408 085E 22 7E 31 INTVAR: LD (BRKLIN),HL ; Initialise RUN variables -1409 0861 2A 5F 31 LD HL,(LSTRAM) ; Get end of RAM -1410 0864 22 73 31 LD (STRBOT),HL ; Clear string space -1411 0867 AF XOR A -1412 0868 CD AA 0B CALL RESTOR ; Reset DATA pointers -1413 086B 2A 86 31 LD HL,(PROGND) ; Get end of program -1414 086E 22 88 31 LD (VAREND),HL ; Clear variables -1415 0871 22 8A 31 LD (ARREND),HL ; Clear arrays -1416 0874 -1417 0874 C1 CLREG: POP BC ; Save return address -1418 0875 2A 0A 31 LD HL,(STRSPC) ; Get end of working RAN -1419 0878 F9 LD SP,HL ; Set stack -1420 0879 21 63 31 LD HL,TMSTPL ; Temporary string pool -1421 087C 22 61 31 LD (TMSTPT),HL ; Reset temporary string ptr -1422 087F AF XOR A ; A = 00 -1423 0880 6F LD L,A ; HL = 0000 -1424 0881 67 LD H,A -1425 0882 22 84 31 LD (CONTAD),HL ; No CONTinue -1426 0885 32 7B 31 LD (FORFLG),A ; Clear FOR flag -1427 0888 22 8E 31 LD (FNRGNM),HL ; Clear FN argument -1428 088B E5 PUSH HL ; HL = 0000 -1429 088C C5 PUSH BC ; Put back return -1430 088D 2A 7E 31 DOAGN: LD HL,(BRKLIN) ; Get address of code to RUN -1431 0890 C9 RET ; Return to execution driver -1432 0891 -1433 0891 3E 3F PROMPT: LD A,'?' ; '?' -1434 0893 CD 1B 0A CALL OUTC ; Output character -1435 0896 3E 20 LD A,' ' ; Space -1436 0898 CD 1B 0A CALL OUTC ; Output character -1437 089B C3 FE 30 JP RINPUT ; Get input line -1438 089E -1439 089E AF CRUNCH: XOR A ; Tokenise line @ HL to BUFFER -1440 089F 32 5E 31 LD (DATFLG),A ; Reset literal flag -1441 08A2 0E 05 LD C,2+3 ; 2 byte number and 3 nulls -1442 08A4 11 11 31 LD DE,BUFFER ; Start of input buffer -1443 08A7 7E CRNCLP: LD A,(HL) ; Get byte -1444 08A8 FE 20 CP ' ' ; Is it a space? -1445 08AA CA 26 09 JP Z,MOVDIR ; Yes - Copy direct -1446 08AD 47 LD B,A ; Save character -1447 08AE FE 22 CP '"' ; Is it a quote? -1448 08B0 CA 46 09 JP Z,CPYLIT ; Yes - Copy literal string -1449 08B3 B7 OR A ; Is it end of buffer? -1450 08B4 CA 4D 09 JP Z,ENDBUF ; Yes - End buffer -1451 08B7 3A 5E 31 LD A,(DATFLG) ; Get data type -1452 08BA B7 OR A ; Literal? -1453 08BB 7E LD A,(HL) ; Get byte to copy -1454 08BC C2 26 09 JP NZ,MOVDIR ; Literal - Copy direct -1455 08BF FE 3F CP '?' ; Is it '?' short for PRINT -1456 08C1 3E 9E LD A,ZPRINT ; "PRINT" token -1457 08C3 CA 26 09 JP Z,MOVDIR ; Yes - replace it -1458 08C6 7E LD A,(HL) ; Get byte again -1459 08C7 FE 30 CP '0' ; Is it less than '0' -1460 08C9 DA D1 08 JP C,FNDWRD ; Yes - Look for reserved words -1461 08CC FE 3C CP 60; ";"+1 ; Is it "0123456789:;" ? -1462 08CE DA 26 09 JP C,MOVDIR ; Yes - copy it direct -1463 08D1 D5 FNDWRD: PUSH DE ; Look for reserved words -1464 08D2 11 CA 04 LD DE,WORDS-1 ; Point to table -1465 08D5 C5 PUSH BC ; Save count -1466 08D6 01 22 09 LD BC,RETNAD ; Where to return to -1467 08D9 C5 PUSH BC ; Save return address -1468 08DA 06 7F LD B,ZEND-1 ; First token value -1 -1469 08DC 7E LD A,(HL) ; Get byte -1470 08DD FE 61 CP 'a' ; Less than 'a' ? -1471 08DF DA EA 08 JP C,SEARCH ; Yes - search for words -1472 08E2 FE 7B CP 'z'+1 ; Greater than 'z' ? -1473 08E4 D2 EA 08 JP NC,SEARCH ; Yes - search for words -1474 08E7 E6 5F AND 01011111B ; Force upper case -1475 08E9 77 LD (HL),A ; Replace byte -1476 08EA 4E SEARCH: LD C,(HL) ; Search for a word -1477 08EB EB EX DE,HL -1478 08EC 23 GETNXT: INC HL ; Get next reserved word -1479 08ED B6 OR (HL) ; Start of word? -1480 08EE F2 EC 08 JP P,GETNXT ; No - move on -1481 08F1 04 INC B ; Increment token value -1482 08F2 7E LD A, (HL) ; Get byte from table -1483 08F3 E6 7F AND 01111111B ; Strip bit 7 -1484 08F5 C8 RET Z ; Return if end of list -1485 08F6 B9 CP C ; Same character as in buffer? -1486 08F7 C2 EC 08 JP NZ,GETNXT ; No - get next word -1487 08FA EB EX DE,HL -1488 08FB E5 PUSH HL ; Save start of word -1489 08FC -1490 08FC 13 NXTBYT: INC DE ; Look through rest of word -1491 08FD 1A LD A,(DE) ; Get byte from table -1492 08FE B7 OR A ; End of word ? -1493 08FF FA 1E 09 JP M,MATCH ; Yes - Match found -1494 0902 4F LD C,A ; Save it -1495 0903 78 LD A,B ; Get token value -1496 0904 FE 88 CP ZGOTO ; Is it "GOTO" token ? -1497 0906 C2 0D 09 JP NZ,NOSPC ; No - Don't allow spaces -1498 0909 CD 9A 0B CALL GETCHR ; Get next character -1499 090C 2B DEC HL ; Cancel increment from GETCHR -1500 090D 23 NOSPC: INC HL ; Next byte -1501 090E 7E LD A,(HL) ; Get byte -1502 090F FE 61 CP 'a' ; Less than 'a' ? -1503 0911 DA 16 09 JP C,NOCHNG ; Yes - don't change -1504 0914 E6 5F AND 01011111B ; Make upper case -1505 0916 B9 NOCHNG: CP C ; Same as in buffer ? -1506 0917 CA FC 08 JP Z,NXTBYT ; Yes - keep testing -1507 091A E1 POP HL ; Get back start of word -1508 091B C3 EA 08 JP SEARCH ; Look at next word -1509 091E -1510 091E 48 MATCH: LD C,B ; Word found - Save token value -1511 091F F1 POP AF ; Throw away return -1512 0920 EB EX DE,HL -1513 0921 C9 RET ; Return to "RETNAD" -1514 0922 EB RETNAD: EX DE,HL ; Get address in string -1515 0923 79 LD A,C ; Get token value -1516 0924 C1 POP BC ; Restore buffer length -1517 0925 D1 POP DE ; Get destination address -1518 0926 23 MOVDIR: INC HL ; Next source in buffer -1519 0927 12 LD (DE),A ; Put byte in buffer -1520 0928 13 INC DE ; Move up buffer -1521 0929 0C INC C ; Increment length of buffer -1522 092A D6 3A SUB ':' ; End of statement? -1523 092C CA 34 09 JP Z,SETLIT ; Jump if multi-statement line -1524 092F FE 49 CP ZDATA-3AH ; Is it DATA statement ? -1525 0931 C2 37 09 JP NZ,TSTREM ; No - see if REM -1526 0934 32 5E 31 SETLIT: LD (DATFLG),A ; Set literal flag -1527 0937 D6 54 TSTREM: SUB ZREM-3AH ; Is it REM? -1528 0939 C2 A7 08 JP NZ,CRNCLP ; No - Leave flag -1529 093C 47 LD B,A ; Copy rest of buffer -1530 093D 7E NXTCHR: LD A,(HL) ; Get byte -1531 093E B7 OR A ; End of line ? -1532 093F CA 4D 09 JP Z,ENDBUF ; Yes - Terminate buffer -1533 0942 B8 CP B ; End of statement ? -1534 0943 CA 26 09 JP Z,MOVDIR ; Yes - Get next one -1535 0946 23 CPYLIT: INC HL ; Move up source string -1536 0947 12 LD (DE),A ; Save in destination -1537 0948 0C INC C ; Increment length -1538 0949 13 INC DE ; Move up destination -1539 094A C3 3D 09 JP NXTCHR ; Repeat -1540 094D -1541 094D 21 10 31 ENDBUF: LD HL,BUFFER-1 ; Point to start of buffer -1542 0950 12 LD (DE),A ; Mark end of buffer (A = 00) -1543 0951 13 INC DE -1544 0952 12 LD (DE),A ; A = 00 -1545 0953 13 INC DE -1546 0954 12 LD (DE),A ; A = 00 -1547 0955 C9 RET -1548 0956 -1549 0956 3A F4 30 DODEL: LD A,(NULFLG) ; Get null flag status -1550 0959 B7 OR A ; Is it zero? -1551 095A 3E 00 LD A,0 ; Zero A - Leave flags -1552 095C 32 F4 30 LD (NULFLG),A ; Zero null flag -1553 095F C2 6A 09 JP NZ,ECHDEL ; Set - Echo it -1554 0962 05 DEC B ; Decrement length -1555 0963 CA 87 09 JP Z,GETLIN ; Get line again if empty -1556 0966 CD 1B 0A CALL OUTC ; Output null character -1557 0969 3E .BYTE 3EH ; Skip "DEC B" -1558 096A 05 ECHDEL: DEC B ; Count bytes in buffer -1559 096B 2B DEC HL ; Back space buffer -1560 096C CA 7E 09 JP Z,OTKLN ; No buffer - Try again -1561 096F 7E LD A,(HL) ; Get deleted byte -1562 0970 CD 1B 0A CALL OUTC ; Echo it -1563 0973 C3 90 09 JP MORINP ; Get more input -1564 0976 -1565 0976 05 DELCHR: DEC B ; Count bytes in buffer -1566 0977 2B DEC HL ; Back space buffer -1567 0978 CD 1B 0A CALL OUTC ; Output character in A -1568 097B C2 90 09 JP NZ,MORINP ; Not end - Get more -1569 097E CD 1B 0A OTKLN: CALL OUTC ; Output character in A -1570 0981 CD 42 0E KILIN: CALL PRNTCRLF ; Output CRLF -1571 0984 C3 87 09 JP TTYLIN ; Get line again -1572 0987 -1573 0987 GETLIN: -1574 0987 21 11 31 TTYLIN: LD HL,BUFFER ; Get a line by character -1575 098A 06 01 LD B,1 ; Set buffer as empty -1576 098C AF XOR A -1577 098D 32 F4 30 LD (NULFLG),A ; Clear null flag -1578 0990 CD 45 0A MORINP: CALL CLOTST ; Get character and test ^O -1579 0993 4F LD C,A ; Save character in C -1580 0994 FE 7F CP DEL ; Delete character? -1581 0996 CA 56 09 JP Z,DODEL ; Yes - Process it -1582 0999 3A F4 30 LD A,(NULFLG) ; Get null flag -1583 099C B7 OR A ; Test null flag status -1584 099D CA A9 09 JP Z,PROCES ; Reset - Process character -1585 09A0 3E 00 LD A,0 ; Set a null -1586 09A2 CD 1B 0A CALL OUTC ; Output null -1587 09A5 AF XOR A ; Clear A -1588 09A6 32 F4 30 LD (NULFLG),A ; Reset null flag -1589 09A9 79 PROCES: LD A,C ; Get character -1590 09AA FE 07 CP CTRLG ; Bell? -1591 09AC CA ED 09 JP Z,PUTCTL ; Yes - Save it -1592 09AF FE 03 CP CTRLC ; Is it control "C"? -1593 09B1 CC 42 0E CALL Z,PRNTCRLF ; Yes - Output CRLF -1594 09B4 37 SCF ; Flag break -1595 09B5 C8 RET Z ; Return if control "C" -1596 09B6 FE 0D CP CR ; Is it enter? -1597 09B8 CA 3D 0E JP Z,ENDINP ; Yes - Terminate input -1598 09BB FE 15 CP CTRLU ; Is it control "U"? -1599 09BD CA 81 09 JP Z,KILIN ; Yes - Get another line -1600 09C0 FE 40 CP '@' ; Is it "kill line"? -1601 09C2 CA 7E 09 JP Z,OTKLN ; Yes - Kill line -1602 09C5 FE 5F CP '_' ; Is it delete? -1603 09C7 CA 76 09 JP Z,DELCHR ; Yes - Delete character -1604 09CA FE 08 CP BKSP ; Is it backspace? -1605 09CC CA 76 09 JP Z,DELCHR ; Yes - Delete character -1606 09CF FE 12 CP CTRLR ; Is it control "R"? -1607 09D1 C2 E8 09 JP NZ,PUTBUF ; No - Put in buffer -1608 09D4 C5 PUSH BC ; Save buffer length -1609 09D5 D5 PUSH DE ; Save DE -1610 09D6 E5 PUSH HL ; Save buffer address -1611 09D7 36 00 LD (HL),0 ; Mark end of buffer -1612 09D9 CD F2 1F CALL OUTNCR ; Output and do CRLF -1613 09DC 21 11 31 LD HL,BUFFER ; Point to buffer start -1614 09DF CD E0 14 CALL PRS ; Output buffer -1615 09E2 E1 POP HL ; Restore buffer address -1616 09E3 D1 POP DE ; Restore DE -1617 09E4 C1 POP BC ; Restore buffer length -1618 09E5 C3 90 09 JP MORINP ; Get another character -1619 09E8 -1620 09E8 FE 20 PUTBUF: CP ' ' ; Is it a control code? -1621 09EA DA 90 09 JP C,MORINP ; Yes - Ignore -1622 09ED 78 PUTCTL: LD A,B ; Get number of bytes in buffer -1623 09EE FE 49 CP 72+1 ; Test for line overflow -1624 09F0 3E 07 LD A,CTRLG ; Set a bell -1625 09F2 D2 02 0A JP NC,OUTNBS ; Ring bell if buffer full -1626 09F5 79 LD A,C ; Get character -1627 09F6 71 LD (HL),C ; Save in buffer -1628 09F7 32 7C 31 LD (LSTBIN),A ; Save last input byte -1629 09FA 23 INC HL ; Move up buffer -1630 09FB 04 INC B ; Increment length -1631 09FC CD 1B 0A OUTIT: CALL OUTC ; Output the character entered -1632 09FF C3 90 09 JP MORINP ; Get another character -1633 0A02 -1634 0A02 CD 1B 0A OUTNBS: CALL OUTC ; Output bell and back over it -1635 0A05 3E 08 LD A,BKSP ; Set back space -1636 0A07 C3 FC 09 JP OUTIT ; Output it and get more -1637 0A0A -1638 0A0A 7C CPDEHL: LD A,H ; Get H -1639 0A0B 92 SUB D ; Compare with D -1640 0A0C C0 RET NZ ; Different - Exit -1641 0A0D 7D LD A,L ; Get L -1642 0A0E 93 SUB E ; Compare with E -1643 0A0F C9 RET ; Return status -1644 0A10 -1645 0A10 7E CHKSYN: LD A,(HL) ; Check syntax of character -1646 0A11 E3 EX (SP),HL ; Address of test byte -1647 0A12 BE CP (HL) ; Same as in code string? -1648 0A13 23 INC HL ; Return address -1649 0A14 E3 EX (SP),HL ; Put it back -1650 0A15 CA 9A 0B JP Z,GETCHR ; Yes - Get next character -1651 0A18 C3 42 07 JP SNERR ; Different - ?SN Error -1652 0A1B -1653 0A1B F5 OUTC: PUSH AF ; Save character -1654 0A1C 3A F5 30 LD A,(CTLOFG) ; Get control "O" flag -1655 0A1F B7 OR A ; Is it set? -1656 0A20 C2 15 15 JP NZ,POPAF ; Yes - don't output -1657 0A23 F1 POP AF ; Restore character -1658 0A24 C5 PUSH BC ; Save buffer length -1659 0A25 F5 PUSH AF ; Save character -1660 0A26 FE 20 CP ' ' ; Is it a control code? -1661 0A28 DA 3F 0A JP C,DINPOS ; Yes - Don't INC POS(X) -1662 0A2B 3A F2 30 LD A,(LWIDTH) ; Get line width -1663 0A2E 47 LD B,A ; To B -1664 0A2F 3A 5B 31 LD A,(CURPOS) ; Get cursor position -1665 0A32 04 INC B ; Width 255? -1666 0A33 CA 3B 0A JP Z,INCLEN ; Yes - No width limit -1667 0A36 05 DEC B ; Restore width -1668 0A37 B8 CP B ; At end of line? -1669 0A38 CC 42 0E CALL Z,PRNTCRLF ; Yes - output CRLF -1670 0A3B 3C INCLEN: INC A ; Move on one character -1671 0A3C 32 5B 31 LD (CURPOS),A ; Save new position -1672 0A3F F1 DINPOS: POP AF ; Restore character -1673 0A40 C1 POP BC ; Restore buffer length -1674 0A41 CD DB 1F CALL MONOUT ; Send it -1675 0A44 C9 RET -1676 0A45 -1677 0A45 CD 9F 1E CLOTST: CALL GETINP ; Get input character -1678 0A48 E6 7F AND 01111111B ; Strip bit 7 -1679 0A4A FE 0F CP CTRLO ; Is it control "O"? -1680 0A4C C0 RET NZ ; No don't flip flag -1681 0A4D 3A F5 30 LD A,(CTLOFG) ; Get flag -1682 0A50 2F CPL ; Flip it -1683 0A51 32 F5 30 LD (CTLOFG),A ; Put it back -1684 0A54 AF XOR A ; Null character -1685 0A55 C9 RET -1686 0A56 -1687 0A56 CD 66 0C LIST: CALL ATOH ; ASCII number to DE -1688 0A59 C0 RET NZ ; Return if anything extra -1689 0A5A C1 POP BC ; Rubbish - Not needed -1690 0A5B CD 2E 08 CALL SRCHLN ; Search for line number in DE -1691 0A5E C5 PUSH BC ; Save address of line -1692 0A5F CD AC 0A CALL SETLIN ; Set up lines counter -1693 0A62 E1 LISTLP: POP HL ; Restore address of line -1694 0A63 4E LD C,(HL) ; Get LSB of next line -1695 0A64 23 INC HL -1696 0A65 46 LD B,(HL) ; Get MSB of next line -1697 0A66 23 INC HL -1698 0A67 78 LD A,B ; BC = 0 (End of program)? -1699 0A68 B1 OR C -1700 0A69 CA 8D 07 JP Z,PRNTOK ; Yes - Go to command mode -1701 0A6C CD B5 0A CALL COUNT ; Count lines -1702 0A6F CD C5 0B CALL TSTBRK ; Test for break key -1703 0A72 C5 PUSH BC ; Save address of next line -1704 0A73 CD 42 0E CALL PRNTCRLF ; Output CRLF -1705 0A76 5E LD E,(HL) ; Get LSB of line number -1706 0A77 23 INC HL -1707 0A78 56 LD D,(HL) ; Get MSB of line number -1708 0A79 23 INC HL -1709 0A7A E5 PUSH HL ; Save address of line start -1710 0A7B EB EX DE,HL ; Line number to HL -1711 0A7C CD 83 1B CALL PRNTHL ; Output line number in decimal -1712 0A7F 3E 20 LD A,' ' ; Space after line number -1713 0A81 E1 POP HL ; Restore start of line address -1714 0A82 CD 1B 0A LSTLP2: CALL OUTC ; Output character in A -1715 0A85 7E LSTLP3: LD A,(HL) ; Get next byte in line -1716 0A86 B7 OR A ; End of line? -1717 0A87 23 INC HL ; To next byte in line -1718 0A88 CA 62 0A JP Z,LISTLP ; Yes - get next line -1719 0A8B F2 82 0A JP P,LSTLP2 ; No token - output it -1720 0A8E D6 7F SUB ZEND-1 ; Find and output word -1721 0A90 4F LD C,A ; Token offset+1 to C -1722 0A91 11 CB 04 LD DE,WORDS ; Reserved word list -1723 0A94 1A FNDTOK: LD A,(DE) ; Get character in list -1724 0A95 13 INC DE ; Move on to next -1725 0A96 B7 OR A ; Is it start of word? -1726 0A97 F2 94 0A JP P,FNDTOK ; No - Keep looking for word -1727 0A9A 0D DEC C ; Count words -1728 0A9B C2 94 0A JP NZ,FNDTOK ; Not there - keep looking -1729 0A9E E6 7F OUTWRD: AND 01111111B ; Strip bit 7 -1730 0AA0 CD 1B 0A CALL OUTC ; Output first character -1731 0AA3 1A LD A,(DE) ; Get next character -1732 0AA4 13 INC DE ; Move on to next -1733 0AA5 B7 OR A ; Is it end of word? -1734 0AA6 F2 9E 0A JP P,OUTWRD ; No - output the rest -1735 0AA9 C3 85 0A JP LSTLP3 ; Next byte in line -1736 0AAC -1737 0AAC E5 SETLIN: PUSH HL ; Set up LINES counter -1738 0AAD 2A F8 30 LD HL,(LINESN) ; Get LINES number -1739 0AB0 22 F6 30 LD (LINESC),HL ; Save in LINES counter -1740 0AB3 E1 POP HL -1741 0AB4 C9 RET -1742 0AB5 -1743 0AB5 E5 COUNT: PUSH HL ; Save code string address -1744 0AB6 D5 PUSH DE -1745 0AB7 2A F6 30 LD HL,(LINESC) ; Get LINES counter -1746 0ABA 11 FF FF LD DE,-1 -1747 0ABD ED 5A ADC HL,DE ; Decrement -1748 0ABF 22 F6 30 LD (LINESC),HL ; Put it back -1749 0AC2 D1 POP DE -1750 0AC3 E1 POP HL ; Restore code string address -1751 0AC4 F0 RET P ; Return if more lines to go -1752 0AC5 E5 PUSH HL ; Save code string address -1753 0AC6 2A F8 30 LD HL,(LINESN) ; Get LINES number -1754 0AC9 22 F6 30 LD (LINESC),HL ; Reset LINES counter -1755 0ACC CD 9F 1E CALL GETINP ; Get input character -1756 0ACF FE 03 CP CTRLC ; Is it control "C"? -1757 0AD1 CA D8 0A JP Z,RSLNBK ; Yes - Reset LINES and break -1758 0AD4 E1 POP HL ; Restore code string address -1759 0AD5 C3 B5 0A JP COUNT ; Keep on counting -1760 0AD8 -1761 0AD8 2A F8 30 RSLNBK: LD HL,(LINESN) ; Get LINES number -1762 0ADB 22 F6 30 LD (LINESC),HL ; Reset LINES counter -1763 0ADE C3 3C 04 JP BRKRET ; Go and output "Break" -1764 0AE1 -1765 0AE1 3E 64 FOR: LD A,64H ; Flag "FOR" assignment -1766 0AE3 32 7B 31 LD (FORFLG),A ; Save "FOR" flag -1767 0AE6 CD 48 0D CALL LET ; Set up initial index -1768 0AE9 C1 POP BC ; Drop RETurn address -1769 0AEA E5 PUSH HL ; Save code string address -1770 0AEB CD 31 0D CALL DATA ; Get next statement address -1771 0AEE 22 77 31 LD (LOOPST),HL ; Save it for start of loop -1772 0AF1 21 02 00 LD HL,2 ; Offset for "FOR" block -1773 0AF4 39 ADD HL,SP ; Point to it -1774 0AF5 CD EF 06 FORSLP: CALL LOKFOR ; Look for existing "FOR" block -1775 0AF8 D1 POP DE ; Get code string address -1776 0AF9 C2 11 0B JP NZ,FORFND ; No nesting found -1777 0AFC 09 ADD HL,BC ; Move into "FOR" block -1778 0AFD D5 PUSH DE ; Save code string address -1779 0AFE 2B DEC HL -1780 0AFF 56 LD D,(HL) ; Get MSB of loop statement -1781 0B00 2B DEC HL -1782 0B01 5E LD E,(HL) ; Get LSB of loop statement -1783 0B02 23 INC HL -1784 0B03 23 INC HL -1785 0B04 E5 PUSH HL ; Save block address -1786 0B05 2A 77 31 LD HL,(LOOPST) ; Get address of loop statement -1787 0B08 CD 0A 0A CALL CPDEHL ; Compare the FOR loops -1788 0B0B E1 POP HL ; Restore block address -1789 0B0C C2 F5 0A JP NZ,FORSLP ; Different FORs - Find another -1790 0B0F D1 POP DE ; Restore code string address -1791 0B10 F9 LD SP,HL ; Remove all nested loops -1792 0B11 -1793 0B11 EB FORFND: EX DE,HL ; Code string address to HL -1794 0B12 0E 08 LD C,8 -1795 0B14 CD 1F 07 CALL CHKSTK ; Check for 8 levels of stack -1796 0B17 E5 PUSH HL ; Save code string address -1797 0B18 2A 77 31 LD HL,(LOOPST) ; Get first statement of loop -1798 0B1B E3 EX (SP),HL ; Save and restore code string -1799 0B1C E5 PUSH HL ; Re-save code string address -1800 0B1D 2A 0C 31 LD HL,(LINEAT) ; Get current line number -1801 0B20 E3 EX (SP),HL ; Save and restore code string -1802 0B21 CD 0A 10 CALL TSTNUM ; Make sure it's a number -1803 0B24 CD 10 0A CALL CHKSYN ; Make sure "TO" is next -1804 0B27 A6 .BYTE ZTO ; "TO" token -1805 0B28 CD 07 10 CALL GETNUM ; Get "TO" expression value -1806 0B2B E5 PUSH HL ; Save code string address -1807 0B2C CD 35 1A CALL BCDEFP ; Move "TO" value to BCDE -1808 0B2F E1 POP HL ; Restore code string address -1809 0B30 C5 PUSH BC ; Save "TO" value in block -1810 0B31 D5 PUSH DE -1811 0B32 01 00 81 LD BC,8100H ; BCDE - 1 (default STEP) -1812 0B35 51 LD D,C ; C=0 -1813 0B36 5A LD E,D ; D=0 -1814 0B37 7E LD A,(HL) ; Get next byte in code string -1815 0B38 FE AB CP ZSTEP ; See if "STEP" is stated -1816 0B3A 3E 01 LD A,1 ; Sign of step = 1 -1817 0B3C C2 4D 0B JP NZ,SAVSTP ; No STEP given - Default to 1 -1818 0B3F CD 9A 0B CALL GETCHR ; Jump over "STEP" token -1819 0B42 CD 07 10 CALL GETNUM ; Get step value -1820 0B45 E5 PUSH HL ; Save code string address -1821 0B46 CD 35 1A CALL BCDEFP ; Move STEP to BCDE -1822 0B49 CD E9 19 CALL TSTSGN ; Test sign of FPREG -1823 0B4C E1 POP HL ; Restore code string address -1824 0B4D C5 SAVSTP: PUSH BC ; Save the STEP value in block -1825 0B4E D5 PUSH DE -1826 0B4F F5 PUSH AF ; Save sign of STEP -1827 0B50 33 INC SP ; Don't save flags -1828 0B51 E5 PUSH HL ; Save code string address -1829 0B52 2A 7E 31 LD HL,(BRKLIN) ; Get address of index variable -1830 0B55 E3 EX (SP),HL ; Save and restore code string -1831 0B56 06 81 PUTFID: LD B,ZFOR ; "FOR" block marker -1832 0B58 C5 PUSH BC ; Save it -1833 0B59 33 INC SP ; Don't save C -1834 0B5A -1835 0B5A CD C5 0B RUNCNT: CALL TSTBRK ; Execution driver - Test break -1836 0B5D 22 7E 31 LD (BRKLIN),HL ; Save code address for break -1837 0B60 7E LD A,(HL) ; Get next byte in code string -1838 0B61 FE 3A CP ':' ; Multi statement line? -1839 0B63 CA 7A 0B JP Z,EXCUTE ; Yes - Execute it -1840 0B66 B7 OR A ; End of line? -1841 0B67 C2 42 07 JP NZ,SNERR ; No - Syntax error -1842 0B6A 23 INC HL ; Point to address of next line -1843 0B6B 7E LD A,(HL) ; Get LSB of line pointer -1844 0B6C 23 INC HL -1845 0B6D B6 OR (HL) ; Is it zero (End of prog)? -1846 0B6E CA EC 0B JP Z,ENDPRG ; Yes - Terminate execution -1847 0B71 23 INC HL ; Point to line number -1848 0B72 5E LD E,(HL) ; Get LSB of line number -1849 0B73 23 INC HL -1850 0B74 56 LD D,(HL) ; Get MSB of line number -1851 0B75 EB EX DE,HL ; Line number to HL -1852 0B76 22 0C 31 LD (LINEAT),HL ; Save as current line number -1853 0B79 EB EX DE,HL ; Line number back to DE -1854 0B7A CD 9A 0B EXCUTE: CALL GETCHR ; Get key word -1855 0B7D 11 5A 0B LD DE,RUNCNT ; Where to RETurn to -1856 0B80 D5 PUSH DE ; Save for RETurn -1857 0B81 C8 IFJMP: RET Z ; Go to RUNCNT if end of STMT -1858 0B82 D6 80 ONJMP: SUB ZEND ; Is it a token? -1859 0B84 DA 48 0D JP C,LET ; No - try to assign it -1860 0B87 FE 25 CP ZNEW+1-ZEND ; END to NEW ? -1861 0B89 D2 42 07 JP NC,SNERR ; Not a key word - ?SN Error -1862 0B8C 07 RLCA ; Double it -1863 0B8D 4F LD C,A ; BC = Offset into table -1864 0B8E 06 00 LD B,0 -1865 0B90 EB EX DE,HL ; Save code string address -1866 0B91 21 EA 05 LD HL,WORDTB ; Keyword address table -1867 0B94 09 ADD HL,BC ; Point to routine address -1868 0B95 4E LD C,(HL) ; Get LSB of routine address -1869 0B96 23 INC HL -1870 0B97 46 LD B,(HL) ; Get MSB of routine address -1871 0B98 C5 PUSH BC ; Save routine address -1872 0B99 EB EX DE,HL ; Restore code string address -1873 0B9A -1874 0B9A 23 GETCHR: INC HL ; Point to next character -1875 0B9B 7E LD A,(HL) ; Get next code string byte -1876 0B9C FE 3A CP ':' ; Z if ':' -1877 0B9E D0 RET NC ; NC if > "9" -1878 0B9F FE 20 CP ' ' -1879 0BA1 CA 9A 0B JP Z,GETCHR ; Skip over spaces -1880 0BA4 FE 30 CP '0' -1881 0BA6 3F CCF ; NC if < '0' -1882 0BA7 3C INC A ; Test for zero - Leave carry -1883 0BA8 3D DEC A ; Z if Null -1884 0BA9 C9 RET -1885 0BAA -1886 0BAA EB RESTOR: EX DE,HL ; Save code string address -1887 0BAB 2A 0E 31 LD HL,(BASTXT) ; Point to start of program -1888 0BAE CA BF 0B JP Z,RESTNL ; Just RESTORE - reset pointer -1889 0BB1 EB EX DE,HL ; Restore code string address -1890 0BB2 CD 66 0C CALL ATOH ; Get line number to DE -1891 0BB5 E5 PUSH HL ; Save code string address -1892 0BB6 CD 2E 08 CALL SRCHLN ; Search for line number in DE -1893 0BB9 60 LD H,B ; HL = Address of line -1894 0BBA 69 LD L,C -1895 0BBB D1 POP DE ; Restore code string address -1896 0BBC D2 07 0D JP NC,ULERR ; ?UL Error if not found -1897 0BBF 2B RESTNL: DEC HL ; Byte before DATA statement -1898 0BC0 22 8C 31 UPDATA: LD (NXTDAT),HL ; Update DATA pointer -1899 0BC3 EB EX DE,HL ; Restore code string address -1900 0BC4 C9 RET -1901 0BC5 -1902 0BC5 -1903 0BC5 DF TSTBRK: RST 18H ; Check input status -1904 0BC6 C8 RET Z ; No key, go back -1905 0BC7 D7 RST 10H ; Get the key into A -1906 0BC8 FE 1B CP ESC ; Escape key? -1907 0BCA 28 11 JR Z,BRK ; Yes, break -1908 0BCC FE 03 CP CTRLC ; -1909 0BCE 28 0D JR Z,BRK ; Yes, break -1910 0BD0 FE 13 CP CTRLS ; Stop scrolling? -1911 0BD2 C0 RET NZ ; Other key, ignore -1912 0BD3 -1913 0BD3 -1914 0BD3 D7 STALL: RST 10H ; Wait for key -1915 0BD4 FE 11 CP CTRLQ ; Resume scrolling? -1916 0BD6 C8 RET Z ; Release the chokehold -1917 0BD7 FE 03 CP CTRLC ; Second break? -1918 0BD9 28 07 JR Z,STOP ; Break during hold exits prog -1919 0BDB 18 F6 JR STALL ; Loop until or -1920 0BDD -1921 0BDD 3E FF BRK LD A,$FF ; Set BRKFLG -1922 0BDF 32 FD 30 LD (BRKFLG),A ; Store it -1923 0BE2 -1924 0BE2 -1925 0BE2 C0 STOP: RET NZ ; Exit if anything else -1926 0BE3 F6 .BYTE 0F6H ; Flag "STOP" -1927 0BE4 C0 PEND: RET NZ ; Exit if anything else -1928 0BE5 22 7E 31 LD (BRKLIN),HL ; Save point of break -1929 0BE8 21 .BYTE 21H ; Skip "OR 11111111B" -1930 0BE9 F6 FF INPBRK: OR 11111111B ; Flag "Break" wanted -1931 0BEB C1 POP BC ; Return not needed and more -1932 0BEC 2A 0C 31 ENDPRG: LD HL,(LINEAT) ; Get current line number -1933 0BEF F5 PUSH AF ; Save STOP / END status -1934 0BF0 7D LD A,L ; Is it direct break? -1935 0BF1 A4 AND H -1936 0BF2 3C INC A ; Line is -1 if direct break -1937 0BF3 CA FF 0B JP Z,NOLIN ; Yes - No line number -1938 0BF6 22 82 31 LD (ERRLIN),HL ; Save line of break -1939 0BF9 2A 7E 31 LD HL,(BRKLIN) ; Get point of break -1940 0BFC 22 84 31 LD (CONTAD),HL ; Save point to CONTinue -1941 0BFF AF NOLIN: XOR A -1942 0C00 32 F5 30 LD (CTLOFG),A ; Enable output -1943 0C03 CD 35 0E CALL STTLIN ; Start a new line -1944 0C06 F1 POP AF ; Restore STOP / END status -1945 0C07 21 E5 06 LD HL,BRKMSG ; "Break" message -1946 0C0A C2 76 07 JP NZ,ERRIN ; "in line" wanted? -1947 0C0D C3 8D 07 JP PRNTOK ; Go to command mode -1948 0C10 -1949 0C10 2A 84 31 CONT: LD HL,(CONTAD) ; Get CONTinue address -1950 0C13 7C LD A,H ; Is it zero? -1951 0C14 B5 OR L -1952 0C15 1E 20 LD E,CN ; ?CN Error -1953 0C17 CA 56 07 JP Z,ERROR ; Yes - output "?CN Error" -1954 0C1A EB EX DE,HL ; Save code string address -1955 0C1B 2A 82 31 LD HL,(ERRLIN) ; Get line of last break -1956 0C1E 22 0C 31 LD (LINEAT),HL ; Set up current line number -1957 0C21 EB EX DE,HL ; Restore code string address -1958 0C22 C9 RET ; CONTinue where left off -1959 0C23 -1960 0C23 CD 68 17 NULL: CALL GETINT ; Get integer 0-255 -1961 0C26 C0 RET NZ ; Return if bad value -1962 0C27 32 F1 30 LD (NULLS),A ; Set nulls number -1963 0C2A C9 RET -1964 0C2B -1965 0C2B -1966 0C2B E5 ACCSUM: PUSH HL ; Save address in array -1967 0C2C 2A FA 30 LD HL,(CHKSUM) ; Get check sum -1968 0C2F 06 00 LD B,0 ; BC - Value of byte -1969 0C31 4F LD C,A -1970 0C32 09 ADD HL,BC ; Add byte to check sum -1971 0C33 22 FA 30 LD (CHKSUM),HL ; Re-save check sum -1972 0C36 E1 POP HL ; Restore address in array -1973 0C37 C9 RET -1974 0C38 -1975 0C38 7E CHKLTR: LD A,(HL) ; Get byte -1976 0C39 FE 41 CP 'A' ; < 'a' ? -1977 0C3B D8 RET C ; Carry set if not letter -1978 0C3C FE 5B CP 'Z'+1 ; > 'z' ? -1979 0C3E 3F CCF -1980 0C3F C9 RET ; Carry set if not letter -1981 0C40 -1982 0C40 CD 9A 0B FPSINT: CALL GETCHR ; Get next character -1983 0C43 CD 07 10 POSINT: CALL GETNUM ; Get integer 0 to 32767 -1984 0C46 CD E9 19 DEPINT: CALL TSTSGN ; Test sign of FPREG -1985 0C49 FA 61 0C JP M,FCERR ; Negative - ?FC Error -1986 0C4C 3A 97 31 DEINT: LD A,(FPEXP) ; Get integer value to DE -1987 0C4F FE 90 CP 80H+16 ; Exponent in range (16 bits)? -1988 0C51 DA 91 1A JP C,FPINT ; Yes - convert it -1989 0C54 01 80 90 LD BC,9080H ; BCDE = -32768 -1990 0C57 11 00 00 LD DE,0000 -1991 0C5A E5 PUSH HL ; Save code string address -1992 0C5B CD 64 1A CALL CMPNUM ; Compare FPREG with BCDE -1993 0C5E E1 POP HL ; Restore code string address -1994 0C5F 51 LD D,C ; MSB to D -1995 0C60 C8 RET Z ; Return if in range -1996 0C61 1E 08 FCERR: LD E,FC ; ?FC Error -1997 0C63 C3 56 07 JP ERROR ; Output error- -1998 0C66 -1999 0C66 2B ATOH: DEC HL ; ASCII number to DE binary -2000 0C67 11 00 00 GETLN: LD DE,0 ; Get number to DE -2001 0C6A CD 9A 0B GTLNLP: CALL GETCHR ; Get next character -2002 0C6D D0 RET NC ; Exit if not a digit -2003 0C6E E5 PUSH HL ; Save code string address -2004 0C6F F5 PUSH AF ; Save digit -2005 0C70 21 98 19 LD HL,65529/10 ; Largest number 65529 -2006 0C73 CD 0A 0A CALL CPDEHL ; Number in range? -2007 0C76 DA 42 07 JP C,SNERR ; No - ?SN Error -2008 0C79 62 LD H,D ; HL = Number -2009 0C7A 6B LD L,E -2010 0C7B 19 ADD HL,DE ; Times 2 -2011 0C7C 29 ADD HL,HL ; Times 4 -2012 0C7D 19 ADD HL,DE ; Times 5 -2013 0C7E 29 ADD HL,HL ; Times 10 -2014 0C7F F1 POP AF ; Restore digit -2015 0C80 D6 30 SUB '0' ; Make it 0 to 9 -2016 0C82 5F LD E,A ; DE = Value of digit -2017 0C83 16 00 LD D,0 -2018 0C85 19 ADD HL,DE ; Add to number -2019 0C86 EB EX DE,HL ; Number to DE -2020 0C87 E1 POP HL ; Restore code string address -2021 0C88 C3 6A 0C JP GTLNLP ; Go to next character -2022 0C8B -2023 0C8B CA 5E 08 CLEAR: JP Z,INTVAR ; Just "CLEAR" Keep parameters -2024 0C8E CD 43 0C CALL POSINT ; Get integer 0 to 32767 to DE -2025 0C91 2B DEC HL ; Cancel increment -2026 0C92 CD 9A 0B CALL GETCHR ; Get next character -2027 0C95 E5 PUSH HL ; Save code string address -2028 0C96 2A 5F 31 LD HL,(LSTRAM) ; Get end of RAM -2029 0C99 CA AE 0C JP Z,STORED ; No value given - Use stored -2030 0C9C E1 POP HL ; Restore code string address -2031 0C9D CD 10 0A CALL CHKSYN ; Check for comma -2032 0CA0 2C .BYTE ',' -2033 0CA1 D5 PUSH DE ; Save number -2034 0CA2 CD 43 0C CALL POSINT ; Get integer 0 to 32767 -2035 0CA5 2B DEC HL ; Cancel increment -2036 0CA6 CD 9A 0B CALL GETCHR ; Get next character -2037 0CA9 C2 42 07 JP NZ,SNERR ; ?SN Error if more on line -2038 0CAC E3 EX (SP),HL ; Save code string address -2039 0CAD EB EX DE,HL ; Number to DE -2040 0CAE 7D STORED: LD A,L ; Get LSB of new RAM top -2041 0CAF 93 SUB E ; Subtract LSB of string space -2042 0CB0 5F LD E,A ; Save LSB -2043 0CB1 7C LD A,H ; Get MSB of new RAM top -2044 0CB2 9A SBC A,D ; Subtract MSB of string space -2045 0CB3 57 LD D,A ; Save MSB -2046 0CB4 DA 37 07 JP C,OMERR ; ?OM Error if not enough mem -2047 0CB7 E5 PUSH HL ; Save RAM top -2048 0CB8 2A 86 31 LD HL,(PROGND) ; Get program end -2049 0CBB 01 28 00 LD BC,40 ; 40 Bytes minimum working RAM -2050 0CBE 09 ADD HL,BC ; Get lowest address -2051 0CBF CD 0A 0A CALL CPDEHL ; Enough memory? -2052 0CC2 D2 37 07 JP NC,OMERR ; No - ?OM Error -2053 0CC5 EB EX DE,HL ; RAM top to HL -2054 0CC6 22 0A 31 LD (STRSPC),HL ; Set new string space -2055 0CC9 E1 POP HL ; End of memory to use -2056 0CCA 22 5F 31 LD (LSTRAM),HL ; Set new top of RAM -2057 0CCD E1 POP HL ; Restore code string address -2058 0CCE C3 5E 08 JP INTVAR ; Initialise variables -2059 0CD1 -2060 0CD1 CA 5A 08 RUN: JP Z,RUNFST ; RUN from start if just RUN -2061 0CD4 CD 5E 08 CALL INTVAR ; Initialise variables -2062 0CD7 01 5A 0B LD BC,RUNCNT ; Execution driver loop -2063 0CDA C3 ED 0C JP RUNLIN ; RUN from line number -2064 0CDD -2065 0CDD 0E 03 GOSUB: LD C,3 ; 3 Levels of stack needed -2066 0CDF CD 1F 07 CALL CHKSTK ; Check for 3 levels of stack -2067 0CE2 C1 POP BC ; Get return address -2068 0CE3 E5 PUSH HL ; Save code string for RETURN -2069 0CE4 E5 PUSH HL ; And for GOSUB routine -2070 0CE5 2A 0C 31 LD HL,(LINEAT) ; Get current line -2071 0CE8 E3 EX (SP),HL ; Into stack - Code string out -2072 0CE9 3E 8C LD A,ZGOSUB ; "GOSUB" token -2073 0CEB F5 PUSH AF ; Save token -2074 0CEC 33 INC SP ; Don't save flags -2075 0CED -2076 0CED C5 RUNLIN: PUSH BC ; Save return address -2077 0CEE CD 66 0C GOTO: CALL ATOH ; ASCII number to DE binary -2078 0CF1 CD 33 0D CALL REM ; Get end of line -2079 0CF4 E5 PUSH HL ; Save end of line -2080 0CF5 2A 0C 31 LD HL,(LINEAT) ; Get current line -2081 0CF8 CD 0A 0A CALL CPDEHL ; Line after current? -2082 0CFB E1 POP HL ; Restore end of line -2083 0CFC 23 INC HL ; Start of next line -2084 0CFD DC 31 08 CALL C,SRCHLP ; Line is after current line -2085 0D00 D4 2E 08 CALL NC,SRCHLN ; Line is before current line -2086 0D03 60 LD H,B ; Set up code string address -2087 0D04 69 LD L,C -2088 0D05 2B DEC HL ; Incremented after -2089 0D06 D8 RET C ; Line found -2090 0D07 1E 0E ULERR: LD E,UL ; ?UL Error -2091 0D09 C3 56 07 JP ERROR ; Output error message -2092 0D0C -2093 0D0C C0 RETURN: RET NZ ; Return if not just RETURN -2094 0D0D 16 FF LD D,-1 ; Flag "GOSUB" search -2095 0D0F CD EB 06 CALL BAKSTK ; Look "GOSUB" block -2096 0D12 F9 LD SP,HL ; Kill all FORs in subroutine -2097 0D13 FE 8C CP ZGOSUB ; Test for "GOSUB" token -2098 0D15 1E 04 LD E,RG ; ?RG Error -2099 0D17 C2 56 07 JP NZ,ERROR ; Error if no "GOSUB" found -2100 0D1A E1 POP HL ; Get RETURN line number -2101 0D1B 22 0C 31 LD (LINEAT),HL ; Save as current -2102 0D1E 23 INC HL ; Was it from direct statement? -2103 0D1F 7C LD A,H -2104 0D20 B5 OR L ; Return to line -2105 0D21 C2 2B 0D JP NZ,RETLIN ; No - Return to line -2106 0D24 3A 7C 31 LD A,(LSTBIN) ; Any INPUT in subroutine? -2107 0D27 B7 OR A ; If so buffer is corrupted -2108 0D28 C2 8C 07 JP NZ,POPNOK ; Yes - Go to command mode -2109 0D2B 21 5A 0B RETLIN: LD HL,RUNCNT ; Execution driver loop -2110 0D2E E3 EX (SP),HL ; Into stack - Code string out -2111 0D2F 3E .BYTE 3EH ; Skip "POP HL" -2112 0D30 E1 NXTDTA: POP HL ; Restore code string address -2113 0D31 -2114 0D31 01 3A DATA: .BYTE 01H,3AH ; ':' End of statement -2115 0D33 0E 00 REM: LD C,0 ; 00 End of statement -2116 0D35 06 00 LD B,0 -2117 0D37 79 NXTSTL: LD A,C ; Statement and byte -2118 0D38 48 LD C,B -2119 0D39 47 LD B,A ; Statement end byte -2120 0D3A 7E NXTSTT: LD A,(HL) ; Get byte -2121 0D3B B7 OR A ; End of line? -2122 0D3C C8 RET Z ; Yes - Exit -2123 0D3D B8 CP B ; End of statement? -2124 0D3E C8 RET Z ; Yes - Exit -2125 0D3F 23 INC HL ; Next byte -2126 0D40 FE 22 CP '"' ; Literal string? -2127 0D42 CA 37 0D JP Z,NXTSTL ; Yes - Look for another '"' -2128 0D45 C3 3A 0D JP NXTSTT ; Keep looking -2129 0D48 -2130 0D48 CD FD 11 LET: CALL GETVAR ; Get variable name -2131 0D4B CD 10 0A CALL CHKSYN ; Make sure "=" follows -2132 0D4E B4 .BYTE ZEQUAL ; "=" token -2133 0D4F D5 PUSH DE ; Save address of variable -2134 0D50 3A 5D 31 LD A,(TYPE) ; Get data type -2135 0D53 F5 PUSH AF ; Save type -2136 0D54 CD 19 10 CALL EVAL ; Evaluate expression -2137 0D57 F1 POP AF ; Restore type -2138 0D58 E3 EX (SP),HL ; Save code - Get var addr -2139 0D59 22 7E 31 LD (BRKLIN),HL ; Save address of variable -2140 0D5C 1F RRA ; Adjust type -2141 0D5D CD 0C 10 CALL CHKTYP ; Check types are the same -2142 0D60 CA 9B 0D JP Z,LETNUM ; Numeric - Move value -2143 0D63 E5 LETSTR: PUSH HL ; Save address of string var -2144 0D64 2A 94 31 LD HL,(FPREG) ; Pointer to string entry -2145 0D67 E5 PUSH HL ; Save it on stack -2146 0D68 23 INC HL ; Skip over length -2147 0D69 23 INC HL -2148 0D6A 5E LD E,(HL) ; LSB of string address -2149 0D6B 23 INC HL -2150 0D6C 56 LD D,(HL) ; MSB of string address -2151 0D6D 2A 0E 31 LD HL,(BASTXT) ; Point to start of program -2152 0D70 CD 0A 0A CALL CPDEHL ; Is string before program? -2153 0D73 D2 8A 0D JP NC,CRESTR ; Yes - Create string entry -2154 0D76 2A 0A 31 LD HL,(STRSPC) ; Point to string space -2155 0D79 CD 0A 0A CALL CPDEHL ; Is string literal in program? -2156 0D7C D1 POP DE ; Restore address of string -2157 0D7D D2 92 0D JP NC,MVSTPT ; Yes - Set up pointer -2158 0D80 21 6F 31 LD HL,TMPSTR ; Temporary string pool -2159 0D83 CD 0A 0A CALL CPDEHL ; Is string in temporary pool? -2160 0D86 D2 92 0D JP NC,MVSTPT ; No - Set up pointer -2161 0D89 3E .BYTE 3EH ; Skip "POP DE" -2162 0D8A D1 CRESTR: POP DE ; Restore address of string -2163 0D8B CD 41 16 CALL BAKTMP ; Back to last tmp-str entry -2164 0D8E EB EX DE,HL ; Address of string entry -2165 0D8F CD 7A 14 CALL SAVSTR ; Save string in string area -2166 0D92 CD 41 16 MVSTPT: CALL BAKTMP ; Back to last tmp-str entry -2167 0D95 E1 POP HL ; Get string pointer -2168 0D96 CD 44 1A CALL DETHL4 ; Move string pointer to var -2169 0D99 E1 POP HL ; Restore code string address -2170 0D9A C9 RET -2171 0D9B -2172 0D9B E5 LETNUM: PUSH HL ; Save address of variable -2173 0D9C CD 41 1A CALL FPTHL ; Move value to variable -2174 0D9F D1 POP DE ; Restore address of variable -2175 0DA0 E1 POP HL ; Restore code string address -2176 0DA1 C9 RET -2177 0DA2 -2178 0DA2 CD 68 17 ON: CALL GETINT ; Get integer 0-255 -2179 0DA5 7E LD A,(HL) ; Get "GOTO" or "GOSUB" token -2180 0DA6 47 LD B,A ; Save in B -2181 0DA7 FE 8C CP ZGOSUB ; "GOSUB" token? -2182 0DA9 CA B1 0D JP Z,ONGO ; Yes - Find line number -2183 0DAC CD 10 0A CALL CHKSYN ; Make sure it's "GOTO" -2184 0DAF 88 .BYTE ZGOTO ; "GOTO" token -2185 0DB0 2B DEC HL ; Cancel increment -2186 0DB1 4B ONGO: LD C,E ; Integer of branch value -2187 0DB2 0D ONGOLP: DEC C ; Count branches -2188 0DB3 78 LD A,B ; Get "GOTO" or "GOSUB" token -2189 0DB4 CA 82 0B JP Z,ONJMP ; Go to that line if right one -2190 0DB7 CD 67 0C CALL GETLN ; Get line number to DE -2191 0DBA FE 2C CP ',' ; Another line number? -2192 0DBC C0 RET NZ ; No - Drop through -2193 0DBD C3 B2 0D JP ONGOLP ; Yes - loop -2194 0DC0 -2195 0DC0 CD 19 10 IF: CALL EVAL ; Evaluate expression -2196 0DC3 7E LD A,(HL) ; Get token -2197 0DC4 FE 88 CP ZGOTO ; "GOTO" token? -2198 0DC6 CA CE 0D JP Z,IFGO ; Yes - Get line -2199 0DC9 CD 10 0A CALL CHKSYN ; Make sure it's "THEN" -2200 0DCC A9 .BYTE ZTHEN ; "THEN" token -2201 0DCD 2B DEC HL ; Cancel increment -2202 0DCE CD 0A 10 IFGO: CALL TSTNUM ; Make sure it's numeric -2203 0DD1 CD E9 19 CALL TSTSGN ; Test state of expression -2204 0DD4 CA 33 0D JP Z,REM ; False - Drop through -2205 0DD7 CD 9A 0B CALL GETCHR ; Get next character -2206 0DDA DA EE 0C JP C,GOTO ; Number - GOTO that line -2207 0DDD C3 81 0B JP IFJMP ; Otherwise do statement -2208 0DE0 -2209 0DE0 2B MRPRNT: DEC HL ; DEC 'cos GETCHR INCs -2210 0DE1 CD 9A 0B CALL GETCHR ; Get next character -2211 0DE4 CA 42 0E PRINT: JP Z,PRNTCRLF ; CRLF if just PRINT -2212 0DE7 C8 PRNTLP: RET Z ; End of list - Exit -2213 0DE8 FE A5 CP ZTAB ; "TAB(" token? -2214 0DEA CA 75 0E JP Z,DOTAB ; Yes - Do TAB routine -2215 0DED FE A8 CP ZSPC ; "SPC(" token? -2216 0DEF CA 75 0E JP Z,DOTAB ; Yes - Do SPC routine -2217 0DF2 E5 PUSH HL ; Save code string address -2218 0DF3 FE 2C CP ',' ; Comma? -2219 0DF5 CA 5E 0E JP Z,DOCOM ; Yes - Move to next zone -2220 0DF8 FE 3B CP 59 ;";" ; Semi-colon? -2221 0DFA CA 98 0E JP Z,NEXITM ; Do semi-colon routine -2222 0DFD C1 POP BC ; Code string address to BC -2223 0DFE CD 19 10 CALL EVAL ; Evaluate expression -2224 0E01 E5 PUSH HL ; Save code string address -2225 0E02 3A 5D 31 LD A,(TYPE) ; Get variable type -2226 0E05 B7 OR A ; Is it a string variable? -2227 0E06 C2 2E 0E JP NZ,PRNTST ; Yes - Output string contents -2228 0E09 CD 8E 1B CALL NUMASC ; Convert number to text -2229 0E0C CD 9E 14 CALL CRTST ; Create temporary string -2230 0E0F 36 20 LD (HL),' ' ; Followed by a space -2231 0E11 2A 94 31 LD HL,(FPREG) ; Get length of output -2232 0E14 34 INC (HL) ; Plus 1 for the space -2233 0E15 2A 94 31 LD HL,(FPREG) ; < Not needed > -2234 0E18 3A F2 30 LD A,(LWIDTH) ; Get width of line -2235 0E1B 47 LD B,A ; To B -2236 0E1C 04 INC B ; Width 255 (No limit)? -2237 0E1D CA 2A 0E JP Z,PRNTNB ; Yes - Output number string -2238 0E20 04 INC B ; Adjust it -2239 0E21 3A 5B 31 LD A,(CURPOS) ; Get cursor position -2240 0E24 86 ADD A,(HL) ; Add length of string -2241 0E25 3D DEC A ; Adjust it -2242 0E26 B8 CP B ; Will output fit on this line? -2243 0E27 D4 42 0E CALL NC,PRNTCRLF ; No - CRLF first -2244 0E2A CD E3 14 PRNTNB: CALL PRS1 ; Output string at (HL) -2245 0E2D AF XOR A ; Skip CALL by setting 'z' flag -2246 0E2E C4 E3 14 PRNTST: CALL NZ,PRS1 ; Output string at (HL) -2247 0E31 E1 POP HL ; Restore code string address -2248 0E32 C3 E0 0D JP MRPRNT ; See if more to PRINT -2249 0E35 -2250 0E35 3A 5B 31 STTLIN: LD A,(CURPOS) ; Make sure on new line -2251 0E38 B7 OR A ; Already at start? -2252 0E39 C8 RET Z ; Yes - Do nothing -2253 0E3A C3 42 0E JP PRNTCRLF ; Start a new line -2254 0E3D -2255 0E3D 36 00 ENDINP: LD (HL),0 ; Mark end of buffer -2256 0E3F 21 10 31 LD HL,BUFFER-1 ; Point to buffer -2257 0E42 3E 0D PRNTCRLF: LD A,CR ; Load a CR -2258 0E44 CD 1B 0A CALL OUTC ; Output character -2259 0E47 3E 0A LD A,LF ; Load a LF -2260 0E49 CD 1B 0A CALL OUTC ; Output character -2261 0E4C AF DONULL: XOR A ; Set to position 0 -2262 0E4D 32 5B 31 LD (CURPOS),A ; Store it -2263 0E50 3A F1 30 LD A,(NULLS) ; Get number of nulls -2264 0E53 3D NULLP: DEC A ; Count them -2265 0E54 C8 RET Z ; Return if done -2266 0E55 F5 PUSH AF ; Save count -2267 0E56 AF XOR A ; Load a null -2268 0E57 CD 1B 0A CALL OUTC ; Output it -2269 0E5A F1 POP AF ; Restore count -2270 0E5B C3 53 0E JP NULLP ; Keep counting -2271 0E5E -2272 0E5E 3A F3 30 DOCOM: LD A,(COMMAN) ; Get comma width -2273 0E61 47 LD B,A ; Save in B -2274 0E62 3A 5B 31 LD A,(CURPOS) ; Get current position -2275 0E65 B8 CP B ; Within the limit? -2276 0E66 D4 42 0E CALL NC,PRNTCRLF ; No - output CRLF -2277 0E69 D2 98 0E JP NC,NEXITM ; Get next item -2278 0E6C D6 0E ZONELP: SUB 14 ; Next zone of 14 characters -2279 0E6E D2 6C 0E JP NC,ZONELP ; Repeat if more zones -2280 0E71 2F CPL ; Number of spaces to output -2281 0E72 C3 8D 0E JP ASPCS ; Output them -2282 0E75 -2283 0E75 F5 DOTAB: PUSH AF ; Save token -2284 0E76 CD 65 17 CALL FNDNUM ; Evaluate expression -2285 0E79 CD 10 0A CALL CHKSYN ; Make sure ")" follows -2286 0E7C 29 .BYTE ")" -2287 0E7D 2B DEC HL ; Back space on to ")" -2288 0E7E F1 POP AF ; Restore token -2289 0E7F D6 A8 SUB ZSPC ; Was it "SPC(" ? -2290 0E81 E5 PUSH HL ; Save code string address -2291 0E82 CA 88 0E JP Z,DOSPC ; Yes - Do 'E' spaces -2292 0E85 3A 5B 31 LD A,(CURPOS) ; Get current position -2293 0E88 2F DOSPC: CPL ; Number of spaces to print to -2294 0E89 83 ADD A,E ; Total number to print -2295 0E8A D2 98 0E JP NC,NEXITM ; TAB < Current POS(X) -2296 0E8D 3C ASPCS: INC A ; Output A spaces -2297 0E8E 47 LD B,A ; Save number to print -2298 0E8F 3E 20 LD A,' ' ; Space -2299 0E91 CD 1B 0A SPCLP: CALL OUTC ; Output character in A -2300 0E94 05 DEC B ; Count them -2301 0E95 C2 91 0E JP NZ,SPCLP ; Repeat if more -2302 0E98 E1 NEXITM: POP HL ; Restore code string address -2303 0E99 CD 9A 0B CALL GETCHR ; Get next character -2304 0E9C C3 E7 0D JP PRNTLP ; More to print -2305 0E9F -2306 0E9F 3F5265646F20REDO: .BYTE "?Redo from start",CR,LF,0 -2306 0EA5 66726F6D2073746172740D0A00 -2307 0EB2 -2308 0EB2 3A 7D 31 BADINP: LD A,(READFG) ; READ or INPUT? -2309 0EB5 B7 OR A -2310 0EB6 C2 3C 07 JP NZ,DATSNR ; READ - ?SN Error -2311 0EB9 C1 POP BC ; Throw away code string addr -2312 0EBA 21 9F 0E LD HL,REDO ; "Redo from start" message -2313 0EBD CD E0 14 CALL PRS ; Output string -2314 0EC0 C3 8D 08 JP DOAGN ; Do last INPUT again -2315 0EC3 -2316 0EC3 CD 4B 14 INPUT: CALL IDTEST ; Test for illegal direct -2317 0EC6 7E LD A,(HL) ; Get character after "INPUT" -2318 0EC7 FE 22 CP '"' ; Is there a prompt string? -2319 0EC9 3E 00 LD A,0 ; Clear A and leave flags -2320 0ECB 32 F5 30 LD (CTLOFG),A ; Enable output -2321 0ECE C2 DD 0E JP NZ,NOPMPT ; No prompt - get input -2322 0ED1 CD 9F 14 CALL QTSTR ; Get string terminated by '"' -2323 0ED4 CD 10 0A CALL CHKSYN ; Check for ';' after prompt -2324 0ED7 3B .BYTE ';' -2325 0ED8 E5 PUSH HL ; Save code string address -2326 0ED9 CD E3 14 CALL PRS1 ; Output prompt string -2327 0EDC 3E .BYTE 3EH ; Skip "PUSH HL" -2328 0EDD E5 NOPMPT: PUSH HL ; Save code string address -2329 0EDE CD 91 08 CALL PROMPT ; Get input with "? " prompt -2330 0EE1 C1 POP BC ; Restore code string address -2331 0EE2 DA E9 0B JP C,INPBRK ; Break pressed - Exit -2332 0EE5 23 INC HL ; Next byte -2333 0EE6 7E LD A,(HL) ; Get it -2334 0EE7 B7 OR A ; End of line? -2335 0EE8 2B DEC HL ; Back again -2336 0EE9 C5 PUSH BC ; Re-save code string address -2337 0EEA CA 30 0D JP Z,NXTDTA ; Yes - Find next DATA stmt -2338 0EED 36 2C LD (HL),',' ; Store comma as separator -2339 0EEF C3 F7 0E JP NXTITM ; Get next item -2340 0EF2 -2341 0EF2 E5 READ: PUSH HL ; Save code string address -2342 0EF3 2A 8C 31 LD HL,(NXTDAT) ; Next DATA statement -2343 0EF6 F6 .BYTE 0F6H ; Flag "READ" -2344 0EF7 AF NXTITM: XOR A ; Flag "INPUT" -2345 0EF8 32 7D 31 LD (READFG),A ; Save "READ"/"INPUT" flag -2346 0EFB E3 EX (SP),HL ; Get code str' , Save pointer -2347 0EFC C3 03 0F JP GTVLUS ; Get values -2348 0EFF -2349 0EFF CD 10 0A NEDMOR: CALL CHKSYN ; Check for comma between items -2350 0F02 2C .BYTE ',' -2351 0F03 CD FD 11 GTVLUS: CALL GETVAR ; Get variable name -2352 0F06 E3 EX (SP),HL ; Save code str" , Get pointer -2353 0F07 D5 PUSH DE ; Save variable address -2354 0F08 7E LD A,(HL) ; Get next "INPUT"/"DATA" byte -2355 0F09 FE 2C CP ',' ; Comma? -2356 0F0B CA 2B 0F JP Z,ANTVLU ; Yes - Get another value -2357 0F0E 3A 7D 31 LD A,(READFG) ; Is it READ? -2358 0F11 B7 OR A -2359 0F12 C2 98 0F JP NZ,FDTLP ; Yes - Find next DATA stmt -2360 0F15 3E 3F LD A,'?' ; More INPUT needed -2361 0F17 CD 1B 0A CALL OUTC ; Output character -2362 0F1A CD 91 08 CALL PROMPT ; Get INPUT with prompt -2363 0F1D D1 POP DE ; Variable address -2364 0F1E C1 POP BC ; Code string address -2365 0F1F DA E9 0B JP C,INPBRK ; Break pressed -2366 0F22 23 INC HL ; Point to next DATA byte -2367 0F23 7E LD A,(HL) ; Get byte -2368 0F24 B7 OR A ; Is it zero (No input) ? -2369 0F25 2B DEC HL ; Back space INPUT pointer -2370 0F26 C5 PUSH BC ; Save code string address -2371 0F27 CA 30 0D JP Z,NXTDTA ; Find end of buffer -2372 0F2A D5 PUSH DE ; Save variable address -2373 0F2B 3A 5D 31 ANTVLU: LD A,(TYPE) ; Check data type -2374 0F2E B7 OR A ; Is it numeric? -2375 0F2F CA 55 0F JP Z,INPBIN ; Yes - Convert to binary -2376 0F32 CD 9A 0B CALL GETCHR ; Get next character -2377 0F35 57 LD D,A ; Save input character -2378 0F36 47 LD B,A ; Again -2379 0F37 FE 22 CP '"' ; Start of literal sting? -2380 0F39 CA 49 0F JP Z,STRENT ; Yes - Create string entry -2381 0F3C 3A 7D 31 LD A,(READFG) ; "READ" or "INPUT" ? -2382 0F3F B7 OR A -2383 0F40 57 LD D,A ; Save 00 if "INPUT" -2384 0F41 CA 46 0F JP Z,ITMSEP ; "INPUT" - End with 00 -2385 0F44 16 3A LD D,':' ; "DATA" - End with 00 or ':' -2386 0F46 06 2C ITMSEP: LD B,',' ; Item separator -2387 0F48 2B DEC HL ; Back space for DTSTR -2388 0F49 CD A2 14 STRENT: CALL DTSTR ; Get string terminated by D -2389 0F4C EB EX DE,HL ; String address to DE -2390 0F4D 21 60 0F LD HL,LTSTND ; Where to go after LETSTR -2391 0F50 E3 EX (SP),HL ; Save HL , get input pointer -2392 0F51 D5 PUSH DE ; Save address of string -2393 0F52 C3 63 0D JP LETSTR ; Assign string to variable -2394 0F55 -2395 0F55 CD 9A 0B INPBIN: CALL GETCHR ; Get next character -2396 0F58 CD F0 1A CALL ASCTFP ; Convert ASCII to FP number -2397 0F5B E3 EX (SP),HL ; Save input ptr, Get var addr -2398 0F5C CD 41 1A CALL FPTHL ; Move FPREG to variable -2399 0F5F E1 POP HL ; Restore input pointer -2400 0F60 2B LTSTND: DEC HL ; DEC 'cos GETCHR INCs -2401 0F61 CD 9A 0B CALL GETCHR ; Get next character -2402 0F64 CA 6C 0F JP Z,MORDT ; End of line - More needed? -2403 0F67 FE 2C CP ',' ; Another value? -2404 0F69 C2 B2 0E JP NZ,BADINP ; No - Bad input -2405 0F6C E3 MORDT: EX (SP),HL ; Get code string address -2406 0F6D 2B DEC HL ; DEC 'cos GETCHR INCs -2407 0F6E CD 9A 0B CALL GETCHR ; Get next character -2408 0F71 C2 FF 0E JP NZ,NEDMOR ; More needed - Get it -2409 0F74 D1 POP DE ; Restore DATA pointer -2410 0F75 3A 7D 31 LD A,(READFG) ; "READ" or "INPUT" ? -2411 0F78 B7 OR A -2412 0F79 EB EX DE,HL ; DATA pointer to HL -2413 0F7A C2 C0 0B JP NZ,UPDATA ; Update DATA pointer if "READ" -2414 0F7D D5 PUSH DE ; Save code string address -2415 0F7E B6 OR (HL) ; More input given? -2416 0F7F 21 87 0F LD HL,EXTIG ; "?Extra ignored" message -2417 0F82 C4 E0 14 CALL NZ,PRS ; Output string if extra given -2418 0F85 E1 POP HL ; Restore code string address -2419 0F86 C9 RET -2420 0F87 -2421 0F87 3F4578747261EXTIG: .BYTE "?Extra ignored",CR,LF,0 -2421 0F8D 2069676E6F7265640D0A00 -2422 0F98 -2423 0F98 CD 31 0D FDTLP: CALL DATA ; Get next statement -2424 0F9B B7 OR A ; End of line? -2425 0F9C C2 B1 0F JP NZ,FANDT ; No - See if DATA statement -2426 0F9F 23 INC HL -2427 0FA0 7E LD A,(HL) ; End of program? -2428 0FA1 23 INC HL -2429 0FA2 B6 OR (HL) ; 00 00 Ends program -2430 0FA3 1E 06 LD E,OD ; ?OD Error -2431 0FA5 CA 56 07 JP Z,ERROR ; Yes - Out of DATA -2432 0FA8 23 INC HL -2433 0FA9 5E LD E,(HL) ; LSB of line number -2434 0FAA 23 INC HL -2435 0FAB 56 LD D,(HL) ; MSB of line number -2436 0FAC EB EX DE,HL -2437 0FAD 22 79 31 LD (DATLIN),HL ; Set line of current DATA item -2438 0FB0 EB EX DE,HL -2439 0FB1 CD 9A 0B FANDT: CALL GETCHR ; Get next character -2440 0FB4 FE 83 CP ZDATA ; "DATA" token -2441 0FB6 C2 98 0F JP NZ,FDTLP ; No "DATA" - Keep looking -2442 0FB9 C3 2B 0F JP ANTVLU ; Found - Convert input -2443 0FBC -2444 0FBC 11 00 00 NEXT: LD DE,0 ; In case no index given -2445 0FBF C4 FD 11 NEXT1: CALL NZ,GETVAR ; Get index address -2446 0FC2 22 7E 31 LD (BRKLIN),HL ; Save code string address -2447 0FC5 CD EB 06 CALL BAKSTK ; Look for "FOR" block -2448 0FC8 C2 48 07 JP NZ,NFERR ; No "FOR" - ?NF Error -2449 0FCB F9 LD SP,HL ; Clear nested loops -2450 0FCC D5 PUSH DE ; Save index address -2451 0FCD 7E LD A,(HL) ; Get sign of STEP -2452 0FCE 23 INC HL -2453 0FCF F5 PUSH AF ; Save sign of STEP -2454 0FD0 D5 PUSH DE ; Save index address -2455 0FD1 CD 27 1A CALL PHLTFP ; Move index value to FPREG -2456 0FD4 E3 EX (SP),HL ; Save address of TO value -2457 0FD5 E5 PUSH HL ; Save address of index -2458 0FD6 CD 94 17 CALL ADDPHL ; Add STEP to index value -2459 0FD9 E1 POP HL ; Restore address of index -2460 0FDA CD 41 1A CALL FPTHL ; Move value to index variable -2461 0FDD E1 POP HL ; Restore address of TO value -2462 0FDE CD 38 1A CALL LOADFP ; Move TO value to BCDE -2463 0FE1 E5 PUSH HL ; Save address of line of FOR -2464 0FE2 CD 64 1A CALL CMPNUM ; Compare index with TO value -2465 0FE5 E1 POP HL ; Restore address of line num -2466 0FE6 C1 POP BC ; Address of sign of STEP -2467 0FE7 90 SUB B ; Compare with expected sign -2468 0FE8 CD 38 1A CALL LOADFP ; BC = Loop stmt,DE = Line num -2469 0FEB CA F7 0F JP Z,KILFOR ; Loop finished - Terminate it -2470 0FEE EB EX DE,HL ; Loop statement line number -2471 0FEF 22 0C 31 LD (LINEAT),HL ; Set loop line number -2472 0FF2 69 LD L,C ; Set code string to loop -2473 0FF3 60 LD H,B -2474 0FF4 C3 56 0B JP PUTFID ; Put back "FOR" and continue -2475 0FF7 -2476 0FF7 F9 KILFOR: LD SP,HL ; Remove "FOR" block -2477 0FF8 2A 7E 31 LD HL,(BRKLIN) ; Code string after "NEXT" -2478 0FFB 7E LD A,(HL) ; Get next byte in code string -2479 0FFC FE 2C CP ',' ; More NEXTs ? -2480 0FFE C2 5A 0B JP NZ,RUNCNT ; No - Do next statement -2481 1001 CD 9A 0B CALL GETCHR ; Position to index name -2482 1004 CD BF 0F CALL NEXT1 ; Re-enter NEXT routine -2483 1007 ; < will not RETurn to here , Exit to RUNCNT or Loop > -2484 1007 -2485 1007 CD 19 10 GETNUM: CALL EVAL ; Get a numeric expression -2486 100A F6 TSTNUM: .BYTE 0F6H ; Clear carry (numeric) -2487 100B 37 TSTSTR: SCF ; Set carry (string) -2488 100C 3A 5D 31 CHKTYP: LD A,(TYPE) ; Check types match -2489 100F 8F ADC A,A ; Expected + actual -2490 1010 B7 OR A ; Clear carry , set parity -2491 1011 E8 RET PE ; Even parity - Types match -2492 1012 C3 54 07 JP TMERR ; Different types - Error -2493 1015 -2494 1015 CD 10 0A OPNPAR: CALL CHKSYN ; Make sure "(" follows -2495 1018 28 .BYTE "(" -2496 1019 2B EVAL: DEC HL ; Evaluate expression & save -2497 101A 16 00 LD D,0 ; Precedence value -2498 101C D5 EVAL1: PUSH DE ; Save precedence -2499 101D 0E 01 LD C,1 -2500 101F CD 1F 07 CALL CHKSTK ; Check for 1 level of stack -2501 1022 CD 90 10 CALL OPRND ; Get next expression value -2502 1025 22 80 31 EVAL2: LD (NXTOPR),HL ; Save address of next operator -2503 1028 2A 80 31 EVAL3: LD HL,(NXTOPR) ; Restore address of next opr -2504 102B C1 POP BC ; Precedence value and operator -2505 102C 78 LD A,B ; Get precedence value -2506 102D FE 78 CP 78H ; "AND" or "OR" ? -2507 102F D4 0A 10 CALL NC,TSTNUM ; No - Make sure it's a number -2508 1032 7E LD A,(HL) ; Get next operator / function -2509 1033 16 00 LD D,0 ; Clear Last relation -2510 1035 D6 B3 RLTLP: SUB ZGTR ; ">" Token -2511 1037 DA 51 10 JP C,FOPRND ; + - * / ^ AND OR - Test it -2512 103A FE 03 CP ZLTH+1-ZGTR ; < = > -2513 103C D2 51 10 JP NC,FOPRND ; Function - Call it -2514 103F FE 01 CP ZEQUAL-ZGTR ; "=" -2515 1041 17 RLA ; <- Test for legal -2516 1042 AA XOR D ; <- combinations of < = > -2517 1043 BA CP D ; <- by combining last token -2518 1044 57 LD D,A ; <- with current one -2519 1045 DA 42 07 JP C,SNERR ; Error if "<<' '==" or ">>" -2520 1048 22 75 31 LD (CUROPR),HL ; Save address of current token -2521 104B CD 9A 0B CALL GETCHR ; Get next character -2522 104E C3 35 10 JP RLTLP ; Treat the two as one -2523 1051 -2524 1051 7A FOPRND: LD A,D ; < = > found ? -2525 1052 B7 OR A -2526 1053 C2 78 11 JP NZ,TSTRED ; Yes - Test for reduction -2527 1056 7E LD A,(HL) ; Get operator token -2528 1057 22 75 31 LD (CUROPR),HL ; Save operator address -2529 105A D6 AC SUB ZPLUS ; Operator or function? -2530 105C D8 RET C ; Neither - Exit -2531 105D FE 07 CP ZOR+1-ZPLUS ; Is it + - * / ^ AND OR ? -2532 105F D0 RET NC ; No - Exit -2533 1060 5F LD E,A ; Coded operator -2534 1061 3A 5D 31 LD A,(TYPE) ; Get data type -2535 1064 3D DEC A ; FF = numeric , 00 = string -2536 1065 B3 OR E ; Combine with coded operator -2537 1066 7B LD A,E ; Get coded operator -2538 1067 CA D6 15 JP Z,CONCAT ; String concatenation -2539 106A 07 RLCA ; Times 2 -2540 106B 83 ADD A,E ; Times 3 -2541 106C 5F LD E,A ; To DE (D is 0) -2542 106D 21 34 06 LD HL,PRITAB ; Precedence table -2543 1070 19 ADD HL,DE ; To the operator concerned -2544 1071 78 LD A,B ; Last operator precedence -2545 1072 56 LD D,(HL) ; Get evaluation precedence -2546 1073 BA CP D ; Compare with eval precedence -2547 1074 D0 RET NC ; Exit if higher precedence -2548 1075 23 INC HL ; Point to routine address -2549 1076 CD 0A 10 CALL TSTNUM ; Make sure it's a number -2550 1079 -2551 1079 C5 STKTHS: PUSH BC ; Save last precedence & token -2552 107A 01 28 10 LD BC,EVAL3 ; Where to go on prec' break -2553 107D C5 PUSH BC ; Save on stack for return -2554 107E 43 LD B,E ; Save operator -2555 107F 4A LD C,D ; Save precedence -2556 1080 CD 1A 1A CALL STAKFP ; Move value to stack -2557 1083 58 LD E,B ; Restore operator -2558 1084 51 LD D,C ; Restore precedence -2559 1085 4E LD C,(HL) ; Get LSB of routine address -2560 1086 23 INC HL -2561 1087 46 LD B,(HL) ; Get MSB of routine address -2562 1088 23 INC HL -2563 1089 C5 PUSH BC ; Save routine address -2564 108A 2A 75 31 LD HL,(CUROPR) ; Address of current operator -2565 108D C3 1C 10 JP EVAL1 ; Loop until prec' break -2566 1090 -2567 1090 AF OPRND: XOR A ; Get operand routine -2568 1091 32 5D 31 LD (TYPE),A ; Set numeric expected -2569 1094 CD 9A 0B CALL GETCHR ; Get next character -2570 1097 1E 24 LD E,MO ; ?MO Error -2571 1099 CA 56 07 JP Z,ERROR ; No operand - Error -2572 109C DA F0 1A JP C,ASCTFP ; Number - Get value -2573 109F CD 38 0C CALL CHKLTR ; See if a letter -2574 10A2 D2 F7 10 JP NC,CONVAR ; Letter - Find variable -2575 10A5 FE 26 CP '&' ; &H = HEX, &B = BINARY -2576 10A7 20 12 JR NZ, NOTAMP -2577 10A9 CD 9A 0B CALL GETCHR ; Get next character -2578 10AC FE 48 CP 'H' ; Hex number indicated? [function added] -2579 10AE CA 34 1F JP Z,HEXTFP ; Convert Hex to FPREG -2580 10B1 FE 42 CP 'B' ; Binary number indicated? [function added] -2581 10B3 CA A4 1F JP Z,BINTFP ; Convert Bin to FPREG -2582 10B6 1E 02 LD E,SN ; If neither then a ?SN Error -2583 10B8 CA 56 07 JP Z,ERROR ; -2584 10BB FE AC NOTAMP: CP ZPLUS ; '+' Token ? -2585 10BD CA 90 10 JP Z,OPRND ; Yes - Look for operand -2586 10C0 FE 2E CP '.' ; '.' ? -2587 10C2 CA F0 1A JP Z,ASCTFP ; Yes - Create FP number -2588 10C5 FE AD CP ZMINUS ; '-' Token ? -2589 10C7 CA E6 10 JP Z,MINUS ; Yes - Do minus -2590 10CA FE 22 CP '"' ; Literal string ? -2591 10CC CA 9F 14 JP Z,QTSTR ; Get string terminated by '"' -2592 10CF FE AA CP ZNOT ; "NOT" Token ? -2593 10D1 CA D8 11 JP Z,EVNOT ; Yes - Eval NOT expression -2594 10D4 FE A7 CP ZFN ; "FN" Token ? -2595 10D6 CA 03 14 JP Z,DOFN ; Yes - Do FN routine -2596 10D9 D6 B6 SUB ZSGN ; Is it a function? -2597 10DB D2 08 11 JP NC,FNOFST ; Yes - Evaluate function -2598 10DE CD 15 10 EVLPAR: CALL OPNPAR ; Evaluate expression in "()" -2599 10E1 CD 10 0A CALL CHKSYN ; Make sure ")" follows -2600 10E4 29 .BYTE ")" -2601 10E5 C9 RET -2602 10E6 -2603 10E6 16 7D MINUS: LD D,7DH ; '-' precedence -2604 10E8 CD 1C 10 CALL EVAL1 ; Evaluate until prec' break -2605 10EB 2A 80 31 LD HL,(NXTOPR) ; Get next operator address -2606 10EE E5 PUSH HL ; Save next operator address -2607 10EF CD 12 1A CALL INVSGN ; Negate value -2608 10F2 CD 0A 10 RETNUM: CALL TSTNUM ; Make sure it's a number -2609 10F5 E1 POP HL ; Restore next operator address -2610 10F6 C9 RET -2611 10F7 -2612 10F7 CD FD 11 CONVAR: CALL GETVAR ; Get variable address to DE -2613 10FA E5 FRMEVL: PUSH HL ; Save code string address -2614 10FB EB EX DE,HL ; Variable address to HL -2615 10FC 22 94 31 LD (FPREG),HL ; Save address of variable -2616 10FF 3A 5D 31 LD A,(TYPE) ; Get type -2617 1102 B7 OR A ; Numeric? -2618 1103 CC 27 1A CALL Z,PHLTFP ; Yes - Move contents to FPREG -2619 1106 E1 POP HL ; Restore code string address -2620 1107 C9 RET -2621 1108 -2622 1108 06 00 FNOFST: LD B,0 ; Get address of function -2623 110A 07 RLCA ; Double function offset -2624 110B 4F LD C,A ; BC = Offset in function table -2625 110C C5 PUSH BC ; Save adjusted token value -2626 110D CD 9A 0B CALL GETCHR ; Get next character -2627 1110 79 LD A,C ; Get adjusted token value -2628 1111 FE 31 CP 2*(ZLEFT-ZSGN)-1; Adj' LEFT$,RIGHT$ or MID$ ? -2629 1113 DA 2F 11 JP C,FNVAL ; No - Do function -2630 1116 CD 15 10 CALL OPNPAR ; Evaluate expression (X,... -2631 1119 CD 10 0A CALL CHKSYN ; Make sure ',' follows -2632 111C 2C .BYTE ',' -2633 111D CD 0B 10 CALL TSTSTR ; Make sure it's a string -2634 1120 EB EX DE,HL ; Save code string address -2635 1121 2A 94 31 LD HL,(FPREG) ; Get address of string -2636 1124 E3 EX (SP),HL ; Save address of string -2637 1125 E5 PUSH HL ; Save adjusted token value -2638 1126 EB EX DE,HL ; Restore code string address -2639 1127 CD 68 17 CALL GETINT ; Get integer 0-255 -2640 112A EB EX DE,HL ; Save code string address -2641 112B E3 EX (SP),HL ; Save integer,HL = adj' token -2642 112C C3 37 11 JP GOFUNC ; Jump to string function -2643 112F -2644 112F CD DE 10 FNVAL: CALL EVLPAR ; Evaluate expression -2645 1132 E3 EX (SP),HL ; HL = Adjusted token value -2646 1133 11 F2 10 LD DE,RETNUM ; Return number from function -2647 1136 D5 PUSH DE ; Save on stack -2648 1137 01 93 04 GOFUNC: LD BC,FNCTAB ; Function routine addresses -2649 113A 09 ADD HL,BC ; Point to right address -2650 113B 4E LD C,(HL) ; Get LSB of address -2651 113C 23 INC HL ; -2652 113D 66 LD H,(HL) ; Get MSB of address -2653 113E 69 LD L,C ; Address to HL -2654 113F E9 JP (HL) ; Jump to function -2655 1140 -2656 1140 15 SGNEXP: DEC D ; Dee to flag negative exponent -2657 1141 FE AD CP ZMINUS ; '-' token ? -2658 1143 C8 RET Z ; Yes - Return -2659 1144 FE 2D CP '-' ; '-' ASCII ? -2660 1146 C8 RET Z ; Yes - Return -2661 1147 14 INC D ; Inc to flag positive exponent -2662 1148 FE 2B CP '+' ; '+' ASCII ? -2663 114A C8 RET Z ; Yes - Return -2664 114B FE AC CP ZPLUS ; '+' token ? -2665 114D C8 RET Z ; Yes - Return -2666 114E 2B DEC HL ; DEC 'cos GETCHR INCs -2667 114F C9 RET ; Return "NZ" -2668 1150 -2669 1150 F6 POR: .BYTE 0F6H ; Flag "OR" -2670 1151 AF PAND: XOR A ; Flag "AND" -2671 1152 F5 PUSH AF ; Save "AND" / "OR" flag -2672 1153 CD 0A 10 CALL TSTNUM ; Make sure it's a number -2673 1156 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 -2674 1159 F1 POP AF ; Restore "AND" / "OR" flag -2675 115A EB EX DE,HL ; <- Get last -2676 115B C1 POP BC ; <- value -2677 115C E3 EX (SP),HL ; <- from -2678 115D EB EX DE,HL ; <- stack -2679 115E CD 2A 1A CALL FPBCDE ; Move last value to FPREG -2680 1161 F5 PUSH AF ; Save "AND" / "OR" flag -2681 1162 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 -2682 1165 F1 POP AF ; Restore "AND" / "OR" flag -2683 1166 C1 POP BC ; Get value -2684 1167 79 LD A,C ; Get LSB -2685 1168 21 C1 13 LD HL,ACPASS ; Address of save AC as current -2686 116B C2 73 11 JP NZ,POR1 ; Jump if OR -2687 116E A3 AND E ; "AND" LSBs -2688 116F 4F LD C,A ; Save LSB -2689 1170 78 LD A,B ; Get MBS -2690 1171 A2 AND D ; "AND" MSBs -2691 1172 E9 JP (HL) ; Save AC as current (ACPASS) -2692 1173 -2693 1173 B3 POR1: OR E ; "OR" LSBs -2694 1174 4F LD C,A ; Save LSB -2695 1175 78 LD A,B ; Get MSB -2696 1176 B2 OR D ; "OR" MSBs -2697 1177 E9 JP (HL) ; Save AC as current (ACPASS) -2698 1178 -2699 1178 21 8A 11 TSTRED: LD HL,CMPLOG ; Logical compare routine -2700 117B 3A 5D 31 LD A,(TYPE) ; Get data type -2701 117E 1F RRA ; Carry set = string -2702 117F 7A LD A,D ; Get last precedence value -2703 1180 17 RLA ; Times 2 plus carry -2704 1181 5F LD E,A ; To E -2705 1182 16 64 LD D,64H ; Relational precedence -2706 1184 78 LD A,B ; Get current precedence -2707 1185 BA CP D ; Compare with last -2708 1186 D0 RET NC ; Eval if last was rel' or log' -2709 1187 C3 79 10 JP STKTHS ; Stack this one and get next -2710 118A -2711 118A 8C 11 CMPLOG: .WORD CMPLG1 ; Compare two values / strings -2712 118C 79 CMPLG1: LD A,C ; Get data type -2713 118D B7 OR A -2714 118E 1F RRA -2715 118F C1 POP BC ; Get last expression to BCDE -2716 1190 D1 POP DE -2717 1191 F5 PUSH AF ; Save status -2718 1192 CD 0C 10 CALL CHKTYP ; Check that types match -2719 1195 21 CE 11 LD HL,CMPRES ; Result to comparison -2720 1198 E5 PUSH HL ; Save for RETurn -2721 1199 CA 64 1A JP Z,CMPNUM ; Compare values if numeric -2722 119C AF XOR A ; Compare two strings -2723 119D 32 5D 31 LD (TYPE),A ; Set type to numeric -2724 11A0 D5 PUSH DE ; Save string name -2725 11A1 CD 23 16 CALL GSTRCU ; Get current string -2726 11A4 7E LD A,(HL) ; Get length of string -2727 11A5 23 INC HL -2728 11A6 23 INC HL -2729 11A7 4E LD C,(HL) ; Get LSB of address -2730 11A8 23 INC HL -2731 11A9 46 LD B,(HL) ; Get MSB of address -2732 11AA D1 POP DE ; Restore string name -2733 11AB C5 PUSH BC ; Save address of string -2734 11AC F5 PUSH AF ; Save length of string -2735 11AD CD 27 16 CALL GSTRDE ; Get second string -2736 11B0 CD 38 1A CALL LOADFP ; Get address of second string -2737 11B3 F1 POP AF ; Restore length of string 1 -2738 11B4 57 LD D,A ; Length to D -2739 11B5 E1 POP HL ; Restore address of string 1 -2740 11B6 7B CMPSTR: LD A,E ; Bytes of string 2 to do -2741 11B7 B2 OR D ; Bytes of string 1 to do -2742 11B8 C8 RET Z ; Exit if all bytes compared -2743 11B9 7A LD A,D ; Get bytes of string 1 to do -2744 11BA D6 01 SUB 1 -2745 11BC D8 RET C ; Exit if end of string 1 -2746 11BD AF XOR A -2747 11BE BB CP E ; Bytes of string 2 to do -2748 11BF 3C INC A -2749 11C0 D0 RET NC ; Exit if end of string 2 -2750 11C1 15 DEC D ; Count bytes in string 1 -2751 11C2 1D DEC E ; Count bytes in string 2 -2752 11C3 0A LD A,(BC) ; Byte in string 2 -2753 11C4 BE CP (HL) ; Compare to byte in string 1 -2754 11C5 23 INC HL ; Move up string 1 -2755 11C6 03 INC BC ; Move up string 2 -2756 11C7 CA B6 11 JP Z,CMPSTR ; Same - Try next bytes -2757 11CA 3F CCF ; Flag difference (">" or "<") -2758 11CB C3 F4 19 JP FLGDIF ; "<" gives -1 , ">" gives +1 -2759 11CE -2760 11CE 3C CMPRES: INC A ; Increment current value -2761 11CF 8F ADC A,A ; Double plus carry -2762 11D0 C1 POP BC ; Get other value -2763 11D1 A0 AND B ; Combine them -2764 11D2 C6 FF ADD A,-1 ; Carry set if different -2765 11D4 9F SBC A,A ; 00 - Equal , FF - Different -2766 11D5 C3 FB 19 JP FLGREL ; Set current value & continue -2767 11D8 -2768 11D8 16 5A EVNOT: LD D,5AH ; Precedence value for "NOT" -2769 11DA CD 1C 10 CALL EVAL1 ; Eval until precedence break -2770 11DD CD 0A 10 CALL TSTNUM ; Make sure it's a number -2771 11E0 CD 4C 0C CALL DEINT ; Get integer -32768 - 32767 -2772 11E3 7B LD A,E ; Get LSB -2773 11E4 2F CPL ; Invert LSB -2774 11E5 4F LD C,A ; Save "NOT" of LSB -2775 11E6 7A LD A,D ; Get MSB -2776 11E7 2F CPL ; Invert MSB -2777 11E8 CD C1 13 CALL ACPASS ; Save AC as current -2778 11EB C1 POP BC ; Clean up stack -2779 11EC C3 28 10 JP EVAL3 ; Continue evaluation -2780 11EF -2781 11EF 2B DIMRET: DEC HL ; DEC 'cos GETCHR INCs -2782 11F0 CD 9A 0B CALL GETCHR ; Get next character -2783 11F3 C8 RET Z ; End of DIM statement -2784 11F4 CD 10 0A CALL CHKSYN ; Make sure ',' follows -2785 11F7 2C .BYTE ',' -2786 11F8 01 EF 11 DIM: LD BC,DIMRET ; Return to "DIMRET" -2787 11FB C5 PUSH BC ; Save on stack -2788 11FC F6 .BYTE 0F6H ; Flag "Create" variable -2789 11FD AF GETVAR: XOR A ; Find variable address,to DE -2790 11FE 32 5C 31 LD (LCRFLG),A ; Set locate / create flag -2791 1201 46 LD B,(HL) ; Get First byte of name -2792 1202 CD 38 0C GTFNAM: CALL CHKLTR ; See if a letter -2793 1205 DA 42 07 JP C,SNERR ; ?SN Error if not a letter -2794 1208 AF XOR A -2795 1209 4F LD C,A ; Clear second byte of name -2796 120A 32 5D 31 LD (TYPE),A ; Set type to numeric -2797 120D CD 9A 0B CALL GETCHR ; Get next character -2798 1210 DA 19 12 JP C,SVNAM2 ; Numeric - Save in name -2799 1213 CD 38 0C CALL CHKLTR ; See if a letter -2800 1216 DA 26 12 JP C,CHARTY ; Not a letter - Check type -2801 1219 4F SVNAM2: LD C,A ; Save second byte of name -2802 121A CD 9A 0B ENDNAM: CALL GETCHR ; Get next character -2803 121D DA 1A 12 JP C,ENDNAM ; Numeric - Get another -2804 1220 CD 38 0C CALL CHKLTR ; See if a letter -2805 1223 D2 1A 12 JP NC,ENDNAM ; Letter - Get another -2806 1226 D6 24 CHARTY: SUB '$' ; String variable? -2807 1228 C2 35 12 JP NZ,NOTSTR ; No - Numeric variable -2808 122B 3C INC A ; A = 1 (string type) -2809 122C 32 5D 31 LD (TYPE),A ; Set type to string -2810 122F 0F RRCA ; A = 80H , Flag for string -2811 1230 81 ADD A,C ; 2nd byte of name has bit 7 on -2812 1231 4F LD C,A ; Resave second byte on name -2813 1232 CD 9A 0B CALL GETCHR ; Get next character -2814 1235 3A 7B 31 NOTSTR: LD A,(FORFLG) ; Array name needed ? -2815 1238 3D DEC A -2816 1239 CA E2 12 JP Z,ARLDSV ; Yes - Get array name -2817 123C F2 45 12 JP P,NSCFOR ; No array with "FOR" or "FN" -2818 123F 7E LD A,(HL) ; Get byte again -2819 1240 D6 28 SUB '(' ; Subscripted variable? -2820 1242 CA BA 12 JP Z,SBSCPT ; Yes - Sort out subscript -2821 1245 -2822 1245 AF NSCFOR: XOR A ; Simple variable -2823 1246 32 7B 31 LD (FORFLG),A ; Clear "FOR" flag -2824 1249 E5 PUSH HL ; Save code string address -2825 124A 50 LD D,B ; DE = Variable name to find -2826 124B 59 LD E,C -2827 124C 2A 8E 31 LD HL,(FNRGNM) ; FN argument name -2828 124F CD 0A 0A CALL CPDEHL ; Is it the FN argument? -2829 1252 11 90 31 LD DE,FNARG ; Point to argument value -2830 1255 CA 2A 19 JP Z,POPHRT ; Yes - Return FN argument value -2831 1258 2A 88 31 LD HL,(VAREND) ; End of variables -2832 125B EB EX DE,HL ; Address of end of search -2833 125C 2A 86 31 LD HL,(PROGND) ; Start of variables address -2834 125F CD 0A 0A FNDVAR: CALL CPDEHL ; End of variable list table? -2835 1262 CA 78 12 JP Z,CFEVAL ; Yes - Called from EVAL? -2836 1265 79 LD A,C ; Get second byte of name -2837 1266 96 SUB (HL) ; Compare with name in list -2838 1267 23 INC HL ; Move on to first byte -2839 1268 C2 6D 12 JP NZ,FNTHR ; Different - Find another -2840 126B 78 LD A,B ; Get first byte of name -2841 126C 96 SUB (HL) ; Compare with name in list -2842 126D 23 FNTHR: INC HL ; Move on to LSB of value -2843 126E CA AC 12 JP Z,RETADR ; Found - Return address -2844 1271 23 INC HL ; <- Skip -2845 1272 23 INC HL ; <- over -2846 1273 23 INC HL ; <- F.P. -2847 1274 23 INC HL ; <- value -2848 1275 C3 5F 12 JP FNDVAR ; Keep looking -2849 1278 -2850 1278 E1 CFEVAL: POP HL ; Restore code string address -2851 1279 E3 EX (SP),HL ; Get return address -2852 127A D5 PUSH DE ; Save address of variable -2853 127B 11 FA 10 LD DE,FRMEVL ; Return address in EVAL -2854 127E CD 0A 0A CALL CPDEHL ; Called from EVAL ? -2855 1281 D1 POP DE ; Restore address of variable -2856 1282 CA AF 12 JP Z,RETNUL ; Yes - Return null variable -2857 1285 E3 EX (SP),HL ; Put back return -2858 1286 E5 PUSH HL ; Save code string address -2859 1287 C5 PUSH BC ; Save variable name -2860 1288 01 06 00 LD BC,6 ; 2 byte name plus 4 byte data -2861 128B 2A 8A 31 LD HL,(ARREND) ; End of arrays -2862 128E E5 PUSH HL ; Save end of arrays -2863 128F 09 ADD HL,BC ; Move up 6 bytes -2864 1290 C1 POP BC ; Source address in BC -2865 1291 E5 PUSH HL ; Save new end address -2866 1292 CD 0E 07 CALL MOVUP ; Move arrays up -2867 1295 E1 POP HL ; Restore new end address -2868 1296 22 8A 31 LD (ARREND),HL ; Set new end address -2869 1299 60 LD H,B ; End of variables to HL -2870 129A 69 LD L,C -2871 129B 22 88 31 LD (VAREND),HL ; Set new end address -2872 129E -2873 129E 2B ZEROLP: DEC HL ; Back through to zero variable -2874 129F 36 00 LD (HL),0 ; Zero byte in variable -2875 12A1 CD 0A 0A CALL CPDEHL ; Done them all? -2876 12A4 C2 9E 12 JP NZ,ZEROLP ; No - Keep on going -2877 12A7 D1 POP DE ; Get variable name -2878 12A8 73 LD (HL),E ; Store second character -2879 12A9 23 INC HL -2880 12AA 72 LD (HL),D ; Store first character -2881 12AB 23 INC HL -2882 12AC EB RETADR: EX DE,HL ; Address of variable in DE -2883 12AD E1 POP HL ; Restore code string address -2884 12AE C9 RET -2885 12AF -2886 12AF 32 97 31 RETNUL: LD (FPEXP),A ; Set result to zero -2887 12B2 21 DE 06 LD HL,ZERBYT ; Also set a null string -2888 12B5 22 94 31 LD (FPREG),HL ; Save for EVAL -2889 12B8 E1 POP HL ; Restore code string address -2890 12B9 C9 RET -2891 12BA -2892 12BA E5 SBSCPT: PUSH HL ; Save code string address -2893 12BB 2A 5C 31 LD HL,(LCRFLG) ; Locate/Create and Type -2894 12BE E3 EX (SP),HL ; Save and get code string -2895 12BF 57 LD D,A ; Zero number of dimensions -2896 12C0 D5 SCPTLP: PUSH DE ; Save number of dimensions -2897 12C1 C5 PUSH BC ; Save array name -2898 12C2 CD 40 0C CALL FPSINT ; Get subscript (0-32767) -2899 12C5 C1 POP BC ; Restore array name -2900 12C6 F1 POP AF ; Get number of dimensions -2901 12C7 EB EX DE,HL -2902 12C8 E3 EX (SP),HL ; Save subscript value -2903 12C9 E5 PUSH HL ; Save LCRFLG and TYPE -2904 12CA EB EX DE,HL -2905 12CB 3C INC A ; Count dimensions -2906 12CC 57 LD D,A ; Save in D -2907 12CD 7E LD A,(HL) ; Get next byte in code string -2908 12CE FE 2C CP ',' ; Comma (more to come)? -2909 12D0 CA C0 12 JP Z,SCPTLP ; Yes - More subscripts -2910 12D3 CD 10 0A CALL CHKSYN ; Make sure ")" follows -2911 12D6 29 .BYTE ")" -2912 12D7 22 80 31 LD (NXTOPR),HL ; Save code string address -2913 12DA E1 POP HL ; Get LCRFLG and TYPE -2914 12DB 22 5C 31 LD (LCRFLG),HL ; Restore Locate/create & type -2915 12DE 1E 00 LD E,0 ; Flag not CSAVE* or CLOAD* -2916 12E0 D5 PUSH DE ; Save number of dimensions (D) -2917 12E1 11 .BYTE 11H ; Skip "PUSH HL" and "PUSH AF' -2918 12E2 -2919 12E2 E5 ARLDSV: PUSH HL ; Save code string address -2920 12E3 F5 PUSH AF ; A = 00 , Flags set = Z,N -2921 12E4 2A 88 31 LD HL,(VAREND) ; Start of arrays -2922 12E7 3E .BYTE 3EH ; Skip "ADD HL,DE" -2923 12E8 19 FNDARY: ADD HL,DE ; Move to next array start -2924 12E9 EB EX DE,HL -2925 12EA 2A 8A 31 LD HL,(ARREND) ; End of arrays -2926 12ED EB EX DE,HL ; Current array pointer -2927 12EE CD 0A 0A CALL CPDEHL ; End of arrays found? -2928 12F1 CA 1A 13 JP Z,CREARY ; Yes - Create array -2929 12F4 7E LD A,(HL) ; Get second byte of name -2930 12F5 B9 CP C ; Compare with name given -2931 12F6 23 INC HL ; Move on -2932 12F7 C2 FC 12 JP NZ,NXTARY ; Different - Find next array -2933 12FA 7E LD A,(HL) ; Get first byte of name -2934 12FB B8 CP B ; Compare with name given -2935 12FC 23 NXTARY: INC HL ; Move on -2936 12FD 5E LD E,(HL) ; Get LSB of next array address -2937 12FE 23 INC HL -2938 12FF 56 LD D,(HL) ; Get MSB of next array address -2939 1300 23 INC HL -2940 1301 C2 E8 12 JP NZ,FNDARY ; Not found - Keep looking -2941 1304 3A 5C 31 LD A,(LCRFLG) ; Found Locate or Create it? -2942 1307 B7 OR A -2943 1308 C2 4B 07 JP NZ,DDERR ; Create - ?DD Error -2944 130B F1 POP AF ; Locate - Get number of dim'ns -2945 130C 44 LD B,H ; BC Points to array dim'ns -2946 130D 4D LD C,L -2947 130E CA 2A 19 JP Z,POPHRT ; Jump if array load/save -2948 1311 96 SUB (HL) ; Same number of dimensions? -2949 1312 CA 78 13 JP Z,FINDEL ; Yes - Find element -2950 1315 1E 10 BSERR: LD E,BS ; ?BS Error -2951 1317 C3 56 07 JP ERROR ; Output error -2952 131A -2953 131A 11 04 00 CREARY: LD DE,4 ; 4 Bytes per entry -2954 131D F1 POP AF ; Array to save or 0 dim'ns? -2955 131E CA 61 0C JP Z,FCERR ; Yes - ?FC Error -2956 1321 71 LD (HL),C ; Save second byte of name -2957 1322 23 INC HL -2958 1323 70 LD (HL),B ; Save first byte of name -2959 1324 23 INC HL -2960 1325 4F LD C,A ; Number of dimensions to C -2961 1326 CD 1F 07 CALL CHKSTK ; Check if enough memory -2962 1329 23 INC HL ; Point to number of dimensions -2963 132A 23 INC HL -2964 132B 22 75 31 LD (CUROPR),HL ; Save address of pointer -2965 132E 71 LD (HL),C ; Set number of dimensions -2966 132F 23 INC HL -2967 1330 3A 5C 31 LD A,(LCRFLG) ; Locate of Create? -2968 1333 17 RLA ; Carry set = Create -2969 1334 79 LD A,C ; Get number of dimensions -2970 1335 01 0B 00 CRARLP: LD BC,10+1 ; Default dimension size 10 -2971 1338 D2 3D 13 JP NC,DEFSIZ ; Locate - Set default size -2972 133B C1 POP BC ; Get specified dimension size -2973 133C 03 INC BC ; Include zero element -2974 133D 71 DEFSIZ: LD (HL),C ; Save LSB of dimension size -2975 133E 23 INC HL -2976 133F 70 LD (HL),B ; Save MSB of dimension size -2977 1340 23 INC HL -2978 1341 F5 PUSH AF ; Save num' of dim'ns an status -2979 1342 E5 PUSH HL ; Save address of dim'n size -2980 1343 CD D5 1A CALL MLDEBC ; Multiply DE by BC to find -2981 1346 EB EX DE,HL ; amount of mem needed (to DE) -2982 1347 E1 POP HL ; Restore address of dimension -2983 1348 F1 POP AF ; Restore number of dimensions -2984 1349 3D DEC A ; Count them -2985 134A C2 35 13 JP NZ,CRARLP ; Do next dimension if more -2986 134D F5 PUSH AF ; Save locate/create flag -2987 134E 42 LD B,D ; MSB of memory needed -2988 134F 4B LD C,E ; LSB of memory needed -2989 1350 EB EX DE,HL -2990 1351 19 ADD HL,DE ; Add bytes to array start -2991 1352 DA 37 07 JP C,OMERR ; Too big - Error -2992 1355 CD 28 07 CALL ENFMEM ; See if enough memory -2993 1358 22 8A 31 LD (ARREND),HL ; Save new end of array -2994 135B -2995 135B 2B ZERARY: DEC HL ; Back through array data -2996 135C 36 00 LD (HL),0 ; Set array element to zero -2997 135E CD 0A 0A CALL CPDEHL ; All elements zeroed? -2998 1361 C2 5B 13 JP NZ,ZERARY ; No - Keep on going -2999 1364 03 INC BC ; Number of bytes + 1 -3000 1365 57 LD D,A ; A=0 -3001 1366 2A 75 31 LD HL,(CUROPR) ; Get address of array -3002 1369 5E LD E,(HL) ; Number of dimensions -3003 136A EB EX DE,HL ; To HL -3004 136B 29 ADD HL,HL ; Two bytes per dimension size -3005 136C 09 ADD HL,BC ; Add number of bytes -3006 136D EB EX DE,HL ; Bytes needed to DE -3007 136E 2B DEC HL -3008 136F 2B DEC HL -3009 1370 73 LD (HL),E ; Save LSB of bytes needed -3010 1371 23 INC HL -3011 1372 72 LD (HL),D ; Save MSB of bytes needed -3012 1373 23 INC HL -3013 1374 F1 POP AF ; Locate / Create? -3014 1375 DA 9C 13 JP C,ENDDIM ; A is 0 , End if create -3015 1378 47 FINDEL: LD B,A ; Find array element -3016 1379 4F LD C,A -3017 137A 7E LD A,(HL) ; Number of dimensions -3018 137B 23 INC HL -3019 137C 16 .BYTE 16H ; Skip "POP HL" -3020 137D E1 FNDELP: POP HL ; Address of next dim' size -3021 137E 5E LD E,(HL) ; Get LSB of dim'n size -3022 137F 23 INC HL -3023 1380 56 LD D,(HL) ; Get MSB of dim'n size -3024 1381 23 INC HL -3025 1382 E3 EX (SP),HL ; Save address - Get index -3026 1383 F5 PUSH AF ; Save number of dim'ns -3027 1384 CD 0A 0A CALL CPDEHL ; Dimension too large? -3028 1387 D2 15 13 JP NC,BSERR ; Yes - ?BS Error -3029 138A E5 PUSH HL ; Save index -3030 138B CD D5 1A CALL MLDEBC ; Multiply previous by size -3031 138E D1 POP DE ; Index supplied to DE -3032 138F 19 ADD HL,DE ; Add index to pointer -3033 1390 F1 POP AF ; Number of dimensions -3034 1391 3D DEC A ; Count them -3035 1392 44 LD B,H ; MSB of pointer -3036 1393 4D LD C,L ; LSB of pointer -3037 1394 C2 7D 13 JP NZ,FNDELP ; More - Keep going -3038 1397 29 ADD HL,HL ; 4 Bytes per element -3039 1398 29 ADD HL,HL -3040 1399 C1 POP BC ; Start of array -3041 139A 09 ADD HL,BC ; Point to element -3042 139B EB EX DE,HL ; Address of element to DE -3043 139C 2A 80 31 ENDDIM: LD HL,(NXTOPR) ; Got code string address -3044 139F C9 RET -3045 13A0 -3046 13A0 2A 8A 31 FRE: LD HL,(ARREND) ; Start of free memory -3047 13A3 EB EX DE,HL ; To DE -3048 13A4 21 00 00 LD HL,0 ; End of free memory -3049 13A7 39 ADD HL,SP ; Current stack value -3050 13A8 3A 5D 31 LD A,(TYPE) ; Dummy argument type -3051 13AB B7 OR A -3052 13AC CA BC 13 JP Z,FRENUM ; Numeric - Free variable space -3053 13AF CD 23 16 CALL GSTRCU ; Current string to pool -3054 13B2 CD 23 15 CALL GARBGE ; Garbage collection -3055 13B5 2A 0A 31 LD HL,(STRSPC) ; Bottom of string space in use -3056 13B8 EB EX DE,HL ; To DE -3057 13B9 2A 73 31 LD HL,(STRBOT) ; Bottom of string space -3058 13BC 7D FRENUM: LD A,L ; Get LSB of end -3059 13BD 93 SUB E ; Subtract LSB of beginning -3060 13BE 4F LD C,A ; Save difference if C -3061 13BF 7C LD A,H ; Get MSB of end -3062 13C0 9A SBC A,D ; Subtract MSB of beginning -3063 13C1 41 ACPASS: LD B,C ; Return integer AC -3064 13C2 50 ABPASS: LD D,B ; Return integer AB -3065 13C3 1E 00 LD E,0 -3066 13C5 21 5D 31 LD HL,TYPE ; Point to type -3067 13C8 73 LD (HL),E ; Set type to numeric -3068 13C9 06 90 LD B,80H+16 ; 16 bit integer -3069 13CB C3 00 1A JP RETINT ; Return the integr -3070 13CE -3071 13CE 3A 5B 31 POS: LD A,(CURPOS) ; Get cursor position -3072 13D1 47 PASSA: LD B,A ; Put A into AB -3073 13D2 AF XOR A ; Zero A -3074 13D3 C3 C2 13 JP ABPASS ; Return integer AB -3075 13D6 -3076 13D6 CD 59 14 DEF: CALL CHEKFN ; Get "FN" and name -3077 13D9 CD 4B 14 CALL IDTEST ; Test for illegal direct -3078 13DC 01 31 0D LD BC,DATA ; To get next statement -3079 13DF C5 PUSH BC ; Save address for RETurn -3080 13E0 D5 PUSH DE ; Save address of function ptr -3081 13E1 CD 10 0A CALL CHKSYN ; Make sure "(" follows -3082 13E4 28 .BYTE "(" -3083 13E5 CD FD 11 CALL GETVAR ; Get argument variable name -3084 13E8 E5 PUSH HL ; Save code string address -3085 13E9 EB EX DE,HL ; Argument address to HL -3086 13EA 2B DEC HL -3087 13EB 56 LD D,(HL) ; Get first byte of arg name -3088 13EC 2B DEC HL -3089 13ED 5E LD E,(HL) ; Get second byte of arg name -3090 13EE E1 POP HL ; Restore code string address -3091 13EF CD 0A 10 CALL TSTNUM ; Make sure numeric argument -3092 13F2 CD 10 0A CALL CHKSYN ; Make sure ")" follows -3093 13F5 29 .BYTE ")" -3094 13F6 CD 10 0A CALL CHKSYN ; Make sure "=" follows -3095 13F9 B4 .BYTE ZEQUAL ; "=" token -3096 13FA 44 LD B,H ; Code string address to BC -3097 13FB 4D LD C,L -3098 13FC E3 EX (SP),HL ; Save code str , Get FN ptr -3099 13FD 71 LD (HL),C ; Save LSB of FN code string -3100 13FE 23 INC HL -3101 13FF 70 LD (HL),B ; Save MSB of FN code string -3102 1400 C3 98 14 JP SVSTAD ; Save address and do function -3103 1403 -3104 1403 CD 59 14 DOFN: CALL CHEKFN ; Make sure FN follows -3105 1406 D5 PUSH DE ; Save function pointer address -3106 1407 CD DE 10 CALL EVLPAR ; Evaluate expression in "()" -3107 140A CD 0A 10 CALL TSTNUM ; Make sure numeric result -3108 140D E3 EX (SP),HL ; Save code str , Get FN ptr -3109 140E 5E LD E,(HL) ; Get LSB of FN code string -3110 140F 23 INC HL -3111 1410 56 LD D,(HL) ; Get MSB of FN code string -3112 1411 23 INC HL -3113 1412 7A LD A,D ; And function DEFined? -3114 1413 B3 OR E -3115 1414 CA 4E 07 JP Z,UFERR ; No - ?UF Error -3116 1417 7E LD A,(HL) ; Get LSB of argument address -3117 1418 23 INC HL -3118 1419 66 LD H,(HL) ; Get MSB of argument address -3119 141A 6F LD L,A ; HL = Arg variable address -3120 141B E5 PUSH HL ; Save it -3121 141C 2A 8E 31 LD HL,(FNRGNM) ; Get old argument name -3122 141F E3 EX (SP),HL ; ; Save old , Get new -3123 1420 22 8E 31 LD (FNRGNM),HL ; Set new argument name -3124 1423 2A 92 31 LD HL,(FNARG+2) ; Get LSB,NLSB of old arg value -3125 1426 E5 PUSH HL ; Save it -3126 1427 2A 90 31 LD HL,(FNARG) ; Get MSB,EXP of old arg value -3127 142A E5 PUSH HL ; Save it -3128 142B 21 90 31 LD HL,FNARG ; HL = Value of argument -3129 142E D5 PUSH DE ; Save FN code string address -3130 142F CD 41 1A CALL FPTHL ; Move FPREG to argument -3131 1432 E1 POP HL ; Get FN code string address -3132 1433 CD 07 10 CALL GETNUM ; Get value from function -3133 1436 2B DEC HL ; DEC 'cos GETCHR INCs -3134 1437 CD 9A 0B CALL GETCHR ; Get next character -3135 143A C2 42 07 JP NZ,SNERR ; Bad character in FN - Error -3136 143D E1 POP HL ; Get MSB,EXP of old arg -3137 143E 22 90 31 LD (FNARG),HL ; Restore it -3138 1441 E1 POP HL ; Get LSB,NLSB of old arg -3139 1442 22 92 31 LD (FNARG+2),HL ; Restore it -3140 1445 E1 POP HL ; Get name of old arg -3141 1446 22 8E 31 LD (FNRGNM),HL ; Restore it -3142 1449 E1 POP HL ; Restore code string address -3143 144A C9 RET -3144 144B -3145 144B E5 IDTEST: PUSH HL ; Save code string address -3146 144C 2A 0C 31 LD HL,(LINEAT) ; Get current line number -3147 144F 23 INC HL ; -1 means direct statement -3148 1450 7C LD A,H -3149 1451 B5 OR L -3150 1452 E1 POP HL ; Restore code string address -3151 1453 C0 RET NZ ; Return if in program -3152 1454 1E 16 LD E,ID ; ?ID Error -3153 1456 C3 56 07 JP ERROR -3154 1459 -3155 1459 CD 10 0A CHEKFN: CALL CHKSYN ; Make sure FN follows -3156 145C A7 .BYTE ZFN ; "FN" token -3157 145D 3E 80 LD A,80H -3158 145F 32 7B 31 LD (FORFLG),A ; Flag FN name to find -3159 1462 B6 OR (HL) ; FN name has bit 7 set -3160 1463 47 LD B,A ; in first byte of name -3161 1464 CD 02 12 CALL GTFNAM ; Get FN name -3162 1467 C3 0A 10 JP TSTNUM ; Make sure numeric function -3163 146A -3164 146A CD 0A 10 STR: CALL TSTNUM ; Make sure it's a number -3165 146D CD 8E 1B CALL NUMASC ; Turn number into text -3166 1470 CD 9E 14 STR1: CALL CRTST ; Create string entry for it -3167 1473 CD 23 16 CALL GSTRCU ; Current string to pool -3168 1476 01 7E 16 LD BC,TOPOOL ; Save in string pool -3169 1479 C5 PUSH BC ; Save address on stack -3170 147A -3171 147A 7E SAVSTR: LD A,(HL) ; Get string length -3172 147B 23 INC HL -3173 147C 23 INC HL -3174 147D E5 PUSH HL ; Save pointer to string -3175 147E CD F9 14 CALL TESTR ; See if enough string space -3176 1481 E1 POP HL ; Restore pointer to string -3177 1482 4E LD C,(HL) ; Get LSB of address -3178 1483 23 INC HL -3179 1484 46 LD B,(HL) ; Get MSB of address -3180 1485 CD 92 14 CALL CRTMST ; Create string entry -3181 1488 E5 PUSH HL ; Save pointer to MSB of addr -3182 1489 6F LD L,A ; Length of string -3183 148A CD 16 16 CALL TOSTRA ; Move to string area -3184 148D D1 POP DE ; Restore pointer to MSB -3185 148E C9 RET -3186 148F -3187 148F CD F9 14 MKTMST: CALL TESTR ; See if enough string space -3188 1492 21 6F 31 CRTMST: LD HL,TMPSTR ; Temporary string -3189 1495 E5 PUSH HL ; Save it -3190 1496 77 LD (HL),A ; Save length of string -3191 1497 23 INC HL -3192 1498 23 SVSTAD: INC HL -3193 1499 73 LD (HL),E ; Save LSB of address -3194 149A 23 INC HL -3195 149B 72 LD (HL),D ; Save MSB of address -3196 149C E1 POP HL ; Restore pointer -3197 149D C9 RET -3198 149E -3199 149E 2B CRTST: DEC HL ; DEC - INCed after -3200 149F 06 22 QTSTR: LD B,'"' ; Terminating quote -3201 14A1 50 LD D,B ; Quote to D -3202 14A2 E5 DTSTR: PUSH HL ; Save start -3203 14A3 0E FF LD C,-1 ; Set counter to -1 -3204 14A5 23 QTSTLP: INC HL ; Move on -3205 14A6 7E LD A,(HL) ; Get byte -3206 14A7 0C INC C ; Count bytes -3207 14A8 B7 OR A ; End of line? -3208 14A9 CA B4 14 JP Z,CRTSTE ; Yes - Create string entry -3209 14AC BA CP D ; Terminator D found? -3210 14AD CA B4 14 JP Z,CRTSTE ; Yes - Create string entry -3211 14B0 B8 CP B ; Terminator B found? -3212 14B1 C2 A5 14 JP NZ,QTSTLP ; No - Keep looking -3213 14B4 FE 22 CRTSTE: CP '"' ; End with '"'? -3214 14B6 CC 9A 0B CALL Z,GETCHR ; Yes - Get next character -3215 14B9 E3 EX (SP),HL ; Starting quote -3216 14BA 23 INC HL ; First byte of string -3217 14BB EB EX DE,HL ; To DE -3218 14BC 79 LD A,C ; Get length -3219 14BD CD 92 14 CALL CRTMST ; Create string entry -3220 14C0 11 6F 31 TSTOPL: LD DE,TMPSTR ; Temporary string -3221 14C3 2A 61 31 LD HL,(TMSTPT) ; Temporary string pool pointer -3222 14C6 22 94 31 LD (FPREG),HL ; Save address of string ptr -3223 14C9 3E 01 LD A,1 -3224 14CB 32 5D 31 LD (TYPE),A ; Set type to string -3225 14CE CD 44 1A CALL DETHL4 ; Move string to pool -3226 14D1 CD 0A 0A CALL CPDEHL ; Out of string pool? -3227 14D4 22 61 31 LD (TMSTPT),HL ; Save new pointer -3228 14D7 E1 POP HL ; Restore code string address -3229 14D8 7E LD A,(HL) ; Get next code byte -3230 14D9 C0 RET NZ ; Return if pool OK -3231 14DA 1E 1E LD E,ST ; ?ST Error -3232 14DC C3 56 07 JP ERROR ; String pool overflow -3233 14DF -3234 14DF 23 PRNUMS: INC HL ; Skip leading space -3235 14E0 CD 9E 14 PRS: CALL CRTST ; Create string entry for it -3236 14E3 CD 23 16 PRS1: CALL GSTRCU ; Current string to pool -3237 14E6 CD 38 1A CALL LOADFP ; Move string block to BCDE -3238 14E9 1C INC E ; Length + 1 -3239 14EA 1D PRSLP: DEC E ; Count characters -3240 14EB C8 RET Z ; End of string -3241 14EC 0A LD A,(BC) ; Get byte to output -3242 14ED CD 1B 0A CALL OUTC ; Output character in A -3243 14F0 FE 0D CP CR ; Return? -3244 14F2 CC 4C 0E CALL Z,DONULL ; Yes - Do nulls -3245 14F5 03 INC BC ; Next byte in string -3246 14F6 C3 EA 14 JP PRSLP ; More characters to output -3247 14F9 -3248 14F9 B7 TESTR: OR A ; Test if enough room -3249 14FA 0E .BYTE 0EH ; No garbage collection done -3250 14FB F1 GRBDON: POP AF ; Garbage collection done -3251 14FC F5 PUSH AF ; Save status -3252 14FD 2A 0A 31 LD HL,(STRSPC) ; Bottom of string space in use -3253 1500 EB EX DE,HL ; To DE -3254 1501 2A 73 31 LD HL,(STRBOT) ; Bottom of string area -3255 1504 2F CPL ; Negate length (Top down) -3256 1505 4F LD C,A ; -Length to BC -3257 1506 06 FF LD B,-1 ; BC = -ve length of string -3258 1508 09 ADD HL,BC ; Add to bottom of space in use -3259 1509 23 INC HL ; Plus one for 2's complement -3260 150A CD 0A 0A CALL CPDEHL ; Below string RAM area? -3261 150D DA 17 15 JP C,TESTOS ; Tidy up if not done else err -3262 1510 22 73 31 LD (STRBOT),HL ; Save new bottom of area -3263 1513 23 INC HL ; Point to first byte of string -3264 1514 EB EX DE,HL ; Address to DE -3265 1515 F1 POPAF: POP AF ; Throw away status push -3266 1516 C9 RET -3267 1517 -3268 1517 F1 TESTOS: POP AF ; Garbage collect been done? -3269 1518 1E 1A LD E,OS ; ?OS Error -3270 151A CA 56 07 JP Z,ERROR ; Yes - Not enough string apace -3271 151D BF CP A ; Flag garbage collect done -3272 151E F5 PUSH AF ; Save status -3273 151F 01 FB 14 LD BC,GRBDON ; Garbage collection done -3274 1522 C5 PUSH BC ; Save for RETurn -3275 1523 2A 5F 31 GARBGE: LD HL,(LSTRAM) ; Get end of RAM pointer -3276 1526 22 73 31 GARBLP: LD (STRBOT),HL ; Reset string pointer -3277 1529 21 00 00 LD HL,0 -3278 152C E5 PUSH HL ; Flag no string found -3279 152D 2A 0A 31 LD HL,(STRSPC) ; Get bottom of string space -3280 1530 E5 PUSH HL ; Save bottom of string space -3281 1531 21 63 31 LD HL,TMSTPL ; Temporary string pool -3282 1534 EB GRBLP: EX DE,HL -3283 1535 2A 61 31 LD HL,(TMSTPT) ; Temporary string pool pointer -3284 1538 EB EX DE,HL -3285 1539 CD 0A 0A CALL CPDEHL ; Temporary string pool done? -3286 153C 01 34 15 LD BC,GRBLP ; Loop until string pool done -3287 153F C2 88 15 JP NZ,STPOOL ; No - See if in string area -3288 1542 2A 86 31 LD HL,(PROGND) ; Start of simple variables -3289 1545 EB SMPVAR: EX DE,HL -3290 1546 2A 88 31 LD HL,(VAREND) ; End of simple variables -3291 1549 EB EX DE,HL -3292 154A CD 0A 0A CALL CPDEHL ; All simple strings done? -3293 154D CA 5B 15 JP Z,ARRLP ; Yes - Do string arrays -3294 1550 7E LD A,(HL) ; Get type of variable -3295 1551 23 INC HL -3296 1552 23 INC HL -3297 1553 B7 OR A ; "S" flag set if string -3298 1554 CD 8B 15 CALL STRADD ; See if string in string area -3299 1557 C3 45 15 JP SMPVAR ; Loop until simple ones done -3300 155A -3301 155A C1 GNXARY: POP BC ; Scrap address of this array -3302 155B EB ARRLP: EX DE,HL -3303 155C 2A 8A 31 LD HL,(ARREND) ; End of string arrays -3304 155F EB EX DE,HL -3305 1560 CD 0A 0A CALL CPDEHL ; All string arrays done? -3306 1563 CA B1 15 JP Z,SCNEND ; Yes - Move string if found -3307 1566 CD 38 1A CALL LOADFP ; Get array name to BCDE -3308 1569 7B LD A,E ; Get type of array -3309 156A E5 PUSH HL ; Save address of num of dim'ns -3310 156B 09 ADD HL,BC ; Start of next array -3311 156C B7 OR A ; Test type of array -3312 156D F2 5A 15 JP P,GNXARY ; Numeric array - Ignore it -3313 1570 22 75 31 LD (CUROPR),HL ; Save address of next array -3314 1573 E1 POP HL ; Get address of num of dim'ns -3315 1574 4E LD C,(HL) ; BC = Number of dimensions -3316 1575 06 00 LD B,0 -3317 1577 09 ADD HL,BC ; Two bytes per dimension size -3318 1578 09 ADD HL,BC -3319 1579 23 INC HL ; Plus one for number of dim'ns -3320 157A EB GRBARY: EX DE,HL -3321 157B 2A 75 31 LD HL,(CUROPR) ; Get address of next array -3322 157E EB EX DE,HL -3323 157F CD 0A 0A CALL CPDEHL ; Is this array finished? -3324 1582 CA 5B 15 JP Z,ARRLP ; Yes - Get next one -3325 1585 01 7A 15 LD BC,GRBARY ; Loop until array all done -3326 1588 C5 STPOOL: PUSH BC ; Save return address -3327 1589 F6 80 OR 80H ; Flag string type -3328 158B 7E STRADD: LD A,(HL) ; Get string length -3329 158C 23 INC HL -3330 158D 23 INC HL -3331 158E 5E LD E,(HL) ; Get LSB of string address -3332 158F 23 INC HL -3333 1590 56 LD D,(HL) ; Get MSB of string address -3334 1591 23 INC HL -3335 1592 F0 RET P ; Not a string - Return -3336 1593 B7 OR A ; Set flags on string length -3337 1594 C8 RET Z ; Null string - Return -3338 1595 44 LD B,H ; Save variable pointer -3339 1596 4D LD C,L -3340 1597 2A 73 31 LD HL,(STRBOT) ; Bottom of new area -3341 159A CD 0A 0A CALL CPDEHL ; String been done? -3342 159D 60 LD H,B ; Restore variable pointer -3343 159E 69 LD L,C -3344 159F D8 RET C ; String done - Ignore -3345 15A0 E1 POP HL ; Return address -3346 15A1 E3 EX (SP),HL ; Lowest available string area -3347 15A2 CD 0A 0A CALL CPDEHL ; String within string area? -3348 15A5 E3 EX (SP),HL ; Lowest available string area -3349 15A6 E5 PUSH HL ; Re-save return address -3350 15A7 60 LD H,B ; Restore variable pointer -3351 15A8 69 LD L,C -3352 15A9 D0 RET NC ; Outside string area - Ignore -3353 15AA C1 POP BC ; Get return , Throw 2 away -3354 15AB F1 POP AF ; -3355 15AC F1 POP AF ; -3356 15AD E5 PUSH HL ; Save variable pointer -3357 15AE D5 PUSH DE ; Save address of current -3358 15AF C5 PUSH BC ; Put back return address -3359 15B0 C9 RET ; Go to it -3360 15B1 -3361 15B1 D1 SCNEND: POP DE ; Addresses of strings -3362 15B2 E1 POP HL ; -3363 15B3 7D LD A,L ; HL = 0 if no more to do -3364 15B4 B4 OR H -3365 15B5 C8 RET Z ; No more to do - Return -3366 15B6 2B DEC HL -3367 15B7 46 LD B,(HL) ; MSB of address of string -3368 15B8 2B DEC HL -3369 15B9 4E LD C,(HL) ; LSB of address of string -3370 15BA E5 PUSH HL ; Save variable address -3371 15BB 2B DEC HL -3372 15BC 2B DEC HL -3373 15BD 6E LD L,(HL) ; HL = Length of string -3374 15BE 26 00 LD H,0 -3375 15C0 09 ADD HL,BC ; Address of end of string+1 -3376 15C1 50 LD D,B ; String address to DE -3377 15C2 59 LD E,C -3378 15C3 2B DEC HL ; Last byte in string -3379 15C4 44 LD B,H ; Address to BC -3380 15C5 4D LD C,L -3381 15C6 2A 73 31 LD HL,(STRBOT) ; Current bottom of string area -3382 15C9 CD 11 07 CALL MOVSTR ; Move string to new address -3383 15CC E1 POP HL ; Restore variable address -3384 15CD 71 LD (HL),C ; Save new LSB of address -3385 15CE 23 INC HL -3386 15CF 70 LD (HL),B ; Save new MSB of address -3387 15D0 69 LD L,C ; Next string area+1 to HL -3388 15D1 60 LD H,B -3389 15D2 2B DEC HL ; Next string area address -3390 15D3 C3 26 15 JP GARBLP ; Look for more strings -3391 15D6 -3392 15D6 C5 CONCAT: PUSH BC ; Save prec' opr & code string -3393 15D7 E5 PUSH HL ; -3394 15D8 2A 94 31 LD HL,(FPREG) ; Get first string -3395 15DB E3 EX (SP),HL ; Save first string -3396 15DC CD 90 10 CALL OPRND ; Get second string -3397 15DF E3 EX (SP),HL ; Restore first string -3398 15E0 CD 0B 10 CALL TSTSTR ; Make sure it's a string -3399 15E3 7E LD A,(HL) ; Get length of second string -3400 15E4 E5 PUSH HL ; Save first string -3401 15E5 2A 94 31 LD HL,(FPREG) ; Get second string -3402 15E8 E5 PUSH HL ; Save second string -3403 15E9 86 ADD A,(HL) ; Add length of second string -3404 15EA 1E 1C LD E,LS ; ?LS Error -3405 15EC DA 56 07 JP C,ERROR ; String too long - Error -3406 15EF CD 8F 14 CALL MKTMST ; Make temporary string -3407 15F2 D1 POP DE ; Get second string to DE -3408 15F3 CD 27 16 CALL GSTRDE ; Move to string pool if needed -3409 15F6 E3 EX (SP),HL ; Get first string -3410 15F7 CD 26 16 CALL GSTRHL ; Move to string pool if needed -3411 15FA E5 PUSH HL ; Save first string -3412 15FB 2A 71 31 LD HL,(TMPSTR+2) ; Temporary string address -3413 15FE EB EX DE,HL ; To DE -3414 15FF CD 0D 16 CALL SSTSA ; First string to string area -3415 1602 CD 0D 16 CALL SSTSA ; Second string to string area -3416 1605 21 25 10 LD HL,EVAL2 ; Return to evaluation loop -3417 1608 E3 EX (SP),HL ; Save return,get code string -3418 1609 E5 PUSH HL ; Save code string address -3419 160A C3 C0 14 JP TSTOPL ; To temporary string to pool -3420 160D -3421 160D E1 SSTSA: POP HL ; Return address -3422 160E E3 EX (SP),HL ; Get string block,save return -3423 160F 7E LD A,(HL) ; Get length of string -3424 1610 23 INC HL -3425 1611 23 INC HL -3426 1612 4E LD C,(HL) ; Get LSB of string address -3427 1613 23 INC HL -3428 1614 46 LD B,(HL) ; Get MSB of string address -3429 1615 6F LD L,A ; Length to L -3430 1616 2C TOSTRA: INC L ; INC - DECed after -3431 1617 2D TSALP: DEC L ; Count bytes moved -3432 1618 C8 RET Z ; End of string - Return -3433 1619 0A LD A,(BC) ; Get source -3434 161A 12 LD (DE),A ; Save destination -3435 161B 03 INC BC ; Next source -3436 161C 13 INC DE ; Next destination -3437 161D C3 17 16 JP TSALP ; Loop until string moved -3438 1620 -3439 1620 CD 0B 10 GETSTR: CALL TSTSTR ; Make sure it's a string -3440 1623 2A 94 31 GSTRCU: LD HL,(FPREG) ; Get current string -3441 1626 EB GSTRHL: EX DE,HL ; Save DE -3442 1627 CD 41 16 GSTRDE: CALL BAKTMP ; Was it last tmp-str? -3443 162A EB EX DE,HL ; Restore DE -3444 162B C0 RET NZ ; No - Return -3445 162C D5 PUSH DE ; Save string -3446 162D 50 LD D,B ; String block address to DE -3447 162E 59 LD E,C -3448 162F 1B DEC DE ; Point to length -3449 1630 4E LD C,(HL) ; Get string length -3450 1631 2A 73 31 LD HL,(STRBOT) ; Current bottom of string area -3451 1634 CD 0A 0A CALL CPDEHL ; Last one in string area? -3452 1637 C2 3F 16 JP NZ,POPHL ; No - Return -3453 163A 47 LD B,A ; Clear B (A=0) -3454 163B 09 ADD HL,BC ; Remove string from str' area -3455 163C 22 73 31 LD (STRBOT),HL ; Save new bottom of str' area -3456 163F E1 POPHL: POP HL ; Restore string -3457 1640 C9 RET -3458 1641 -3459 1641 2A 61 31 BAKTMP: LD HL,(TMSTPT) ; Get temporary string pool top -3460 1644 2B DEC HL ; Back -3461 1645 46 LD B,(HL) ; Get MSB of address -3462 1646 2B DEC HL ; Back -3463 1647 4E LD C,(HL) ; Get LSB of address -3464 1648 2B DEC HL ; Back -3465 1649 2B DEC HL ; Back -3466 164A CD 0A 0A CALL CPDEHL ; String last in string pool? -3467 164D C0 RET NZ ; Yes - Leave it -3468 164E 22 61 31 LD (TMSTPT),HL ; Save new string pool top -3469 1651 C9 RET -3470 1652 -3471 1652 01 D1 13 LEN: LD BC,PASSA ; To return integer A -3472 1655 C5 PUSH BC ; Save address -3473 1656 CD 20 16 GETLEN: CALL GETSTR ; Get string and its length -3474 1659 AF XOR A -3475 165A 57 LD D,A ; Clear D -3476 165B 32 5D 31 LD (TYPE),A ; Set type to numeric -3477 165E 7E LD A,(HL) ; Get length of string -3478 165F B7 OR A ; Set status flags -3479 1660 C9 RET -3480 1661 -3481 1661 01 D1 13 ASC: LD BC,PASSA ; To return integer A -3482 1664 C5 PUSH BC ; Save address -3483 1665 CD 56 16 GTFLNM: CALL GETLEN ; Get length of string -3484 1668 CA 61 0C JP Z,FCERR ; Null string - Error -3485 166B 23 INC HL -3486 166C 23 INC HL -3487 166D 5E LD E,(HL) ; Get LSB of address -3488 166E 23 INC HL -3489 166F 56 LD D,(HL) ; Get MSB of address -3490 1670 1A LD A,(DE) ; Get first byte of string -3491 1671 C9 RET -3492 1672 -3493 1672 3E 01 CHR: LD A,1 ; One character string -3494 1674 CD 8F 14 CALL MKTMST ; Make a temporary string -3495 1677 CD 6B 17 CALL MAKINT ; Make it integer A -3496 167A 2A 71 31 LD HL,(TMPSTR+2) ; Get address of string -3497 167D 73 LD (HL),E ; Save character -3498 167E C1 TOPOOL: POP BC ; Clean up stack -3499 167F C3 C0 14 JP TSTOPL ; Temporary string to pool -3500 1682 -3501 1682 CD 1B 17 LEFT: CALL LFRGNM ; Get number and ending ")" -3502 1685 AF XOR A ; Start at first byte in string -3503 1686 E3 RIGHT1: EX (SP),HL ; Save code string,Get string -3504 1687 4F LD C,A ; Starting position in string -3505 1688 E5 MID1: PUSH HL ; Save string block address -3506 1689 7E LD A,(HL) ; Get length of string -3507 168A B8 CP B ; Compare with number given -3508 168B DA 90 16 JP C,ALLFOL ; All following bytes required -3509 168E 78 LD A,B ; Get new length -3510 168F 11 .BYTE 11H ; Skip "LD C,0" -3511 1690 0E 00 ALLFOL: LD C,0 ; First byte of string -3512 1692 C5 PUSH BC ; Save position in string -3513 1693 CD F9 14 CALL TESTR ; See if enough string space -3514 1696 C1 POP BC ; Get position in string -3515 1697 E1 POP HL ; Restore string block address -3516 1698 E5 PUSH HL ; And re-save it -3517 1699 23 INC HL -3518 169A 23 INC HL -3519 169B 46 LD B,(HL) ; Get LSB of address -3520 169C 23 INC HL -3521 169D 66 LD H,(HL) ; Get MSB of address -3522 169E 68 LD L,B ; HL = address of string -3523 169F 06 00 LD B,0 ; BC = starting address -3524 16A1 09 ADD HL,BC ; Point to that byte -3525 16A2 44 LD B,H ; BC = source string -3526 16A3 4D LD C,L -3527 16A4 CD 92 14 CALL CRTMST ; Create a string entry -3528 16A7 6F LD L,A ; Length of new string -3529 16A8 CD 16 16 CALL TOSTRA ; Move string to string area -3530 16AB D1 POP DE ; Clear stack -3531 16AC CD 27 16 CALL GSTRDE ; Move to string pool if needed -3532 16AF C3 C0 14 JP TSTOPL ; Temporary string to pool -3533 16B2 -3534 16B2 CD 1B 17 RIGHT: CALL LFRGNM ; Get number and ending ")" -3535 16B5 D1 POP DE ; Get string length -3536 16B6 D5 PUSH DE ; And re-save -3537 16B7 1A LD A,(DE) ; Get length -3538 16B8 90 SUB B ; Move back N bytes -3539 16B9 C3 86 16 JP RIGHT1 ; Go and get sub-string -3540 16BC -3541 16BC EB MID: EX DE,HL ; Get code string address -3542 16BD 7E LD A,(HL) ; Get next byte ',' or ")" -3543 16BE CD 20 17 CALL MIDNUM ; Get number supplied -3544 16C1 04 INC B ; Is it character zero? -3545 16C2 05 DEC B -3546 16C3 CA 61 0C JP Z,FCERR ; Yes - Error -3547 16C6 C5 PUSH BC ; Save starting position -3548 16C7 1E FF LD E,255 ; All of string -3549 16C9 FE 29 CP ')' ; Any length given? -3550 16CB CA D5 16 JP Z,RSTSTR ; No - Rest of string -3551 16CE CD 10 0A CALL CHKSYN ; Make sure ',' follows -3552 16D1 2C .BYTE ',' -3553 16D2 CD 68 17 CALL GETINT ; Get integer 0-255 -3554 16D5 CD 10 0A RSTSTR: CALL CHKSYN ; Make sure ")" follows -3555 16D8 29 .BYTE ")" -3556 16D9 F1 POP AF ; Restore starting position -3557 16DA E3 EX (SP),HL ; Get string,8ave code string -3558 16DB 01 88 16 LD BC,MID1 ; Continuation of MID$ routine -3559 16DE C5 PUSH BC ; Save for return -3560 16DF 3D DEC A ; Starting position-1 -3561 16E0 BE CP (HL) ; Compare with length -3562 16E1 06 00 LD B,0 ; Zero bytes length -3563 16E3 D0 RET NC ; Null string if start past end -3564 16E4 4F LD C,A ; Save starting position-1 -3565 16E5 7E LD A,(HL) ; Get length of string -3566 16E6 91 SUB C ; Subtract start -3567 16E7 BB CP E ; Enough string for it? -3568 16E8 47 LD B,A ; Save maximum length available -3569 16E9 D8 RET C ; Truncate string if needed -3570 16EA 43 LD B,E ; Set specified length -3571 16EB C9 RET ; Go and create string -3572 16EC -3573 16EC CD 56 16 VAL: CALL GETLEN ; Get length of string -3574 16EF CA 09 18 JP Z,RESZER ; Result zero -3575 16F2 5F LD E,A ; Save length -3576 16F3 23 INC HL -3577 16F4 23 INC HL -3578 16F5 7E LD A,(HL) ; Get LSB of address -3579 16F6 23 INC HL -3580 16F7 66 LD H,(HL) ; Get MSB of address -3581 16F8 6F LD L,A ; HL = String address -3582 16F9 E5 PUSH HL ; Save string address -3583 16FA 19 ADD HL,DE -3584 16FB 46 LD B,(HL) ; Get end of string+1 byte -3585 16FC 72 LD (HL),D ; Zero it to terminate -3586 16FD E3 EX (SP),HL ; Save string end,get start -3587 16FE C5 PUSH BC ; Save end+1 byte -3588 16FF 7E LD A,(HL) ; Get starting byte -3589 1700 FE 24 CP '$' ; Hex number indicated? [function added] -3590 1702 C2 0A 17 JP NZ,VAL1 -3591 1705 CD 34 1F CALL HEXTFP ; Convert Hex to FPREG -3592 1708 18 0D JR VAL3 -3593 170A FE 25 VAL1: CP '%' ; Binary number indicated? [function added] -3594 170C C2 14 17 JP NZ,VAL2 -3595 170F CD A4 1F CALL BINTFP ; Convert Bin to FPREG -3596 1712 18 03 JR VAL3 -3597 1714 CD F0 1A VAL2: CALL ASCTFP ; Convert ASCII string to FP -3598 1717 C1 VAL3: POP BC ; Restore end+1 byte -3599 1718 E1 POP HL ; Restore end+1 address -3600 1719 70 LD (HL),B ; Put back original byte -3601 171A C9 RET -3602 171B -3603 171B EB LFRGNM: EX DE,HL ; Code string address to HL -3604 171C CD 10 0A CALL CHKSYN ; Make sure ")" follows -3605 171F 29 .BYTE ")" -3606 1720 C1 MIDNUM: POP BC ; Get return address -3607 1721 D1 POP DE ; Get number supplied -3608 1722 C5 PUSH BC ; Re-save return address -3609 1723 43 LD B,E ; Number to B -3610 1724 C9 RET -3611 1725 -3612 1725 CD 6B 17 INP: CALL MAKINT ; Make it integer A -3613 1728 32 EF 30 LD (INPORT),A ; Set input port -3614 172B CD EE 30 CALL INPSUB ; Get input from port -3615 172E C3 D1 13 JP PASSA ; Return integer A -3616 1731 -3617 1731 CD 55 17 POUT: CALL SETIO ; Set up port number -3618 1734 C3 B6 30 JP OUTSUB ; Output data and return -3619 1737 -3620 1737 CD 55 17 WAIT: CALL SETIO ; Set up port number -3621 173A F5 PUSH AF ; Save AND mask -3622 173B 1E 00 LD E,0 ; Assume zero if none given -3623 173D 2B DEC HL ; DEC 'cos GETCHR INCs -3624 173E CD 9A 0B CALL GETCHR ; Get next character -3625 1741 CA 4B 17 JP Z,NOXOR ; No XOR byte given -3626 1744 CD 10 0A CALL CHKSYN ; Make sure ',' follows -3627 1747 2C .BYTE ',' -3628 1748 CD 68 17 CALL GETINT ; Get integer 0-255 to XOR with -3629 174B C1 NOXOR: POP BC ; Restore AND mask -3630 174C CD EE 30 WAITLP: CALL INPSUB ; Get input -3631 174F AB XOR E ; Flip selected bits -3632 1750 A0 AND B ; Result non-zero? -3633 1751 CA 4C 17 JP Z,WAITLP ; No = keep waiting -3634 1754 C9 RET -3635 1755 -3636 1755 CD 68 17 SETIO: CALL GETINT ; Get integer 0-255 -3637 1758 32 EF 30 LD (INPORT),A ; Set input port -3638 175B 32 B7 30 LD (OTPORT),A ; Set output port -3639 175E CD 10 0A CALL CHKSYN ; Make sure ',' follows -3640 1761 2C .BYTE ',' -3641 1762 C3 68 17 JP GETINT ; Get integer 0-255 and return -3642 1765 -3643 1765 CD 9A 0B FNDNUM: CALL GETCHR ; Get next character -3644 1768 CD 07 10 GETINT: CALL GETNUM ; Get a number from 0 to 255 -3645 176B CD 46 0C MAKINT: CALL DEPINT ; Make sure value 0 - 255 -3646 176E 7A LD A,D ; Get MSB of number -3647 176F B7 OR A ; Zero? -3648 1770 C2 61 0C JP NZ,FCERR ; No - Error -3649 1773 2B DEC HL ; DEC 'cos GETCHR INCs -3650 1774 CD 9A 0B CALL GETCHR ; Get next character -3651 1777 7B LD A,E ; Get number to A -3652 1778 C9 RET -3653 1779 -3654 1779 CD 4C 0C PEEK: CALL DEINT ; Get memory address -3655 177C 1A LD A,(DE) ; Get byte in memory -3656 177D C3 D1 13 JP PASSA ; Return integer A -3657 1780 -3658 1780 CD 07 10 POKE: CALL GETNUM ; Get memory address -3659 1783 CD 4C 0C CALL DEINT ; Get integer -32768 to 3276 -3660 1786 D5 PUSH DE ; Save memory address -3661 1787 CD 10 0A CALL CHKSYN ; Make sure ',' follows -3662 178A 2C .BYTE ',' -3663 178B CD 68 17 CALL GETINT ; Get integer 0-255 -3664 178E D1 POP DE ; Restore memory address -3665 178F 12 LD (DE),A ; Load it into memory -3666 1790 C9 RET -3667 1791 -3668 1791 21 67 1C ROUND: LD HL,HALF ; Add 0.5 to FPREG -3669 1794 CD 38 1A ADDPHL: CALL LOADFP ; Load FP at (HL) to BCDE -3670 1797 C3 A3 17 JP FPADD ; Add BCDE to FPREG -3671 179A -3672 179A CD 38 1A SUBPHL: CALL LOADFP ; FPREG = -FPREG + number at HL -3673 179D 21 .BYTE 21H ; Skip "POP BC" and "POP DE" -3674 179E C1 PSUB: POP BC ; Get FP number from stack -3675 179F D1 POP DE -3676 17A0 CD 12 1A SUBCDE: CALL INVSGN ; Negate FPREG -3677 17A3 78 FPADD: LD A,B ; Get FP exponent -3678 17A4 B7 OR A ; Is number zero? -3679 17A5 C8 RET Z ; Yes - Nothing to add -3680 17A6 3A 97 31 LD A,(FPEXP) ; Get FPREG exponent -3681 17A9 B7 OR A ; Is this number zero? -3682 17AA CA 2A 1A JP Z,FPBCDE ; Yes - Move BCDE to FPREG -3683 17AD 90 SUB B ; BCDE number larger? -3684 17AE D2 BD 17 JP NC,NOSWAP ; No - Don't swap them -3685 17B1 2F CPL ; Two's complement -3686 17B2 3C INC A ; FP exponent -3687 17B3 EB EX DE,HL -3688 17B4 CD 1A 1A CALL STAKFP ; Put FPREG on stack -3689 17B7 EB EX DE,HL -3690 17B8 CD 2A 1A CALL FPBCDE ; Move BCDE to FPREG -3691 17BB C1 POP BC ; Restore number from stack -3692 17BC D1 POP DE -3693 17BD FE 19 NOSWAP: CP 24+1 ; Second number insignificant? -3694 17BF D0 RET NC ; Yes - First number is result -3695 17C0 F5 PUSH AF ; Save number of bits to scale -3696 17C1 CD 4F 1A CALL SIGNS ; Set MSBs & sign of result -3697 17C4 67 LD H,A ; Save sign of result -3698 17C5 F1 POP AF ; Restore scaling factor -3699 17C6 CD 68 18 CALL SCALE ; Scale BCDE to same exponent -3700 17C9 B4 OR H ; Result to be positive? -3701 17CA 21 94 31 LD HL,FPREG ; Point to FPREG -3702 17CD F2 E3 17 JP P,MINCDE ; No - Subtract FPREG from CDE -3703 17D0 CD 48 18 CALL PLUCDE ; Add FPREG to CDE -3704 17D3 D2 29 18 JP NC,RONDUP ; No overflow - Round it up -3705 17D6 23 INC HL ; Point to exponent -3706 17D7 34 INC (HL) ; Increment it -3707 17D8 CA 51 07 JP Z,OVERR ; Number overflowed - Error -3708 17DB 2E 01 LD L,1 ; 1 bit to shift right -3709 17DD CD 7E 18 CALL SHRT1 ; Shift result right -3710 17E0 C3 29 18 JP RONDUP ; Round it up -3711 17E3 -3712 17E3 AF MINCDE: XOR A ; Clear A and carry -3713 17E4 90 SUB B ; Negate exponent -3714 17E5 47 LD B,A ; Re-save exponent -3715 17E6 7E LD A,(HL) ; Get LSB of FPREG -3716 17E7 9B SBC A, E ; Subtract LSB of BCDE -3717 17E8 5F LD E,A ; Save LSB of BCDE -3718 17E9 23 INC HL -3719 17EA 7E LD A,(HL) ; Get NMSB of FPREG -3720 17EB 9A SBC A,D ; Subtract NMSB of BCDE -3721 17EC 57 LD D,A ; Save NMSB of BCDE -3722 17ED 23 INC HL -3723 17EE 7E LD A,(HL) ; Get MSB of FPREG -3724 17EF 99 SBC A,C ; Subtract MSB of BCDE -3725 17F0 4F LD C,A ; Save MSB of BCDE -3726 17F1 DC 54 18 CONPOS: CALL C,COMPL ; Overflow - Make it positive -3727 17F4 -3728 17F4 68 BNORM: LD L,B ; L = Exponent -3729 17F5 63 LD H,E ; H = LSB -3730 17F6 AF XOR A -3731 17F7 47 BNRMLP: LD B,A ; Save bit count -3732 17F8 79 LD A,C ; Get MSB -3733 17F9 B7 OR A ; Is it zero? -3734 17FA C2 16 18 JP NZ,PNORM ; No - Do it bit at a time -3735 17FD 4A LD C,D ; MSB = NMSB -3736 17FE 54 LD D,H ; NMSB= LSB -3737 17FF 65 LD H,L ; LSB = VLSB -3738 1800 6F LD L,A ; VLSB= 0 -3739 1801 78 LD A,B ; Get exponent -3740 1802 D6 08 SUB 8 ; Count 8 bits -3741 1804 FE E0 CP -24-8 ; Was number zero? -3742 1806 C2 F7 17 JP NZ,BNRMLP ; No - Keep normalising -3743 1809 AF RESZER: XOR A ; Result is zero -3744 180A 32 97 31 SAVEXP: LD (FPEXP),A ; Save result as zero -3745 180D C9 RET -3746 180E -3747 180E 05 NORMAL: DEC B ; Count bits -3748 180F 29 ADD HL,HL ; Shift HL left -3749 1810 7A LD A,D ; Get NMSB -3750 1811 17 RLA ; Shift left with last bit -3751 1812 57 LD D,A ; Save NMSB -3752 1813 79 LD A,C ; Get MSB -3753 1814 8F ADC A,A ; Shift left with last bit -3754 1815 4F LD C,A ; Save MSB -3755 1816 F2 0E 18 PNORM: JP P,NORMAL ; Not done - Keep going -3756 1819 78 LD A,B ; Number of bits shifted -3757 181A 5C LD E,H ; Save HL in EB -3758 181B 45 LD B,L -3759 181C B7 OR A ; Any shifting done? -3760 181D CA 29 18 JP Z,RONDUP ; No - Round it up -3761 1820 21 97 31 LD HL,FPEXP ; Point to exponent -3762 1823 86 ADD A,(HL) ; Add shifted bits -3763 1824 77 LD (HL),A ; Re-save exponent -3764 1825 D2 09 18 JP NC,RESZER ; Underflow - Result is zero -3765 1828 C8 RET Z ; Result is zero -3766 1829 78 RONDUP: LD A,B ; Get VLSB of number -3767 182A 21 97 31 RONDB: LD HL,FPEXP ; Point to exponent -3768 182D B7 OR A ; Any rounding? -3769 182E FC 3B 18 CALL M,FPROND ; Yes - Round number up -3770 1831 46 LD B,(HL) ; B = Exponent -3771 1832 23 INC HL -3772 1833 7E LD A,(HL) ; Get sign of result -3773 1834 E6 80 AND 10000000B ; Only bit 7 needed -3774 1836 A9 XOR C ; Set correct sign -3775 1837 4F LD C,A ; Save correct sign in number -3776 1838 C3 2A 1A JP FPBCDE ; Move BCDE to FPREG -3777 183B -3778 183B 1C FPROND: INC E ; Round LSB -3779 183C C0 RET NZ ; Return if ok -3780 183D 14 INC D ; Round NMSB -3781 183E C0 RET NZ ; Return if ok -3782 183F 0C INC C ; Round MSB -3783 1840 C0 RET NZ ; Return if ok -3784 1841 0E 80 LD C,80H ; Set normal value -3785 1843 34 INC (HL) ; Increment exponent -3786 1844 C0 RET NZ ; Return if ok -3787 1845 C3 51 07 JP OVERR ; Overflow error -3788 1848 -3789 1848 7E PLUCDE: LD A,(HL) ; Get LSB of FPREG -3790 1849 83 ADD A,E ; Add LSB of BCDE -3791 184A 5F LD E,A ; Save LSB of BCDE -3792 184B 23 INC HL -3793 184C 7E LD A,(HL) ; Get NMSB of FPREG -3794 184D 8A ADC A,D ; Add NMSB of BCDE -3795 184E 57 LD D,A ; Save NMSB of BCDE -3796 184F 23 INC HL -3797 1850 7E LD A,(HL) ; Get MSB of FPREG -3798 1851 89 ADC A,C ; Add MSB of BCDE -3799 1852 4F LD C,A ; Save MSB of BCDE -3800 1853 C9 RET -3801 1854 -3802 1854 21 98 31 COMPL: LD HL,SGNRES ; Sign of result -3803 1857 7E LD A,(HL) ; Get sign of result -3804 1858 2F CPL ; Negate it -3805 1859 77 LD (HL),A ; Put it back -3806 185A AF XOR A -3807 185B 6F LD L,A ; Set L to zero -3808 185C 90 SUB B ; Negate exponent,set carry -3809 185D 47 LD B,A ; Re-save exponent -3810 185E 7D LD A,L ; Load zero -3811 185F 9B SBC A,E ; Negate LSB -3812 1860 5F LD E,A ; Re-save LSB -3813 1861 7D LD A,L ; Load zero -3814 1862 9A SBC A,D ; Negate NMSB -3815 1863 57 LD D,A ; Re-save NMSB -3816 1864 7D LD A,L ; Load zero -3817 1865 99 SBC A,C ; Negate MSB -3818 1866 4F LD C,A ; Re-save MSB -3819 1867 C9 RET -3820 1868 -3821 1868 06 00 SCALE: LD B,0 ; Clear underflow -3822 186A D6 08 SCALLP: SUB 8 ; 8 bits (a whole byte)? -3823 186C DA 77 18 JP C,SHRITE ; No - Shift right A bits -3824 186F 43 LD B,E ; <- Shift -3825 1870 5A LD E,D ; <- right -3826 1871 51 LD D,C ; <- eight -3827 1872 0E 00 LD C,0 ; <- bits -3828 1874 C3 6A 18 JP SCALLP ; More bits to shift -3829 1877 -3830 1877 C6 09 SHRITE: ADD A,8+1 ; Adjust count -3831 1879 6F LD L,A ; Save bits to shift -3832 187A AF SHRLP: XOR A ; Flag for all done -3833 187B 2D DEC L ; All shifting done? -3834 187C C8 RET Z ; Yes - Return -3835 187D 79 LD A,C ; Get MSB -3836 187E 1F SHRT1: RRA ; Shift it right -3837 187F 4F LD C,A ; Re-save -3838 1880 7A LD A,D ; Get NMSB -3839 1881 1F RRA ; Shift right with last bit -3840 1882 57 LD D,A ; Re-save it -3841 1883 7B LD A,E ; Get LSB -3842 1884 1F RRA ; Shift right with last bit -3843 1885 5F LD E,A ; Re-save it -3844 1886 78 LD A,B ; Get underflow -3845 1887 1F RRA ; Shift right with last bit -3846 1888 47 LD B,A ; Re-save underflow -3847 1889 C3 7A 18 JP SHRLP ; More bits to do -3848 188C -3849 188C 00 00 00 81 UNITY: .BYTE 000H,000H,000H,081H ; 1.00000 -3850 1890 -3851 1890 03 LOGTAB: .BYTE 3 ; Table used by LOG -3852 1891 AA 56 19 80 .BYTE 0AAH,056H,019H,080H ; 0.59898 -3853 1895 F1 22 76 80 .BYTE 0F1H,022H,076H,080H ; 0.96147 -3854 1899 45 AA 38 82 .BYTE 045H,0AAH,038H,082H ; 2.88539 -3855 189D -3856 189D CD E9 19 LOG: CALL TSTSGN ; Test sign of value -3857 18A0 B7 OR A -3858 18A1 EA 61 0C JP PE,FCERR ; ?FC Error if <= zero -3859 18A4 21 97 31 LD HL,FPEXP ; Point to exponent -3860 18A7 7E LD A,(HL) ; Get exponent -3861 18A8 01 35 80 LD BC,8035H ; BCDE = SQR(1/2) -3862 18AB 11 F3 04 LD DE,04F3H -3863 18AE 90 SUB B ; Scale value to be < 1 -3864 18AF F5 PUSH AF ; Save scale factor -3865 18B0 70 LD (HL),B ; Save new exponent -3866 18B1 D5 PUSH DE ; Save SQR(1/2) -3867 18B2 C5 PUSH BC -3868 18B3 CD A3 17 CALL FPADD ; Add SQR(1/2) to value -3869 18B6 C1 POP BC ; Restore SQR(1/2) -3870 18B7 D1 POP DE -3871 18B8 04 INC B ; Make it SQR(2) -3872 18B9 CD 3F 19 CALL DVBCDE ; Divide by SQR(2) -3873 18BC 21 8C 18 LD HL,UNITY ; Point to 1. -3874 18BF CD 9A 17 CALL SUBPHL ; Subtract FPREG from 1 -3875 18C2 21 90 18 LD HL,LOGTAB ; Coefficient table -3876 18C5 CD 31 1D CALL SUMSER ; Evaluate sum of series -3877 18C8 01 80 80 LD BC,8080H ; BCDE = -0.5 -3878 18CB 11 00 00 LD DE,0000H -3879 18CE CD A3 17 CALL FPADD ; Subtract 0.5 from FPREG -3880 18D1 F1 POP AF ; Restore scale factor -3881 18D2 CD 64 1B CALL RSCALE ; Re-scale number -3882 18D5 01 31 80 MULLN2: LD BC,8031H ; BCDE = Ln(2) -3883 18D8 11 18 72 LD DE,7218H -3884 18DB 21 .BYTE 21H ; Skip "POP BC" and "POP DE" -3885 18DC -3886 18DC C1 MULT: POP BC ; Get number from stack -3887 18DD D1 POP DE -3888 18DE CD E9 19 FPMULT: CALL TSTSGN ; Test sign of FPREG -3889 18E1 C8 RET Z ; Return zero if zero -3890 18E2 2E 00 LD L,0 ; Flag add exponents -3891 18E4 CD A7 19 CALL ADDEXP ; Add exponents -3892 18E7 79 LD A,C ; Get MSB of multiplier -3893 18E8 32 A6 31 LD (MULVAL),A ; Save MSB of multiplier -3894 18EB EB EX DE,HL -3895 18EC 22 A7 31 LD (MULVAL+1),HL ; Save rest of multiplier -3896 18EF 01 00 00 LD BC,0 ; Partial product (BCDE) = zero -3897 18F2 50 LD D,B -3898 18F3 58 LD E,B -3899 18F4 21 F4 17 LD HL,BNORM ; Address of normalise -3900 18F7 E5 PUSH HL ; Save for return -3901 18F8 21 00 19 LD HL,MULT8 ; Address of 8 bit multiply -3902 18FB E5 PUSH HL ; Save for NMSB,MSB -3903 18FC E5 PUSH HL ; -3904 18FD 21 94 31 LD HL,FPREG ; Point to number -3905 1900 7E MULT8: LD A,(HL) ; Get LSB of number -3906 1901 23 INC HL ; Point to NMSB -3907 1902 B7 OR A ; Test LSB -3908 1903 CA 2C 19 JP Z,BYTSFT ; Zero - shift to next byte -3909 1906 E5 PUSH HL ; Save address of number -3910 1907 2E 08 LD L,8 ; 8 bits to multiply by -3911 1909 1F MUL8LP: RRA ; Shift LSB right -3912 190A 67 LD H,A ; Save LSB -3913 190B 79 LD A,C ; Get MSB -3914 190C D2 1A 19 JP NC,NOMADD ; Bit was zero - Don't add -3915 190F E5 PUSH HL ; Save LSB and count -3916 1910 2A A7 31 LD HL,(MULVAL+1) ; Get LSB and NMSB -3917 1913 19 ADD HL,DE ; Add NMSB and LSB -3918 1914 EB EX DE,HL ; Leave sum in DE -3919 1915 E1 POP HL ; Restore MSB and count -3920 1916 3A A6 31 LD A,(MULVAL) ; Get MSB of multiplier -3921 1919 89 ADC A,C ; Add MSB -3922 191A 1F NOMADD: RRA ; Shift MSB right -3923 191B 4F LD C,A ; Re-save MSB -3924 191C 7A LD A,D ; Get NMSB -3925 191D 1F RRA ; Shift NMSB right -3926 191E 57 LD D,A ; Re-save NMSB -3927 191F 7B LD A,E ; Get LSB -3928 1920 1F RRA ; Shift LSB right -3929 1921 5F LD E,A ; Re-save LSB -3930 1922 78 LD A,B ; Get VLSB -3931 1923 1F RRA ; Shift VLSB right -3932 1924 47 LD B,A ; Re-save VLSB -3933 1925 2D DEC L ; Count bits multiplied -3934 1926 7C LD A,H ; Get LSB of multiplier -3935 1927 C2 09 19 JP NZ,MUL8LP ; More - Do it -3936 192A E1 POPHRT: POP HL ; Restore address of number -3937 192B C9 RET -3938 192C -3939 192C 43 BYTSFT: LD B,E ; Shift partial product left -3940 192D 5A LD E,D -3941 192E 51 LD D,C -3942 192F 4F LD C,A -3943 1930 C9 RET -3944 1931 -3945 1931 CD 1A 1A DIV10: CALL STAKFP ; Save FPREG on stack -3946 1934 01 20 84 LD BC,8420H ; BCDE = 10. -3947 1937 11 00 00 LD DE,0000H -3948 193A CD 2A 1A CALL FPBCDE ; Move 10 to FPREG -3949 193D -3950 193D C1 DIV: POP BC ; Get number from stack -3951 193E D1 POP DE -3952 193F CD E9 19 DVBCDE: CALL TSTSGN ; Test sign of FPREG -3953 1942 CA 45 07 JP Z,DZERR ; Error if division by zero -3954 1945 2E FF LD L,-1 ; Flag subtract exponents -3955 1947 CD A7 19 CALL ADDEXP ; Subtract exponents -3956 194A 34 INC (HL) ; Add 2 to exponent to adjust -3957 194B 34 INC (HL) -3958 194C 2B DEC HL ; Point to MSB -3959 194D 7E LD A,(HL) ; Get MSB of dividend -3960 194E 32 C2 30 LD (DIV3),A ; Save for subtraction -3961 1951 2B DEC HL -3962 1952 7E LD A,(HL) ; Get NMSB of dividend -3963 1953 32 BE 30 LD (DIV2),A ; Save for subtraction -3964 1956 2B DEC HL -3965 1957 7E LD A,(HL) ; Get MSB of dividend -3966 1958 32 BA 30 LD (DIV1),A ; Save for subtraction -3967 195B 41 LD B,C ; Get MSB -3968 195C EB EX DE,HL ; NMSB,LSB to HL -3969 195D AF XOR A -3970 195E 4F LD C,A ; Clear MSB of quotient -3971 195F 57 LD D,A ; Clear NMSB of quotient -3972 1960 5F LD E,A ; Clear LSB of quotient -3973 1961 32 C5 30 LD (DIV4),A ; Clear overflow count -3974 1964 E5 DIVLP: PUSH HL ; Save divisor -3975 1965 C5 PUSH BC -3976 1966 7D LD A,L ; Get LSB of number -3977 1967 CD B9 30 CALL DIVSUP ; Subt' divisor from dividend -3978 196A DE 00 SBC A,0 ; Count for overflows -3979 196C 3F CCF -3980 196D D2 77 19 JP NC,RESDIV ; Restore divisor if borrow -3981 1970 32 C5 30 LD (DIV4),A ; Re-save overflow count -3982 1973 F1 POP AF ; Scrap divisor -3983 1974 F1 POP AF -3984 1975 37 SCF ; Set carry to -3985 1976 D2 .BYTE 0D2H ; Skip "POP BC" and "POP HL" -3986 1977 -3987 1977 C1 RESDIV: POP BC ; Restore divisor -3988 1978 E1 POP HL -3989 1979 79 LD A,C ; Get MSB of quotient -3990 197A 3C INC A -3991 197B 3D DEC A -3992 197C 1F RRA ; Bit 0 to bit 7 -3993 197D FA 2A 18 JP M,RONDB ; Done - Normalise result -3994 1980 17 RLA ; Restore carry -3995 1981 7B LD A,E ; Get LSB of quotient -3996 1982 17 RLA ; Double it -3997 1983 5F LD E,A ; Put it back -3998 1984 7A LD A,D ; Get NMSB of quotient -3999 1985 17 RLA ; Double it -4000 1986 57 LD D,A ; Put it back -4001 1987 79 LD A,C ; Get MSB of quotient -4002 1988 17 RLA ; Double it -4003 1989 4F LD C,A ; Put it back -4004 198A 29 ADD HL,HL ; Double NMSB,LSB of divisor -4005 198B 78 LD A,B ; Get MSB of divisor -4006 198C 17 RLA ; Double it -4007 198D 47 LD B,A ; Put it back -4008 198E 3A C5 30 LD A,(DIV4) ; Get VLSB of quotient -4009 1991 17 RLA ; Double it -4010 1992 32 C5 30 LD (DIV4),A ; Put it back -4011 1995 79 LD A,C ; Get MSB of quotient -4012 1996 B2 OR D ; Merge NMSB -4013 1997 B3 OR E ; Merge LSB -4014 1998 C2 64 19 JP NZ,DIVLP ; Not done - Keep dividing -4015 199B E5 PUSH HL ; Save divisor -4016 199C 21 97 31 LD HL,FPEXP ; Point to exponent -4017 199F 35 DEC (HL) ; Divide by 2 -4018 19A0 E1 POP HL ; Restore divisor -4019 19A1 C2 64 19 JP NZ,DIVLP ; Ok - Keep going -4020 19A4 C3 51 07 JP OVERR ; Overflow error -4021 19A7 -4022 19A7 78 ADDEXP: LD A,B ; Get exponent of dividend -4023 19A8 B7 OR A ; Test it -4024 19A9 CA CB 19 JP Z,OVTST3 ; Zero - Result zero -4025 19AC 7D LD A,L ; Get add/subtract flag -4026 19AD 21 97 31 LD HL,FPEXP ; Point to exponent -4027 19B0 AE XOR (HL) ; Add or subtract it -4028 19B1 80 ADD A,B ; Add the other exponent -4029 19B2 47 LD B,A ; Save new exponent -4030 19B3 1F RRA ; Test exponent for overflow -4031 19B4 A8 XOR B -4032 19B5 78 LD A,B ; Get exponent -4033 19B6 F2 CA 19 JP P,OVTST2 ; Positive - Test for overflow -4034 19B9 C6 80 ADD A,80H ; Add excess 128 -4035 19BB 77 LD (HL),A ; Save new exponent -4036 19BC CA 2A 19 JP Z,POPHRT ; Zero - Result zero -4037 19BF CD 4F 1A CALL SIGNS ; Set MSBs and sign of result -4038 19C2 77 LD (HL),A ; Save new exponent -4039 19C3 2B DEC HL ; Point to MSB -4040 19C4 C9 RET -4041 19C5 -4042 19C5 CD E9 19 OVTST1: CALL TSTSGN ; Test sign of FPREG -4043 19C8 2F CPL ; Invert sign -4044 19C9 E1 POP HL ; Clean up stack -4045 19CA B7 OVTST2: OR A ; Test if new exponent zero -4046 19CB E1 OVTST3: POP HL ; Clear off return address -4047 19CC F2 09 18 JP P,RESZER ; Result zero -4048 19CF C3 51 07 JP OVERR ; Overflow error -4049 19D2 -4050 19D2 CD 35 1A MLSP10: CALL BCDEFP ; Move FPREG to BCDE -4051 19D5 78 LD A,B ; Get exponent -4052 19D6 B7 OR A ; Is it zero? -4053 19D7 C8 RET Z ; Yes - Result is zero -4054 19D8 C6 02 ADD A,2 ; Multiply by 4 -4055 19DA DA 51 07 JP C,OVERR ; Overflow - ?OV Error -4056 19DD 47 LD B,A ; Re-save exponent -4057 19DE CD A3 17 CALL FPADD ; Add BCDE to FPREG (Times 5) -4058 19E1 21 97 31 LD HL,FPEXP ; Point to exponent -4059 19E4 34 INC (HL) ; Double number (Times 10) -4060 19E5 C0 RET NZ ; Ok - Return -4061 19E6 C3 51 07 JP OVERR ; Overflow error -4062 19E9 -4063 19E9 3A 97 31 TSTSGN: LD A,(FPEXP) ; Get sign of FPREG -4064 19EC B7 OR A -4065 19ED C8 RET Z ; RETurn if number is zero -4066 19EE 3A 96 31 LD A,(FPREG+2) ; Get MSB of FPREG -4067 19F1 FE .BYTE 0FEH ; Test sign -4068 19F2 2F RETREL: CPL ; Invert sign -4069 19F3 17 RLA ; Sign bit to carry -4070 19F4 9F FLGDIF: SBC A,A ; Carry to all bits of A -4071 19F5 C0 RET NZ ; Return -1 if negative -4072 19F6 3C INC A ; Bump to +1 -4073 19F7 C9 RET ; Positive - Return +1 -4074 19F8 -4075 19F8 CD E9 19 SGN: CALL TSTSGN ; Test sign of FPREG -4076 19FB 06 88 FLGREL: LD B,80H+8 ; 8 bit integer in exponent -4077 19FD 11 00 00 LD DE,0 ; Zero NMSB and LSB -4078 1A00 21 97 31 RETINT: LD HL,FPEXP ; Point to exponent -4079 1A03 4F LD C,A ; CDE = MSB,NMSB and LSB -4080 1A04 70 LD (HL),B ; Save exponent -4081 1A05 06 00 LD B,0 ; CDE = integer to normalise -4082 1A07 23 INC HL ; Point to sign of result -4083 1A08 36 80 LD (HL),80H ; Set sign of result -4084 1A0A 17 RLA ; Carry = sign of integer -4085 1A0B C3 F1 17 JP CONPOS ; Set sign of result -4086 1A0E -4087 1A0E CD E9 19 ABS: CALL TSTSGN ; Test sign of FPREG -4088 1A11 F0 RET P ; Return if positive -4089 1A12 21 96 31 INVSGN: LD HL,FPREG+2 ; Point to MSB -4090 1A15 7E LD A,(HL) ; Get sign of mantissa -4091 1A16 EE 80 XOR 80H ; Invert sign of mantissa -4092 1A18 77 LD (HL),A ; Re-save sign of mantissa -4093 1A19 C9 RET -4094 1A1A -4095 1A1A EB STAKFP: EX DE,HL ; Save code string address -4096 1A1B 2A 94 31 LD HL,(FPREG) ; LSB,NLSB of FPREG -4097 1A1E E3 EX (SP),HL ; Stack them,get return -4098 1A1F E5 PUSH HL ; Re-save return -4099 1A20 2A 96 31 LD HL,(FPREG+2) ; MSB and exponent of FPREG -4100 1A23 E3 EX (SP),HL ; Stack them,get return -4101 1A24 E5 PUSH HL ; Re-save return -4102 1A25 EB EX DE,HL ; Restore code string address -4103 1A26 C9 RET -4104 1A27 -4105 1A27 CD 38 1A PHLTFP: CALL LOADFP ; Number at HL to BCDE -4106 1A2A EB FPBCDE: EX DE,HL ; Save code string address -4107 1A2B 22 94 31 LD (FPREG),HL ; Save LSB,NLSB of number -4108 1A2E 60 LD H,B ; Exponent of number -4109 1A2F 69 LD L,C ; MSB of number -4110 1A30 22 96 31 LD (FPREG+2),HL ; Save MSB and exponent -4111 1A33 EB EX DE,HL ; Restore code string address -4112 1A34 C9 RET -4113 1A35 -4114 1A35 21 94 31 BCDEFP: LD HL,FPREG ; Point to FPREG -4115 1A38 5E LOADFP: LD E,(HL) ; Get LSB of number -4116 1A39 23 INC HL -4117 1A3A 56 LD D,(HL) ; Get NMSB of number -4118 1A3B 23 INC HL -4119 1A3C 4E LD C,(HL) ; Get MSB of number -4120 1A3D 23 INC HL -4121 1A3E 46 LD B,(HL) ; Get exponent of number -4122 1A3F 23 INCHL: INC HL ; Used for conditional "INC HL" -4123 1A40 C9 RET -4124 1A41 -4125 1A41 11 94 31 FPTHL: LD DE,FPREG ; Point to FPREG -4126 1A44 06 04 DETHL4: LD B,4 ; 4 bytes to move -4127 1A46 1A DETHLB: LD A,(DE) ; Get source -4128 1A47 77 LD (HL),A ; Save destination -4129 1A48 13 INC DE ; Next source -4130 1A49 23 INC HL ; Next destination -4131 1A4A 05 DEC B ; Count bytes -4132 1A4B C2 46 1A JP NZ,DETHLB ; Loop if more -4133 1A4E C9 RET -4134 1A4F -4135 1A4F 21 96 31 SIGNS: LD HL,FPREG+2 ; Point to MSB of FPREG -4136 1A52 7E LD A,(HL) ; Get MSB -4137 1A53 07 RLCA ; Old sign to carry -4138 1A54 37 SCF ; Set MSBit -4139 1A55 1F RRA ; Set MSBit of MSB -4140 1A56 77 LD (HL),A ; Save new MSB -4141 1A57 3F CCF ; Complement sign -4142 1A58 1F RRA ; Old sign to carry -4143 1A59 23 INC HL -4144 1A5A 23 INC HL -4145 1A5B 77 LD (HL),A ; Set sign of result -4146 1A5C 79 LD A,C ; Get MSB -4147 1A5D 07 RLCA ; Old sign to carry -4148 1A5E 37 SCF ; Set MSBit -4149 1A5F 1F RRA ; Set MSBit of MSB -4150 1A60 4F LD C,A ; Save MSB -4151 1A61 1F RRA -4152 1A62 AE XOR (HL) ; New sign of result -4153 1A63 C9 RET -4154 1A64 -4155 1A64 78 CMPNUM: LD A,B ; Get exponent of number -4156 1A65 B7 OR A -4157 1A66 CA E9 19 JP Z,TSTSGN ; Zero - Test sign of FPREG -4158 1A69 21 F2 19 LD HL,RETREL ; Return relation routine -4159 1A6C E5 PUSH HL ; Save for return -4160 1A6D CD E9 19 CALL TSTSGN ; Test sign of FPREG -4161 1A70 79 LD A,C ; Get MSB of number -4162 1A71 C8 RET Z ; FPREG zero - Number's MSB -4163 1A72 21 96 31 LD HL,FPREG+2 ; MSB of FPREG -4164 1A75 AE XOR (HL) ; Combine signs -4165 1A76 79 LD A,C ; Get MSB of number -4166 1A77 F8 RET M ; Exit if signs different -4167 1A78 CD 7E 1A CALL CMPFP ; Compare FP numbers -4168 1A7B 1F RRA ; Get carry to sign -4169 1A7C A9 XOR C ; Combine with MSB of number -4170 1A7D C9 RET -4171 1A7E -4172 1A7E 23 CMPFP: INC HL ; Point to exponent -4173 1A7F 78 LD A,B ; Get exponent -4174 1A80 BE CP (HL) ; Compare exponents -4175 1A81 C0 RET NZ ; Different -4176 1A82 2B DEC HL ; Point to MBS -4177 1A83 79 LD A,C ; Get MSB -4178 1A84 BE CP (HL) ; Compare MSBs -4179 1A85 C0 RET NZ ; Different -4180 1A86 2B DEC HL ; Point to NMSB -4181 1A87 7A LD A,D ; Get NMSB -4182 1A88 BE CP (HL) ; Compare NMSBs -4183 1A89 C0 RET NZ ; Different -4184 1A8A 2B DEC HL ; Point to LSB -4185 1A8B 7B LD A,E ; Get LSB -4186 1A8C 96 SUB (HL) ; Compare LSBs -4187 1A8D C0 RET NZ ; Different -4188 1A8E E1 POP HL ; Drop RETurn -4189 1A8F E1 POP HL ; Drop another RETurn -4190 1A90 C9 RET -4191 1A91 -4192 1A91 47 FPINT: LD B,A ; <- Move -4193 1A92 4F LD C,A ; <- exponent -4194 1A93 57 LD D,A ; <- to all -4195 1A94 5F LD E,A ; <- bits -4196 1A95 B7 OR A ; Test exponent -4197 1A96 C8 RET Z ; Zero - Return zero -4198 1A97 E5 PUSH HL ; Save pointer to number -4199 1A98 CD 35 1A CALL BCDEFP ; Move FPREG to BCDE -4200 1A9B CD 4F 1A CALL SIGNS ; Set MSBs & sign of result -4201 1A9E AE XOR (HL) ; Combine with sign of FPREG -4202 1A9F 67 LD H,A ; Save combined signs -4203 1AA0 FC B5 1A CALL M,DCBCDE ; Negative - Decrement BCDE -4204 1AA3 3E 98 LD A,80H+24 ; 24 bits -4205 1AA5 90 SUB B ; Bits to shift -4206 1AA6 CD 68 18 CALL SCALE ; Shift BCDE -4207 1AA9 7C LD A,H ; Get combined sign -4208 1AAA 17 RLA ; Sign to carry -4209 1AAB DC 3B 18 CALL C,FPROND ; Negative - Round number up -4210 1AAE 06 00 LD B,0 ; Zero exponent -4211 1AB0 DC 54 18 CALL C,COMPL ; If negative make positive -4212 1AB3 E1 POP HL ; Restore pointer to number -4213 1AB4 C9 RET -4214 1AB5 -4215 1AB5 1B DCBCDE: DEC DE ; Decrement BCDE -4216 1AB6 7A LD A,D ; Test LSBs -4217 1AB7 A3 AND E -4218 1AB8 3C INC A -4219 1AB9 C0 RET NZ ; Exit if LSBs not FFFF -4220 1ABA 0B DEC BC ; Decrement MSBs -4221 1ABB C9 RET -4222 1ABC -4223 1ABC 21 97 31 INT: LD HL,FPEXP ; Point to exponent -4224 1ABF 7E LD A,(HL) ; Get exponent -4225 1AC0 FE 98 CP 80H+24 ; Integer accuracy only? -4226 1AC2 3A 94 31 LD A,(FPREG) ; Get LSB -4227 1AC5 D0 RET NC ; Yes - Already integer -4228 1AC6 7E LD A,(HL) ; Get exponent -4229 1AC7 CD 91 1A CALL FPINT ; F.P to integer -4230 1ACA 36 98 LD (HL),80H+24 ; Save 24 bit integer -4231 1ACC 7B LD A,E ; Get LSB of number -4232 1ACD F5 PUSH AF ; Save LSB -4233 1ACE 79 LD A,C ; Get MSB of number -4234 1ACF 17 RLA ; Sign to carry -4235 1AD0 CD F1 17 CALL CONPOS ; Set sign of result -4236 1AD3 F1 POP AF ; Restore LSB of number -4237 1AD4 C9 RET -4238 1AD5 -4239 1AD5 21 00 00 MLDEBC: LD HL,0 ; Clear partial product -4240 1AD8 78 LD A,B ; Test multiplier -4241 1AD9 B1 OR C -4242 1ADA C8 RET Z ; Return zero if zero -4243 1ADB 3E 10 LD A,16 ; 16 bits -4244 1ADD 29 MLDBLP: ADD HL,HL ; Shift P.P left -4245 1ADE DA 15 13 JP C,BSERR ; ?BS Error if overflow -4246 1AE1 EB EX DE,HL -4247 1AE2 29 ADD HL,HL ; Shift multiplier left -4248 1AE3 EB EX DE,HL -4249 1AE4 D2 EB 1A JP NC,NOMLAD ; Bit was zero - No add -4250 1AE7 09 ADD HL,BC ; Add multiplicand -4251 1AE8 DA 15 13 JP C,BSERR ; ?BS Error if overflow -4252 1AEB 3D NOMLAD: DEC A ; Count bits -4253 1AEC C2 DD 1A JP NZ,MLDBLP ; More -4254 1AEF C9 RET -4255 1AF0 -4256 1AF0 FE 2D ASCTFP: CP '-' ; Negative? -4257 1AF2 F5 PUSH AF ; Save it and flags -4258 1AF3 CA FC 1A JP Z,CNVNUM ; Yes - Convert number -4259 1AF6 FE 2B CP '+' ; Positive? -4260 1AF8 CA FC 1A JP Z,CNVNUM ; Yes - Convert number -4261 1AFB 2B DEC HL ; DEC 'cos GETCHR INCs -4262 1AFC CD 09 18 CNVNUM: CALL RESZER ; Set result to zero -4263 1AFF 47 LD B,A ; Digits after point counter -4264 1B00 57 LD D,A ; Sign of exponent -4265 1B01 5F LD E,A ; Exponent of ten -4266 1B02 2F CPL -4267 1B03 4F LD C,A ; Before or after point flag -4268 1B04 CD 9A 0B MANLP: CALL GETCHR ; Get next character -4269 1B07 DA 4D 1B JP C,ADDIG ; Digit - Add to number -4270 1B0A FE 2E CP '.' -4271 1B0C CA 28 1B JP Z,DPOINT ; '.' - Flag point -4272 1B0F FE 45 CP 'E' -4273 1B11 C2 2C 1B JP NZ,CONEXP ; Not 'E' - Scale number -4274 1B14 CD 9A 0B CALL GETCHR ; Get next character -4275 1B17 CD 40 11 CALL SGNEXP ; Get sign of exponent -4276 1B1A CD 9A 0B EXPLP: CALL GETCHR ; Get next character -4277 1B1D DA 6F 1B JP C,EDIGIT ; Digit - Add to exponent -4278 1B20 14 INC D ; Is sign negative? -4279 1B21 C2 2C 1B JP NZ,CONEXP ; No - Scale number -4280 1B24 AF XOR A -4281 1B25 93 SUB E ; Negate exponent -4282 1B26 5F LD E,A ; And re-save it -4283 1B27 0C INC C ; Flag end of number -4284 1B28 0C DPOINT: INC C ; Flag point passed -4285 1B29 CA 04 1B JP Z,MANLP ; Zero - Get another digit -4286 1B2C E5 CONEXP: PUSH HL ; Save code string address -4287 1B2D 7B LD A,E ; Get exponent -4288 1B2E 90 SUB B ; Subtract digits after point -4289 1B2F F4 45 1B SCALMI: CALL P,SCALPL ; Positive - Multiply number -4290 1B32 F2 3B 1B JP P,ENDCON ; Positive - All done -4291 1B35 F5 PUSH AF ; Save number of times to /10 -4292 1B36 CD 31 19 CALL DIV10 ; Divide by 10 -4293 1B39 F1 POP AF ; Restore count -4294 1B3A 3C INC A ; Count divides -4295 1B3B -4296 1B3B C2 2F 1B ENDCON: JP NZ,SCALMI ; More to do -4297 1B3E D1 POP DE ; Restore code string address -4298 1B3F F1 POP AF ; Restore sign of number -4299 1B40 CC 12 1A CALL Z,INVSGN ; Negative - Negate number -4300 1B43 EB EX DE,HL ; Code string address to HL -4301 1B44 C9 RET -4302 1B45 -4303 1B45 C8 SCALPL: RET Z ; Exit if no scaling needed -4304 1B46 F5 MULTEN: PUSH AF ; Save count -4305 1B47 CD D2 19 CALL MLSP10 ; Multiply number by 10 -4306 1B4A F1 POP AF ; Restore count -4307 1B4B 3D DEC A ; Count multiplies -4308 1B4C C9 RET -4309 1B4D -4310 1B4D D5 ADDIG: PUSH DE ; Save sign of exponent -4311 1B4E 57 LD D,A ; Save digit -4312 1B4F 78 LD A,B ; Get digits after point -4313 1B50 89 ADC A,C ; Add one if after point -4314 1B51 47 LD B,A ; Re-save counter -4315 1B52 C5 PUSH BC ; Save point flags -4316 1B53 E5 PUSH HL ; Save code string address -4317 1B54 D5 PUSH DE ; Save digit -4318 1B55 CD D2 19 CALL MLSP10 ; Multiply number by 10 -4319 1B58 F1 POP AF ; Restore digit -4320 1B59 D6 30 SUB '0' ; Make it absolute -4321 1B5B CD 64 1B CALL RSCALE ; Re-scale number -4322 1B5E E1 POP HL ; Restore code string address -4323 1B5F C1 POP BC ; Restore point flags -4324 1B60 D1 POP DE ; Restore sign of exponent -4325 1B61 C3 04 1B JP MANLP ; Get another digit -4326 1B64 -4327 1B64 CD 1A 1A RSCALE: CALL STAKFP ; Put number on stack -4328 1B67 CD FB 19 CALL FLGREL ; Digit to add to FPREG -4329 1B6A C1 PADD: POP BC ; Restore number -4330 1B6B D1 POP DE -4331 1B6C C3 A3 17 JP FPADD ; Add BCDE to FPREG and return -4332 1B6F -4333 1B6F 7B EDIGIT: LD A,E ; Get digit -4334 1B70 07 RLCA ; Times 2 -4335 1B71 07 RLCA ; Times 4 -4336 1B72 83 ADD A,E ; Times 5 -4337 1B73 07 RLCA ; Times 10 -4338 1B74 86 ADD A,(HL) ; Add next digit -4339 1B75 D6 30 SUB '0' ; Make it absolute -4340 1B77 5F LD E,A ; Save new digit -4341 1B78 C3 1A 1B JP EXPLP ; Look for another digit -4342 1B7B -4343 1B7B E5 LINEIN: PUSH HL ; Save code string address -4344 1B7C 21 DA 06 LD HL,INMSG ; Output " in " -4345 1B7F CD E0 14 CALL PRS ; Output string at HL -4346 1B82 E1 POP HL ; Restore code string address -4347 1B83 EB PRNTHL: EX DE,HL ; Code string address to DE -4348 1B84 AF XOR A -4349 1B85 06 98 LD B,80H+24 ; 24 bits -4350 1B87 CD 00 1A CALL RETINT ; Return the integer -4351 1B8A 21 DF 14 LD HL,PRNUMS ; Print number string -4352 1B8D E5 PUSH HL ; Save for return -4353 1B8E 21 99 31 NUMASC: LD HL,PBUFF ; Convert number to ASCII -4354 1B91 E5 PUSH HL ; Save for return -4355 1B92 CD E9 19 CALL TSTSGN ; Test sign of FPREG -4356 1B95 36 20 LD (HL),' ' ; Space at start -4357 1B97 F2 9C 1B JP P,SPCFST ; Positive - Space to start -4358 1B9A 36 2D LD (HL),'-' ; '-' sign at start -4359 1B9C 23 SPCFST: INC HL ; First byte of number -4360 1B9D 36 30 LD (HL),'0' ; '0' if zero -4361 1B9F CA 52 1C JP Z,JSTZER ; Return '0' if zero -4362 1BA2 E5 PUSH HL ; Save buffer address -4363 1BA3 FC 12 1A CALL M,INVSGN ; Negate FPREG if negative -4364 1BA6 AF XOR A ; Zero A -4365 1BA7 F5 PUSH AF ; Save it -4366 1BA8 CD 58 1C CALL RNGTST ; Test number is in range -4367 1BAB 01 43 91 SIXDIG: LD BC,9143H ; BCDE - 99999.9 -4368 1BAE 11 F8 4F LD DE,4FF8H -4369 1BB1 CD 64 1A CALL CMPNUM ; Compare numbers -4370 1BB4 B7 OR A -4371 1BB5 E2 C9 1B JP PO,INRNG ; > 99999.9 - Sort it out -4372 1BB8 F1 POP AF ; Restore count -4373 1BB9 CD 46 1B CALL MULTEN ; Multiply by ten -4374 1BBC F5 PUSH AF ; Re-save count -4375 1BBD C3 AB 1B JP SIXDIG ; Test it again -4376 1BC0 -4377 1BC0 CD 31 19 GTSIXD: CALL DIV10 ; Divide by 10 -4378 1BC3 F1 POP AF ; Get count -4379 1BC4 3C INC A ; Count divides -4380 1BC5 F5 PUSH AF ; Re-save count -4381 1BC6 CD 58 1C CALL RNGTST ; Test number is in range -4382 1BC9 CD 91 17 INRNG: CALL ROUND ; Add 0.5 to FPREG -4383 1BCC 3C INC A -4384 1BCD CD 91 1A CALL FPINT ; F.P to integer -4385 1BD0 CD 2A 1A CALL FPBCDE ; Move BCDE to FPREG -4386 1BD3 01 06 03 LD BC,0306H ; 1E+06 to 1E-03 range -4387 1BD6 F1 POP AF ; Restore count -4388 1BD7 81 ADD A,C ; 6 digits before point -4389 1BD8 3C INC A ; Add one -4390 1BD9 FA E5 1B JP M,MAKNUM ; Do it in 'E' form if < 1E-02 -4391 1BDC FE 08 CP 6+1+1 ; More than 999999 ? -4392 1BDE D2 E5 1B JP NC,MAKNUM ; Yes - Do it in 'E' form -4393 1BE1 3C INC A ; Adjust for exponent -4394 1BE2 47 LD B,A ; Exponent of number -4395 1BE3 3E 02 LD A,2 ; Make it zero after -4396 1BE5 -4397 1BE5 3D MAKNUM: DEC A ; Adjust for digits to do -4398 1BE6 3D DEC A -4399 1BE7 E1 POP HL ; Restore buffer address -4400 1BE8 F5 PUSH AF ; Save count -4401 1BE9 11 6B 1C LD DE,POWERS ; Powers of ten -4402 1BEC 05 DEC B ; Count digits before point -4403 1BED C2 F6 1B JP NZ,DIGTXT ; Not zero - Do number -4404 1BF0 36 2E LD (HL),'.' ; Save point -4405 1BF2 23 INC HL ; Move on -4406 1BF3 36 30 LD (HL),'0' ; Save zero -4407 1BF5 23 INC HL ; Move on -4408 1BF6 05 DIGTXT: DEC B ; Count digits before point -4409 1BF7 36 2E LD (HL),'.' ; Save point in case -4410 1BF9 CC 3F 1A CALL Z,INCHL ; Last digit - move on -4411 1BFC C5 PUSH BC ; Save digits before point -4412 1BFD E5 PUSH HL ; Save buffer address -4413 1BFE D5 PUSH DE ; Save powers of ten -4414 1BFF CD 35 1A CALL BCDEFP ; Move FPREG to BCDE -4415 1C02 E1 POP HL ; Powers of ten table -4416 1C03 06 2F LD B, '0'-1 ; ASCII '0' - 1 -4417 1C05 04 TRYAGN: INC B ; Count subtractions -4418 1C06 7B LD A,E ; Get LSB -4419 1C07 96 SUB (HL) ; Subtract LSB -4420 1C08 5F LD E,A ; Save LSB -4421 1C09 23 INC HL -4422 1C0A 7A LD A,D ; Get NMSB -4423 1C0B 9E SBC A,(HL) ; Subtract NMSB -4424 1C0C 57 LD D,A ; Save NMSB -4425 1C0D 23 INC HL -4426 1C0E 79 LD A,C ; Get MSB -4427 1C0F 9E SBC A,(HL) ; Subtract MSB -4428 1C10 4F LD C,A ; Save MSB -4429 1C11 2B DEC HL ; Point back to start -4430 1C12 2B DEC HL -4431 1C13 D2 05 1C JP NC,TRYAGN ; No overflow - Try again -4432 1C16 CD 48 18 CALL PLUCDE ; Restore number -4433 1C19 23 INC HL ; Start of next number -4434 1C1A CD 2A 1A CALL FPBCDE ; Move BCDE to FPREG -4435 1C1D EB EX DE,HL ; Save point in table -4436 1C1E E1 POP HL ; Restore buffer address -4437 1C1F 70 LD (HL),B ; Save digit in buffer -4438 1C20 23 INC HL ; And move on -4439 1C21 C1 POP BC ; Restore digit count -4440 1C22 0D DEC C ; Count digits -4441 1C23 C2 F6 1B JP NZ,DIGTXT ; More - Do them -4442 1C26 05 DEC B ; Any decimal part? -4443 1C27 CA 36 1C JP Z,DOEBIT ; No - Do 'E' bit -4444 1C2A 2B SUPTLZ: DEC HL ; Move back through buffer -4445 1C2B 7E LD A,(HL) ; Get character -4446 1C2C FE 30 CP '0' ; '0' character? -4447 1C2E CA 2A 1C JP Z,SUPTLZ ; Yes - Look back for more -4448 1C31 FE 2E CP '.' ; A decimal point? -4449 1C33 C4 3F 1A CALL NZ,INCHL ; Move back over digit -4450 1C36 -4451 1C36 F1 DOEBIT: POP AF ; Get 'E' flag -4452 1C37 CA 55 1C JP Z,NOENED ; No 'E' needed - End buffer -4453 1C3A 36 45 LD (HL),'E' ; Put 'E' in buffer -4454 1C3C 23 INC HL ; And move on -4455 1C3D 36 2B LD (HL),'+' ; Put '+' in buffer -4456 1C3F F2 46 1C JP P,OUTEXP ; Positive - Output exponent -4457 1C42 36 2D LD (HL),'-' ; Put '-' in buffer -4458 1C44 2F CPL ; Negate exponent -4459 1C45 3C INC A -4460 1C46 06 2F OUTEXP: LD B,'0'-1 ; ASCII '0' - 1 -4461 1C48 04 EXPTEN: INC B ; Count subtractions -4462 1C49 D6 0A SUB 10 ; Tens digit -4463 1C4B D2 48 1C JP NC,EXPTEN ; More to do -4464 1C4E C6 3A ADD A,'0'+10 ; Restore and make ASCII -4465 1C50 23 INC HL ; Move on -4466 1C51 70 LD (HL),B ; Save MSB of exponent -4467 1C52 23 JSTZER: INC HL ; -4468 1C53 77 LD (HL),A ; Save LSB of exponent -4469 1C54 23 INC HL -4470 1C55 71 NOENED: LD (HL),C ; Mark end of buffer -4471 1C56 E1 POP HL ; Restore code string address -4472 1C57 C9 RET -4473 1C58 -4474 1C58 01 74 94 RNGTST: LD BC,9474H ; BCDE = 999999. -4475 1C5B 11 F7 23 LD DE,23F7H -4476 1C5E CD 64 1A CALL CMPNUM ; Compare numbers -4477 1C61 B7 OR A -4478 1C62 E1 POP HL ; Return address to HL -4479 1C63 E2 C0 1B JP PO,GTSIXD ; Too big - Divide by ten -4480 1C66 E9 JP (HL) ; Otherwise return to caller -4481 1C67 -4482 1C67 00 00 00 80 HALF: .BYTE 00H,00H,00H,80H ; 0.5 -4483 1C6B -4484 1C6B A0 86 01 POWERS: .BYTE 0A0H,086H,001H ; 100000 -4485 1C6E 10 27 00 .BYTE 010H,027H,000H ; 10000 -4486 1C71 E8 03 00 .BYTE 0E8H,003H,000H ; 1000 -4487 1C74 64 00 00 .BYTE 064H,000H,000H ; 100 -4488 1C77 0A 00 00 .BYTE 00AH,000H,000H ; 10 -4489 1C7A 01 00 00 .BYTE 001H,000H,000H ; 1 -4490 1C7D -4491 1C7D 21 12 1A NEGAFT: LD HL,INVSGN ; Negate result -4492 1C80 E3 EX (SP),HL ; To be done after caller -4493 1C81 E9 JP (HL) ; Return to caller -4494 1C82 -4495 1C82 CD 1A 1A SQR: CALL STAKFP ; Put value on stack -4496 1C85 21 67 1C LD HL,HALF ; Set power to 1/2 -4497 1C88 CD 27 1A CALL PHLTFP ; Move 1/2 to FPREG -4498 1C8B -4499 1C8B C1 POWER: POP BC ; Get base -4500 1C8C D1 POP DE -4501 1C8D CD E9 19 CALL TSTSGN ; Test sign of power -4502 1C90 78 LD A,B ; Get exponent of base -4503 1C91 CA D0 1C JP Z,EXP ; Make result 1 if zero -4504 1C94 F2 9B 1C JP P,POWER1 ; Positive base - Ok -4505 1C97 B7 OR A ; Zero to negative power? -4506 1C98 CA 45 07 JP Z,DZERR ; Yes - ?/0 Error -4507 1C9B B7 POWER1: OR A ; Base zero? -4508 1C9C CA 0A 18 JP Z,SAVEXP ; Yes - Return zero -4509 1C9F D5 PUSH DE ; Save base -4510 1CA0 C5 PUSH BC -4511 1CA1 79 LD A,C ; Get MSB of base -4512 1CA2 F6 7F OR 01111111B ; Get sign status -4513 1CA4 CD 35 1A CALL BCDEFP ; Move power to BCDE -4514 1CA7 F2 B8 1C JP P,POWER2 ; Positive base - Ok -4515 1CAA D5 PUSH DE ; Save power -4516 1CAB C5 PUSH BC -4517 1CAC CD BC 1A CALL INT ; Get integer of power -4518 1CAF C1 POP BC ; Restore power -4519 1CB0 D1 POP DE -4520 1CB1 F5 PUSH AF ; MSB of base -4521 1CB2 CD 64 1A CALL CMPNUM ; Power an integer? -4522 1CB5 E1 POP HL ; Restore MSB of base -4523 1CB6 7C LD A,H ; but don't affect flags -4524 1CB7 1F RRA ; Exponent odd or even? -4525 1CB8 E1 POWER2: POP HL ; Restore MSB and exponent -4526 1CB9 22 96 31 LD (FPREG+2),HL ; Save base in FPREG -4527 1CBC E1 POP HL ; LSBs of base -4528 1CBD 22 94 31 LD (FPREG),HL ; Save in FPREG -4529 1CC0 DC 7D 1C CALL C,NEGAFT ; Odd power - Negate result -4530 1CC3 CC 12 1A CALL Z,INVSGN ; Negative base - Negate it -4531 1CC6 D5 PUSH DE ; Save power -4532 1CC7 C5 PUSH BC -4533 1CC8 CD 9D 18 CALL LOG ; Get LOG of base -4534 1CCB C1 POP BC ; Restore power -4535 1CCC D1 POP DE -4536 1CCD CD DE 18 CALL FPMULT ; Multiply LOG by power -4537 1CD0 -4538 1CD0 CD 1A 1A EXP: CALL STAKFP ; Put value on stack -4539 1CD3 01 38 81 LD BC,08138H ; BCDE = 1/Ln(2) -4540 1CD6 11 3B AA LD DE,0AA3BH -4541 1CD9 CD DE 18 CALL FPMULT ; Multiply value by 1/LN(2) -4542 1CDC 3A 97 31 LD A,(FPEXP) ; Get exponent -4543 1CDF FE 88 CP 80H+8 ; Is it in range? -4544 1CE1 D2 C5 19 JP NC,OVTST1 ; No - Test for overflow -4545 1CE4 CD BC 1A CALL INT ; Get INT of FPREG -4546 1CE7 C6 80 ADD A,80H ; For excess 128 -4547 1CE9 C6 02 ADD A,2 ; Exponent > 126? -4548 1CEB DA C5 19 JP C,OVTST1 ; Yes - Test for overflow -4549 1CEE F5 PUSH AF ; Save scaling factor -4550 1CEF 21 8C 18 LD HL,UNITY ; Point to 1. -4551 1CF2 CD 94 17 CALL ADDPHL ; Add 1 to FPREG -4552 1CF5 CD D5 18 CALL MULLN2 ; Multiply by LN(2) -4553 1CF8 F1 POP AF ; Restore scaling factor -4554 1CF9 C1 POP BC ; Restore exponent -4555 1CFA D1 POP DE -4556 1CFB F5 PUSH AF ; Save scaling factor -4557 1CFC CD A0 17 CALL SUBCDE ; Subtract exponent from FPREG -4558 1CFF CD 12 1A CALL INVSGN ; Negate result -4559 1D02 21 10 1D LD HL,EXPTAB ; Coefficient table -4560 1D05 CD 40 1D CALL SMSER1 ; Sum the series -4561 1D08 11 00 00 LD DE,0 ; Zero LSBs -4562 1D0B C1 POP BC ; Scaling factor -4563 1D0C 4A LD C,D ; Zero MSB -4564 1D0D C3 DE 18 JP FPMULT ; Scale result to correct value -4565 1D10 -4566 1D10 08 EXPTAB: .BYTE 8 ; Table used by EXP -4567 1D11 40 2E 94 74 .BYTE 040H,02EH,094H,074H ; -1/7! (-1/5040) -4568 1D15 70 4F 2E 77 .BYTE 070H,04FH,02EH,077H ; 1/6! ( 1/720) -4569 1D19 6E 02 88 7A .BYTE 06EH,002H,088H,07AH ; -1/5! (-1/120) -4570 1D1D E6 A0 2A 7C .BYTE 0E6H,0A0H,02AH,07CH ; 1/4! ( 1/24) -4571 1D21 50 AA AA 7E .BYTE 050H,0AAH,0AAH,07EH ; -1/3! (-1/6) -4572 1D25 FF FF 7F 7F .BYTE 0FFH,0FFH,07FH,07FH ; 1/2! ( 1/2) -4573 1D29 00 00 80 81 .BYTE 000H,000H,080H,081H ; -1/1! (-1/1) -4574 1D2D 00 00 00 81 .BYTE 000H,000H,000H,081H ; 1/0! ( 1/1) -4575 1D31 -4576 1D31 CD 1A 1A SUMSER: CALL STAKFP ; Put FPREG on stack -4577 1D34 11 DC 18 LD DE,MULT ; Multiply by "X" -4578 1D37 D5 PUSH DE ; To be done after -4579 1D38 E5 PUSH HL ; Save address of table -4580 1D39 CD 35 1A CALL BCDEFP ; Move FPREG to BCDE -4581 1D3C CD DE 18 CALL FPMULT ; Square the value -4582 1D3F E1 POP HL ; Restore address of table -4583 1D40 CD 1A 1A SMSER1: CALL STAKFP ; Put value on stack -4584 1D43 7E LD A,(HL) ; Get number of coefficients -4585 1D44 23 INC HL ; Point to start of table -4586 1D45 CD 27 1A CALL PHLTFP ; Move coefficient to FPREG -4587 1D48 06 .BYTE 06H ; Skip "POP AF" -4588 1D49 F1 SUMLP: POP AF ; Restore count -4589 1D4A C1 POP BC ; Restore number -4590 1D4B D1 POP DE -4591 1D4C 3D DEC A ; Cont coefficients -4592 1D4D C8 RET Z ; All done -4593 1D4E D5 PUSH DE ; Save number -4594 1D4F C5 PUSH BC -4595 1D50 F5 PUSH AF ; Save count -4596 1D51 E5 PUSH HL ; Save address in table -4597 1D52 CD DE 18 CALL FPMULT ; Multiply FPREG by BCDE -4598 1D55 E1 POP HL ; Restore address in table -4599 1D56 CD 38 1A CALL LOADFP ; Number at HL to BCDE -4600 1D59 E5 PUSH HL ; Save address in table -4601 1D5A CD A3 17 CALL FPADD ; Add coefficient to FPREG -4602 1D5D E1 POP HL ; Restore address in table -4603 1D5E C3 49 1D JP SUMLP ; More coefficients -4604 1D61 -4605 1D61 CD E9 19 RND: CALL TSTSGN ; Test sign of FPREG -4606 1D64 21 C9 30 LD HL,SEED+2 ; Random number seed -4607 1D67 FA C2 1D JP M,RESEED ; Negative - Re-seed -4608 1D6A 21 EA 30 LD HL,LSTRND ; Last random number -4609 1D6D CD 27 1A CALL PHLTFP ; Move last RND to FPREG -4610 1D70 21 C9 30 LD HL,SEED+2 ; Random number seed -4611 1D73 C8 RET Z ; Return if RND(0) -4612 1D74 86 ADD A,(HL) ; Add (SEED)+2) -4613 1D75 E6 07 AND 00000111B ; 0 to 7 -4614 1D77 06 00 LD B,0 -4615 1D79 77 LD (HL),A ; Re-save seed -4616 1D7A 23 INC HL ; Move to coefficient table -4617 1D7B 87 ADD A,A ; 4 bytes -4618 1D7C 87 ADD A,A ; per entry -4619 1D7D 4F LD C,A ; BC = Offset into table -4620 1D7E 09 ADD HL,BC ; Point to coefficient -4621 1D7F CD 38 1A CALL LOADFP ; Coefficient to BCDE -4622 1D82 CD DE 18 CALL FPMULT ; ; Multiply FPREG by coefficient -4623 1D85 3A C8 30 LD A,(SEED+1) ; Get (SEED+1) -4624 1D88 3C INC A ; Add 1 -4625 1D89 E6 03 AND 00000011B ; 0 to 3 -4626 1D8B 06 00 LD B,0 -4627 1D8D FE 01 CP 1 ; Is it zero? -4628 1D8F 88 ADC A,B ; Yes - Make it 1 -4629 1D90 32 C8 30 LD (SEED+1),A ; Re-save seed -4630 1D93 21 C6 1D LD HL,RNDTAB-4 ; Addition table -4631 1D96 87 ADD A,A ; 4 bytes -4632 1D97 87 ADD A,A ; per entry -4633 1D98 4F LD C,A ; BC = Offset into table -4634 1D99 09 ADD HL,BC ; Point to value -4635 1D9A CD 94 17 CALL ADDPHL ; Add value to FPREG -4636 1D9D CD 35 1A RND1: CALL BCDEFP ; Move FPREG to BCDE -4637 1DA0 7B LD A,E ; Get LSB -4638 1DA1 59 LD E,C ; LSB = MSB -4639 1DA2 EE 4F XOR 01001111B ; Fiddle around -4640 1DA4 4F LD C,A ; New MSB -4641 1DA5 36 80 LD (HL),80H ; Set exponent -4642 1DA7 2B DEC HL ; Point to MSB -4643 1DA8 46 LD B,(HL) ; Get MSB -4644 1DA9 36 80 LD (HL),80H ; Make value -0.5 -4645 1DAB 21 C7 30 LD HL,SEED ; Random number seed -4646 1DAE 34 INC (HL) ; Count seed -4647 1DAF 7E LD A,(HL) ; Get seed -4648 1DB0 D6 AB SUB 171 ; Do it modulo 171 -4649 1DB2 C2 B9 1D JP NZ,RND2 ; Non-zero - Ok -4650 1DB5 77 LD (HL),A ; Zero seed -4651 1DB6 0C INC C ; Fillde about -4652 1DB7 15 DEC D ; with the -4653 1DB8 1C INC E ; number -4654 1DB9 CD F4 17 RND2: CALL BNORM ; Normalise number -4655 1DBC 21 EA 30 LD HL,LSTRND ; Save random number -4656 1DBF C3 41 1A JP FPTHL ; Move FPREG to last and return -4657 1DC2 -4658 1DC2 77 RESEED: LD (HL),A ; Re-seed random numbers -4659 1DC3 2B DEC HL -4660 1DC4 77 LD (HL),A -4661 1DC5 2B DEC HL -4662 1DC6 77 LD (HL),A -4663 1DC7 C3 9D 1D JP RND1 ; Return RND seed -4664 1DCA -4665 1DCA 68 B1 46 68 RNDTAB: .BYTE 068H,0B1H,046H,068H ; Table used by RND -4666 1DCE 99 E9 92 69 .BYTE 099H,0E9H,092H,069H -4667 1DD2 10 D1 75 68 .BYTE 010H,0D1H,075H,068H -4668 1DD6 -4669 1DD6 21 20 1E COS: LD HL,HALFPI ; Point to PI/2 -4670 1DD9 CD 94 17 CALL ADDPHL ; Add it to PPREG -4671 1DDC CD 1A 1A SIN: CALL STAKFP ; Put angle on stack -4672 1DDF 01 49 83 LD BC,8349H ; BCDE = 2 PI -4673 1DE2 11 DB 0F LD DE,0FDBH -4674 1DE5 CD 2A 1A CALL FPBCDE ; Move 2 PI to FPREG -4675 1DE8 C1 POP BC ; Restore angle -4676 1DE9 D1 POP DE -4677 1DEA CD 3F 19 CALL DVBCDE ; Divide angle by 2 PI -4678 1DED CD 1A 1A CALL STAKFP ; Put it on stack -4679 1DF0 CD BC 1A CALL INT ; Get INT of result -4680 1DF3 C1 POP BC ; Restore number -4681 1DF4 D1 POP DE -4682 1DF5 CD A0 17 CALL SUBCDE ; Make it 0 <= value < 1 -4683 1DF8 21 24 1E LD HL,QUARTR ; Point to 0.25 -4684 1DFB CD 9A 17 CALL SUBPHL ; Subtract value from 0.25 -4685 1DFE CD E9 19 CALL TSTSGN ; Test sign of value -4686 1E01 37 SCF ; Flag positive -4687 1E02 F2 0C 1E JP P,SIN1 ; Positive - Ok -4688 1E05 CD 91 17 CALL ROUND ; Add 0.5 to value -4689 1E08 CD E9 19 CALL TSTSGN ; Test sign of value -4690 1E0B B7 OR A ; Flag negative -4691 1E0C F5 SIN1: PUSH AF ; Save sign -4692 1E0D F4 12 1A CALL P,INVSGN ; Negate value if positive -4693 1E10 21 24 1E LD HL,QUARTR ; Point to 0.25 -4694 1E13 CD 94 17 CALL ADDPHL ; Add 0.25 to value -4695 1E16 F1 POP AF ; Restore sign -4696 1E17 D4 12 1A CALL NC,INVSGN ; Negative - Make positive -4697 1E1A 21 28 1E LD HL,SINTAB ; Coefficient table -4698 1E1D C3 31 1D JP SUMSER ; Evaluate sum of series -4699 1E20 -4700 1E20 DB 0F 49 81 HALFPI: .BYTE 0DBH,00FH,049H,081H ; 1.5708 (PI/2) -4701 1E24 -4702 1E24 00 00 00 7F QUARTR: .BYTE 000H,000H,000H,07FH ; 0.25 -4703 1E28 -4704 1E28 05 SINTAB: .BYTE 5 ; Table used by SIN -4705 1E29 BA D7 1E 86 .BYTE 0BAH,0D7H,01EH,086H ; 39.711 -4706 1E2D 64 26 99 87 .BYTE 064H,026H,099H,087H ;-76.575 -4707 1E31 58 34 23 87 .BYTE 058H,034H,023H,087H ; 81.602 -4708 1E35 E0 5D A5 86 .BYTE 0E0H,05DH,0A5H,086H ;-41.342 -4709 1E39 DA 0F 49 83 .BYTE 0DAH,00FH,049H,083H ; 6.2832 -4710 1E3D -4711 1E3D CD 1A 1A TAN: CALL STAKFP ; Put angle on stack -4712 1E40 CD DC 1D CALL SIN ; Get SIN of angle -4713 1E43 C1 POP BC ; Restore angle -4714 1E44 E1 POP HL -4715 1E45 CD 1A 1A CALL STAKFP ; Save SIN of angle -4716 1E48 EB EX DE,HL ; BCDE = Angle -4717 1E49 CD 2A 1A CALL FPBCDE ; Angle to FPREG -4718 1E4C CD D6 1D CALL COS ; Get COS of angle -4719 1E4F C3 3D 19 JP DIV ; TAN = SIN / COS -4720 1E52 -4721 1E52 CD E9 19 ATN: CALL TSTSGN ; Test sign of value -4722 1E55 FC 7D 1C CALL M,NEGAFT ; Negate result after if -ve -4723 1E58 FC 12 1A CALL M,INVSGN ; Negate value if -ve -4724 1E5B 3A 97 31 LD A,(FPEXP) ; Get exponent -4725 1E5E FE 81 CP 81H ; Number less than 1? -4726 1E60 DA 6F 1E JP C,ATN1 ; Yes - Get arc tangnt -4727 1E63 01 00 81 LD BC,8100H ; BCDE = 1 -4728 1E66 51 LD D,C -4729 1E67 59 LD E,C -4730 1E68 CD 3F 19 CALL DVBCDE ; Get reciprocal of number -4731 1E6B 21 9A 17 LD HL,SUBPHL ; Sub angle from PI/2 -4732 1E6E E5 PUSH HL ; Save for angle > 1 -4733 1E6F 21 79 1E ATN1: LD HL,ATNTAB ; Coefficient table -4734 1E72 CD 31 1D CALL SUMSER ; Evaluate sum of series -4735 1E75 21 20 1E LD HL,HALFPI ; PI/2 - angle in case > 1 -4736 1E78 C9 RET ; Number > 1 - Sub from PI/2 -4737 1E79 -4738 1E79 09 ATNTAB: .BYTE 9 ; Table used by ATN -4739 1E7A 4A D7 3B 78 .BYTE 04AH,0D7H,03BH,078H ; 1/17 -4740 1E7E 02 6E 84 7B .BYTE 002H,06EH,084H,07BH ;-1/15 -4741 1E82 FE C1 2F 7C .BYTE 0FEH,0C1H,02FH,07CH ; 1/13 -4742 1E86 74 31 9A 7D .BYTE 074H,031H,09AH,07DH ;-1/11 -4743 1E8A 84 3D 5A 7D .BYTE 084H,03DH,05AH,07DH ; 1/9 -4744 1E8E C8 7F 91 7E .BYTE 0C8H,07FH,091H,07EH ;-1/7 -4745 1E92 E4 BB 4C 7E .BYTE 0E4H,0BBH,04CH,07EH ; 1/5 -4746 1E96 6C AA AA 7F .BYTE 06CH,0AAH,0AAH,07FH ;-1/3 -4747 1E9A 00 00 00 81 .BYTE 000H,000H,000H,081H ; 1/1 -4748 1E9E -4749 1E9E -4750 1E9E C9 ARET: RET ; A RETurn instruction -4751 1E9F -4752 1E9F D7 GETINP: RST 10H ;input a character -4753 1EA0 C9 RET -4754 1EA1 -4755 1EA1 CLS: -4756 1EA1 3E 0C LD A,CS ; ASCII Clear screen -4757 1EA3 C3 DB 1F JP MONOUT ; Output character -4758 1EA6 -4759 1EA6 CD 68 17 WIDTH: CALL GETINT ; Get integer 0-255 -4760 1EA9 7B LD A,E ; Width to A -4761 1EAA 32 F2 30 LD (LWIDTH),A ; Set width -4762 1EAD C9 RET -4763 1EAE -4764 1EAE CD 07 10 LINES: CALL GETNUM ; Get a number -4765 1EB1 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 -4766 1EB4 ED 53 F6 30 LD (LINESC),DE ; Set lines counter -4767 1EB8 ED 53 F8 30 LD (LINESN),DE ; Set lines number -4768 1EBC C9 RET -4769 1EBD -4770 1EBD CD 4C 0C DEEK: CALL DEINT ; Get integer -32768 to 32767 -4771 1EC0 D5 PUSH DE ; Save number -4772 1EC1 E1 POP HL ; Number to HL -4773 1EC2 46 LD B,(HL) ; Get LSB of contents -4774 1EC3 23 INC HL -4775 1EC4 7E LD A,(HL) ; Get MSB of contents -4776 1EC5 C3 C2 13 JP ABPASS ; Return integer AB -4777 1EC8 -4778 1EC8 CD 07 10 DOKE: CALL GETNUM ; Get a number -4779 1ECB CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 -4780 1ECE D5 PUSH DE ; Save address -4781 1ECF CD 10 0A CALL CHKSYN ; Make sure ',' follows -4782 1ED2 2C .BYTE ',' -4783 1ED3 CD 07 10 CALL GETNUM ; Get a number -4784 1ED6 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 -4785 1ED9 E3 EX (SP),HL ; Save value,get address -4786 1EDA 73 LD (HL),E ; Save LSB of value -4787 1EDB 23 INC HL -4788 1EDC 72 LD (HL),D ; Save MSB of value -4789 1EDD E1 POP HL ; Restore code string address -4790 1EDE C9 RET -4791 1EDF -4792 1EDF -4793 1EDF ; HEX$(nn) Convert 16 bit number to Hexadecimal string -4794 1EDF -4795 1EDF CD 0A 10 HEX: CALL TSTNUM ; Verify it's a number -4796 1EE2 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 -4797 1EE5 C5 PUSH BC ; Save contents of BC -4798 1EE6 21 99 31 LD HL,PBUFF -4799 1EE9 7A LD A,D ; Get high order into A -4800 1EEA FE 00 CP $0 -4801 1EEC 28 0C JR Z,HEX2 ; Skip output if both high digits are zero -4802 1EEE CD 17 1F CALL BYT2ASC ; Convert D to ASCII -4803 1EF1 78 LD A,B -4804 1EF2 FE 30 CP '0' -4805 1EF4 28 02 JR Z,HEX1 ; Don't store high digit if zero -4806 1EF6 70 LD (HL),B ; Store it to PBUFF -4807 1EF7 23 INC HL ; Next location -4808 1EF8 71 HEX1: LD (HL),C ; Store C to PBUFF+1 -4809 1EF9 23 INC HL ; Next location -4810 1EFA 7B HEX2: LD A,E ; Get lower byte -4811 1EFB CD 17 1F CALL BYT2ASC ; Convert E to ASCII -4812 1EFE 7A LD A,D -4813 1EFF FE 00 CP $0 -4814 1F01 20 05 JR NZ,HEX3 ; If upper byte was not zero then always print lower byte -4815 1F03 78 LD A,B -4816 1F04 FE 30 CP '0' ; If high digit of lower byte is zero then don't print -4817 1F06 28 02 JR Z,HEX4 -4818 1F08 70 HEX3: LD (HL),B ; to PBUFF+2 -4819 1F09 23 INC HL ; Next location -4820 1F0A 71 HEX4: LD (HL),C ; to PBUFF+3 -4821 1F0B 23 INC HL ; PBUFF+4 to zero -4822 1F0C AF XOR A ; Terminating character -4823 1F0D 77 LD (HL),A ; Store zero to terminate -4824 1F0E 23 INC HL ; Make sure PBUFF is terminated -4825 1F0F 77 LD (HL),A ; Store the double zero there -4826 1F10 C1 POP BC ; Get BC back -4827 1F11 21 99 31 LD HL,PBUFF ; Reset to start of PBUFF -4828 1F14 C3 70 14 JP STR1 ; Convert the PBUFF to a string and return it -4829 1F17 -4830 1F17 47 BYT2ASC LD B,A ; Save original value -4831 1F18 E6 0F AND $0F ; Strip off upper nybble -4832 1F1A FE 0A CP $0A ; 0-9? -4833 1F1C 38 02 JR C,ADD30 ; If A-F, add 7 more -4834 1F1E C6 07 ADD A,$07 ; Bring value up to ASCII A-F -4835 1F20 C6 30 ADD30 ADD A,$30 ; And make ASCII -4836 1F22 4F LD C,A ; Save converted char to C -4837 1F23 78 LD A,B ; Retrieve original value -4838 1F24 0F RRCA ; and Rotate it right -4839 1F25 0F RRCA -4840 1F26 0F RRCA -4841 1F27 0F RRCA -4842 1F28 E6 0F AND $0F ; Mask off upper nybble -4843 1F2A FE 0A CP $0A ; 0-9? < A hex? -4844 1F2C 38 02 JR C,ADD301 ; Skip Add 7 -4845 1F2E C6 07 ADD A,$07 ; Bring it up to ASCII A-F -4846 1F30 C6 30 ADD301 ADD A,$30 ; And make it full ASCII -4847 1F32 47 LD B,A ; Store high order byte -4848 1F33 C9 RET -4849 1F34 -4850 1F34 ; Convert "&Hnnnn" to FPREG -4851 1F34 ; Gets a character from (HL) checks for Hexadecimal ASCII numbers "&Hnnnn" -4852 1F34 ; Char is in A, NC if char is ;<=>?@ A-z, CY is set if 0-9 -4853 1F34 EB HEXTFP EX DE,HL ; Move code string pointer to DE -4854 1F35 21 00 00 LD HL,$0000 ; Zero out the value -4855 1F38 CD 4D 1F CALL GETHEX ; Check the number for valid hex -4856 1F3B DA 6D 1F JP C,HXERR ; First value wasn't hex, HX error -4857 1F3E 18 05 JR HEXLP1 ; Convert first character -4858 1F40 CD 4D 1F HEXLP CALL GETHEX ; Get second and addtional characters -4859 1F43 38 1F JR C,HEXIT ; Exit if not a hex character -4860 1F45 29 HEXLP1 ADD HL,HL ; Rotate 4 bits to the left -4861 1F46 29 ADD HL,HL -4862 1F47 29 ADD HL,HL -4863 1F48 29 ADD HL,HL -4864 1F49 B5 OR L ; Add in D0-D3 into L -4865 1F4A 6F LD L,A ; Save new value -4866 1F4B 18 F3 JR HEXLP ; And continue until all hex characters are in -4867 1F4D -4868 1F4D 13 GETHEX INC DE ; Next location -4869 1F4E 1A LD A,(DE) ; Load character at pointer -4870 1F4F FE 20 CP ' ' -4871 1F51 CA 4D 1F JP Z,GETHEX ; Skip spaces -4872 1F54 D6 30 SUB $30 ; Get absolute value -4873 1F56 D8 RET C ; < "0", error -4874 1F57 FE 0A CP $0A -4875 1F59 38 05 JR C,NOSUB7 ; Is already in the range 0-9 -4876 1F5B D6 07 SUB $07 ; Reduce to A-F -4877 1F5D FE 0A CP $0A ; Value should be $0A-$0F at this point -4878 1F5F D8 RET C ; CY set if was : ; < = > ? @ -4879 1F60 FE 10 NOSUB7 CP $10 ; > Greater than "F"? -4880 1F62 3F CCF -4881 1F63 C9 RET ; CY set if it wasn't valid hex -4882 1F64 -4883 1F64 EB HEXIT EX DE,HL ; Value into DE, Code string into HL -4884 1F65 7A LD A,D ; Load DE into AC -4885 1F66 4B LD C,E ; For prep to -4886 1F67 E5 PUSH HL -4887 1F68 CD C1 13 CALL ACPASS ; ACPASS to set AC as integer into FPREG -4888 1F6B E1 POP HL -4889 1F6C C9 RET -4890 1F6D -4891 1F6D 1E 26 HXERR: LD E,HX ; ?HEX Error -4892 1F6F C3 56 07 JP ERROR -4893 1F72 -4894 1F72 ; BIN$(NN) Convert integer to a 1-16 char binary string -4895 1F72 CD 0A 10 BIN: CALL TSTNUM ; Verify it's a number -4896 1F75 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 -4897 1F78 C5 BIN2: PUSH BC ; Save contents of BC -4898 1F79 21 99 31 LD HL,PBUFF -4899 1F7C 06 11 LD B,17 ; One higher than max char count -4900 1F7E ZEROSUP: ; Suppress leading zeros -4901 1F7E 05 DEC B ; Max 16 chars -4902 1F7F 78 LD A,B -4903 1F80 FE 01 CP $01 -4904 1F82 28 08 JR Z,BITOUT ; Always output at least one character -4905 1F84 CB 13 RL E -4906 1F86 CB 12 RL D -4907 1F88 30 F4 JR NC,ZEROSUP -4908 1F8A 18 04 JR BITOUT2 -4909 1F8C BITOUT: -4910 1F8C CB 13 RL E -4911 1F8E CB 12 RL D ; Top bit now in carry -4912 1F90 BITOUT2: -4913 1F90 3E 30 LD A,'0' ; Char for '0' -4914 1F92 CE 00 ADC A,0 ; If carry set then '0' --> '1' -4915 1F94 77 LD (HL),A -4916 1F95 23 INC HL -4917 1F96 05 DEC B -4918 1F97 20 F3 JR NZ,BITOUT -4919 1F99 AF XOR A ; Terminating character -4920 1F9A 77 LD (HL),A ; Store zero to terminate -4921 1F9B 23 INC HL ; Make sure PBUFF is terminated -4922 1F9C 77 LD (HL),A ; Store the double zero there -4923 1F9D C1 POP BC -4924 1F9E 21 99 31 LD HL,PBUFF -4925 1FA1 C3 70 14 JP STR1 -4926 1FA4 -4927 1FA4 ; Convert "&Bnnnn" to FPREG -4928 1FA4 ; Gets a character from (HL) checks for Binary ASCII numbers "&Bnnnn" -4929 1FA4 EB BINTFP: EX DE,HL ; Move code string pointer to DE -4930 1FA5 21 00 00 LD HL,$0000 ; Zero out the value -4931 1FA8 CD C1 1F CALL CHKBIN ; Check the number for valid bin -4932 1FAB DA CF 1F JP C,BINERR ; First value wasn't bin, HX error -4933 1FAE D6 30 BINIT: SUB '0' -4934 1FB0 29 ADD HL,HL ; Rotate HL left -4935 1FB1 B5 OR L -4936 1FB2 6F LD L,A -4937 1FB3 CD C1 1F CALL CHKBIN ; Get second and addtional characters -4938 1FB6 30 F6 JR NC,BINIT ; Process if a bin character -4939 1FB8 EB EX DE,HL ; Value into DE, Code string into HL -4940 1FB9 7A LD A,D ; Load DE into AC -4941 1FBA 4B LD C,E ; For prep to -4942 1FBB E5 PUSH HL -4943 1FBC CD C1 13 CALL ACPASS ; ACPASS to set AC as integer into FPREG -4944 1FBF E1 POP HL -4945 1FC0 C9 RET -4946 1FC1 -4947 1FC1 ; Char is in A, NC if char is 0 or 1 -4948 1FC1 13 CHKBIN: INC DE -4949 1FC2 1A LD A,(DE) -4950 1FC3 FE 20 CP ' ' -4951 1FC5 CA C1 1F JP Z,CHKBIN ; Skip spaces -4952 1FC8 FE 30 CP '0' ; Set C if < '0' -4953 1FCA D8 RET C -4954 1FCB FE 32 CP '2' -4955 1FCD 3F CCF ; Set C if > '1' -4956 1FCE C9 RET -4957 1FCF -4958 1FCF 1E 28 BINERR: LD E,BN ; ?BIN Error -4959 1FD1 C3 56 07 JP ERROR -4960 1FD4 -4961 1FD4 -4962 1FD4 JJUMP1: -4963 1FD4 DD 21 FF FF LD IX,-1 ; Flag cold start -4964 1FD8 C3 A6 03 JP CSTART ; Go and initialise -4965 1FDB -4966 1FDB MONOUT: -4967 1FDB C3 08 00 JP $0008 ; output a char -4968 1FDE -4969 1FDE -4970 1FDE MONITR: -4971 1FDE C3 00 00 JP $0000 ; Restart (Normally Monitor Start) -4972 1FE1 -4973 1FE1 -4974 1FE1 3E 00 INITST: LD A,0 ; Clear break flag -4975 1FE3 32 FD 30 LD (BRKFLG),A -4976 1FE6 C3 AD 03 JP INIT -4977 1FE9 -4978 1FE9 ED 45 ARETN: RETN ; Return from NMI -4979 1FEB -4980 1FEB -4981 1FEB F5 TSTBIT: PUSH AF ; Save bit mask -4982 1FEC A0 AND B ; Get common bits -4983 1FED C1 POP BC ; Restore bit mask -4984 1FEE B8 CP B ; Same bit set? -4985 1FEF 3E 00 LD A,0 ; Return 0 in A -4986 1FF1 C9 RET -4987 1FF2 -4988 1FF2 CD 1B 0A OUTNCR: CALL OUTC ; Output character in A -4989 1FF5 C3 42 0E JP PRNTCRLF ; Output CRLF -4990 1FF8 -4991 1FF8 .end -4992 1FF8 -tasm: Number of errors = 0 +0001 0000 ;================================================================================== +0002 0000 ; The updates to the original BASIC within this file are copyright Grant Searle +0003 0000 ; +0004 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY +0005 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. +0006 0000 ; +0007 0000 ; http://searle.hostei.com/grant/index.html +0008 0000 ; +0009 0000 ; eMail: home.micros01@btinternet.com +0010 0000 ; +0011 0000 ; If the above don't work, please perform an Internet search to see if I have +0012 0000 ; updated the web page hosting service. +0013 0000 ; +0014 0000 ;================================================================================== +0015 0000 +0016 0000 +0017 0000 ;================================================================================== +0018 0000 ; Contents of this file are copyright Grant Searle +0019 0000 ; HEX routines from Joel Owens. +0020 0000 ; +0021 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY +0022 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. +0023 0000 ; +0024 0000 ; http://searle.hostei.com/grant/index.html +0025 0000 ; +0026 0000 ; eMail: home.micros01@btinternet.com +0027 0000 ; +0028 0000 ; If the above don't work, please perform an Internet search to see if I have +0029 0000 ; updated the web page hosting service. +0030 0000 ; +0031 0000 ;================================================================================== +0032 0000 +0033 0000 ;------------------------------------------------------------------------------ +0034 0000 ; +0035 0000 ; Z80 Monitor Rom +0036 0000 ; +0037 0000 ;------------------------------------------------------------------------------ +0038 0000 ; General Equates +0039 0000 ;------------------------------------------------------------------------------ +0040 0000 +0041 0000 ;CR .EQU 0DH +0042 0000 ;LF .EQU 0AH +0043 0000 ;ESC .EQU 1BH +0044 0000 ;CTRLC .EQU 03H +0045 0000 M_CLS .EQU 0CH +0046 0000 +0047 0000 +0048 0000 loadAddr .EQU 0D000h ; CP/M load address +0049 0000 numSecs .EQU 24 ; Number of 512 sectors to be loaded +0050 0000 +0051 0000 +0052 0000 RTS_HIGH .EQU 0D5H +0053 0000 RTS_LOW .EQU 095H +0054 0000 +0055 0000 ACIA0_D .EQU $81 +0056 0000 ACIA0_C .EQU $80 +0057 0000 ACIA1_D .EQU $83 +0058 0000 ACIA1_C .EQU $82 +0059 0000 +0060 0000 SD_DATA .EQU 088H +0061 0000 SD_CONTROL .EQU 089H +0062 0000 SD_STATUS .EQU 089H +0063 0000 SD_LBA0 .EQU 08AH +0064 0000 SD_LBA1 .EQU 08BH +0065 0000 SD_LBA2 .EQU 08CH +0066 0000 +0067 3000 .ORG $3000 +0068 3000 +0069 3000 primaryIO .ds 1 +0070 3001 secNo .ds 1 +0071 3002 dmaAddr .ds 2 +0072 3004 +0073 3004 00 lba0 .DB 00h +0074 3005 00 lba1 .DB 00h +0075 3006 00 lba2 .DB 00h +0076 3007 00 lba3 .DB 00h +0077 3008 +0078 3008 stackSpace .ds 32 +0079 3028 M_STACK .EQU $ ; Stack top +0080 3028 +0081 3028 +0082 3028 ;------------------------------------------------------------------------------ +0083 3028 ; START OF MONITOR ROM +0084 3028 ;------------------------------------------------------------------------------ +0085 3028 +0086 0000 MON .ORG $0000 ; MONITOR ROM RESET VECTOR +0087 0000 ;------------------------------------------------------------------------------ +0088 0000 ; Reset +0089 0000 ;------------------------------------------------------------------------------ +0090 0000 F3 RST00 DI ;Disable INTerrupts +0091 0001 C3 94 00 JP M_INIT ;Initialize Hardware and go +0092 0004 00 NOP +0093 0005 00 NOP +0094 0006 00 NOP +0095 0007 00 NOP +0096 0008 ;------------------------------------------------------------------------------ +0097 0008 ; TX a character over RS232 wait for TXDONE first. +0098 0008 ;------------------------------------------------------------------------------ +0099 0008 C3 32 00 RST08 JP conout +0100 000B 00 NOP +0101 000C 00 NOP +0102 000D 00 NOP +0103 000E 00 NOP +0104 000F 00 NOP +0105 0010 ;------------------------------------------------------------------------------ +0106 0010 ; RX a character from buffer wait until char ready. +0107 0010 ;------------------------------------------------------------------------------ +0108 0010 C3 1B 00 RST10 JP conin +0109 0013 00 NOP +0110 0014 00 NOP +0111 0015 00 NOP +0112 0016 00 NOP +0113 0017 00 NOP +0114 0018 ;------------------------------------------------------------------------------ +0115 0018 ; Check input buffer status +0116 0018 ;------------------------------------------------------------------------------ +0117 0018 C3 5C 00 RST18 JP CKINCHAR +0118 001B +0119 001B +0120 001B ;------------------------------------------------------------------------------ +0121 001B ; Console input routine +0122 001B ; Use the "primaryIO" flag to determine which input port to monitor. +0123 001B ;------------------------------------------------------------------------------ +0124 001B conin: +0125 001B 3A 00 30 LD A,(primaryIO) +0126 001E FE 00 CP 0 +0127 0020 20 08 JR NZ,coninB +0128 0022 coninA: +0129 0022 +0130 0022 waitForCharA: +0131 0022 CD 63 00 call ckincharA +0132 0025 28 FB JR Z, waitForCharA +0133 0027 DB 81 IN A,(ACIA0_D) +0134 0029 C9 RET ; Char ready in A +0135 002A +0136 002A coninB: +0137 002A +0138 002A waitForCharB: +0139 002A CD 6A 00 call ckincharB +0140 002D 28 FB JR Z, waitForCharB +0141 002F DB 83 IN A,(ACIA1_D) +0142 0031 C9 RET ; Char ready in A +0143 0032 +0144 0032 ;------------------------------------------------------------------------------ +0145 0032 ; Console output routine +0146 0032 ; Use the "primaryIO" flag to determine which output port to send a character. +0147 0032 ;------------------------------------------------------------------------------ +0148 0032 F5 conout: PUSH AF ; Store character +0149 0033 3A 00 30 LD A,(primaryIO) +0150 0036 FE 00 CP 0 +0151 0038 20 0D JR NZ,conoutB1 +0152 003A 18 01 JR conoutA1 +0153 003C conoutA: +0154 003C F5 PUSH AF +0155 003D +0156 003D CD 50 00 conoutA1: CALL CKACIA0 ; See if ACIA channel A is finished transmitting +0157 0040 28 FB JR Z,conoutA1 ; Loop until ACIA flag signals ready +0158 0042 F1 POP AF ; RETrieve character +0159 0043 D3 81 OUT (ACIA0_D),A ; OUTput the character +0160 0045 C9 RET +0161 0046 +0162 0046 conoutB: +0163 0046 F5 PUSH AF +0164 0047 +0165 0047 CD 56 00 conoutB1: CALL CKACIA1 ; See if ACIA channel B is finished transmitting +0166 004A 28 FB JR Z,conoutB1 ; Loop until ACIA flag signals ready +0167 004C F1 POP AF ; RETrieve character +0168 004D D3 83 OUT (ACIA1_D),A ; OUTput the character +0169 004F C9 RET +0170 0050 +0171 0050 ;------------------------------------------------------------------------------ +0172 0050 ; I/O status check routine +0173 0050 ; Use the "primaryIO" flag to determine which port to check. +0174 0050 ;------------------------------------------------------------------------------ +0175 0050 CKACIA0 +0176 0050 DB 80 IN A,(ACIA0_C) ; Status byte D1=TX Buff Empty, D0=RX char ready +0177 0052 0F RRCA ; Rotates RX status into Carry Flag, +0178 0053 CB 47 BIT 0,A ; Set Zero flag if still transmitting character +0179 0055 C9 RET +0180 0056 +0181 0056 CKACIA1 +0182 0056 DB 82 IN A,(ACIA1_C) ; Status byte D1=TX Buff Empty, D0=RX char ready +0183 0058 0F RRCA ; Rotates RX status into Carry Flag, +0184 0059 CB 47 BIT 0,A ; Set Zero flag if still transmitting character +0185 005B C9 RET +0186 005C +0187 005C ;------------------------------------------------------------------------------ +0188 005C ; Check if there is a character in the input buffer +0189 005C ; Use the "primaryIO" flag to determine which port to check. +0190 005C ;------------------------------------------------------------------------------ +0191 005C CKINCHAR +0192 005C 3A 00 30 LD A,(primaryIO) +0193 005F FE 00 CP 0 +0194 0061 20 07 JR NZ,ckincharB +0195 0063 +0196 0063 ckincharA: +0197 0063 +0198 0063 DB 80 IN A,(ACIA0_C) ; Status byte +0199 0065 E6 01 AND $01 +0200 0067 FE 00 CP $0 ; Z flag set if no char +0201 0069 C9 RET +0202 006A +0203 006A ckincharB: +0204 006A +0205 006A DB 82 IN A,(ACIA1_C) ; Status byte +0206 006C E6 01 AND $01 +0207 006E FE 00 CP $0 ; Z flag set if no char +0208 0070 C9 RET +0209 0071 +0210 0071 ;------------------------------------------------------------------------------ +0211 0071 ; Filtered Character I/O +0212 0071 ;------------------------------------------------------------------------------ +0213 0071 +0214 0071 D7 RDCHR RST 10H +0215 0072 FE 0A CP LF +0216 0074 28 FB JR Z,RDCHR ; Ignore LF +0217 0076 FE 1B CP ESC +0218 0078 20 02 JR NZ,RDCHR1 +0219 007A 3E 03 LD A,CTRLC ; Change ESC to CTRL-C +0220 007C C9 RDCHR1 RET +0221 007D +0222 007D FE 0D WRCHR CP CR +0223 007F 28 0A JR Z,WRCRLF ; When CR, write CRLF +0224 0081 FE 0C CP M_CLS +0225 0083 28 04 JR Z,WR ; Allow write of "CLS" +0226 0085 FE 20 CP ' ' ; Don't write out any other control codes +0227 0087 38 01 JR C,NOWR ; ie. < space +0228 0089 CF WR RST 08H +0229 008A C9 NOWR RET +0230 008B +0231 008B 3E 0D WRCRLF LD A,CR +0232 008D CF RST 08H +0233 008E 3E 0A LD A,LF +0234 0090 CF RST 08H +0235 0091 3E 0D LD A,CR +0236 0093 C9 RET +0237 0094 +0238 0094 +0239 0094 ;------------------------------------------------------------------------------ +0240 0094 ; Initialise hardware and start main loop +0241 0094 ;------------------------------------------------------------------------------ +0242 0094 31 28 30 M_INIT LD SP,M_STACK ; Set the Stack Pointer +0243 0097 +0244 0097 3E 95 LD A,RTS_LOW +0245 0099 D3 80 OUT (ACIA0_C),A ; Initialise ACIA0 +0246 009B D3 82 OUT (ACIA1_C),A ; Initialise ACIA1 +0247 009D ; Display the "Press space to start" message on both consoles +0248 009D 3E 00 LD A,$00 +0249 009F 32 00 30 LD (primaryIO),A +0250 00A2 21 65 03 LD HL,INITTXT +0251 00A5 CD 1B 01 CALL M_PRINT +0252 00A8 3E 01 LD A,$01 +0253 00AA 32 00 30 LD (primaryIO),A +0254 00AD 21 65 03 LD HL,INITTXT +0255 00B0 CD 1B 01 CALL M_PRINT +0256 00B3 +0257 00B3 ; Wait until space is in one of the buffers to determine the active console +0258 00B3 +0259 00B3 waitForSpace: +0260 00B3 +0261 00B3 CD 63 00 CALL ckincharA +0262 00B6 28 0F jr Z,notInA +0263 00B8 3E 00 LD A,$00 +0264 00BA 32 00 30 LD (primaryIO),A +0265 00BD CD 1B 00 CALL conin +0266 00C0 FE 20 CP ' ' +0267 00C2 C2 B3 00 JP NZ, waitForSpace +0268 00C5 18 14 JR spacePressed +0269 00C7 +0270 00C7 notInA: +0271 00C7 CD 6A 00 CALL ckincharB +0272 00CA 28 E7 JR Z,waitForSpace +0273 00CC 3E 01 LD A,$01 +0274 00CE 32 00 30 LD (primaryIO),A +0275 00D1 CD 1B 00 CALL conin +0276 00D4 FE 20 CP ' ' +0277 00D6 C2 B3 00 JP NZ, waitForSpace +0278 00D9 18 00 JR spacePressed +0279 00DB +0280 00DB spacePressed: +0281 00DB +0282 00DB ; Clear message on both consoles +0283 00DB 3E 0C LD A,$0C +0284 00DD CD 3C 00 CALL conoutA +0285 00E0 CD 46 00 CALL conoutB +0286 00E3 +0287 00E3 ; primaryIO is now set to the channel where SPACE was pressed +0288 00E3 +0289 00E3 +0290 00E3 CD 22 01 CALL TXCRLF ; TXCRLF +0291 00E6 21 96 02 LD HL,M_SIGNON ; Print SIGNON message +0292 00E9 CD 1B 01 CALL M_PRINT +0293 00EC +0294 00EC ;------------------------------------------------------------------------------ +0295 00EC ; Monitor command loop +0296 00EC ;------------------------------------------------------------------------------ +0297 00EC 21 EC 00 MAIN LD HL,MAIN ; Save entry point for Monitor +0298 00EF E5 PUSH HL ; This is the return address +0299 00F0 CD 22 01 MAIN0 CALL TXCRLF ; Entry point for Monitor, Normal +0300 00F3 3E 3E LD A,'>' ; Get a ">" +0301 00F5 CF RST 08H ; print it +0302 00F6 +0303 00F6 CD 71 00 MAIN1 CALL RDCHR ; Get a character from the input port +0304 00F9 FE 20 CP ' ' ; or less? +0305 00FB 38 F9 JR C,MAIN1 ; Go back +0306 00FD +0307 00FD FE 3A CP ':' ; ":"? +0308 00FF CA 99 01 JP Z,LOAD ; First character of a HEX load +0309 0102 +0310 0102 CD 7D 00 CALL WRCHR ; Print char on console +0311 0105 +0312 0105 E6 5F AND $5F ; Make character uppercase +0313 0107 +0314 0107 FE 42 CP 'B' +0315 0109 CA DA 01 JP Z,BASIC +0316 010C +0317 010C FE 47 CP 'G' +0318 010E CA 93 01 JP Z,M_GOTO +0319 0111 +0320 0111 FE 58 CP 'X' +0321 0113 CA F1 01 JP Z,CPMLOAD +0322 0116 +0323 0116 3E 3F LD A,'?' ; Get a "?" +0324 0118 CF RST 08H ; Print it +0325 0119 18 D5 JR MAIN0 +0326 011B +0327 011B ;------------------------------------------------------------------------------ +0328 011B ; Print string of characters to Serial A until byte=$00, WITH CR, LF +0329 011B ;------------------------------------------------------------------------------ +0330 011B 7E M_PRINT LD A,(HL) ; Get character +0331 011C B7 OR A ; Is it $00 ? +0332 011D C8 RET Z ; Then RETurn on terminator +0333 011E CF RST 08H ; Print it +0334 011F 23 INC HL ; Next Character +0335 0120 18 F9 JR M_PRINT ; Continue until $00 +0336 0122 +0337 0122 +0338 0122 3E 0D TXCRLF LD A,$0D ; +0339 0124 CF RST 08H ; Print character +0340 0125 3E 0A LD A,$0A ; +0341 0127 CF RST 08H ; Print character +0342 0128 C9 RET +0343 0129 +0344 0129 ;------------------------------------------------------------------------------ +0345 0129 ; Get a character from the console, must be $20-$7F to be valid (no control characters) +0346 0129 ; and breaks with the Zero Flag set +0347 0129 ;------------------------------------------------------------------------------ +0348 0129 CD 71 00 M_GETCHR CALL RDCHR ; RX a Character +0349 012C FE 03 CP $03 ; User break? +0350 012E C8 RET Z +0351 012F FE 20 CP $20 ; or better? +0352 0131 38 F6 JR C,M_GETCHR ; Do it again until we get something usable +0353 0133 C9 RET +0354 0134 ;------------------------------------------------------------------------------ +0355 0134 ; Gets two ASCII characters from the console (assuming them to be HEX 0-9 A-F) +0356 0134 ; Moves them into B and C, converts them into a byte value in A and updates a +0357 0134 ; Checksum value in E +0358 0134 ;------------------------------------------------------------------------------ +0359 0134 CD 29 01 GET2 CALL M_GETCHR ; Get us a valid character to work with +0360 0137 47 LD B,A ; Load it in B +0361 0138 CD 29 01 CALL M_GETCHR ; Get us another character +0362 013B 4F LD C,A ; load it in C +0363 013C CD 73 01 CALL BCTOA ; Convert ASCII to byte +0364 013F 4F LD C,A ; Build the checksum +0365 0140 7B LD A,E +0366 0141 91 SUB C ; The checksum should always equal zero when checked +0367 0142 5F LD E,A ; Save the checksum back where it came from +0368 0143 79 LD A,C ; Retrieve the byte and go back +0369 0144 C9 RET +0370 0145 ;------------------------------------------------------------------------------ +0371 0145 ; Gets four Hex characters from the console, converts them to values in HL +0372 0145 ;------------------------------------------------------------------------------ +0373 0145 21 00 00 GETHL LD HL,$0000 ; Gets xxxx but sets Carry Flag on any Terminator +0374 0148 CD 8C 01 CALL ECHO ; RX a Character +0375 014B FE 0D CP $0D ; ? +0376 014D 20 0E JR NZ,GETX2 ; other key +0377 014F 37 SETCY SCF ; Set Carry Flag +0378 0150 C9 RET ; and Return to main program +0379 0151 ;------------------------------------------------------------------------------ +0380 0151 ; This routine converts last four hex characters (0-9 A-F) user types into a value in HL +0381 0151 ; Rotates the old out and replaces with the new until the user hits a terminating character +0382 0151 ;------------------------------------------------------------------------------ +0383 0151 21 00 00 GETX LD HL,$0000 ; CLEAR HL +0384 0154 CD 8C 01 GETX1 CALL ECHO ; RX a character from the console +0385 0157 FE 0D CP $0D ; +0386 0159 C8 RET Z ; quit +0387 015A FE 2C CP $2C ; <,> can be used to safely quit for multiple entries +0388 015C C8 RET Z ; (Like filling both DE and HL from the user) +0389 015D FE 03 GETX2 CP $03 ; Likewise, a will terminate clean, too, but +0390 015F 28 EE JR Z,SETCY ; It also sets the Carry Flag for testing later. +0391 0161 29 ADD HL,HL ; Otherwise, rotate the previous low nibble to high +0392 0162 29 ADD HL,HL ; rather slowly +0393 0163 29 ADD HL,HL ; until we get to the top +0394 0164 29 ADD HL,HL ; and then we can continue on. +0395 0165 D6 30 SUB $30 ; Convert ASCII to byte value +0396 0167 FE 0A CP $0A ; Are we in the 0-9 range? +0397 0169 38 02 JR C,GETX3 ; Then we just need to sub $30, but if it is A-F +0398 016B D6 07 SUB $07 ; We need to take off 7 more to get the value down to +0399 016D E6 0F GETX3 AND $0F ; to the right hex value +0400 016F 85 ADD A,L ; Add the high nibble to the low +0401 0170 6F LD L,A ; Move the byte back to A +0402 0171 18 E1 JR GETX1 ; and go back for next character until he terminates +0403 0173 ;------------------------------------------------------------------------------ +0404 0173 ; Convert ASCII characters in B C registers to a byte value in A +0405 0173 ;------------------------------------------------------------------------------ +0406 0173 78 BCTOA LD A,B ; Move the hi order byte to A +0407 0174 D6 30 SUB $30 ; Take it down from Ascii +0408 0176 FE 0A CP $0A ; Are we in the 0-9 range here? +0409 0178 38 02 JR C,BCTOA1 ; If so, get the next nybble +0410 017A D6 07 SUB $07 ; But if A-F, take it down some more +0411 017C 07 BCTOA1 RLCA ; Rotate the nybble from low to high +0412 017D 07 RLCA ; One bit at a time +0413 017E 07 RLCA ; Until we +0414 017F 07 RLCA ; Get there with it +0415 0180 47 LD B,A ; Save the converted high nybble +0416 0181 79 LD A,C ; Now get the low order byte +0417 0182 D6 30 SUB $30 ; Convert it down from Ascii +0418 0184 FE 0A CP $0A ; 0-9 at this point? +0419 0186 38 02 JR C,BCTOA2 ; Good enough then, but +0420 0188 D6 07 SUB $07 ; Take off 7 more if it's A-F +0421 018A 80 BCTOA2 ADD A,B ; Add in the high order nybble +0422 018B C9 RET +0423 018C +0424 018C ;------------------------------------------------------------------------------ +0425 018C ; Get a character and echo it back to the user +0426 018C ;------------------------------------------------------------------------------ +0427 018C CD 71 00 ECHO CALL RDCHR +0428 018F CD 7D 00 CALL WRCHR +0429 0192 C9 RET +0430 0193 +0431 0193 ;------------------------------------------------------------------------------ +0432 0193 ; GOTO command +0433 0193 ;------------------------------------------------------------------------------ +0434 0193 CD 45 01 M_GOTO CALL GETHL ; ENTRY POINT FOR oto addr. Get XXXX from user. +0435 0196 D8 RET C ; Return if invalid +0436 0197 E5 PUSH HL +0437 0198 C9 RET ; Jump to HL address value +0438 0199 +0439 0199 ;------------------------------------------------------------------------------ +0440 0199 ; LOAD Intel Hex format file from the console. +0441 0199 ; [Intel Hex Format is: +0442 0199 ; 1) Colon (Frame 0) +0443 0199 ; 2) Record Length Field (Frames 1 and 2) +0444 0199 ; 3) Load Address Field (Frames 3,4,5,6) +0445 0199 ; 4) Record Type Field (Frames 7 and 8) +0446 0199 ; 5) Data Field (Frames 9 to 9+2*(Record Length)-1 +0447 0199 ; 6) Checksum Field - Sum of all byte values from Record Length to and +0448 0199 ; including Checksum Field = 0 ] +0449 0199 ;------------------------------------------------------------------------------ +0450 0199 1E 00 LOAD LD E,0 ; First two Characters is the Record Length Field +0451 019B CD 34 01 CALL GET2 ; Get us two characters into BC, convert it to a byte +0452 019E 57 LD D,A ; Load Record Length count into D +0453 019F CD 34 01 CALL GET2 ; Get next two characters, Memory Load Address +0454 01A2 67 LD H,A ; put value in H register. +0455 01A3 CD 34 01 CALL GET2 ; Get next two characters, Memory Load Address +0456 01A6 6F LD L,A ; put value in L register. +0457 01A7 CD 34 01 CALL GET2 ; Get next two characters, Record Field Type +0458 01AA FE 01 CP $01 ; Record Field Type 00 is Data, 01 is End of File +0459 01AC 20 09 JR NZ,LOAD2 ; Must be the end of that file +0460 01AE CD 34 01 CALL GET2 ; Get next two characters, assemble into byte +0461 01B1 7B LD A,E ; Recall the Checksum byte +0462 01B2 A7 AND A ; Is it Zero? +0463 01B3 28 1E JR Z,LOAD00 ; Print footer reached message +0464 01B5 18 15 JR LOADERR ; Checksums don't add up, Error out +0465 01B7 +0466 01B7 7A LOAD2 LD A,D ; Retrieve line character counter +0467 01B8 A7 AND A ; Are we done with this line? +0468 01B9 28 0B JR Z,LOAD3 ; Get two more ascii characters, build a byte and checksum +0469 01BB CD 34 01 CALL GET2 ; Get next two chars, convert to byte in A, checksum it +0470 01BE 77 LD (HL),A ; Move converted byte in A to memory location +0471 01BF 23 INC HL ; Increment pointer to next memory location +0472 01C0 3E 2E LD A,'.' ; Print out a "." for every byte loaded +0473 01C2 CF RST 08H ; +0474 01C3 15 DEC D ; Decrement line character counter +0475 01C4 18 F1 JR LOAD2 ; and keep loading into memory until line is complete +0476 01C6 +0477 01C6 CD 34 01 LOAD3 CALL GET2 ; Get two chars, build byte and checksum +0478 01C9 7B LD A,E ; Check the checksum value +0479 01CA A7 AND A ; Is it zero? +0480 01CB C8 RET Z +0481 01CC +0482 01CC 21 54 03 LOADERR LD HL,CKSUMERR ; Get "Checksum Error" message +0483 01CF CD 1B 01 CALL M_PRINT ; Print Message from (HL) and terminate the load +0484 01D2 C9 RET +0485 01D3 +0486 01D3 21 8A 03 LOAD00 LD HL,LDETXT ; Print load complete message +0487 01D6 CD 1B 01 CALL M_PRINT +0488 01D9 C9 RET +0489 01DA +0490 01DA ;------------------------------------------------------------------------------ +0491 01DA ; Start BASIC command +0492 01DA ;------------------------------------------------------------------------------ +0493 01DA BASIC +0494 01DA 21 42 03 LD HL,M_BASTXT +0495 01DD CD 1B 01 CALL M_PRINT +0496 01E0 CD 29 01 CALL M_GETCHR +0497 01E3 C8 RET Z ; Cancel if CTRL-C +0498 01E4 E6 5F AND $5F ; uppercase +0499 01E6 FE 43 CP 'C' +0500 01E8 CA 95 03 JP Z,COLD +0501 01EB FE 57 CP 'W' +0502 01ED CA 98 03 JP Z,WARM +0503 01F0 C9 RET +0504 01F1 +0505 01F1 ;------------------------------------------------------------------------------ +0506 01F1 ; CP/M load command +0507 01F1 ;------------------------------------------------------------------------------ +0508 01F1 CPMLOAD +0509 01F1 +0510 01F1 21 03 02 LD HL,CPMTXT +0511 01F4 CD 1B 01 CALL M_PRINT +0512 01F7 CD 29 01 CALL M_GETCHR +0513 01FA C8 RET Z ; Cancel if CTRL-C +0514 01FB E6 5F AND $5F ; uppercase +0515 01FD FE 59 CP 'Y' +0516 01FF CA 24 02 JP Z,CPMLOAD2 +0517 0202 C9 RET +0518 0203 CPMTXT +0519 0203 0D 0A .BYTE $0D,$0A +0520 0205 42 6F 6F 74 .TEXT "Boot CP/M?" +0520 0209 20 43 50 2F +0520 020D 4D 3F +0521 020F 00 .BYTE $00 +0522 0210 +0523 0210 CPMTXT2 +0524 0210 0D 0A .BYTE $0D,$0A +0525 0212 4C 6F 61 64 .TEXT "Loading CP/M..." +0525 0216 69 6E 67 20 +0525 021A 43 50 2F 4D +0525 021E 2E 2E 2E +0526 0221 0D 0A 00 .BYTE $0D,$0A,$00 +0527 0224 +0528 0224 CPMLOAD2 +0529 0224 21 10 02 LD HL,CPMTXT2 +0530 0227 CD 1B 01 CALL M_PRINT +0531 022A +0532 022A 06 18 LD B,numSecs +0533 022C +0534 022C 3E 00 LD A,0 +0535 022E 32 04 30 LD (lba0),A +0536 0231 32 05 30 ld (lba1),A +0537 0234 32 06 30 ld (lba2),A +0538 0237 32 07 30 ld (lba3),A +0539 023A +0540 023A 21 00 D0 LD HL,loadAddr +0541 023D 22 02 30 LD (dmaAddr),HL +0542 0240 processSectors: +0543 0240 +0544 0240 CD 6E 02 call readhst +0545 0243 +0546 0243 11 00 02 LD DE,0200H +0547 0246 2A 02 30 LD HL,(dmaAddr) +0548 0249 19 ADD HL,DE +0549 024A 22 02 30 LD (dmaAddr),HL +0550 024D 3A 04 30 LD A,(lba0) +0551 0250 3C INC A +0552 0251 32 04 30 LD (lba0),A +0553 0254 +0554 0254 10 EA djnz processSectors +0555 0256 +0556 0256 ; Start CP/M using entry at top of BIOS +0557 0256 ; The current active console stream ID is pushed onto the stack +0558 0256 ; to allow the CBIOS to pick it up +0559 0256 ; 0 = ACIA0, 1 = ACIA1 +0560 0256 +0561 0256 3A 00 30 ld A,(primaryIO) +0562 0259 F5 PUSH AF +0563 025A 2A FE FF ld HL,($FFFE) +0564 025D E9 jp (HL) +0565 025E +0566 025E +0567 025E ;------------------------------------------------------------------------------ +0568 025E ; ROUTINES AS USED IN BIOS +0569 025E ;------------------------------------------------------------------------------ +0570 025E +0571 025E ;================================================================================================ +0572 025E ; Convert track/head/sector into LBA for physical access to the disk +0573 025E ;================================================================================================ +0574 025E setLBAaddr: +0575 025E ; Transfer LBA to disk (LBA3 not used on SD card) +0576 025E 3A 06 30 LD A,(lba2) +0577 0261 D3 8C OUT (SD_LBA2),A +0578 0263 3A 05 30 LD A,(lba1) +0579 0266 D3 8B OUT (SD_LBA1),A +0580 0268 3A 04 30 LD A,(lba0) +0581 026B D3 8A OUT (SD_LBA0),A +0582 026D C9 RET +0583 026E +0584 026E ;================================================================================================ +0585 026E ; Read physical sector from host +0586 026E ;================================================================================================ +0587 026E +0588 026E readhst: +0589 026E F5 PUSH AF +0590 026F C5 PUSH BC +0591 0270 E5 PUSH HL +0592 0271 +0593 0271 DB 89 rdWait1: IN A,(SD_STATUS) +0594 0273 FE 80 CP 128 +0595 0275 20 FA JR NZ,rdWait1 +0596 0277 +0597 0277 CD 5E 02 CALL setLBAaddr +0598 027A +0599 027A 3E 00 LD A,$00 ; 00 = Read block +0600 027C D3 89 OUT (SD_CONTROL),A +0601 027E +0602 027E 0E 04 LD c,4 +0603 0280 ; LD HL,hstbuf +0604 0280 rd4secs: +0605 0280 06 80 LD b,128 +0606 0282 rdByte: +0607 0282 +0608 0282 DB 89 rdWait2: IN A,(SD_STATUS) +0609 0284 FE E0 CP 224 ; Read byte waiting +0610 0286 20 FA JR NZ,rdWait2 +0611 0288 +0612 0288 DB 88 IN A,(SD_DATA) +0613 028A +0614 028A 77 LD (HL),A +0615 028B 23 INC HL +0616 028C 05 dec b +0617 028D 20 F3 JR NZ, rdByte +0618 028F 0D dec c +0619 0290 20 EE JR NZ,rd4secs +0620 0292 +0621 0292 E1 POP HL +0622 0293 C1 POP BC +0623 0294 F1 POP AF +0624 0295 +0625 0295 ; XOR a +0626 0295 ; ld (erflag),a +0627 0295 C9 RET +0628 0296 +0629 0296 ;------------------------------------------------------------------------------ +0630 0296 ; END OF ROUTINES AS USED IN BIOS +0631 0296 ;------------------------------------------------------------------------------ +0632 0296 +0633 0296 +0634 0296 43 50 2F 4D M_SIGNON .BYTE "CP/M Boot ROM 2.0" +0634 029A 20 42 6F 6F +0634 029E 74 20 52 4F +0634 02A2 4D 20 32 2E +0634 02A6 30 +0635 02A7 20 62 79 20 .BYTE " by G. Searle" +0635 02AB 47 2E 20 53 +0635 02AF 65 61 72 6C +0635 02B3 65 +0636 02B4 0D 0A .BYTE $0D,$0A +0637 02B6 0D 0A .BYTE $0D,$0A +0638 02B8 42 43 20 6F .TEXT "BC or BW - ROM BASIC Cold/Warm" +0638 02BC 72 20 42 57 +0638 02C0 20 2D 20 52 +0638 02C4 4F 4D 20 42 +0638 02C8 41 53 49 43 +0638 02CC 20 43 6F 6C +0638 02D0 64 2F 57 61 +0638 02D4 72 6D +0639 02D6 0D 0A .BYTE $0D,$0A +0640 02D8 58 20 20 20 .TEXT "X - Boot CP/M (load $D000-$FFFF)" +0640 02DC 20 20 20 20 +0640 02E0 20 2D 20 42 +0640 02E4 6F 6F 74 20 +0640 02E8 43 50 2F 4D +0640 02EC 20 28 6C 6F +0640 02F0 61 64 20 24 +0640 02F4 44 30 30 30 +0640 02F8 2D 24 46 46 +0640 02FC 46 46 29 +0641 02FF 0D 0A .BYTE $0D,$0A +0642 0301 3A 6E 6E 6E .TEXT ":nnnn... - Load Intel-Hex file record" +0642 0305 6E 2E 2E 2E +0642 0309 20 2D 20 4C +0642 030D 6F 61 64 20 +0642 0311 49 6E 74 65 +0642 0315 6C 2D 48 65 +0642 0319 78 20 66 69 +0642 031D 6C 65 20 72 +0642 0321 65 63 6F 72 +0642 0325 64 +0643 0326 0D 0A .BYTE $0D,$0A +0644 0328 47 6E 6E 6E .TEXT "Gnnnn - Run loc nnnn" +0644 032C 6E 20 20 20 +0644 0330 20 2D 20 52 +0644 0334 75 6E 20 6C +0644 0338 6F 63 20 6E +0644 033C 6E 6E 6E +0645 033F 0D 0A .BYTE $0D,$0A +0646 0341 00 .BYTE $00 +0647 0342 +0648 0342 M_BASTXT +0649 0342 0D 0A .BYTE $0D,$0A +0650 0344 43 6F 6C 64 .TEXT "Cold or warm?" +0650 0348 20 6F 72 20 +0650 034C 77 61 72 6D +0650 0350 3F +0651 0351 0D 0A 00 .BYTE $0D,$0A,$00 +0652 0354 +0653 0354 43 68 65 63 CKSUMERR .BYTE "Checksum error" +0653 0358 6B 73 75 6D +0653 035C 20 65 72 72 +0653 0360 6F 72 +0654 0362 0D 0A 00 .BYTE $0D,$0A,$00 +0655 0365 +0656 0365 INITTXT +0657 0365 0C .BYTE $0C +0658 0366 50 72 65 73 .TEXT "Press [SPACE] to activate console" +0658 036A 73 20 5B 53 +0658 036E 50 41 43 45 +0658 0372 5D 20 74 6F +0658 0376 20 61 63 74 +0658 037A 69 76 61 74 +0658 037E 65 20 63 6F +0658 0382 6E 73 6F 6C +0658 0386 65 +0659 0387 0D 0A 00 .BYTE $0D,$0A, $00 +0660 038A +0661 038A LDETXT +0662 038A 43 6F 6D 70 .TEXT "Complete" +0662 038E 6C 65 74 65 +0663 0392 0D 0A 00 .BYTE $0D,$0A, $00 +0664 0395 +0665 0395 ;=========================================================================================================================== +0666 0395 +0667 0395 ; NASCOM ROM BASIC Ver 4.7, (C) 1978 Microsoft +0668 0395 ; Scanned from source published in 80-BUS NEWS from Vol 2, Issue 3 +0669 0395 ; (May-June 1983) to Vol 3, Issue 3 (May-June 1984) +0670 0395 ; Adapted for the freeware Zilog Macro Assembler 2.10 to produce +0671 0395 ; the original ROM code (checksum A934H). PA +0672 0395 +0673 0395 ; GENERAL EQUATES +0674 0395 +0675 0395 CTRLC .EQU 03H ; Control "C" +0676 0395 CTRLG .EQU 07H ; Control "G" +0677 0395 BKSP .EQU 08H ; Back space +0678 0395 LF .EQU 0AH ; Line feed +0679 0395 CS .EQU 0CH ; Clear screen +0680 0395 CR .EQU 0DH ; Carriage return +0681 0395 CTRLO .EQU 0FH ; Control "O" +0682 0395 CTRLQ .EQU 11H ; Control "Q" +0683 0395 CTRLR .EQU 12H ; Control "R" +0684 0395 CTRLS .EQU 13H ; Control "S" +0685 0395 CTRLU .EQU 15H ; Control "U" +0686 0395 ESC .EQU 1BH ; Escape +0687 0395 DEL .EQU 7FH ; Delete +0688 0395 +0689 0395 ; BASIC WORK SPACE LOCATIONS +0690 0395 +0691 0395 WRKSPC .EQU 30B0H ; BASIC Work space +0692 0395 USR .EQU WRKSPC+3H ; "USR (x)" jump +0693 0395 OUTSUB .EQU WRKSPC+6H ; "OUT p,n" +0694 0395 OTPORT .EQU WRKSPC+7H ; Port (p) +0695 0395 DIVSUP .EQU WRKSPC+9H ; Division support routine +0696 0395 DIV1 .EQU WRKSPC+0AH ; <- Values +0697 0395 DIV2 .EQU WRKSPC+0EH ; <- to +0698 0395 DIV3 .EQU WRKSPC+12H ; <- be +0699 0395 DIV4 .EQU WRKSPC+15H ; <-inserted +0700 0395 SEED .EQU WRKSPC+17H ; Random number seed +0701 0395 LSTRND .EQU WRKSPC+3AH ; Last random number +0702 0395 INPSUB .EQU WRKSPC+3EH ; #INP (x)" Routine +0703 0395 INPORT .EQU WRKSPC+3FH ; PORT (x) +0704 0395 NULLS .EQU WRKSPC+41H ; Number of nulls +0705 0395 LWIDTH .EQU WRKSPC+42H ; Terminal width +0706 0395 COMMAN .EQU WRKSPC+43H ; Width for commas +0707 0395 NULFLG .EQU WRKSPC+44H ; Null after input byte flag +0708 0395 CTLOFG .EQU WRKSPC+45H ; Control "O" flag +0709 0395 LINESC .EQU WRKSPC+46H ; Lines counter +0710 0395 LINESN .EQU WRKSPC+48H ; Lines number +0711 0395 CHKSUM .EQU WRKSPC+4AH ; Array load/save check sum +0712 0395 NMIFLG .EQU WRKSPC+4CH ; Flag for NMI break routine +0713 0395 BRKFLG .EQU WRKSPC+4DH ; Break flag +0714 0395 RINPUT .EQU WRKSPC+4EH ; Input reflection +0715 0395 POINT .EQU WRKSPC+51H ; "POINT" reflection (unused) +0716 0395 PSET .EQU WRKSPC+54H ; "SET" reflection +0717 0395 RESET .EQU WRKSPC+57H ; "RESET" reflection +0718 0395 STRSPC .EQU WRKSPC+5AH ; Bottom of string space +0719 0395 LINEAT .EQU WRKSPC+5CH ; Current line number +0720 0395 BASTXT .EQU WRKSPC+5EH ; Pointer to start of program +0721 0395 BUFFER .EQU WRKSPC+61H ; Input buffer +0722 0395 STACK .EQU WRKSPC+66H ; Initial stack +0723 0395 CURPOS .EQU WRKSPC+0ABH ; Character position on line +0724 0395 LCRFLG .EQU WRKSPC+0ACH ; Locate/Create flag +0725 0395 TYPE .EQU WRKSPC+0ADH ; Data type flag +0726 0395 DATFLG .EQU WRKSPC+0AEH ; Literal statement flag +0727 0395 LSTRAM .EQU WRKSPC+0AFH ; Last available RAM +0728 0395 TMSTPT .EQU WRKSPC+0B1H ; Temporary string pointer +0729 0395 TMSTPL .EQU WRKSPC+0B3H ; Temporary string pool +0730 0395 TMPSTR .EQU WRKSPC+0BFH ; Temporary string +0731 0395 STRBOT .EQU WRKSPC+0C3H ; Bottom of string space +0732 0395 CUROPR .EQU WRKSPC+0C5H ; Current operator in EVAL +0733 0395 LOOPST .EQU WRKSPC+0C7H ; First statement of loop +0734 0395 DATLIN .EQU WRKSPC+0C9H ; Line of current DATA item +0735 0395 FORFLG .EQU WRKSPC+0CBH ; "FOR" loop flag +0736 0395 LSTBIN .EQU WRKSPC+0CCH ; Last byte entered +0737 0395 READFG .EQU WRKSPC+0CDH ; Read/Input flag +0738 0395 BRKLIN .EQU WRKSPC+0CEH ; Line of break +0739 0395 NXTOPR .EQU WRKSPC+0D0H ; Next operator in EVAL +0740 0395 ERRLIN .EQU WRKSPC+0D2H ; Line of error +0741 0395 CONTAD .EQU WRKSPC+0D4H ; Where to CONTinue +0742 0395 PROGND .EQU WRKSPC+0D6H ; End of program +0743 0395 VAREND .EQU WRKSPC+0D8H ; End of variables +0744 0395 ARREND .EQU WRKSPC+0DAH ; End of arrays +0745 0395 NXTDAT .EQU WRKSPC+0DCH ; Next data item +0746 0395 FNRGNM .EQU WRKSPC+0DEH ; Name of FN argument +0747 0395 FNARG .EQU WRKSPC+0E0H ; FN argument value +0748 0395 FPREG .EQU WRKSPC+0E4H ; Floating point register +0749 0395 FPEXP .EQU FPREG+3 ; Floating point exponent +0750 0395 SGNRES .EQU WRKSPC+0E8H ; Sign of result +0751 0395 PBUFF .EQU WRKSPC+0E9H ; Number print buffer +0752 0395 MULVAL .EQU WRKSPC+0F6H ; Multiplier +0753 0395 PROGST .EQU WRKSPC+0F9H ; Start of program text area +0754 0395 STLOOK .EQU WRKSPC+15DH ; Start of memory test +0755 0395 +0756 0395 ; BASIC ERROR CODE VALUES +0757 0395 +0758 0395 NF .EQU 00H ; NEXT without FOR +0759 0395 SN .EQU 02H ; Syntax error +0760 0395 RG .EQU 04H ; RETURN without GOSUB +0761 0395 OD .EQU 06H ; Out of DATA +0762 0395 FC .EQU 08H ; Function call error +0763 0395 OV .EQU 0AH ; Overflow +0764 0395 OM .EQU 0CH ; Out of memory +0765 0395 UL .EQU 0EH ; Undefined line number +0766 0395 BS .EQU 10H ; Bad subscript +0767 0395 DD .EQU 12H ; Re-DIMensioned array +0768 0395 DZ .EQU 14H ; Division by zero (/0) +0769 0395 ID .EQU 16H ; Illegal direct +0770 0395 TM .EQU 18H ; Type miss-match +0771 0395 OS .EQU 1AH ; Out of string space +0772 0395 LS .EQU 1CH ; String too long +0773 0395 ST .EQU 1EH ; String formula too complex +0774 0395 CN .EQU 20H ; Can't CONTinue +0775 0395 UF .EQU 22H ; UnDEFined FN function +0776 0395 MO .EQU 24H ; Missing operand +0777 0395 HX .EQU 26H ; HEX error +0778 0395 BN .EQU 28H ; BIN error +0779 0395 +0780 0395 ; .ORG 00396H +0781 0395 +0782 0395 C3 9B 03 COLD: JP STARTB ; Jump for cold start +0783 0398 C3 39 04 WARM: JP WARMST ; Jump for warm start +0784 039B STARTB: +0785 039B DD 21 00 00 LD IX,0 ; Flag cold start +0786 039F C3 A6 03 JP CSTART ; Jump to initialise +0787 03A2 +0788 03A2 4C 0C .WORD DEINT ; Get integer -32768 to 32767 +0789 03A4 C2 13 .WORD ABPASS ; Return integer in AB +0790 03A6 +0791 03A6 +0792 03A6 21 B0 30 CSTART: LD HL,WRKSPC ; Start of workspace RAM +0793 03A9 F9 LD SP,HL ; Set up a temporary stack +0794 03AA C3 E1 1F JP INITST ; Go to initialise +0795 03AD +0796 03AD 11 73 06 INIT: LD DE,INITAB ; Initialise workspace +0797 03B0 06 63 LD B,INITBE-INITAB+3; Bytes to copy +0798 03B2 21 B0 30 LD HL,WRKSPC ; Into workspace RAM +0799 03B5 1A COPY: LD A,(DE) ; Get source +0800 03B6 77 LD (HL),A ; To destination +0801 03B7 23 INC HL ; Next destination +0802 03B8 13 INC DE ; Next source +0803 03B9 05 DEC B ; Count bytes +0804 03BA C2 B5 03 JP NZ,COPY ; More to move +0805 03BD F9 LD SP,HL ; Temporary stack +0806 03BE CD 74 08 CALL CLREG ; Clear registers and stack +0807 03C1 CD 42 0E CALL PRNTCRLF ; Output CRLF +0808 03C4 32 5A 31 LD (BUFFER+72+1),A ; Mark end of buffer +0809 03C7 32 A9 31 LD (PROGST),A ; Initialise program area +0810 03CA 21 88 04 MSIZE: LD HL,MEMMSG ; Point to message +0811 03CD CD E0 14 CALL PRS ; Output "Memory size" +0812 03D0 CD 91 08 CALL PROMPT ; Get input with '?' +0813 03D3 CD 9A 0B CALL GETCHR ; Get next character +0814 03D6 B7 OR A ; Set flags +0815 03D7 C2 EF 03 JP NZ,TSTMEM ; If number - Test if RAM there +0816 03DA 21 0D 32 LD HL,STLOOK ; Point to start of RAM +0817 03DD 23 MLOOP: INC HL ; Next byte +0818 03DE 7C LD A,H ; Above address FFFF ? +0819 03DF B5 OR L +0820 03E0 CA 01 04 JP Z,SETTOP ; Yes - 64K RAM +0821 03E3 7E LD A,(HL) ; Get contents +0822 03E4 47 LD B,A ; Save it +0823 03E5 2F CPL ; Flip all bits +0824 03E6 77 LD (HL),A ; Put it back +0825 03E7 BE CP (HL) ; RAM there if same +0826 03E8 70 LD (HL),B ; Restore old contents +0827 03E9 CA DD 03 JP Z,MLOOP ; If RAM - test next byte +0828 03EC C3 01 04 JP SETTOP ; Top of RAM found +0829 03EF +0830 03EF CD 66 0C TSTMEM: CALL ATOH ; Get high memory into DE +0831 03F2 B7 OR A ; Set flags on last byte +0832 03F3 C2 42 07 JP NZ,SNERR ; ?SN Error if bad character +0833 03F6 EB EX DE,HL ; Address into HL +0834 03F7 2B DEC HL ; Back one byte +0835 03F8 3E D9 LD A,11011001B ; Test byte +0836 03FA 46 LD B,(HL) ; Get old contents +0837 03FB 77 LD (HL),A ; Load test byte +0838 03FC BE CP (HL) ; RAM there if same +0839 03FD 70 LD (HL),B ; Restore old contents +0840 03FE C2 CA 03 JP NZ,MSIZE ; Ask again if no RAM +0841 0401 +0842 0401 2B SETTOP: DEC HL ; Back one byte +0843 0402 11 0C 32 LD DE,STLOOK-1 ; See if enough RAM +0844 0405 CD 0A 0A CALL CPDEHL ; Compare DE with HL +0845 0408 DA CA 03 JP C,MSIZE ; Ask again if not enough RAM +0846 040B 11 CE FF LD DE,0-50 ; 50 Bytes string space +0847 040E 22 5F 31 LD (LSTRAM),HL ; Save last available RAM +0848 0411 19 ADD HL,DE ; Allocate string space +0849 0412 22 0A 31 LD (STRSPC),HL ; Save string space +0850 0415 CD 4F 08 CALL CLRPTR ; Clear program area +0851 0418 2A 0A 31 LD HL,(STRSPC) ; Get end of memory +0852 041B 11 EF FF LD DE,0-17 ; Offset for free bytes +0853 041E 19 ADD HL,DE ; Adjust HL +0854 041F 11 A9 31 LD DE,PROGST ; Start of program text +0855 0422 7D LD A,L ; Get LSB +0856 0423 93 SUB E ; Adjust it +0857 0424 6F LD L,A ; Re-save +0858 0425 7C LD A,H ; Get MSB +0859 0426 9A SBC A,D ; Adjust it +0860 0427 67 LD H,A ; Re-save +0861 0428 E5 PUSH HL ; Save bytes free +0862 0429 21 51 04 LD HL,SIGNON ; Sign-on message +0863 042C CD E0 14 CALL PRS ; Output string +0864 042F E1 POP HL ; Get bytes free back +0865 0430 CD 83 1B CALL PRNTHL ; Output amount of free memory +0866 0433 21 42 04 LD HL,BFREE ; " Bytes free" message +0867 0436 CD E0 14 CALL PRS ; Output string +0868 0439 +0869 0439 31 16 31 WARMST: LD SP,STACK ; Temporary stack +0870 043C CD 74 08 BRKRET: CALL CLREG ; Clear registers and stack +0871 043F C3 8D 07 JP PRNTOK ; Go to get command line +0872 0442 +0873 0442 20 42 79 74 BFREE: .BYTE " Bytes free",CR,LF,0,0 +0873 0446 65 73 20 66 +0873 044A 72 65 65 0D +0873 044E 0A 00 00 +0874 0451 +0875 0451 5A 38 30 20 SIGNON: .BYTE "Z80 BASIC Ver 4.7b",CR,LF +0875 0455 42 41 53 49 +0875 0459 43 20 56 65 +0875 045D 72 20 34 2E +0875 0461 37 62 0D 0A +0876 0465 43 6F 70 79 .BYTE "Copyright ",40,"C",41 +0876 0469 72 69 67 68 +0876 046D 74 20 28 43 +0876 0471 29 +0877 0472 20 31 39 37 .BYTE " 1978 by Microsoft",CR,LF,0,0 +0877 0476 38 20 62 79 +0877 047A 20 4D 69 63 +0877 047E 72 6F 73 6F +0877 0482 66 74 0D 0A +0877 0486 00 00 +0878 0488 +0879 0488 4D 65 6D 6F MEMMSG: .BYTE "Memory top",0 +0879 048C 72 79 20 74 +0879 0490 6F 70 00 +0880 0493 +0881 0493 ; FUNCTION ADDRESS TABLE +0882 0493 +0883 0493 F8 19 FNCTAB: .WORD SGN +0884 0495 BC 1A .WORD INT +0885 0497 0E 1A .WORD ABS +0886 0499 B3 30 .WORD USR +0887 049B A0 13 .WORD FRE +0888 049D 25 17 .WORD INP +0889 049F CE 13 .WORD POS +0890 04A1 82 1C .WORD SQR +0891 04A3 61 1D .WORD RND +0892 04A5 9D 18 .WORD LOG +0893 04A7 D0 1C .WORD EXP +0894 04A9 D6 1D .WORD COS +0895 04AB DC 1D .WORD SIN +0896 04AD 3D 1E .WORD TAN +0897 04AF 52 1E .WORD ATN +0898 04B1 79 17 .WORD PEEK +0899 04B3 BD 1E .WORD DEEK +0900 04B5 01 31 .WORD POINT +0901 04B7 52 16 .WORD LEN +0902 04B9 6A 14 .WORD STR +0903 04BB EC 16 .WORD VAL +0904 04BD 61 16 .WORD ASC +0905 04BF 72 16 .WORD CHR +0906 04C1 DF 1E .WORD HEX +0907 04C3 72 1F .WORD BIN +0908 04C5 82 16 .WORD LEFT +0909 04C7 B2 16 .WORD RIGHT +0910 04C9 BC 16 .WORD MID +0911 04CB +0912 04CB ; RESERVED WORD LIST +0913 04CB +0914 04CB C5 4E 44 WORDS: .BYTE 'E'+80H,"ND" +0915 04CE C6 4F 52 .BYTE 'F'+80H,"OR" +0916 04D1 CE 45 58 54 .BYTE 'N'+80H,"EXT" +0917 04D5 C4 41 54 41 .BYTE 'D'+80H,"ATA" +0918 04D9 C9 4E 50 55 .BYTE 'I'+80H,"NPUT" +0918 04DD 54 +0919 04DE C4 49 4D .BYTE 'D'+80H,"IM" +0920 04E1 D2 45 41 44 .BYTE 'R'+80H,"EAD" +0921 04E5 CC 45 54 .BYTE 'L'+80H,"ET" +0922 04E8 C7 4F 54 4F .BYTE 'G'+80H,"OTO" +0923 04EC D2 55 4E .BYTE 'R'+80H,"UN" +0924 04EF C9 46 .BYTE 'I'+80H,"F" +0925 04F1 D2 45 53 54 .BYTE 'R'+80H,"ESTORE" +0925 04F5 4F 52 45 +0926 04F8 C7 4F 53 55 .BYTE 'G'+80H,"OSUB" +0926 04FC 42 +0927 04FD D2 45 54 55 .BYTE 'R'+80H,"ETURN" +0927 0501 52 4E +0928 0503 D2 45 4D .BYTE 'R'+80H,"EM" +0929 0506 D3 54 4F 50 .BYTE 'S'+80H,"TOP" +0930 050A CF 55 54 .BYTE 'O'+80H,"UT" +0931 050D CF 4E .BYTE 'O'+80H,"N" +0932 050F CE 55 4C 4C .BYTE 'N'+80H,"ULL" +0933 0513 D7 41 49 54 .BYTE 'W'+80H,"AIT" +0934 0517 C4 45 46 .BYTE 'D'+80H,"EF" +0935 051A D0 4F 4B 45 .BYTE 'P'+80H,"OKE" +0936 051E C4 4F 4B 45 .BYTE 'D'+80H,"OKE" +0937 0522 D3 43 52 45 .BYTE 'S'+80H,"CREEN" +0937 0526 45 4E +0938 0528 CC 49 4E 45 .BYTE 'L'+80H,"INES" +0938 052C 53 +0939 052D C3 4C 53 .BYTE 'C'+80H,"LS" +0940 0530 D7 49 44 54 .BYTE 'W'+80H,"IDTH" +0940 0534 48 +0941 0535 CD 4F 4E 49 .BYTE 'M'+80H,"ONITOR" +0941 0539 54 4F 52 +0942 053C D3 45 54 .BYTE 'S'+80H,"ET" +0943 053F D2 45 53 45 .BYTE 'R'+80H,"ESET" +0943 0543 54 +0944 0544 D0 52 49 4E .BYTE 'P'+80H,"RINT" +0944 0548 54 +0945 0549 C3 4F 4E 54 .BYTE 'C'+80H,"ONT" +0946 054D CC 49 53 54 .BYTE 'L'+80H,"IST" +0947 0551 C3 4C 45 41 .BYTE 'C'+80H,"LEAR" +0947 0555 52 +0948 0556 C3 4C 4F 41 .BYTE 'C'+80H,"LOAD" +0948 055A 44 +0949 055B C3 53 41 56 .BYTE 'C'+80H,"SAVE" +0949 055F 45 +0950 0560 CE 45 57 .BYTE 'N'+80H,"EW" +0951 0563 +0952 0563 D4 41 42 28 .BYTE 'T'+80H,"AB(" +0953 0567 D4 4F .BYTE 'T'+80H,"O" +0954 0569 C6 4E .BYTE 'F'+80H,"N" +0955 056B D3 50 43 28 .BYTE 'S'+80H,"PC(" +0956 056F D4 48 45 4E .BYTE 'T'+80H,"HEN" +0957 0573 CE 4F 54 .BYTE 'N'+80H,"OT" +0958 0576 D3 54 45 50 .BYTE 'S'+80H,"TEP" +0959 057A +0960 057A AB .BYTE '+'+80H +0961 057B AD .BYTE '-'+80H +0962 057C AA .BYTE '*'+80H +0963 057D AF .BYTE '/'+80H +0964 057E DE .BYTE '^'+80H +0965 057F C1 4E 44 .BYTE 'A'+80H,"ND" +0966 0582 CF 52 .BYTE 'O'+80H,"R" +0967 0584 BE .BYTE '>'+80H +0968 0585 BD .BYTE '='+80H +0969 0586 BC .BYTE '<'+80H +0970 0587 +0971 0587 D3 47 4E .BYTE 'S'+80H,"GN" +0972 058A C9 4E 54 .BYTE 'I'+80H,"NT" +0973 058D C1 42 53 .BYTE 'A'+80H,"BS" +0974 0590 D5 53 52 .BYTE 'U'+80H,"SR" +0975 0593 C6 52 45 .BYTE 'F'+80H,"RE" +0976 0596 C9 4E 50 .BYTE 'I'+80H,"NP" +0977 0599 D0 4F 53 .BYTE 'P'+80H,"OS" +0978 059C D3 51 52 .BYTE 'S'+80H,"QR" +0979 059F D2 4E 44 .BYTE 'R'+80H,"ND" +0980 05A2 CC 4F 47 .BYTE 'L'+80H,"OG" +0981 05A5 C5 58 50 .BYTE 'E'+80H,"XP" +0982 05A8 C3 4F 53 .BYTE 'C'+80H,"OS" +0983 05AB D3 49 4E .BYTE 'S'+80H,"IN" +0984 05AE D4 41 4E .BYTE 'T'+80H,"AN" +0985 05B1 C1 54 4E .BYTE 'A'+80H,"TN" +0986 05B4 D0 45 45 4B .BYTE 'P'+80H,"EEK" +0987 05B8 C4 45 45 4B .BYTE 'D'+80H,"EEK" +0988 05BC D0 4F 49 4E .BYTE 'P'+80H,"OINT" +0988 05C0 54 +0989 05C1 CC 45 4E .BYTE 'L'+80H,"EN" +0990 05C4 D3 54 52 24 .BYTE 'S'+80H,"TR$" +0991 05C8 D6 41 4C .BYTE 'V'+80H,"AL" +0992 05CB C1 53 43 .BYTE 'A'+80H,"SC" +0993 05CE C3 48 52 24 .BYTE 'C'+80H,"HR$" +0994 05D2 C8 45 58 24 .BYTE 'H'+80H,"EX$" +0995 05D6 C2 49 4E 24 .BYTE 'B'+80H,"IN$" +0996 05DA CC 45 46 54 .BYTE 'L'+80H,"EFT$" +0996 05DE 24 +0997 05DF D2 49 47 48 .BYTE 'R'+80H,"IGHT$" +0997 05E3 54 24 +0998 05E5 CD 49 44 24 .BYTE 'M'+80H,"ID$" +0999 05E9 80 .BYTE 80H ; End of list marker +1000 05EA +1001 05EA ; KEYWORD ADDRESS TABLE +1002 05EA +1003 05EA E4 0B WORDTB: .WORD PEND +1004 05EC E1 0A .WORD FOR +1005 05EE BC 0F .WORD NEXT +1006 05F0 31 0D .WORD DATA +1007 05F2 C3 0E .WORD INPUT +1008 05F4 F8 11 .WORD DIM +1009 05F6 F2 0E .WORD READ +1010 05F8 48 0D .WORD LET +1011 05FA EE 0C .WORD GOTO +1012 05FC D1 0C .WORD RUN +1013 05FE C0 0D .WORD IF +1014 0600 AA 0B .WORD RESTOR +1015 0602 DD 0C .WORD GOSUB +1016 0604 0C 0D .WORD RETURN +1017 0606 33 0D .WORD REM +1018 0608 E2 0B .WORD STOP +1019 060A 31 17 .WORD POUT +1020 060C A2 0D .WORD ON +1021 060E 23 0C .WORD NULL +1022 0610 37 17 .WORD WAIT +1023 0612 D6 13 .WORD DEF +1024 0614 80 17 .WORD POKE +1025 0616 C8 1E .WORD DOKE +1026 0618 33 0D .WORD REM +1027 061A AE 1E .WORD LINES +1028 061C A1 1E .WORD CLS +1029 061E A6 1E .WORD WIDTH +1030 0620 DE 1F .WORD MONITR +1031 0622 04 31 .WORD PSET +1032 0624 07 31 .WORD RESET +1033 0626 E4 0D .WORD PRINT +1034 0628 10 0C .WORD CONT +1035 062A 56 0A .WORD LIST +1036 062C 8B 0C .WORD CLEAR +1037 062E 33 0D .WORD REM +1038 0630 33 0D .WORD REM +1039 0632 4E 08 .WORD NEW +1040 0634 +1041 0634 ; RESERVED WORD TOKEN VALUES +1042 0634 +1043 0634 ZEND .EQU 080H ; END +1044 0634 ZFOR .EQU 081H ; FOR +1045 0634 ZDATA .EQU 083H ; DATA +1046 0634 ZGOTO .EQU 088H ; GOTO +1047 0634 ZGOSUB .EQU 08CH ; GOSUB +1048 0634 ZREM .EQU 08EH ; REM +1049 0634 ZPRINT .EQU 09EH ; PRINT +1050 0634 ZNEW .EQU 0A4H ; NEW +1051 0634 +1052 0634 ZTAB .EQU 0A5H ; TAB +1053 0634 ZTO .EQU 0A6H ; TO +1054 0634 ZFN .EQU 0A7H ; FN +1055 0634 ZSPC .EQU 0A8H ; SPC +1056 0634 ZTHEN .EQU 0A9H ; THEN +1057 0634 ZNOT .EQU 0AAH ; NOT +1058 0634 ZSTEP .EQU 0ABH ; STEP +1059 0634 +1060 0634 ZPLUS .EQU 0ACH ; + +1061 0634 ZMINUS .EQU 0ADH ; - +1062 0634 ZTIMES .EQU 0AEH ; * +1063 0634 ZDIV .EQU 0AFH ; / +1064 0634 ZOR .EQU 0B2H ; OR +1065 0634 ZGTR .EQU 0B3H ; > +1066 0634 ZEQUAL .EQU 0B4H ; M +1067 0634 ZLTH .EQU 0B5H ; < +1068 0634 ZSGN .EQU 0B6H ; SGN +1069 0634 ZPOINT .EQU 0C7H ; POINT +1070 0634 ZLEFT .EQU 0CDH +2 ; LEFT$ +1071 0634 +1072 0634 ; ARITHMETIC PRECEDENCE TABLE +1073 0634 +1074 0634 79 PRITAB: .BYTE 79H ; Precedence value +1075 0635 6A 1B .WORD PADD ; FPREG = + FPREG +1076 0637 +1077 0637 79 .BYTE 79H ; Precedence value +1078 0638 9E 17 .WORD PSUB ; FPREG = - FPREG +1079 063A +1080 063A 7C .BYTE 7CH ; Precedence value +1081 063B DC 18 .WORD MULT ; PPREG = * FPREG +1082 063D +1083 063D 7C .BYTE 7CH ; Precedence value +1084 063E 3D 19 .WORD DIV ; FPREG = / FPREG +1085 0640 +1086 0640 7F .BYTE 7FH ; Precedence value +1087 0641 8B 1C .WORD POWER ; FPREG = ^ FPREG +1088 0643 +1089 0643 50 .BYTE 50H ; Precedence value +1090 0644 51 11 .WORD PAND ; FPREG = AND FPREG +1091 0646 +1092 0646 46 .BYTE 46H ; Precedence value +1093 0647 50 11 .WORD POR ; FPREG = OR FPREG +1094 0649 +1095 0649 ; BASIC ERROR CODE LIST +1096 0649 +1097 0649 4E 46 ERRORS: .BYTE "NF" ; NEXT without FOR +1098 064B 53 4E .BYTE "SN" ; Syntax error +1099 064D 52 47 .BYTE "RG" ; RETURN without GOSUB +1100 064F 4F 44 .BYTE "OD" ; Out of DATA +1101 0651 46 43 .BYTE "FC" ; Illegal function call +1102 0653 4F 56 .BYTE "OV" ; Overflow error +1103 0655 4F 4D .BYTE "OM" ; Out of memory +1104 0657 55 4C .BYTE "UL" ; Undefined line +1105 0659 42 53 .BYTE "BS" ; Bad subscript +1106 065B 44 44 .BYTE "DD" ; Re-DIMensioned array +1107 065D 2F 30 .BYTE "/0" ; Division by zero +1108 065F 49 44 .BYTE "ID" ; Illegal direct +1109 0661 54 4D .BYTE "TM" ; Type mis-match +1110 0663 4F 53 .BYTE "OS" ; Out of string space +1111 0665 4C 53 .BYTE "LS" ; String too long +1112 0667 53 54 .BYTE "ST" ; String formula too complex +1113 0669 43 4E .BYTE "CN" ; Can't CONTinue +1114 066B 55 46 .BYTE "UF" ; Undefined FN function +1115 066D 4D 4F .BYTE "MO" ; Missing operand +1116 066F 48 58 .BYTE "HX" ; HEX error +1117 0671 42 4E .BYTE "BN" ; BIN error +1118 0673 +1119 0673 ; INITIALISATION TABLE ------------------------------------------------------- +1120 0673 +1121 0673 C3 39 04 INITAB: JP WARMST ; Warm start jump +1122 0676 C3 61 0C JP FCERR ; "USR (X)" jump (Set to Error) +1123 0679 D3 00 OUT (0),A ; "OUT p,n" skeleton +1124 067B C9 RET +1125 067C D6 00 SUB 0 ; Division support routine +1126 067E 6F LD L,A +1127 067F 7C LD A,H +1128 0680 DE 00 SBC A,0 +1129 0682 67 LD H,A +1130 0683 78 LD A,B +1131 0684 DE 00 SBC A,0 +1132 0686 47 LD B,A +1133 0687 3E 00 LD A,0 +1134 0689 C9 RET +1135 068A 00 00 00 .BYTE 0,0,0 ; Random number seed table used by RND +1136 068D 35 4A CA 99 .BYTE 035H,04AH,0CAH,099H ;-2.65145E+07 +1137 0691 39 1C 76 98 .BYTE 039H,01CH,076H,098H ; 1.61291E+07 +1138 0695 22 95 B3 98 .BYTE 022H,095H,0B3H,098H ;-1.17691E+07 +1139 0699 0A DD 47 98 .BYTE 00AH,0DDH,047H,098H ; 1.30983E+07 +1140 069D 53 D1 99 99 .BYTE 053H,0D1H,099H,099H ;-2-01612E+07 +1141 06A1 0A 1A 9F 98 .BYTE 00AH,01AH,09FH,098H ;-1.04269E+07 +1142 06A5 65 BC CD 98 .BYTE 065H,0BCH,0CDH,098H ;-1.34831E+07 +1143 06A9 D6 77 3E 98 .BYTE 0D6H,077H,03EH,098H ; 1.24825E+07 +1144 06AD 52 C7 4F 80 .BYTE 052H,0C7H,04FH,080H ; Last random number +1145 06B1 DB 00 IN A,(0) ; INP (x) skeleton +1146 06B3 C9 RET +1147 06B4 01 .BYTE 1 ; POS (x) number (1) +1148 06B5 FF .BYTE 255 ; Terminal width (255 = no auto CRLF) +1149 06B6 1C .BYTE 28 ; Width for commas (3 columns) +1150 06B7 00 .BYTE 0 ; No nulls after input bytes +1151 06B8 00 .BYTE 0 ; Output enabled (^O off) +1152 06B9 14 00 .WORD 20 ; Initial lines counter +1153 06BB 14 00 .WORD 20 ; Initial lines number +1154 06BD 00 00 .WORD 0 ; Array load/save check sum +1155 06BF 00 .BYTE 0 ; Break not by NMI +1156 06C0 00 .BYTE 0 ; Break flag +1157 06C1 C3 87 09 JP TTYLIN ; Input reflection (set to TTY) +1158 06C4 C3 00 00 JP $0000 ; POINT reflection unused +1159 06C7 C3 00 00 JP $0000 ; SET reflection +1160 06CA C3 00 00 JP $0000 ; RESET reflection +1161 06CD 0D 32 .WORD STLOOK ; Temp string space +1162 06CF FE FF .WORD -2 ; Current line number (cold) +1163 06D1 AA 31 .WORD PROGST+1 ; Start of program text +1164 06D3 INITBE: +1165 06D3 +1166 06D3 ; END OF INITIALISATION TABLE --------------------------------------------------- +1167 06D3 +1168 06D3 20 45 72 72 ERRMSG: .BYTE " Error",0 +1168 06D7 6F 72 00 +1169 06DA 20 69 6E 20 INMSG: .BYTE " in ",0 +1169 06DE 00 +1170 06DF ZERBYT .EQU $-1 ; A zero byte +1171 06DF 4F 6B 0D 0A OKMSG: .BYTE "Ok",CR,LF,0,0 +1171 06E3 00 00 +1172 06E5 42 72 65 61 BRKMSG: .BYTE "Break",0 +1172 06E9 6B 00 +1173 06EB +1174 06EB 21 04 00 BAKSTK: LD HL,4 ; Look for "FOR" block with +1175 06EE 39 ADD HL,SP ; same index as specified +1176 06EF 7E LOKFOR: LD A,(HL) ; Get block ID +1177 06F0 23 INC HL ; Point to index address +1178 06F1 FE 81 CP ZFOR ; Is it a "FOR" token +1179 06F3 C0 RET NZ ; No - exit +1180 06F4 4E LD C,(HL) ; BC = Address of "FOR" index +1181 06F5 23 INC HL +1182 06F6 46 LD B,(HL) +1183 06F7 23 INC HL ; Point to sign of STEP +1184 06F8 E5 PUSH HL ; Save pointer to sign +1185 06F9 69 LD L,C ; HL = address of "FOR" index +1186 06FA 60 LD H,B +1187 06FB 7A LD A,D ; See if an index was specified +1188 06FC B3 OR E ; DE = 0 if no index specified +1189 06FD EB EX DE,HL ; Specified index into HL +1190 06FE CA 05 07 JP Z,INDFND ; Skip if no index given +1191 0701 EB EX DE,HL ; Index back into DE +1192 0702 CD 0A 0A CALL CPDEHL ; Compare index with one given +1193 0705 01 0D 00 INDFND: LD BC,16-3 ; Offset to next block +1194 0708 E1 POP HL ; Restore pointer to sign +1195 0709 C8 RET Z ; Return if block found +1196 070A 09 ADD HL,BC ; Point to next block +1197 070B C3 EF 06 JP LOKFOR ; Keep on looking +1198 070E +1199 070E CD 28 07 MOVUP: CALL ENFMEM ; See if enough memory +1200 0711 C5 MOVSTR: PUSH BC ; Save end of source +1201 0712 E3 EX (SP),HL ; Swap source and dest" end +1202 0713 C1 POP BC ; Get end of destination +1203 0714 CD 0A 0A MOVLP: CALL CPDEHL ; See if list moved +1204 0717 7E LD A,(HL) ; Get byte +1205 0718 02 LD (BC),A ; Move it +1206 0719 C8 RET Z ; Exit if all done +1207 071A 0B DEC BC ; Next byte to move to +1208 071B 2B DEC HL ; Next byte to move +1209 071C C3 14 07 JP MOVLP ; Loop until all bytes moved +1210 071F +1211 071F E5 CHKSTK: PUSH HL ; Save code string address +1212 0720 2A 8A 31 LD HL,(ARREND) ; Lowest free memory +1213 0723 06 00 LD B,0 ; BC = Number of levels to test +1214 0725 09 ADD HL,BC ; 2 Bytes for each level +1215 0726 09 ADD HL,BC +1216 0727 3E .BYTE 3EH ; Skip "PUSH HL" +1217 0728 E5 ENFMEM: PUSH HL ; Save code string address +1218 0729 3E D0 LD A,0D0H ;LOW -48 ; 48 Bytes minimum RAM +1219 072B 95 SUB L +1220 072C 6F LD L,A +1221 072D 3E FF LD A,0FFH; HIGH (-48) ; 48 Bytes minimum RAM +1222 072F 9C SBC A,H +1223 0730 DA 37 07 JP C,OMERR ; Not enough - ?OM Error +1224 0733 67 LD H,A +1225 0734 39 ADD HL,SP ; Test if stack is overflowed +1226 0735 E1 POP HL ; Restore code string address +1227 0736 D8 RET C ; Return if enough mmory +1228 0737 1E 0C OMERR: LD E,OM ; ?OM Error +1229 0739 C3 56 07 JP ERROR +1230 073C +1231 073C 2A 79 31 DATSNR: LD HL,(DATLIN) ; Get line of current DATA item +1232 073F 22 0C 31 LD (LINEAT),HL ; Save as current line +1233 0742 1E 02 SNERR: LD E,SN ; ?SN Error +1234 0744 01 .BYTE 01H ; Skip "LD E,DZ" +1235 0745 1E 14 DZERR: LD E,DZ ; ?/0 Error +1236 0747 01 .BYTE 01H ; Skip "LD E,NF" +1237 0748 1E 00 NFERR: LD E,NF ; ?NF Error +1238 074A 01 .BYTE 01H ; Skip "LD E,DD" +1239 074B 1E 12 DDERR: LD E,DD ; ?DD Error +1240 074D 01 .BYTE 01H ; Skip "LD E,UF" +1241 074E 1E 22 UFERR: LD E,UF ; ?UF Error +1242 0750 01 .BYTE 01H ; Skip "LD E,OV +1243 0751 1E 0A OVERR: LD E,OV ; ?OV Error +1244 0753 01 .BYTE 01H ; Skip "LD E,TM" +1245 0754 1E 18 TMERR: LD E,TM ; ?TM Error +1246 0756 +1247 0756 CD 74 08 ERROR: CALL CLREG ; Clear registers and stack +1248 0759 32 F5 30 LD (CTLOFG),A ; Enable output (A is 0) +1249 075C CD 35 0E CALL STTLIN ; Start new line +1250 075F 21 49 06 LD HL,ERRORS ; Point to error codes +1251 0762 57 LD D,A ; D = 0 (A is 0) +1252 0763 3E 3F LD A,'?' +1253 0765 CD 1B 0A CALL OUTC ; Output '?' +1254 0768 19 ADD HL,DE ; Offset to correct error code +1255 0769 7E LD A,(HL) ; First character +1256 076A CD 1B 0A CALL OUTC ; Output it +1257 076D CD 9A 0B CALL GETCHR ; Get next character +1258 0770 CD 1B 0A CALL OUTC ; Output it +1259 0773 21 D3 06 LD HL,ERRMSG ; "Error" message +1260 0776 CD E0 14 ERRIN: CALL PRS ; Output message +1261 0779 2A 0C 31 LD HL,(LINEAT) ; Get line of error +1262 077C 11 FE FF LD DE,-2 ; Cold start error if -2 +1263 077F CD 0A 0A CALL CPDEHL ; See if cold start error +1264 0782 CA A6 03 JP Z,CSTART ; Cold start error - Restart +1265 0785 7C LD A,H ; Was it a direct error? +1266 0786 A5 AND L ; Line = -1 if direct error +1267 0787 3C INC A +1268 0788 C4 7B 1B CALL NZ,LINEIN ; No - output line of error +1269 078B 3E .BYTE 3EH ; Skip "POP BC" +1270 078C C1 POPNOK: POP BC ; Drop address in input buffer +1271 078D +1272 078D AF PRNTOK: XOR A ; Output "Ok" and get command +1273 078E 32 F5 30 LD (CTLOFG),A ; Enable output +1274 0791 CD 35 0E CALL STTLIN ; Start new line +1275 0794 21 DF 06 LD HL,OKMSG ; "Ok" message +1276 0797 CD E0 14 CALL PRS ; Output "Ok" +1277 079A 21 FF FF GETCMD: LD HL,-1 ; Flag direct mode +1278 079D 22 0C 31 LD (LINEAT),HL ; Save as current line +1279 07A0 CD 87 09 CALL GETLIN ; Get an input line +1280 07A3 DA 9A 07 JP C,GETCMD ; Get line again if break +1281 07A6 CD 9A 0B CALL GETCHR ; Get first character +1282 07A9 3C INC A ; Test if end of line +1283 07AA 3D DEC A ; Without affecting Carry +1284 07AB CA 9A 07 JP Z,GETCMD ; Nothing entered - Get another +1285 07AE F5 PUSH AF ; Save Carry status +1286 07AF CD 66 0C CALL ATOH ; Get line number into DE +1287 07B2 D5 PUSH DE ; Save line number +1288 07B3 CD 9E 08 CALL CRUNCH ; Tokenise rest of line +1289 07B6 47 LD B,A ; Length of tokenised line +1290 07B7 D1 POP DE ; Restore line number +1291 07B8 F1 POP AF ; Restore Carry +1292 07B9 D2 7A 0B JP NC,EXCUTE ; No line number - Direct mode +1293 07BC D5 PUSH DE ; Save line number +1294 07BD C5 PUSH BC ; Save length of tokenised line +1295 07BE AF XOR A +1296 07BF 32 7C 31 LD (LSTBIN),A ; Clear last byte input +1297 07C2 CD 9A 0B CALL GETCHR ; Get next character +1298 07C5 B7 OR A ; Set flags +1299 07C6 F5 PUSH AF ; And save them +1300 07C7 CD 2E 08 CALL SRCHLN ; Search for line number in DE +1301 07CA DA D3 07 JP C,LINFND ; Jump if line found +1302 07CD F1 POP AF ; Get status +1303 07CE F5 PUSH AF ; And re-save +1304 07CF CA 07 0D JP Z,ULERR ; Nothing after number - Error +1305 07D2 B7 OR A ; Clear Carry +1306 07D3 C5 LINFND: PUSH BC ; Save address of line in prog +1307 07D4 D2 EA 07 JP NC,INEWLN ; Line not found - Insert new +1308 07D7 EB EX DE,HL ; Next line address in DE +1309 07D8 2A 86 31 LD HL,(PROGND) ; End of program +1310 07DB 1A SFTPRG: LD A,(DE) ; Shift rest of program down +1311 07DC 02 LD (BC),A +1312 07DD 03 INC BC ; Next destination +1313 07DE 13 INC DE ; Next source +1314 07DF CD 0A 0A CALL CPDEHL ; All done? +1315 07E2 C2 DB 07 JP NZ,SFTPRG ; More to do +1316 07E5 60 LD H,B ; HL - New end of program +1317 07E6 69 LD L,C +1318 07E7 22 86 31 LD (PROGND),HL ; Update end of program +1319 07EA +1320 07EA D1 INEWLN: POP DE ; Get address of line, +1321 07EB F1 POP AF ; Get status +1322 07EC CA 11 08 JP Z,SETPTR ; No text - Set up pointers +1323 07EF 2A 86 31 LD HL,(PROGND) ; Get end of program +1324 07F2 E3 EX (SP),HL ; Get length of input line +1325 07F3 C1 POP BC ; End of program to BC +1326 07F4 09 ADD HL,BC ; Find new end +1327 07F5 E5 PUSH HL ; Save new end +1328 07F6 CD 0E 07 CALL MOVUP ; Make space for line +1329 07F9 E1 POP HL ; Restore new end +1330 07FA 22 86 31 LD (PROGND),HL ; Update end of program pointer +1331 07FD EB EX DE,HL ; Get line to move up in HL +1332 07FE 74 LD (HL),H ; Save MSB +1333 07FF D1 POP DE ; Get new line number +1334 0800 23 INC HL ; Skip pointer +1335 0801 23 INC HL +1336 0802 73 LD (HL),E ; Save LSB of line number +1337 0803 23 INC HL +1338 0804 72 LD (HL),D ; Save MSB of line number +1339 0805 23 INC HL ; To first byte in line +1340 0806 11 11 31 LD DE,BUFFER ; Copy buffer to program +1341 0809 1A MOVBUF: LD A,(DE) ; Get source +1342 080A 77 LD (HL),A ; Save destinations +1343 080B 23 INC HL ; Next source +1344 080C 13 INC DE ; Next destination +1345 080D B7 OR A ; Done? +1346 080E C2 09 08 JP NZ,MOVBUF ; No - Repeat +1347 0811 CD 5A 08 SETPTR: CALL RUNFST ; Set line pointers +1348 0814 23 INC HL ; To LSB of pointer +1349 0815 EB EX DE,HL ; Address to DE +1350 0816 62 PTRLP: LD H,D ; Address to HL +1351 0817 6B LD L,E +1352 0818 7E LD A,(HL) ; Get LSB of pointer +1353 0819 23 INC HL ; To MSB of pointer +1354 081A B6 OR (HL) ; Compare with MSB pointer +1355 081B CA 9A 07 JP Z,GETCMD ; Get command line if end +1356 081E 23 INC HL ; To LSB of line number +1357 081F 23 INC HL ; Skip line number +1358 0820 23 INC HL ; Point to first byte in line +1359 0821 AF XOR A ; Looking for 00 byte +1360 0822 BE FNDEND: CP (HL) ; Found end of line? +1361 0823 23 INC HL ; Move to next byte +1362 0824 C2 22 08 JP NZ,FNDEND ; No - Keep looking +1363 0827 EB EX DE,HL ; Next line address to HL +1364 0828 73 LD (HL),E ; Save LSB of pointer +1365 0829 23 INC HL +1366 082A 72 LD (HL),D ; Save MSB of pointer +1367 082B C3 16 08 JP PTRLP ; Do next line +1368 082E +1369 082E 2A 0E 31 SRCHLN: LD HL,(BASTXT) ; Start of program text +1370 0831 44 SRCHLP: LD B,H ; BC = Address to look at +1371 0832 4D LD C,L +1372 0833 7E LD A,(HL) ; Get address of next line +1373 0834 23 INC HL +1374 0835 B6 OR (HL) ; End of program found? +1375 0836 2B DEC HL +1376 0837 C8 RET Z ; Yes - Line not found +1377 0838 23 INC HL +1378 0839 23 INC HL +1379 083A 7E LD A,(HL) ; Get LSB of line number +1380 083B 23 INC HL +1381 083C 66 LD H,(HL) ; Get MSB of line number +1382 083D 6F LD L,A +1383 083E CD 0A 0A CALL CPDEHL ; Compare with line in DE +1384 0841 60 LD H,B ; HL = Start of this line +1385 0842 69 LD L,C +1386 0843 7E LD A,(HL) ; Get LSB of next line address +1387 0844 23 INC HL +1388 0845 66 LD H,(HL) ; Get MSB of next line address +1389 0846 6F LD L,A ; Next line to HL +1390 0847 3F CCF +1391 0848 C8 RET Z ; Lines found - Exit +1392 0849 3F CCF +1393 084A D0 RET NC ; Line not found,at line after +1394 084B C3 31 08 JP SRCHLP ; Keep looking +1395 084E +1396 084E C0 NEW: RET NZ ; Return if any more on line +1397 084F 2A 0E 31 CLRPTR: LD HL,(BASTXT) ; Point to start of program +1398 0852 AF XOR A ; Set program area to empty +1399 0853 77 LD (HL),A ; Save LSB = 00 +1400 0854 23 INC HL +1401 0855 77 LD (HL),A ; Save MSB = 00 +1402 0856 23 INC HL +1403 0857 22 86 31 LD (PROGND),HL ; Set program end +1404 085A +1405 085A 2A 0E 31 RUNFST: LD HL,(BASTXT) ; Clear all variables +1406 085D 2B DEC HL +1407 085E +1408 085E 22 7E 31 INTVAR: LD (BRKLIN),HL ; Initialise RUN variables +1409 0861 2A 5F 31 LD HL,(LSTRAM) ; Get end of RAM +1410 0864 22 73 31 LD (STRBOT),HL ; Clear string space +1411 0867 AF XOR A +1412 0868 CD AA 0B CALL RESTOR ; Reset DATA pointers +1413 086B 2A 86 31 LD HL,(PROGND) ; Get end of program +1414 086E 22 88 31 LD (VAREND),HL ; Clear variables +1415 0871 22 8A 31 LD (ARREND),HL ; Clear arrays +1416 0874 +1417 0874 C1 CLREG: POP BC ; Save return address +1418 0875 2A 0A 31 LD HL,(STRSPC) ; Get end of working RAN +1419 0878 F9 LD SP,HL ; Set stack +1420 0879 21 63 31 LD HL,TMSTPL ; Temporary string pool +1421 087C 22 61 31 LD (TMSTPT),HL ; Reset temporary string ptr +1422 087F AF XOR A ; A = 00 +1423 0880 6F LD L,A ; HL = 0000 +1424 0881 67 LD H,A +1425 0882 22 84 31 LD (CONTAD),HL ; No CONTinue +1426 0885 32 7B 31 LD (FORFLG),A ; Clear FOR flag +1427 0888 22 8E 31 LD (FNRGNM),HL ; Clear FN argument +1428 088B E5 PUSH HL ; HL = 0000 +1429 088C C5 PUSH BC ; Put back return +1430 088D 2A 7E 31 DOAGN: LD HL,(BRKLIN) ; Get address of code to RUN +1431 0890 C9 RET ; Return to execution driver +1432 0891 +1433 0891 3E 3F PROMPT: LD A,'?' ; '?' +1434 0893 CD 1B 0A CALL OUTC ; Output character +1435 0896 3E 20 LD A,' ' ; Space +1436 0898 CD 1B 0A CALL OUTC ; Output character +1437 089B C3 FE 30 JP RINPUT ; Get input line +1438 089E +1439 089E AF CRUNCH: XOR A ; Tokenise line @ HL to BUFFER +1440 089F 32 5E 31 LD (DATFLG),A ; Reset literal flag +1441 08A2 0E 05 LD C,2+3 ; 2 byte number and 3 nulls +1442 08A4 11 11 31 LD DE,BUFFER ; Start of input buffer +1443 08A7 7E CRNCLP: LD A,(HL) ; Get byte +1444 08A8 FE 20 CP ' ' ; Is it a space? +1445 08AA CA 26 09 JP Z,MOVDIR ; Yes - Copy direct +1446 08AD 47 LD B,A ; Save character +1447 08AE FE 22 CP '"' ; Is it a quote? +1448 08B0 CA 46 09 JP Z,CPYLIT ; Yes - Copy literal string +1449 08B3 B7 OR A ; Is it end of buffer? +1450 08B4 CA 4D 09 JP Z,ENDBUF ; Yes - End buffer +1451 08B7 3A 5E 31 LD A,(DATFLG) ; Get data type +1452 08BA B7 OR A ; Literal? +1453 08BB 7E LD A,(HL) ; Get byte to copy +1454 08BC C2 26 09 JP NZ,MOVDIR ; Literal - Copy direct +1455 08BF FE 3F CP '?' ; Is it '?' short for PRINT +1456 08C1 3E 9E LD A,ZPRINT ; "PRINT" token +1457 08C3 CA 26 09 JP Z,MOVDIR ; Yes - replace it +1458 08C6 7E LD A,(HL) ; Get byte again +1459 08C7 FE 30 CP '0' ; Is it less than '0' +1460 08C9 DA D1 08 JP C,FNDWRD ; Yes - Look for reserved words +1461 08CC FE 3C CP 60; ";"+1 ; Is it "0123456789:;" ? +1462 08CE DA 26 09 JP C,MOVDIR ; Yes - copy it direct +1463 08D1 D5 FNDWRD: PUSH DE ; Look for reserved words +1464 08D2 11 CA 04 LD DE,WORDS-1 ; Point to table +1465 08D5 C5 PUSH BC ; Save count +1466 08D6 01 22 09 LD BC,RETNAD ; Where to return to +1467 08D9 C5 PUSH BC ; Save return address +1468 08DA 06 7F LD B,ZEND-1 ; First token value -1 +1469 08DC 7E LD A,(HL) ; Get byte +1470 08DD FE 61 CP 'a' ; Less than 'a' ? +1471 08DF DA EA 08 JP C,SEARCH ; Yes - search for words +1472 08E2 FE 7B CP 'z'+1 ; Greater than 'z' ? +1473 08E4 D2 EA 08 JP NC,SEARCH ; Yes - search for words +1474 08E7 E6 5F AND 01011111B ; Force upper case +1475 08E9 77 LD (HL),A ; Replace byte +1476 08EA 4E SEARCH: LD C,(HL) ; Search for a word +1477 08EB EB EX DE,HL +1478 08EC 23 GETNXT: INC HL ; Get next reserved word +1479 08ED B6 OR (HL) ; Start of word? +1480 08EE F2 EC 08 JP P,GETNXT ; No - move on +1481 08F1 04 INC B ; Increment token value +1482 08F2 7E LD A, (HL) ; Get byte from table +1483 08F3 E6 7F AND 01111111B ; Strip bit 7 +1484 08F5 C8 RET Z ; Return if end of list +1485 08F6 B9 CP C ; Same character as in buffer? +1486 08F7 C2 EC 08 JP NZ,GETNXT ; No - get next word +1487 08FA EB EX DE,HL +1488 08FB E5 PUSH HL ; Save start of word +1489 08FC +1490 08FC 13 NXTBYT: INC DE ; Look through rest of word +1491 08FD 1A LD A,(DE) ; Get byte from table +1492 08FE B7 OR A ; End of word ? +1493 08FF FA 1E 09 JP M,MATCH ; Yes - Match found +1494 0902 4F LD C,A ; Save it +1495 0903 78 LD A,B ; Get token value +1496 0904 FE 88 CP ZGOTO ; Is it "GOTO" token ? +1497 0906 C2 0D 09 JP NZ,NOSPC ; No - Don't allow spaces +1498 0909 CD 9A 0B CALL GETCHR ; Get next character +1499 090C 2B DEC HL ; Cancel increment from GETCHR +1500 090D 23 NOSPC: INC HL ; Next byte +1501 090E 7E LD A,(HL) ; Get byte +1502 090F FE 61 CP 'a' ; Less than 'a' ? +1503 0911 DA 16 09 JP C,NOCHNG ; Yes - don't change +1504 0914 E6 5F AND 01011111B ; Make upper case +1505 0916 B9 NOCHNG: CP C ; Same as in buffer ? +1506 0917 CA FC 08 JP Z,NXTBYT ; Yes - keep testing +1507 091A E1 POP HL ; Get back start of word +1508 091B C3 EA 08 JP SEARCH ; Look at next word +1509 091E +1510 091E 48 MATCH: LD C,B ; Word found - Save token value +1511 091F F1 POP AF ; Throw away return +1512 0920 EB EX DE,HL +1513 0921 C9 RET ; Return to "RETNAD" +1514 0922 EB RETNAD: EX DE,HL ; Get address in string +1515 0923 79 LD A,C ; Get token value +1516 0924 C1 POP BC ; Restore buffer length +1517 0925 D1 POP DE ; Get destination address +1518 0926 23 MOVDIR: INC HL ; Next source in buffer +1519 0927 12 LD (DE),A ; Put byte in buffer +1520 0928 13 INC DE ; Move up buffer +1521 0929 0C INC C ; Increment length of buffer +1522 092A D6 3A SUB ':' ; End of statement? +1523 092C CA 34 09 JP Z,SETLIT ; Jump if multi-statement line +1524 092F FE 49 CP ZDATA-3AH ; Is it DATA statement ? +1525 0931 C2 37 09 JP NZ,TSTREM ; No - see if REM +1526 0934 32 5E 31 SETLIT: LD (DATFLG),A ; Set literal flag +1527 0937 D6 54 TSTREM: SUB ZREM-3AH ; Is it REM? +1528 0939 C2 A7 08 JP NZ,CRNCLP ; No - Leave flag +1529 093C 47 LD B,A ; Copy rest of buffer +1530 093D 7E NXTCHR: LD A,(HL) ; Get byte +1531 093E B7 OR A ; End of line ? +1532 093F CA 4D 09 JP Z,ENDBUF ; Yes - Terminate buffer +1533 0942 B8 CP B ; End of statement ? +1534 0943 CA 26 09 JP Z,MOVDIR ; Yes - Get next one +1535 0946 23 CPYLIT: INC HL ; Move up source string +1536 0947 12 LD (DE),A ; Save in destination +1537 0948 0C INC C ; Increment length +1538 0949 13 INC DE ; Move up destination +1539 094A C3 3D 09 JP NXTCHR ; Repeat +1540 094D +1541 094D 21 10 31 ENDBUF: LD HL,BUFFER-1 ; Point to start of buffer +1542 0950 12 LD (DE),A ; Mark end of buffer (A = 00) +1543 0951 13 INC DE +1544 0952 12 LD (DE),A ; A = 00 +1545 0953 13 INC DE +1546 0954 12 LD (DE),A ; A = 00 +1547 0955 C9 RET +1548 0956 +1549 0956 3A F4 30 DODEL: LD A,(NULFLG) ; Get null flag status +1550 0959 B7 OR A ; Is it zero? +1551 095A 3E 00 LD A,0 ; Zero A - Leave flags +1552 095C 32 F4 30 LD (NULFLG),A ; Zero null flag +1553 095F C2 6A 09 JP NZ,ECHDEL ; Set - Echo it +1554 0962 05 DEC B ; Decrement length +1555 0963 CA 87 09 JP Z,GETLIN ; Get line again if empty +1556 0966 CD 1B 0A CALL OUTC ; Output null character +1557 0969 3E .BYTE 3EH ; Skip "DEC B" +1558 096A 05 ECHDEL: DEC B ; Count bytes in buffer +1559 096B 2B DEC HL ; Back space buffer +1560 096C CA 7E 09 JP Z,OTKLN ; No buffer - Try again +1561 096F 7E LD A,(HL) ; Get deleted byte +1562 0970 CD 1B 0A CALL OUTC ; Echo it +1563 0973 C3 90 09 JP MORINP ; Get more input +1564 0976 +1565 0976 05 DELCHR: DEC B ; Count bytes in buffer +1566 0977 2B DEC HL ; Back space buffer +1567 0978 CD 1B 0A CALL OUTC ; Output character in A +1568 097B C2 90 09 JP NZ,MORINP ; Not end - Get more +1569 097E CD 1B 0A OTKLN: CALL OUTC ; Output character in A +1570 0981 CD 42 0E KILIN: CALL PRNTCRLF ; Output CRLF +1571 0984 C3 87 09 JP TTYLIN ; Get line again +1572 0987 +1573 0987 GETLIN: +1574 0987 21 11 31 TTYLIN: LD HL,BUFFER ; Get a line by character +1575 098A 06 01 LD B,1 ; Set buffer as empty +1576 098C AF XOR A +1577 098D 32 F4 30 LD (NULFLG),A ; Clear null flag +1578 0990 CD 45 0A MORINP: CALL CLOTST ; Get character and test ^O +1579 0993 4F LD C,A ; Save character in C +1580 0994 FE 7F CP DEL ; Delete character? +1581 0996 CA 56 09 JP Z,DODEL ; Yes - Process it +1582 0999 3A F4 30 LD A,(NULFLG) ; Get null flag +1583 099C B7 OR A ; Test null flag status +1584 099D CA A9 09 JP Z,PROCES ; Reset - Process character +1585 09A0 3E 00 LD A,0 ; Set a null +1586 09A2 CD 1B 0A CALL OUTC ; Output null +1587 09A5 AF XOR A ; Clear A +1588 09A6 32 F4 30 LD (NULFLG),A ; Reset null flag +1589 09A9 79 PROCES: LD A,C ; Get character +1590 09AA FE 07 CP CTRLG ; Bell? +1591 09AC CA ED 09 JP Z,PUTCTL ; Yes - Save it +1592 09AF FE 03 CP CTRLC ; Is it control "C"? +1593 09B1 CC 42 0E CALL Z,PRNTCRLF ; Yes - Output CRLF +1594 09B4 37 SCF ; Flag break +1595 09B5 C8 RET Z ; Return if control "C" +1596 09B6 FE 0D CP CR ; Is it enter? +1597 09B8 CA 3D 0E JP Z,ENDINP ; Yes - Terminate input +1598 09BB FE 15 CP CTRLU ; Is it control "U"? +1599 09BD CA 81 09 JP Z,KILIN ; Yes - Get another line +1600 09C0 FE 40 CP '@' ; Is it "kill line"? +1601 09C2 CA 7E 09 JP Z,OTKLN ; Yes - Kill line +1602 09C5 FE 5F CP '_' ; Is it delete? +1603 09C7 CA 76 09 JP Z,DELCHR ; Yes - Delete character +1604 09CA FE 08 CP BKSP ; Is it backspace? +1605 09CC CA 76 09 JP Z,DELCHR ; Yes - Delete character +1606 09CF FE 12 CP CTRLR ; Is it control "R"? +1607 09D1 C2 E8 09 JP NZ,PUTBUF ; No - Put in buffer +1608 09D4 C5 PUSH BC ; Save buffer length +1609 09D5 D5 PUSH DE ; Save DE +1610 09D6 E5 PUSH HL ; Save buffer address +1611 09D7 36 00 LD (HL),0 ; Mark end of buffer +1612 09D9 CD F2 1F CALL OUTNCR ; Output and do CRLF +1613 09DC 21 11 31 LD HL,BUFFER ; Point to buffer start +1614 09DF CD E0 14 CALL PRS ; Output buffer +1615 09E2 E1 POP HL ; Restore buffer address +1616 09E3 D1 POP DE ; Restore DE +1617 09E4 C1 POP BC ; Restore buffer length +1618 09E5 C3 90 09 JP MORINP ; Get another character +1619 09E8 +1620 09E8 FE 20 PUTBUF: CP ' ' ; Is it a control code? +1621 09EA DA 90 09 JP C,MORINP ; Yes - Ignore +1622 09ED 78 PUTCTL: LD A,B ; Get number of bytes in buffer +1623 09EE FE 49 CP 72+1 ; Test for line overflow +1624 09F0 3E 07 LD A,CTRLG ; Set a bell +1625 09F2 D2 02 0A JP NC,OUTNBS ; Ring bell if buffer full +1626 09F5 79 LD A,C ; Get character +1627 09F6 71 LD (HL),C ; Save in buffer +1628 09F7 32 7C 31 LD (LSTBIN),A ; Save last input byte +1629 09FA 23 INC HL ; Move up buffer +1630 09FB 04 INC B ; Increment length +1631 09FC CD 1B 0A OUTIT: CALL OUTC ; Output the character entered +1632 09FF C3 90 09 JP MORINP ; Get another character +1633 0A02 +1634 0A02 CD 1B 0A OUTNBS: CALL OUTC ; Output bell and back over it +1635 0A05 3E 08 LD A,BKSP ; Set back space +1636 0A07 C3 FC 09 JP OUTIT ; Output it and get more +1637 0A0A +1638 0A0A 7C CPDEHL: LD A,H ; Get H +1639 0A0B 92 SUB D ; Compare with D +1640 0A0C C0 RET NZ ; Different - Exit +1641 0A0D 7D LD A,L ; Get L +1642 0A0E 93 SUB E ; Compare with E +1643 0A0F C9 RET ; Return status +1644 0A10 +1645 0A10 7E CHKSYN: LD A,(HL) ; Check syntax of character +1646 0A11 E3 EX (SP),HL ; Address of test byte +1647 0A12 BE CP (HL) ; Same as in code string? +1648 0A13 23 INC HL ; Return address +1649 0A14 E3 EX (SP),HL ; Put it back +1650 0A15 CA 9A 0B JP Z,GETCHR ; Yes - Get next character +1651 0A18 C3 42 07 JP SNERR ; Different - ?SN Error +1652 0A1B +1653 0A1B F5 OUTC: PUSH AF ; Save character +1654 0A1C 3A F5 30 LD A,(CTLOFG) ; Get control "O" flag +1655 0A1F B7 OR A ; Is it set? +1656 0A20 C2 15 15 JP NZ,POPAF ; Yes - don't output +1657 0A23 F1 POP AF ; Restore character +1658 0A24 C5 PUSH BC ; Save buffer length +1659 0A25 F5 PUSH AF ; Save character +1660 0A26 FE 20 CP ' ' ; Is it a control code? +1661 0A28 DA 3F 0A JP C,DINPOS ; Yes - Don't INC POS(X) +1662 0A2B 3A F2 30 LD A,(LWIDTH) ; Get line width +1663 0A2E 47 LD B,A ; To B +1664 0A2F 3A 5B 31 LD A,(CURPOS) ; Get cursor position +1665 0A32 04 INC B ; Width 255? +1666 0A33 CA 3B 0A JP Z,INCLEN ; Yes - No width limit +1667 0A36 05 DEC B ; Restore width +1668 0A37 B8 CP B ; At end of line? +1669 0A38 CC 42 0E CALL Z,PRNTCRLF ; Yes - output CRLF +1670 0A3B 3C INCLEN: INC A ; Move on one character +1671 0A3C 32 5B 31 LD (CURPOS),A ; Save new position +1672 0A3F F1 DINPOS: POP AF ; Restore character +1673 0A40 C1 POP BC ; Restore buffer length +1674 0A41 CD DB 1F CALL MONOUT ; Send it +1675 0A44 C9 RET +1676 0A45 +1677 0A45 CD 9F 1E CLOTST: CALL GETINP ; Get input character +1678 0A48 E6 7F AND 01111111B ; Strip bit 7 +1679 0A4A FE 0F CP CTRLO ; Is it control "O"? +1680 0A4C C0 RET NZ ; No don't flip flag +1681 0A4D 3A F5 30 LD A,(CTLOFG) ; Get flag +1682 0A50 2F CPL ; Flip it +1683 0A51 32 F5 30 LD (CTLOFG),A ; Put it back +1684 0A54 AF XOR A ; Null character +1685 0A55 C9 RET +1686 0A56 +1687 0A56 CD 66 0C LIST: CALL ATOH ; ASCII number to DE +1688 0A59 C0 RET NZ ; Return if anything extra +1689 0A5A C1 POP BC ; Rubbish - Not needed +1690 0A5B CD 2E 08 CALL SRCHLN ; Search for line number in DE +1691 0A5E C5 PUSH BC ; Save address of line +1692 0A5F CD AC 0A CALL SETLIN ; Set up lines counter +1693 0A62 E1 LISTLP: POP HL ; Restore address of line +1694 0A63 4E LD C,(HL) ; Get LSB of next line +1695 0A64 23 INC HL +1696 0A65 46 LD B,(HL) ; Get MSB of next line +1697 0A66 23 INC HL +1698 0A67 78 LD A,B ; BC = 0 (End of program)? +1699 0A68 B1 OR C +1700 0A69 CA 8D 07 JP Z,PRNTOK ; Yes - Go to command mode +1701 0A6C CD B5 0A CALL COUNT ; Count lines +1702 0A6F CD C5 0B CALL TSTBRK ; Test for break key +1703 0A72 C5 PUSH BC ; Save address of next line +1704 0A73 CD 42 0E CALL PRNTCRLF ; Output CRLF +1705 0A76 5E LD E,(HL) ; Get LSB of line number +1706 0A77 23 INC HL +1707 0A78 56 LD D,(HL) ; Get MSB of line number +1708 0A79 23 INC HL +1709 0A7A E5 PUSH HL ; Save address of line start +1710 0A7B EB EX DE,HL ; Line number to HL +1711 0A7C CD 83 1B CALL PRNTHL ; Output line number in decimal +1712 0A7F 3E 20 LD A,' ' ; Space after line number +1713 0A81 E1 POP HL ; Restore start of line address +1714 0A82 CD 1B 0A LSTLP2: CALL OUTC ; Output character in A +1715 0A85 7E LSTLP3: LD A,(HL) ; Get next byte in line +1716 0A86 B7 OR A ; End of line? +1717 0A87 23 INC HL ; To next byte in line +1718 0A88 CA 62 0A JP Z,LISTLP ; Yes - get next line +1719 0A8B F2 82 0A JP P,LSTLP2 ; No token - output it +1720 0A8E D6 7F SUB ZEND-1 ; Find and output word +1721 0A90 4F LD C,A ; Token offset+1 to C +1722 0A91 11 CB 04 LD DE,WORDS ; Reserved word list +1723 0A94 1A FNDTOK: LD A,(DE) ; Get character in list +1724 0A95 13 INC DE ; Move on to next +1725 0A96 B7 OR A ; Is it start of word? +1726 0A97 F2 94 0A JP P,FNDTOK ; No - Keep looking for word +1727 0A9A 0D DEC C ; Count words +1728 0A9B C2 94 0A JP NZ,FNDTOK ; Not there - keep looking +1729 0A9E E6 7F OUTWRD: AND 01111111B ; Strip bit 7 +1730 0AA0 CD 1B 0A CALL OUTC ; Output first character +1731 0AA3 1A LD A,(DE) ; Get next character +1732 0AA4 13 INC DE ; Move on to next +1733 0AA5 B7 OR A ; Is it end of word? +1734 0AA6 F2 9E 0A JP P,OUTWRD ; No - output the rest +1735 0AA9 C3 85 0A JP LSTLP3 ; Next byte in line +1736 0AAC +1737 0AAC E5 SETLIN: PUSH HL ; Set up LINES counter +1738 0AAD 2A F8 30 LD HL,(LINESN) ; Get LINES number +1739 0AB0 22 F6 30 LD (LINESC),HL ; Save in LINES counter +1740 0AB3 E1 POP HL +1741 0AB4 C9 RET +1742 0AB5 +1743 0AB5 E5 COUNT: PUSH HL ; Save code string address +1744 0AB6 D5 PUSH DE +1745 0AB7 2A F6 30 LD HL,(LINESC) ; Get LINES counter +1746 0ABA 11 FF FF LD DE,-1 +1747 0ABD ED 5A ADC HL,DE ; Decrement +1748 0ABF 22 F6 30 LD (LINESC),HL ; Put it back +1749 0AC2 D1 POP DE +1750 0AC3 E1 POP HL ; Restore code string address +1751 0AC4 F0 RET P ; Return if more lines to go +1752 0AC5 E5 PUSH HL ; Save code string address +1753 0AC6 2A F8 30 LD HL,(LINESN) ; Get LINES number +1754 0AC9 22 F6 30 LD (LINESC),HL ; Reset LINES counter +1755 0ACC CD 9F 1E CALL GETINP ; Get input character +1756 0ACF FE 03 CP CTRLC ; Is it control "C"? +1757 0AD1 CA D8 0A JP Z,RSLNBK ; Yes - Reset LINES and break +1758 0AD4 E1 POP HL ; Restore code string address +1759 0AD5 C3 B5 0A JP COUNT ; Keep on counting +1760 0AD8 +1761 0AD8 2A F8 30 RSLNBK: LD HL,(LINESN) ; Get LINES number +1762 0ADB 22 F6 30 LD (LINESC),HL ; Reset LINES counter +1763 0ADE C3 3C 04 JP BRKRET ; Go and output "Break" +1764 0AE1 +1765 0AE1 3E 64 FOR: LD A,64H ; Flag "FOR" assignment +1766 0AE3 32 7B 31 LD (FORFLG),A ; Save "FOR" flag +1767 0AE6 CD 48 0D CALL LET ; Set up initial index +1768 0AE9 C1 POP BC ; Drop RETurn address +1769 0AEA E5 PUSH HL ; Save code string address +1770 0AEB CD 31 0D CALL DATA ; Get next statement address +1771 0AEE 22 77 31 LD (LOOPST),HL ; Save it for start of loop +1772 0AF1 21 02 00 LD HL,2 ; Offset for "FOR" block +1773 0AF4 39 ADD HL,SP ; Point to it +1774 0AF5 CD EF 06 FORSLP: CALL LOKFOR ; Look for existing "FOR" block +1775 0AF8 D1 POP DE ; Get code string address +1776 0AF9 C2 11 0B JP NZ,FORFND ; No nesting found +1777 0AFC 09 ADD HL,BC ; Move into "FOR" block +1778 0AFD D5 PUSH DE ; Save code string address +1779 0AFE 2B DEC HL +1780 0AFF 56 LD D,(HL) ; Get MSB of loop statement +1781 0B00 2B DEC HL +1782 0B01 5E LD E,(HL) ; Get LSB of loop statement +1783 0B02 23 INC HL +1784 0B03 23 INC HL +1785 0B04 E5 PUSH HL ; Save block address +1786 0B05 2A 77 31 LD HL,(LOOPST) ; Get address of loop statement +1787 0B08 CD 0A 0A CALL CPDEHL ; Compare the FOR loops +1788 0B0B E1 POP HL ; Restore block address +1789 0B0C C2 F5 0A JP NZ,FORSLP ; Different FORs - Find another +1790 0B0F D1 POP DE ; Restore code string address +1791 0B10 F9 LD SP,HL ; Remove all nested loops +1792 0B11 +1793 0B11 EB FORFND: EX DE,HL ; Code string address to HL +1794 0B12 0E 08 LD C,8 +1795 0B14 CD 1F 07 CALL CHKSTK ; Check for 8 levels of stack +1796 0B17 E5 PUSH HL ; Save code string address +1797 0B18 2A 77 31 LD HL,(LOOPST) ; Get first statement of loop +1798 0B1B E3 EX (SP),HL ; Save and restore code string +1799 0B1C E5 PUSH HL ; Re-save code string address +1800 0B1D 2A 0C 31 LD HL,(LINEAT) ; Get current line number +1801 0B20 E3 EX (SP),HL ; Save and restore code string +1802 0B21 CD 0A 10 CALL TSTNUM ; Make sure it's a number +1803 0B24 CD 10 0A CALL CHKSYN ; Make sure "TO" is next +1804 0B27 A6 .BYTE ZTO ; "TO" token +1805 0B28 CD 07 10 CALL GETNUM ; Get "TO" expression value +1806 0B2B E5 PUSH HL ; Save code string address +1807 0B2C CD 35 1A CALL BCDEFP ; Move "TO" value to BCDE +1808 0B2F E1 POP HL ; Restore code string address +1809 0B30 C5 PUSH BC ; Save "TO" value in block +1810 0B31 D5 PUSH DE +1811 0B32 01 00 81 LD BC,8100H ; BCDE - 1 (default STEP) +1812 0B35 51 LD D,C ; C=0 +1813 0B36 5A LD E,D ; D=0 +1814 0B37 7E LD A,(HL) ; Get next byte in code string +1815 0B38 FE AB CP ZSTEP ; See if "STEP" is stated +1816 0B3A 3E 01 LD A,1 ; Sign of step = 1 +1817 0B3C C2 4D 0B JP NZ,SAVSTP ; No STEP given - Default to 1 +1818 0B3F CD 9A 0B CALL GETCHR ; Jump over "STEP" token +1819 0B42 CD 07 10 CALL GETNUM ; Get step value +1820 0B45 E5 PUSH HL ; Save code string address +1821 0B46 CD 35 1A CALL BCDEFP ; Move STEP to BCDE +1822 0B49 CD E9 19 CALL TSTSGN ; Test sign of FPREG +1823 0B4C E1 POP HL ; Restore code string address +1824 0B4D C5 SAVSTP: PUSH BC ; Save the STEP value in block +1825 0B4E D5 PUSH DE +1826 0B4F F5 PUSH AF ; Save sign of STEP +1827 0B50 33 INC SP ; Don't save flags +1828 0B51 E5 PUSH HL ; Save code string address +1829 0B52 2A 7E 31 LD HL,(BRKLIN) ; Get address of index variable +1830 0B55 E3 EX (SP),HL ; Save and restore code string +1831 0B56 06 81 PUTFID: LD B,ZFOR ; "FOR" block marker +1832 0B58 C5 PUSH BC ; Save it +1833 0B59 33 INC SP ; Don't save C +1834 0B5A +1835 0B5A CD C5 0B RUNCNT: CALL TSTBRK ; Execution driver - Test break +1836 0B5D 22 7E 31 LD (BRKLIN),HL ; Save code address for break +1837 0B60 7E LD A,(HL) ; Get next byte in code string +1838 0B61 FE 3A CP ':' ; Multi statement line? +1839 0B63 CA 7A 0B JP Z,EXCUTE ; Yes - Execute it +1840 0B66 B7 OR A ; End of line? +1841 0B67 C2 42 07 JP NZ,SNERR ; No - Syntax error +1842 0B6A 23 INC HL ; Point to address of next line +1843 0B6B 7E LD A,(HL) ; Get LSB of line pointer +1844 0B6C 23 INC HL +1845 0B6D B6 OR (HL) ; Is it zero (End of prog)? +1846 0B6E CA EC 0B JP Z,ENDPRG ; Yes - Terminate execution +1847 0B71 23 INC HL ; Point to line number +1848 0B72 5E LD E,(HL) ; Get LSB of line number +1849 0B73 23 INC HL +1850 0B74 56 LD D,(HL) ; Get MSB of line number +1851 0B75 EB EX DE,HL ; Line number to HL +1852 0B76 22 0C 31 LD (LINEAT),HL ; Save as current line number +1853 0B79 EB EX DE,HL ; Line number back to DE +1854 0B7A CD 9A 0B EXCUTE: CALL GETCHR ; Get key word +1855 0B7D 11 5A 0B LD DE,RUNCNT ; Where to RETurn to +1856 0B80 D5 PUSH DE ; Save for RETurn +1857 0B81 C8 IFJMP: RET Z ; Go to RUNCNT if end of STMT +1858 0B82 D6 80 ONJMP: SUB ZEND ; Is it a token? +1859 0B84 DA 48 0D JP C,LET ; No - try to assign it +1860 0B87 FE 25 CP ZNEW+1-ZEND ; END to NEW ? +1861 0B89 D2 42 07 JP NC,SNERR ; Not a key word - ?SN Error +1862 0B8C 07 RLCA ; Double it +1863 0B8D 4F LD C,A ; BC = Offset into table +1864 0B8E 06 00 LD B,0 +1865 0B90 EB EX DE,HL ; Save code string address +1866 0B91 21 EA 05 LD HL,WORDTB ; Keyword address table +1867 0B94 09 ADD HL,BC ; Point to routine address +1868 0B95 4E LD C,(HL) ; Get LSB of routine address +1869 0B96 23 INC HL +1870 0B97 46 LD B,(HL) ; Get MSB of routine address +1871 0B98 C5 PUSH BC ; Save routine address +1872 0B99 EB EX DE,HL ; Restore code string address +1873 0B9A +1874 0B9A 23 GETCHR: INC HL ; Point to next character +1875 0B9B 7E LD A,(HL) ; Get next code string byte +1876 0B9C FE 3A CP ':' ; Z if ':' +1877 0B9E D0 RET NC ; NC if > "9" +1878 0B9F FE 20 CP ' ' +1879 0BA1 CA 9A 0B JP Z,GETCHR ; Skip over spaces +1880 0BA4 FE 30 CP '0' +1881 0BA6 3F CCF ; NC if < '0' +1882 0BA7 3C INC A ; Test for zero - Leave carry +1883 0BA8 3D DEC A ; Z if Null +1884 0BA9 C9 RET +1885 0BAA +1886 0BAA EB RESTOR: EX DE,HL ; Save code string address +1887 0BAB 2A 0E 31 LD HL,(BASTXT) ; Point to start of program +1888 0BAE CA BF 0B JP Z,RESTNL ; Just RESTORE - reset pointer +1889 0BB1 EB EX DE,HL ; Restore code string address +1890 0BB2 CD 66 0C CALL ATOH ; Get line number to DE +1891 0BB5 E5 PUSH HL ; Save code string address +1892 0BB6 CD 2E 08 CALL SRCHLN ; Search for line number in DE +1893 0BB9 60 LD H,B ; HL = Address of line +1894 0BBA 69 LD L,C +1895 0BBB D1 POP DE ; Restore code string address +1896 0BBC D2 07 0D JP NC,ULERR ; ?UL Error if not found +1897 0BBF 2B RESTNL: DEC HL ; Byte before DATA statement +1898 0BC0 22 8C 31 UPDATA: LD (NXTDAT),HL ; Update DATA pointer +1899 0BC3 EB EX DE,HL ; Restore code string address +1900 0BC4 C9 RET +1901 0BC5 +1902 0BC5 +1903 0BC5 DF TSTBRK: RST 18H ; Check input status +1904 0BC6 C8 RET Z ; No key, go back +1905 0BC7 D7 RST 10H ; Get the key into A +1906 0BC8 FE 1B CP ESC ; Escape key? +1907 0BCA 28 11 JR Z,BRK ; Yes, break +1908 0BCC FE 03 CP CTRLC ; +1909 0BCE 28 0D JR Z,BRK ; Yes, break +1910 0BD0 FE 13 CP CTRLS ; Stop scrolling? +1911 0BD2 C0 RET NZ ; Other key, ignore +1912 0BD3 +1913 0BD3 +1914 0BD3 D7 STALL: RST 10H ; Wait for key +1915 0BD4 FE 11 CP CTRLQ ; Resume scrolling? +1916 0BD6 C8 RET Z ; Release the chokehold +1917 0BD7 FE 03 CP CTRLC ; Second break? +1918 0BD9 28 07 JR Z,STOP ; Break during hold exits prog +1919 0BDB 18 F6 JR STALL ; Loop until or +1920 0BDD +1921 0BDD 3E FF BRK LD A,$FF ; Set BRKFLG +1922 0BDF 32 FD 30 LD (BRKFLG),A ; Store it +1923 0BE2 +1924 0BE2 +1925 0BE2 C0 STOP: RET NZ ; Exit if anything else +1926 0BE3 F6 .BYTE 0F6H ; Flag "STOP" +1927 0BE4 C0 PEND: RET NZ ; Exit if anything else +1928 0BE5 22 7E 31 LD (BRKLIN),HL ; Save point of break +1929 0BE8 21 .BYTE 21H ; Skip "OR 11111111B" +1930 0BE9 F6 FF INPBRK: OR 11111111B ; Flag "Break" wanted +1931 0BEB C1 POP BC ; Return not needed and more +1932 0BEC 2A 0C 31 ENDPRG: LD HL,(LINEAT) ; Get current line number +1933 0BEF F5 PUSH AF ; Save STOP / END status +1934 0BF0 7D LD A,L ; Is it direct break? +1935 0BF1 A4 AND H +1936 0BF2 3C INC A ; Line is -1 if direct break +1937 0BF3 CA FF 0B JP Z,NOLIN ; Yes - No line number +1938 0BF6 22 82 31 LD (ERRLIN),HL ; Save line of break +1939 0BF9 2A 7E 31 LD HL,(BRKLIN) ; Get point of break +1940 0BFC 22 84 31 LD (CONTAD),HL ; Save point to CONTinue +1941 0BFF AF NOLIN: XOR A +1942 0C00 32 F5 30 LD (CTLOFG),A ; Enable output +1943 0C03 CD 35 0E CALL STTLIN ; Start a new line +1944 0C06 F1 POP AF ; Restore STOP / END status +1945 0C07 21 E5 06 LD HL,BRKMSG ; "Break" message +1946 0C0A C2 76 07 JP NZ,ERRIN ; "in line" wanted? +1947 0C0D C3 8D 07 JP PRNTOK ; Go to command mode +1948 0C10 +1949 0C10 2A 84 31 CONT: LD HL,(CONTAD) ; Get CONTinue address +1950 0C13 7C LD A,H ; Is it zero? +1951 0C14 B5 OR L +1952 0C15 1E 20 LD E,CN ; ?CN Error +1953 0C17 CA 56 07 JP Z,ERROR ; Yes - output "?CN Error" +1954 0C1A EB EX DE,HL ; Save code string address +1955 0C1B 2A 82 31 LD HL,(ERRLIN) ; Get line of last break +1956 0C1E 22 0C 31 LD (LINEAT),HL ; Set up current line number +1957 0C21 EB EX DE,HL ; Restore code string address +1958 0C22 C9 RET ; CONTinue where left off +1959 0C23 +1960 0C23 CD 68 17 NULL: CALL GETINT ; Get integer 0-255 +1961 0C26 C0 RET NZ ; Return if bad value +1962 0C27 32 F1 30 LD (NULLS),A ; Set nulls number +1963 0C2A C9 RET +1964 0C2B +1965 0C2B +1966 0C2B E5 ACCSUM: PUSH HL ; Save address in array +1967 0C2C 2A FA 30 LD HL,(CHKSUM) ; Get check sum +1968 0C2F 06 00 LD B,0 ; BC - Value of byte +1969 0C31 4F LD C,A +1970 0C32 09 ADD HL,BC ; Add byte to check sum +1971 0C33 22 FA 30 LD (CHKSUM),HL ; Re-save check sum +1972 0C36 E1 POP HL ; Restore address in array +1973 0C37 C9 RET +1974 0C38 +1975 0C38 7E CHKLTR: LD A,(HL) ; Get byte +1976 0C39 FE 41 CP 'A' ; < 'a' ? +1977 0C3B D8 RET C ; Carry set if not letter +1978 0C3C FE 5B CP 'Z'+1 ; > 'z' ? +1979 0C3E 3F CCF +1980 0C3F C9 RET ; Carry set if not letter +1981 0C40 +1982 0C40 CD 9A 0B FPSINT: CALL GETCHR ; Get next character +1983 0C43 CD 07 10 POSINT: CALL GETNUM ; Get integer 0 to 32767 +1984 0C46 CD E9 19 DEPINT: CALL TSTSGN ; Test sign of FPREG +1985 0C49 FA 61 0C JP M,FCERR ; Negative - ?FC Error +1986 0C4C 3A 97 31 DEINT: LD A,(FPEXP) ; Get integer value to DE +1987 0C4F FE 90 CP 80H+16 ; Exponent in range (16 bits)? +1988 0C51 DA 91 1A JP C,FPINT ; Yes - convert it +1989 0C54 01 80 90 LD BC,9080H ; BCDE = -32768 +1990 0C57 11 00 00 LD DE,0000 +1991 0C5A E5 PUSH HL ; Save code string address +1992 0C5B CD 64 1A CALL CMPNUM ; Compare FPREG with BCDE +1993 0C5E E1 POP HL ; Restore code string address +1994 0C5F 51 LD D,C ; MSB to D +1995 0C60 C8 RET Z ; Return if in range +1996 0C61 1E 08 FCERR: LD E,FC ; ?FC Error +1997 0C63 C3 56 07 JP ERROR ; Output error- +1998 0C66 +1999 0C66 2B ATOH: DEC HL ; ASCII number to DE binary +2000 0C67 11 00 00 GETLN: LD DE,0 ; Get number to DE +2001 0C6A CD 9A 0B GTLNLP: CALL GETCHR ; Get next character +2002 0C6D D0 RET NC ; Exit if not a digit +2003 0C6E E5 PUSH HL ; Save code string address +2004 0C6F F5 PUSH AF ; Save digit +2005 0C70 21 98 19 LD HL,65529/10 ; Largest number 65529 +2006 0C73 CD 0A 0A CALL CPDEHL ; Number in range? +2007 0C76 DA 42 07 JP C,SNERR ; No - ?SN Error +2008 0C79 62 LD H,D ; HL = Number +2009 0C7A 6B LD L,E +2010 0C7B 19 ADD HL,DE ; Times 2 +2011 0C7C 29 ADD HL,HL ; Times 4 +2012 0C7D 19 ADD HL,DE ; Times 5 +2013 0C7E 29 ADD HL,HL ; Times 10 +2014 0C7F F1 POP AF ; Restore digit +2015 0C80 D6 30 SUB '0' ; Make it 0 to 9 +2016 0C82 5F LD E,A ; DE = Value of digit +2017 0C83 16 00 LD D,0 +2018 0C85 19 ADD HL,DE ; Add to number +2019 0C86 EB EX DE,HL ; Number to DE +2020 0C87 E1 POP HL ; Restore code string address +2021 0C88 C3 6A 0C JP GTLNLP ; Go to next character +2022 0C8B +2023 0C8B CA 5E 08 CLEAR: JP Z,INTVAR ; Just "CLEAR" Keep parameters +2024 0C8E CD 43 0C CALL POSINT ; Get integer 0 to 32767 to DE +2025 0C91 2B DEC HL ; Cancel increment +2026 0C92 CD 9A 0B CALL GETCHR ; Get next character +2027 0C95 E5 PUSH HL ; Save code string address +2028 0C96 2A 5F 31 LD HL,(LSTRAM) ; Get end of RAM +2029 0C99 CA AE 0C JP Z,STORED ; No value given - Use stored +2030 0C9C E1 POP HL ; Restore code string address +2031 0C9D CD 10 0A CALL CHKSYN ; Check for comma +2032 0CA0 2C .BYTE ',' +2033 0CA1 D5 PUSH DE ; Save number +2034 0CA2 CD 43 0C CALL POSINT ; Get integer 0 to 32767 +2035 0CA5 2B DEC HL ; Cancel increment +2036 0CA6 CD 9A 0B CALL GETCHR ; Get next character +2037 0CA9 C2 42 07 JP NZ,SNERR ; ?SN Error if more on line +2038 0CAC E3 EX (SP),HL ; Save code string address +2039 0CAD EB EX DE,HL ; Number to DE +2040 0CAE 7D STORED: LD A,L ; Get LSB of new RAM top +2041 0CAF 93 SUB E ; Subtract LSB of string space +2042 0CB0 5F LD E,A ; Save LSB +2043 0CB1 7C LD A,H ; Get MSB of new RAM top +2044 0CB2 9A SBC A,D ; Subtract MSB of string space +2045 0CB3 57 LD D,A ; Save MSB +2046 0CB4 DA 37 07 JP C,OMERR ; ?OM Error if not enough mem +2047 0CB7 E5 PUSH HL ; Save RAM top +2048 0CB8 2A 86 31 LD HL,(PROGND) ; Get program end +2049 0CBB 01 28 00 LD BC,40 ; 40 Bytes minimum working RAM +2050 0CBE 09 ADD HL,BC ; Get lowest address +2051 0CBF CD 0A 0A CALL CPDEHL ; Enough memory? +2052 0CC2 D2 37 07 JP NC,OMERR ; No - ?OM Error +2053 0CC5 EB EX DE,HL ; RAM top to HL +2054 0CC6 22 0A 31 LD (STRSPC),HL ; Set new string space +2055 0CC9 E1 POP HL ; End of memory to use +2056 0CCA 22 5F 31 LD (LSTRAM),HL ; Set new top of RAM +2057 0CCD E1 POP HL ; Restore code string address +2058 0CCE C3 5E 08 JP INTVAR ; Initialise variables +2059 0CD1 +2060 0CD1 CA 5A 08 RUN: JP Z,RUNFST ; RUN from start if just RUN +2061 0CD4 CD 5E 08 CALL INTVAR ; Initialise variables +2062 0CD7 01 5A 0B LD BC,RUNCNT ; Execution driver loop +2063 0CDA C3 ED 0C JP RUNLIN ; RUN from line number +2064 0CDD +2065 0CDD 0E 03 GOSUB: LD C,3 ; 3 Levels of stack needed +2066 0CDF CD 1F 07 CALL CHKSTK ; Check for 3 levels of stack +2067 0CE2 C1 POP BC ; Get return address +2068 0CE3 E5 PUSH HL ; Save code string for RETURN +2069 0CE4 E5 PUSH HL ; And for GOSUB routine +2070 0CE5 2A 0C 31 LD HL,(LINEAT) ; Get current line +2071 0CE8 E3 EX (SP),HL ; Into stack - Code string out +2072 0CE9 3E 8C LD A,ZGOSUB ; "GOSUB" token +2073 0CEB F5 PUSH AF ; Save token +2074 0CEC 33 INC SP ; Don't save flags +2075 0CED +2076 0CED C5 RUNLIN: PUSH BC ; Save return address +2077 0CEE CD 66 0C GOTO: CALL ATOH ; ASCII number to DE binary +2078 0CF1 CD 33 0D CALL REM ; Get end of line +2079 0CF4 E5 PUSH HL ; Save end of line +2080 0CF5 2A 0C 31 LD HL,(LINEAT) ; Get current line +2081 0CF8 CD 0A 0A CALL CPDEHL ; Line after current? +2082 0CFB E1 POP HL ; Restore end of line +2083 0CFC 23 INC HL ; Start of next line +2084 0CFD DC 31 08 CALL C,SRCHLP ; Line is after current line +2085 0D00 D4 2E 08 CALL NC,SRCHLN ; Line is before current line +2086 0D03 60 LD H,B ; Set up code string address +2087 0D04 69 LD L,C +2088 0D05 2B DEC HL ; Incremented after +2089 0D06 D8 RET C ; Line found +2090 0D07 1E 0E ULERR: LD E,UL ; ?UL Error +2091 0D09 C3 56 07 JP ERROR ; Output error message +2092 0D0C +2093 0D0C C0 RETURN: RET NZ ; Return if not just RETURN +2094 0D0D 16 FF LD D,-1 ; Flag "GOSUB" search +2095 0D0F CD EB 06 CALL BAKSTK ; Look "GOSUB" block +2096 0D12 F9 LD SP,HL ; Kill all FORs in subroutine +2097 0D13 FE 8C CP ZGOSUB ; Test for "GOSUB" token +2098 0D15 1E 04 LD E,RG ; ?RG Error +2099 0D17 C2 56 07 JP NZ,ERROR ; Error if no "GOSUB" found +2100 0D1A E1 POP HL ; Get RETURN line number +2101 0D1B 22 0C 31 LD (LINEAT),HL ; Save as current +2102 0D1E 23 INC HL ; Was it from direct statement? +2103 0D1F 7C LD A,H +2104 0D20 B5 OR L ; Return to line +2105 0D21 C2 2B 0D JP NZ,RETLIN ; No - Return to line +2106 0D24 3A 7C 31 LD A,(LSTBIN) ; Any INPUT in subroutine? +2107 0D27 B7 OR A ; If so buffer is corrupted +2108 0D28 C2 8C 07 JP NZ,POPNOK ; Yes - Go to command mode +2109 0D2B 21 5A 0B RETLIN: LD HL,RUNCNT ; Execution driver loop +2110 0D2E E3 EX (SP),HL ; Into stack - Code string out +2111 0D2F 3E .BYTE 3EH ; Skip "POP HL" +2112 0D30 E1 NXTDTA: POP HL ; Restore code string address +2113 0D31 +2114 0D31 01 3A DATA: .BYTE 01H,3AH ; ':' End of statement +2115 0D33 0E 00 REM: LD C,0 ; 00 End of statement +2116 0D35 06 00 LD B,0 +2117 0D37 79 NXTSTL: LD A,C ; Statement and byte +2118 0D38 48 LD C,B +2119 0D39 47 LD B,A ; Statement end byte +2120 0D3A 7E NXTSTT: LD A,(HL) ; Get byte +2121 0D3B B7 OR A ; End of line? +2122 0D3C C8 RET Z ; Yes - Exit +2123 0D3D B8 CP B ; End of statement? +2124 0D3E C8 RET Z ; Yes - Exit +2125 0D3F 23 INC HL ; Next byte +2126 0D40 FE 22 CP '"' ; Literal string? +2127 0D42 CA 37 0D JP Z,NXTSTL ; Yes - Look for another '"' +2128 0D45 C3 3A 0D JP NXTSTT ; Keep looking +2129 0D48 +2130 0D48 CD FD 11 LET: CALL GETVAR ; Get variable name +2131 0D4B CD 10 0A CALL CHKSYN ; Make sure "=" follows +2132 0D4E B4 .BYTE ZEQUAL ; "=" token +2133 0D4F D5 PUSH DE ; Save address of variable +2134 0D50 3A 5D 31 LD A,(TYPE) ; Get data type +2135 0D53 F5 PUSH AF ; Save type +2136 0D54 CD 19 10 CALL EVAL ; Evaluate expression +2137 0D57 F1 POP AF ; Restore type +2138 0D58 E3 EX (SP),HL ; Save code - Get var addr +2139 0D59 22 7E 31 LD (BRKLIN),HL ; Save address of variable +2140 0D5C 1F RRA ; Adjust type +2141 0D5D CD 0C 10 CALL CHKTYP ; Check types are the same +2142 0D60 CA 9B 0D JP Z,LETNUM ; Numeric - Move value +2143 0D63 E5 LETSTR: PUSH HL ; Save address of string var +2144 0D64 2A 94 31 LD HL,(FPREG) ; Pointer to string entry +2145 0D67 E5 PUSH HL ; Save it on stack +2146 0D68 23 INC HL ; Skip over length +2147 0D69 23 INC HL +2148 0D6A 5E LD E,(HL) ; LSB of string address +2149 0D6B 23 INC HL +2150 0D6C 56 LD D,(HL) ; MSB of string address +2151 0D6D 2A 0E 31 LD HL,(BASTXT) ; Point to start of program +2152 0D70 CD 0A 0A CALL CPDEHL ; Is string before program? +2153 0D73 D2 8A 0D JP NC,CRESTR ; Yes - Create string entry +2154 0D76 2A 0A 31 LD HL,(STRSPC) ; Point to string space +2155 0D79 CD 0A 0A CALL CPDEHL ; Is string literal in program? +2156 0D7C D1 POP DE ; Restore address of string +2157 0D7D D2 92 0D JP NC,MVSTPT ; Yes - Set up pointer +2158 0D80 21 6F 31 LD HL,TMPSTR ; Temporary string pool +2159 0D83 CD 0A 0A CALL CPDEHL ; Is string in temporary pool? +2160 0D86 D2 92 0D JP NC,MVSTPT ; No - Set up pointer +2161 0D89 3E .BYTE 3EH ; Skip "POP DE" +2162 0D8A D1 CRESTR: POP DE ; Restore address of string +2163 0D8B CD 41 16 CALL BAKTMP ; Back to last tmp-str entry +2164 0D8E EB EX DE,HL ; Address of string entry +2165 0D8F CD 7A 14 CALL SAVSTR ; Save string in string area +2166 0D92 CD 41 16 MVSTPT: CALL BAKTMP ; Back to last tmp-str entry +2167 0D95 E1 POP HL ; Get string pointer +2168 0D96 CD 44 1A CALL DETHL4 ; Move string pointer to var +2169 0D99 E1 POP HL ; Restore code string address +2170 0D9A C9 RET +2171 0D9B +2172 0D9B E5 LETNUM: PUSH HL ; Save address of variable +2173 0D9C CD 41 1A CALL FPTHL ; Move value to variable +2174 0D9F D1 POP DE ; Restore address of variable +2175 0DA0 E1 POP HL ; Restore code string address +2176 0DA1 C9 RET +2177 0DA2 +2178 0DA2 CD 68 17 ON: CALL GETINT ; Get integer 0-255 +2179 0DA5 7E LD A,(HL) ; Get "GOTO" or "GOSUB" token +2180 0DA6 47 LD B,A ; Save in B +2181 0DA7 FE 8C CP ZGOSUB ; "GOSUB" token? +2182 0DA9 CA B1 0D JP Z,ONGO ; Yes - Find line number +2183 0DAC CD 10 0A CALL CHKSYN ; Make sure it's "GOTO" +2184 0DAF 88 .BYTE ZGOTO ; "GOTO" token +2185 0DB0 2B DEC HL ; Cancel increment +2186 0DB1 4B ONGO: LD C,E ; Integer of branch value +2187 0DB2 0D ONGOLP: DEC C ; Count branches +2188 0DB3 78 LD A,B ; Get "GOTO" or "GOSUB" token +2189 0DB4 CA 82 0B JP Z,ONJMP ; Go to that line if right one +2190 0DB7 CD 67 0C CALL GETLN ; Get line number to DE +2191 0DBA FE 2C CP ',' ; Another line number? +2192 0DBC C0 RET NZ ; No - Drop through +2193 0DBD C3 B2 0D JP ONGOLP ; Yes - loop +2194 0DC0 +2195 0DC0 CD 19 10 IF: CALL EVAL ; Evaluate expression +2196 0DC3 7E LD A,(HL) ; Get token +2197 0DC4 FE 88 CP ZGOTO ; "GOTO" token? +2198 0DC6 CA CE 0D JP Z,IFGO ; Yes - Get line +2199 0DC9 CD 10 0A CALL CHKSYN ; Make sure it's "THEN" +2200 0DCC A9 .BYTE ZTHEN ; "THEN" token +2201 0DCD 2B DEC HL ; Cancel increment +2202 0DCE CD 0A 10 IFGO: CALL TSTNUM ; Make sure it's numeric +2203 0DD1 CD E9 19 CALL TSTSGN ; Test state of expression +2204 0DD4 CA 33 0D JP Z,REM ; False - Drop through +2205 0DD7 CD 9A 0B CALL GETCHR ; Get next character +2206 0DDA DA EE 0C JP C,GOTO ; Number - GOTO that line +2207 0DDD C3 81 0B JP IFJMP ; Otherwise do statement +2208 0DE0 +2209 0DE0 2B MRPRNT: DEC HL ; DEC 'cos GETCHR INCs +2210 0DE1 CD 9A 0B CALL GETCHR ; Get next character +2211 0DE4 CA 42 0E PRINT: JP Z,PRNTCRLF ; CRLF if just PRINT +2212 0DE7 C8 PRNTLP: RET Z ; End of list - Exit +2213 0DE8 FE A5 CP ZTAB ; "TAB(" token? +2214 0DEA CA 75 0E JP Z,DOTAB ; Yes - Do TAB routine +2215 0DED FE A8 CP ZSPC ; "SPC(" token? +2216 0DEF CA 75 0E JP Z,DOTAB ; Yes - Do SPC routine +2217 0DF2 E5 PUSH HL ; Save code string address +2218 0DF3 FE 2C CP ',' ; Comma? +2219 0DF5 CA 5E 0E JP Z,DOCOM ; Yes - Move to next zone +2220 0DF8 FE 3B CP 59 ;";" ; Semi-colon? +2221 0DFA CA 98 0E JP Z,NEXITM ; Do semi-colon routine +2222 0DFD C1 POP BC ; Code string address to BC +2223 0DFE CD 19 10 CALL EVAL ; Evaluate expression +2224 0E01 E5 PUSH HL ; Save code string address +2225 0E02 3A 5D 31 LD A,(TYPE) ; Get variable type +2226 0E05 B7 OR A ; Is it a string variable? +2227 0E06 C2 2E 0E JP NZ,PRNTST ; Yes - Output string contents +2228 0E09 CD 8E 1B CALL NUMASC ; Convert number to text +2229 0E0C CD 9E 14 CALL CRTST ; Create temporary string +2230 0E0F 36 20 LD (HL),' ' ; Followed by a space +2231 0E11 2A 94 31 LD HL,(FPREG) ; Get length of output +2232 0E14 34 INC (HL) ; Plus 1 for the space +2233 0E15 2A 94 31 LD HL,(FPREG) ; < Not needed > +2234 0E18 3A F2 30 LD A,(LWIDTH) ; Get width of line +2235 0E1B 47 LD B,A ; To B +2236 0E1C 04 INC B ; Width 255 (No limit)? +2237 0E1D CA 2A 0E JP Z,PRNTNB ; Yes - Output number string +2238 0E20 04 INC B ; Adjust it +2239 0E21 3A 5B 31 LD A,(CURPOS) ; Get cursor position +2240 0E24 86 ADD A,(HL) ; Add length of string +2241 0E25 3D DEC A ; Adjust it +2242 0E26 B8 CP B ; Will output fit on this line? +2243 0E27 D4 42 0E CALL NC,PRNTCRLF ; No - CRLF first +2244 0E2A CD E3 14 PRNTNB: CALL PRS1 ; Output string at (HL) +2245 0E2D AF XOR A ; Skip CALL by setting 'z' flag +2246 0E2E C4 E3 14 PRNTST: CALL NZ,PRS1 ; Output string at (HL) +2247 0E31 E1 POP HL ; Restore code string address +2248 0E32 C3 E0 0D JP MRPRNT ; See if more to PRINT +2249 0E35 +2250 0E35 3A 5B 31 STTLIN: LD A,(CURPOS) ; Make sure on new line +2251 0E38 B7 OR A ; Already at start? +2252 0E39 C8 RET Z ; Yes - Do nothing +2253 0E3A C3 42 0E JP PRNTCRLF ; Start a new line +2254 0E3D +2255 0E3D 36 00 ENDINP: LD (HL),0 ; Mark end of buffer +2256 0E3F 21 10 31 LD HL,BUFFER-1 ; Point to buffer +2257 0E42 3E 0D PRNTCRLF: LD A,CR ; Load a CR +2258 0E44 CD 1B 0A CALL OUTC ; Output character +2259 0E47 3E 0A LD A,LF ; Load a LF +2260 0E49 CD 1B 0A CALL OUTC ; Output character +2261 0E4C AF DONULL: XOR A ; Set to position 0 +2262 0E4D 32 5B 31 LD (CURPOS),A ; Store it +2263 0E50 3A F1 30 LD A,(NULLS) ; Get number of nulls +2264 0E53 3D NULLP: DEC A ; Count them +2265 0E54 C8 RET Z ; Return if done +2266 0E55 F5 PUSH AF ; Save count +2267 0E56 AF XOR A ; Load a null +2268 0E57 CD 1B 0A CALL OUTC ; Output it +2269 0E5A F1 POP AF ; Restore count +2270 0E5B C3 53 0E JP NULLP ; Keep counting +2271 0E5E +2272 0E5E 3A F3 30 DOCOM: LD A,(COMMAN) ; Get comma width +2273 0E61 47 LD B,A ; Save in B +2274 0E62 3A 5B 31 LD A,(CURPOS) ; Get current position +2275 0E65 B8 CP B ; Within the limit? +2276 0E66 D4 42 0E CALL NC,PRNTCRLF ; No - output CRLF +2277 0E69 D2 98 0E JP NC,NEXITM ; Get next item +2278 0E6C D6 0E ZONELP: SUB 14 ; Next zone of 14 characters +2279 0E6E D2 6C 0E JP NC,ZONELP ; Repeat if more zones +2280 0E71 2F CPL ; Number of spaces to output +2281 0E72 C3 8D 0E JP ASPCS ; Output them +2282 0E75 +2283 0E75 F5 DOTAB: PUSH AF ; Save token +2284 0E76 CD 65 17 CALL FNDNUM ; Evaluate expression +2285 0E79 CD 10 0A CALL CHKSYN ; Make sure ")" follows +2286 0E7C 29 .BYTE ")" +2287 0E7D 2B DEC HL ; Back space on to ")" +2288 0E7E F1 POP AF ; Restore token +2289 0E7F D6 A8 SUB ZSPC ; Was it "SPC(" ? +2290 0E81 E5 PUSH HL ; Save code string address +2291 0E82 CA 88 0E JP Z,DOSPC ; Yes - Do 'E' spaces +2292 0E85 3A 5B 31 LD A,(CURPOS) ; Get current position +2293 0E88 2F DOSPC: CPL ; Number of spaces to print to +2294 0E89 83 ADD A,E ; Total number to print +2295 0E8A D2 98 0E JP NC,NEXITM ; TAB < Current POS(X) +2296 0E8D 3C ASPCS: INC A ; Output A spaces +2297 0E8E 47 LD B,A ; Save number to print +2298 0E8F 3E 20 LD A,' ' ; Space +2299 0E91 CD 1B 0A SPCLP: CALL OUTC ; Output character in A +2300 0E94 05 DEC B ; Count them +2301 0E95 C2 91 0E JP NZ,SPCLP ; Repeat if more +2302 0E98 E1 NEXITM: POP HL ; Restore code string address +2303 0E99 CD 9A 0B CALL GETCHR ; Get next character +2304 0E9C C3 E7 0D JP PRNTLP ; More to print +2305 0E9F +2306 0E9F 3F 52 65 64 REDO: .BYTE "?Redo from start",CR,LF,0 +2306 0EA3 6F 20 66 72 +2306 0EA7 6F 6D 20 73 +2306 0EAB 74 61 72 74 +2306 0EAF 0D 0A 00 +2307 0EB2 +2308 0EB2 3A 7D 31 BADINP: LD A,(READFG) ; READ or INPUT? +2309 0EB5 B7 OR A +2310 0EB6 C2 3C 07 JP NZ,DATSNR ; READ - ?SN Error +2311 0EB9 C1 POP BC ; Throw away code string addr +2312 0EBA 21 9F 0E LD HL,REDO ; "Redo from start" message +2313 0EBD CD E0 14 CALL PRS ; Output string +2314 0EC0 C3 8D 08 JP DOAGN ; Do last INPUT again +2315 0EC3 +2316 0EC3 CD 4B 14 INPUT: CALL IDTEST ; Test for illegal direct +2317 0EC6 7E LD A,(HL) ; Get character after "INPUT" +2318 0EC7 FE 22 CP '"' ; Is there a prompt string? +2319 0EC9 3E 00 LD A,0 ; Clear A and leave flags +2320 0ECB 32 F5 30 LD (CTLOFG),A ; Enable output +2321 0ECE C2 DD 0E JP NZ,NOPMPT ; No prompt - get input +2322 0ED1 CD 9F 14 CALL QTSTR ; Get string terminated by '"' +2323 0ED4 CD 10 0A CALL CHKSYN ; Check for ';' after prompt +2324 0ED7 3B .BYTE ';' +2325 0ED8 E5 PUSH HL ; Save code string address +2326 0ED9 CD E3 14 CALL PRS1 ; Output prompt string +2327 0EDC 3E .BYTE 3EH ; Skip "PUSH HL" +2328 0EDD E5 NOPMPT: PUSH HL ; Save code string address +2329 0EDE CD 91 08 CALL PROMPT ; Get input with "? " prompt +2330 0EE1 C1 POP BC ; Restore code string address +2331 0EE2 DA E9 0B JP C,INPBRK ; Break pressed - Exit +2332 0EE5 23 INC HL ; Next byte +2333 0EE6 7E LD A,(HL) ; Get it +2334 0EE7 B7 OR A ; End of line? +2335 0EE8 2B DEC HL ; Back again +2336 0EE9 C5 PUSH BC ; Re-save code string address +2337 0EEA CA 30 0D JP Z,NXTDTA ; Yes - Find next DATA stmt +2338 0EED 36 2C LD (HL),',' ; Store comma as separator +2339 0EEF C3 F7 0E JP NXTITM ; Get next item +2340 0EF2 +2341 0EF2 E5 READ: PUSH HL ; Save code string address +2342 0EF3 2A 8C 31 LD HL,(NXTDAT) ; Next DATA statement +2343 0EF6 F6 .BYTE 0F6H ; Flag "READ" +2344 0EF7 AF NXTITM: XOR A ; Flag "INPUT" +2345 0EF8 32 7D 31 LD (READFG),A ; Save "READ"/"INPUT" flag +2346 0EFB E3 EX (SP),HL ; Get code str' , Save pointer +2347 0EFC C3 03 0F JP GTVLUS ; Get values +2348 0EFF +2349 0EFF CD 10 0A NEDMOR: CALL CHKSYN ; Check for comma between items +2350 0F02 2C .BYTE ',' +2351 0F03 CD FD 11 GTVLUS: CALL GETVAR ; Get variable name +2352 0F06 E3 EX (SP),HL ; Save code str" , Get pointer +2353 0F07 D5 PUSH DE ; Save variable address +2354 0F08 7E LD A,(HL) ; Get next "INPUT"/"DATA" byte +2355 0F09 FE 2C CP ',' ; Comma? +2356 0F0B CA 2B 0F JP Z,ANTVLU ; Yes - Get another value +2357 0F0E 3A 7D 31 LD A,(READFG) ; Is it READ? +2358 0F11 B7 OR A +2359 0F12 C2 98 0F JP NZ,FDTLP ; Yes - Find next DATA stmt +2360 0F15 3E 3F LD A,'?' ; More INPUT needed +2361 0F17 CD 1B 0A CALL OUTC ; Output character +2362 0F1A CD 91 08 CALL PROMPT ; Get INPUT with prompt +2363 0F1D D1 POP DE ; Variable address +2364 0F1E C1 POP BC ; Code string address +2365 0F1F DA E9 0B JP C,INPBRK ; Break pressed +2366 0F22 23 INC HL ; Point to next DATA byte +2367 0F23 7E LD A,(HL) ; Get byte +2368 0F24 B7 OR A ; Is it zero (No input) ? +2369 0F25 2B DEC HL ; Back space INPUT pointer +2370 0F26 C5 PUSH BC ; Save code string address +2371 0F27 CA 30 0D JP Z,NXTDTA ; Find end of buffer +2372 0F2A D5 PUSH DE ; Save variable address +2373 0F2B 3A 5D 31 ANTVLU: LD A,(TYPE) ; Check data type +2374 0F2E B7 OR A ; Is it numeric? +2375 0F2F CA 55 0F JP Z,INPBIN ; Yes - Convert to binary +2376 0F32 CD 9A 0B CALL GETCHR ; Get next character +2377 0F35 57 LD D,A ; Save input character +2378 0F36 47 LD B,A ; Again +2379 0F37 FE 22 CP '"' ; Start of literal sting? +2380 0F39 CA 49 0F JP Z,STRENT ; Yes - Create string entry +2381 0F3C 3A 7D 31 LD A,(READFG) ; "READ" or "INPUT" ? +2382 0F3F B7 OR A +2383 0F40 57 LD D,A ; Save 00 if "INPUT" +2384 0F41 CA 46 0F JP Z,ITMSEP ; "INPUT" - End with 00 +2385 0F44 16 3A LD D,':' ; "DATA" - End with 00 or ':' +2386 0F46 06 2C ITMSEP: LD B,',' ; Item separator +2387 0F48 2B DEC HL ; Back space for DTSTR +2388 0F49 CD A2 14 STRENT: CALL DTSTR ; Get string terminated by D +2389 0F4C EB EX DE,HL ; String address to DE +2390 0F4D 21 60 0F LD HL,LTSTND ; Where to go after LETSTR +2391 0F50 E3 EX (SP),HL ; Save HL , get input pointer +2392 0F51 D5 PUSH DE ; Save address of string +2393 0F52 C3 63 0D JP LETSTR ; Assign string to variable +2394 0F55 +2395 0F55 CD 9A 0B INPBIN: CALL GETCHR ; Get next character +2396 0F58 CD F0 1A CALL ASCTFP ; Convert ASCII to FP number +2397 0F5B E3 EX (SP),HL ; Save input ptr, Get var addr +2398 0F5C CD 41 1A CALL FPTHL ; Move FPREG to variable +2399 0F5F E1 POP HL ; Restore input pointer +2400 0F60 2B LTSTND: DEC HL ; DEC 'cos GETCHR INCs +2401 0F61 CD 9A 0B CALL GETCHR ; Get next character +2402 0F64 CA 6C 0F JP Z,MORDT ; End of line - More needed? +2403 0F67 FE 2C CP ',' ; Another value? +2404 0F69 C2 B2 0E JP NZ,BADINP ; No - Bad input +2405 0F6C E3 MORDT: EX (SP),HL ; Get code string address +2406 0F6D 2B DEC HL ; DEC 'cos GETCHR INCs +2407 0F6E CD 9A 0B CALL GETCHR ; Get next character +2408 0F71 C2 FF 0E JP NZ,NEDMOR ; More needed - Get it +2409 0F74 D1 POP DE ; Restore DATA pointer +2410 0F75 3A 7D 31 LD A,(READFG) ; "READ" or "INPUT" ? +2411 0F78 B7 OR A +2412 0F79 EB EX DE,HL ; DATA pointer to HL +2413 0F7A C2 C0 0B JP NZ,UPDATA ; Update DATA pointer if "READ" +2414 0F7D D5 PUSH DE ; Save code string address +2415 0F7E B6 OR (HL) ; More input given? +2416 0F7F 21 87 0F LD HL,EXTIG ; "?Extra ignored" message +2417 0F82 C4 E0 14 CALL NZ,PRS ; Output string if extra given +2418 0F85 E1 POP HL ; Restore code string address +2419 0F86 C9 RET +2420 0F87 +2421 0F87 3F 45 78 74 EXTIG: .BYTE "?Extra ignored",CR,LF,0 +2421 0F8B 72 61 20 69 +2421 0F8F 67 6E 6F 72 +2421 0F93 65 64 0D 0A +2421 0F97 00 +2422 0F98 +2423 0F98 CD 31 0D FDTLP: CALL DATA ; Get next statement +2424 0F9B B7 OR A ; End of line? +2425 0F9C C2 B1 0F JP NZ,FANDT ; No - See if DATA statement +2426 0F9F 23 INC HL +2427 0FA0 7E LD A,(HL) ; End of program? +2428 0FA1 23 INC HL +2429 0FA2 B6 OR (HL) ; 00 00 Ends program +2430 0FA3 1E 06 LD E,OD ; ?OD Error +2431 0FA5 CA 56 07 JP Z,ERROR ; Yes - Out of DATA +2432 0FA8 23 INC HL +2433 0FA9 5E LD E,(HL) ; LSB of line number +2434 0FAA 23 INC HL +2435 0FAB 56 LD D,(HL) ; MSB of line number +2436 0FAC EB EX DE,HL +2437 0FAD 22 79 31 LD (DATLIN),HL ; Set line of current DATA item +2438 0FB0 EB EX DE,HL +2439 0FB1 CD 9A 0B FANDT: CALL GETCHR ; Get next character +2440 0FB4 FE 83 CP ZDATA ; "DATA" token +2441 0FB6 C2 98 0F JP NZ,FDTLP ; No "DATA" - Keep looking +2442 0FB9 C3 2B 0F JP ANTVLU ; Found - Convert input +2443 0FBC +2444 0FBC 11 00 00 NEXT: LD DE,0 ; In case no index given +2445 0FBF C4 FD 11 NEXT1: CALL NZ,GETVAR ; Get index address +2446 0FC2 22 7E 31 LD (BRKLIN),HL ; Save code string address +2447 0FC5 CD EB 06 CALL BAKSTK ; Look for "FOR" block +2448 0FC8 C2 48 07 JP NZ,NFERR ; No "FOR" - ?NF Error +2449 0FCB F9 LD SP,HL ; Clear nested loops +2450 0FCC D5 PUSH DE ; Save index address +2451 0FCD 7E LD A,(HL) ; Get sign of STEP +2452 0FCE 23 INC HL +2453 0FCF F5 PUSH AF ; Save sign of STEP +2454 0FD0 D5 PUSH DE ; Save index address +2455 0FD1 CD 27 1A CALL PHLTFP ; Move index value to FPREG +2456 0FD4 E3 EX (SP),HL ; Save address of TO value +2457 0FD5 E5 PUSH HL ; Save address of index +2458 0FD6 CD 94 17 CALL ADDPHL ; Add STEP to index value +2459 0FD9 E1 POP HL ; Restore address of index +2460 0FDA CD 41 1A CALL FPTHL ; Move value to index variable +2461 0FDD E1 POP HL ; Restore address of TO value +2462 0FDE CD 38 1A CALL LOADFP ; Move TO value to BCDE +2463 0FE1 E5 PUSH HL ; Save address of line of FOR +2464 0FE2 CD 64 1A CALL CMPNUM ; Compare index with TO value +2465 0FE5 E1 POP HL ; Restore address of line num +2466 0FE6 C1 POP BC ; Address of sign of STEP +2467 0FE7 90 SUB B ; Compare with expected sign +2468 0FE8 CD 38 1A CALL LOADFP ; BC = Loop stmt,DE = Line num +2469 0FEB CA F7 0F JP Z,KILFOR ; Loop finished - Terminate it +2470 0FEE EB EX DE,HL ; Loop statement line number +2471 0FEF 22 0C 31 LD (LINEAT),HL ; Set loop line number +2472 0FF2 69 LD L,C ; Set code string to loop +2473 0FF3 60 LD H,B +2474 0FF4 C3 56 0B JP PUTFID ; Put back "FOR" and continue +2475 0FF7 +2476 0FF7 F9 KILFOR: LD SP,HL ; Remove "FOR" block +2477 0FF8 2A 7E 31 LD HL,(BRKLIN) ; Code string after "NEXT" +2478 0FFB 7E LD A,(HL) ; Get next byte in code string +2479 0FFC FE 2C CP ',' ; More NEXTs ? +2480 0FFE C2 5A 0B JP NZ,RUNCNT ; No - Do next statement +2481 1001 CD 9A 0B CALL GETCHR ; Position to index name +2482 1004 CD BF 0F CALL NEXT1 ; Re-enter NEXT routine +2483 1007 ; < will not RETurn to here , Exit to RUNCNT or Loop > +2484 1007 +2485 1007 CD 19 10 GETNUM: CALL EVAL ; Get a numeric expression +2486 100A F6 TSTNUM: .BYTE 0F6H ; Clear carry (numeric) +2487 100B 37 TSTSTR: SCF ; Set carry (string) +2488 100C 3A 5D 31 CHKTYP: LD A,(TYPE) ; Check types match +2489 100F 8F ADC A,A ; Expected + actual +2490 1010 B7 OR A ; Clear carry , set parity +2491 1011 E8 RET PE ; Even parity - Types match +2492 1012 C3 54 07 JP TMERR ; Different types - Error +2493 1015 +2494 1015 CD 10 0A OPNPAR: CALL CHKSYN ; Make sure "(" follows +2495 1018 28 .BYTE "(" +2496 1019 2B EVAL: DEC HL ; Evaluate expression & save +2497 101A 16 00 LD D,0 ; Precedence value +2498 101C D5 EVAL1: PUSH DE ; Save precedence +2499 101D 0E 01 LD C,1 +2500 101F CD 1F 07 CALL CHKSTK ; Check for 1 level of stack +2501 1022 CD 90 10 CALL OPRND ; Get next expression value +2502 1025 22 80 31 EVAL2: LD (NXTOPR),HL ; Save address of next operator +2503 1028 2A 80 31 EVAL3: LD HL,(NXTOPR) ; Restore address of next opr +2504 102B C1 POP BC ; Precedence value and operator +2505 102C 78 LD A,B ; Get precedence value +2506 102D FE 78 CP 78H ; "AND" or "OR" ? +2507 102F D4 0A 10 CALL NC,TSTNUM ; No - Make sure it's a number +2508 1032 7E LD A,(HL) ; Get next operator / function +2509 1033 16 00 LD D,0 ; Clear Last relation +2510 1035 D6 B3 RLTLP: SUB ZGTR ; ">" Token +2511 1037 DA 51 10 JP C,FOPRND ; + - * / ^ AND OR - Test it +2512 103A FE 03 CP ZLTH+1-ZGTR ; < = > +2513 103C D2 51 10 JP NC,FOPRND ; Function - Call it +2514 103F FE 01 CP ZEQUAL-ZGTR ; "=" +2515 1041 17 RLA ; <- Test for legal +2516 1042 AA XOR D ; <- combinations of < = > +2517 1043 BA CP D ; <- by combining last token +2518 1044 57 LD D,A ; <- with current one +2519 1045 DA 42 07 JP C,SNERR ; Error if "<<' '==" or ">>" +2520 1048 22 75 31 LD (CUROPR),HL ; Save address of current token +2521 104B CD 9A 0B CALL GETCHR ; Get next character +2522 104E C3 35 10 JP RLTLP ; Treat the two as one +2523 1051 +2524 1051 7A FOPRND: LD A,D ; < = > found ? +2525 1052 B7 OR A +2526 1053 C2 78 11 JP NZ,TSTRED ; Yes - Test for reduction +2527 1056 7E LD A,(HL) ; Get operator token +2528 1057 22 75 31 LD (CUROPR),HL ; Save operator address +2529 105A D6 AC SUB ZPLUS ; Operator or function? +2530 105C D8 RET C ; Neither - Exit +2531 105D FE 07 CP ZOR+1-ZPLUS ; Is it + - * / ^ AND OR ? +2532 105F D0 RET NC ; No - Exit +2533 1060 5F LD E,A ; Coded operator +2534 1061 3A 5D 31 LD A,(TYPE) ; Get data type +2535 1064 3D DEC A ; FF = numeric , 00 = string +2536 1065 B3 OR E ; Combine with coded operator +2537 1066 7B LD A,E ; Get coded operator +2538 1067 CA D6 15 JP Z,CONCAT ; String concatenation +2539 106A 07 RLCA ; Times 2 +2540 106B 83 ADD A,E ; Times 3 +2541 106C 5F LD E,A ; To DE (D is 0) +2542 106D 21 34 06 LD HL,PRITAB ; Precedence table +2543 1070 19 ADD HL,DE ; To the operator concerned +2544 1071 78 LD A,B ; Last operator precedence +2545 1072 56 LD D,(HL) ; Get evaluation precedence +2546 1073 BA CP D ; Compare with eval precedence +2547 1074 D0 RET NC ; Exit if higher precedence +2548 1075 23 INC HL ; Point to routine address +2549 1076 CD 0A 10 CALL TSTNUM ; Make sure it's a number +2550 1079 +2551 1079 C5 STKTHS: PUSH BC ; Save last precedence & token +2552 107A 01 28 10 LD BC,EVAL3 ; Where to go on prec' break +2553 107D C5 PUSH BC ; Save on stack for return +2554 107E 43 LD B,E ; Save operator +2555 107F 4A LD C,D ; Save precedence +2556 1080 CD 1A 1A CALL STAKFP ; Move value to stack +2557 1083 58 LD E,B ; Restore operator +2558 1084 51 LD D,C ; Restore precedence +2559 1085 4E LD C,(HL) ; Get LSB of routine address +2560 1086 23 INC HL +2561 1087 46 LD B,(HL) ; Get MSB of routine address +2562 1088 23 INC HL +2563 1089 C5 PUSH BC ; Save routine address +2564 108A 2A 75 31 LD HL,(CUROPR) ; Address of current operator +2565 108D C3 1C 10 JP EVAL1 ; Loop until prec' break +2566 1090 +2567 1090 AF OPRND: XOR A ; Get operand routine +2568 1091 32 5D 31 LD (TYPE),A ; Set numeric expected +2569 1094 CD 9A 0B CALL GETCHR ; Get next character +2570 1097 1E 24 LD E,MO ; ?MO Error +2571 1099 CA 56 07 JP Z,ERROR ; No operand - Error +2572 109C DA F0 1A JP C,ASCTFP ; Number - Get value +2573 109F CD 38 0C CALL CHKLTR ; See if a letter +2574 10A2 D2 F7 10 JP NC,CONVAR ; Letter - Find variable +2575 10A5 FE 26 CP '&' ; &H = HEX, &B = BINARY +2576 10A7 20 12 JR NZ, NOTAMP +2577 10A9 CD 9A 0B CALL GETCHR ; Get next character +2578 10AC FE 48 CP 'H' ; Hex number indicated? [function added] +2579 10AE CA 34 1F JP Z,HEXTFP ; Convert Hex to FPREG +2580 10B1 FE 42 CP 'B' ; Binary number indicated? [function added] +2581 10B3 CA A4 1F JP Z,BINTFP ; Convert Bin to FPREG +2582 10B6 1E 02 LD E,SN ; If neither then a ?SN Error +2583 10B8 CA 56 07 JP Z,ERROR ; +2584 10BB FE AC NOTAMP: CP ZPLUS ; '+' Token ? +2585 10BD CA 90 10 JP Z,OPRND ; Yes - Look for operand +2586 10C0 FE 2E CP '.' ; '.' ? +2587 10C2 CA F0 1A JP Z,ASCTFP ; Yes - Create FP number +2588 10C5 FE AD CP ZMINUS ; '-' Token ? +2589 10C7 CA E6 10 JP Z,MINUS ; Yes - Do minus +2590 10CA FE 22 CP '"' ; Literal string ? +2591 10CC CA 9F 14 JP Z,QTSTR ; Get string terminated by '"' +2592 10CF FE AA CP ZNOT ; "NOT" Token ? +2593 10D1 CA D8 11 JP Z,EVNOT ; Yes - Eval NOT expression +2594 10D4 FE A7 CP ZFN ; "FN" Token ? +2595 10D6 CA 03 14 JP Z,DOFN ; Yes - Do FN routine +2596 10D9 D6 B6 SUB ZSGN ; Is it a function? +2597 10DB D2 08 11 JP NC,FNOFST ; Yes - Evaluate function +2598 10DE CD 15 10 EVLPAR: CALL OPNPAR ; Evaluate expression in "()" +2599 10E1 CD 10 0A CALL CHKSYN ; Make sure ")" follows +2600 10E4 29 .BYTE ")" +2601 10E5 C9 RET +2602 10E6 +2603 10E6 16 7D MINUS: LD D,7DH ; '-' precedence +2604 10E8 CD 1C 10 CALL EVAL1 ; Evaluate until prec' break +2605 10EB 2A 80 31 LD HL,(NXTOPR) ; Get next operator address +2606 10EE E5 PUSH HL ; Save next operator address +2607 10EF CD 12 1A CALL INVSGN ; Negate value +2608 10F2 CD 0A 10 RETNUM: CALL TSTNUM ; Make sure it's a number +2609 10F5 E1 POP HL ; Restore next operator address +2610 10F6 C9 RET +2611 10F7 +2612 10F7 CD FD 11 CONVAR: CALL GETVAR ; Get variable address to DE +2613 10FA E5 FRMEVL: PUSH HL ; Save code string address +2614 10FB EB EX DE,HL ; Variable address to HL +2615 10FC 22 94 31 LD (FPREG),HL ; Save address of variable +2616 10FF 3A 5D 31 LD A,(TYPE) ; Get type +2617 1102 B7 OR A ; Numeric? +2618 1103 CC 27 1A CALL Z,PHLTFP ; Yes - Move contents to FPREG +2619 1106 E1 POP HL ; Restore code string address +2620 1107 C9 RET +2621 1108 +2622 1108 06 00 FNOFST: LD B,0 ; Get address of function +2623 110A 07 RLCA ; Double function offset +2624 110B 4F LD C,A ; BC = Offset in function table +2625 110C C5 PUSH BC ; Save adjusted token value +2626 110D CD 9A 0B CALL GETCHR ; Get next character +2627 1110 79 LD A,C ; Get adjusted token value +2628 1111 FE 31 CP 2*(ZLEFT-ZSGN)-1; Adj' LEFT$,RIGHT$ or MID$ ? +2629 1113 DA 2F 11 JP C,FNVAL ; No - Do function +2630 1116 CD 15 10 CALL OPNPAR ; Evaluate expression (X,... +2631 1119 CD 10 0A CALL CHKSYN ; Make sure ',' follows +2632 111C 2C .BYTE ',' +2633 111D CD 0B 10 CALL TSTSTR ; Make sure it's a string +2634 1120 EB EX DE,HL ; Save code string address +2635 1121 2A 94 31 LD HL,(FPREG) ; Get address of string +2636 1124 E3 EX (SP),HL ; Save address of string +2637 1125 E5 PUSH HL ; Save adjusted token value +2638 1126 EB EX DE,HL ; Restore code string address +2639 1127 CD 68 17 CALL GETINT ; Get integer 0-255 +2640 112A EB EX DE,HL ; Save code string address +2641 112B E3 EX (SP),HL ; Save integer,HL = adj' token +2642 112C C3 37 11 JP GOFUNC ; Jump to string function +2643 112F +2644 112F CD DE 10 FNVAL: CALL EVLPAR ; Evaluate expression +2645 1132 E3 EX (SP),HL ; HL = Adjusted token value +2646 1133 11 F2 10 LD DE,RETNUM ; Return number from function +2647 1136 D5 PUSH DE ; Save on stack +2648 1137 01 93 04 GOFUNC: LD BC,FNCTAB ; Function routine addresses +2649 113A 09 ADD HL,BC ; Point to right address +2650 113B 4E LD C,(HL) ; Get LSB of address +2651 113C 23 INC HL ; +2652 113D 66 LD H,(HL) ; Get MSB of address +2653 113E 69 LD L,C ; Address to HL +2654 113F E9 JP (HL) ; Jump to function +2655 1140 +2656 1140 15 SGNEXP: DEC D ; Dee to flag negative exponent +2657 1141 FE AD CP ZMINUS ; '-' token ? +2658 1143 C8 RET Z ; Yes - Return +2659 1144 FE 2D CP '-' ; '-' ASCII ? +2660 1146 C8 RET Z ; Yes - Return +2661 1147 14 INC D ; Inc to flag positive exponent +2662 1148 FE 2B CP '+' ; '+' ASCII ? +2663 114A C8 RET Z ; Yes - Return +2664 114B FE AC CP ZPLUS ; '+' token ? +2665 114D C8 RET Z ; Yes - Return +2666 114E 2B DEC HL ; DEC 'cos GETCHR INCs +2667 114F C9 RET ; Return "NZ" +2668 1150 +2669 1150 F6 POR: .BYTE 0F6H ; Flag "OR" +2670 1151 AF PAND: XOR A ; Flag "AND" +2671 1152 F5 PUSH AF ; Save "AND" / "OR" flag +2672 1153 CD 0A 10 CALL TSTNUM ; Make sure it's a number +2673 1156 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 +2674 1159 F1 POP AF ; Restore "AND" / "OR" flag +2675 115A EB EX DE,HL ; <- Get last +2676 115B C1 POP BC ; <- value +2677 115C E3 EX (SP),HL ; <- from +2678 115D EB EX DE,HL ; <- stack +2679 115E CD 2A 1A CALL FPBCDE ; Move last value to FPREG +2680 1161 F5 PUSH AF ; Save "AND" / "OR" flag +2681 1162 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 +2682 1165 F1 POP AF ; Restore "AND" / "OR" flag +2683 1166 C1 POP BC ; Get value +2684 1167 79 LD A,C ; Get LSB +2685 1168 21 C1 13 LD HL,ACPASS ; Address of save AC as current +2686 116B C2 73 11 JP NZ,POR1 ; Jump if OR +2687 116E A3 AND E ; "AND" LSBs +2688 116F 4F LD C,A ; Save LSB +2689 1170 78 LD A,B ; Get MBS +2690 1171 A2 AND D ; "AND" MSBs +2691 1172 E9 JP (HL) ; Save AC as current (ACPASS) +2692 1173 +2693 1173 B3 POR1: OR E ; "OR" LSBs +2694 1174 4F LD C,A ; Save LSB +2695 1175 78 LD A,B ; Get MSB +2696 1176 B2 OR D ; "OR" MSBs +2697 1177 E9 JP (HL) ; Save AC as current (ACPASS) +2698 1178 +2699 1178 21 8A 11 TSTRED: LD HL,CMPLOG ; Logical compare routine +2700 117B 3A 5D 31 LD A,(TYPE) ; Get data type +2701 117E 1F RRA ; Carry set = string +2702 117F 7A LD A,D ; Get last precedence value +2703 1180 17 RLA ; Times 2 plus carry +2704 1181 5F LD E,A ; To E +2705 1182 16 64 LD D,64H ; Relational precedence +2706 1184 78 LD A,B ; Get current precedence +2707 1185 BA CP D ; Compare with last +2708 1186 D0 RET NC ; Eval if last was rel' or log' +2709 1187 C3 79 10 JP STKTHS ; Stack this one and get next +2710 118A +2711 118A 8C 11 CMPLOG: .WORD CMPLG1 ; Compare two values / strings +2712 118C 79 CMPLG1: LD A,C ; Get data type +2713 118D B7 OR A +2714 118E 1F RRA +2715 118F C1 POP BC ; Get last expression to BCDE +2716 1190 D1 POP DE +2717 1191 F5 PUSH AF ; Save status +2718 1192 CD 0C 10 CALL CHKTYP ; Check that types match +2719 1195 21 CE 11 LD HL,CMPRES ; Result to comparison +2720 1198 E5 PUSH HL ; Save for RETurn +2721 1199 CA 64 1A JP Z,CMPNUM ; Compare values if numeric +2722 119C AF XOR A ; Compare two strings +2723 119D 32 5D 31 LD (TYPE),A ; Set type to numeric +2724 11A0 D5 PUSH DE ; Save string name +2725 11A1 CD 23 16 CALL GSTRCU ; Get current string +2726 11A4 7E LD A,(HL) ; Get length of string +2727 11A5 23 INC HL +2728 11A6 23 INC HL +2729 11A7 4E LD C,(HL) ; Get LSB of address +2730 11A8 23 INC HL +2731 11A9 46 LD B,(HL) ; Get MSB of address +2732 11AA D1 POP DE ; Restore string name +2733 11AB C5 PUSH BC ; Save address of string +2734 11AC F5 PUSH AF ; Save length of string +2735 11AD CD 27 16 CALL GSTRDE ; Get second string +2736 11B0 CD 38 1A CALL LOADFP ; Get address of second string +2737 11B3 F1 POP AF ; Restore length of string 1 +2738 11B4 57 LD D,A ; Length to D +2739 11B5 E1 POP HL ; Restore address of string 1 +2740 11B6 7B CMPSTR: LD A,E ; Bytes of string 2 to do +2741 11B7 B2 OR D ; Bytes of string 1 to do +2742 11B8 C8 RET Z ; Exit if all bytes compared +2743 11B9 7A LD A,D ; Get bytes of string 1 to do +2744 11BA D6 01 SUB 1 +2745 11BC D8 RET C ; Exit if end of string 1 +2746 11BD AF XOR A +2747 11BE BB CP E ; Bytes of string 2 to do +2748 11BF 3C INC A +2749 11C0 D0 RET NC ; Exit if end of string 2 +2750 11C1 15 DEC D ; Count bytes in string 1 +2751 11C2 1D DEC E ; Count bytes in string 2 +2752 11C3 0A LD A,(BC) ; Byte in string 2 +2753 11C4 BE CP (HL) ; Compare to byte in string 1 +2754 11C5 23 INC HL ; Move up string 1 +2755 11C6 03 INC BC ; Move up string 2 +2756 11C7 CA B6 11 JP Z,CMPSTR ; Same - Try next bytes +2757 11CA 3F CCF ; Flag difference (">" or "<") +2758 11CB C3 F4 19 JP FLGDIF ; "<" gives -1 , ">" gives +1 +2759 11CE +2760 11CE 3C CMPRES: INC A ; Increment current value +2761 11CF 8F ADC A,A ; Double plus carry +2762 11D0 C1 POP BC ; Get other value +2763 11D1 A0 AND B ; Combine them +2764 11D2 C6 FF ADD A,-1 ; Carry set if different +2765 11D4 9F SBC A,A ; 00 - Equal , FF - Different +2766 11D5 C3 FB 19 JP FLGREL ; Set current value & continue +2767 11D8 +2768 11D8 16 5A EVNOT: LD D,5AH ; Precedence value for "NOT" +2769 11DA CD 1C 10 CALL EVAL1 ; Eval until precedence break +2770 11DD CD 0A 10 CALL TSTNUM ; Make sure it's a number +2771 11E0 CD 4C 0C CALL DEINT ; Get integer -32768 - 32767 +2772 11E3 7B LD A,E ; Get LSB +2773 11E4 2F CPL ; Invert LSB +2774 11E5 4F LD C,A ; Save "NOT" of LSB +2775 11E6 7A LD A,D ; Get MSB +2776 11E7 2F CPL ; Invert MSB +2777 11E8 CD C1 13 CALL ACPASS ; Save AC as current +2778 11EB C1 POP BC ; Clean up stack +2779 11EC C3 28 10 JP EVAL3 ; Continue evaluation +2780 11EF +2781 11EF 2B DIMRET: DEC HL ; DEC 'cos GETCHR INCs +2782 11F0 CD 9A 0B CALL GETCHR ; Get next character +2783 11F3 C8 RET Z ; End of DIM statement +2784 11F4 CD 10 0A CALL CHKSYN ; Make sure ',' follows +2785 11F7 2C .BYTE ',' +2786 11F8 01 EF 11 DIM: LD BC,DIMRET ; Return to "DIMRET" +2787 11FB C5 PUSH BC ; Save on stack +2788 11FC F6 .BYTE 0F6H ; Flag "Create" variable +2789 11FD AF GETVAR: XOR A ; Find variable address,to DE +2790 11FE 32 5C 31 LD (LCRFLG),A ; Set locate / create flag +2791 1201 46 LD B,(HL) ; Get First byte of name +2792 1202 CD 38 0C GTFNAM: CALL CHKLTR ; See if a letter +2793 1205 DA 42 07 JP C,SNERR ; ?SN Error if not a letter +2794 1208 AF XOR A +2795 1209 4F LD C,A ; Clear second byte of name +2796 120A 32 5D 31 LD (TYPE),A ; Set type to numeric +2797 120D CD 9A 0B CALL GETCHR ; Get next character +2798 1210 DA 19 12 JP C,SVNAM2 ; Numeric - Save in name +2799 1213 CD 38 0C CALL CHKLTR ; See if a letter +2800 1216 DA 26 12 JP C,CHARTY ; Not a letter - Check type +2801 1219 4F SVNAM2: LD C,A ; Save second byte of name +2802 121A CD 9A 0B ENDNAM: CALL GETCHR ; Get next character +2803 121D DA 1A 12 JP C,ENDNAM ; Numeric - Get another +2804 1220 CD 38 0C CALL CHKLTR ; See if a letter +2805 1223 D2 1A 12 JP NC,ENDNAM ; Letter - Get another +2806 1226 D6 24 CHARTY: SUB '$' ; String variable? +2807 1228 C2 35 12 JP NZ,NOTSTR ; No - Numeric variable +2808 122B 3C INC A ; A = 1 (string type) +2809 122C 32 5D 31 LD (TYPE),A ; Set type to string +2810 122F 0F RRCA ; A = 80H , Flag for string +2811 1230 81 ADD A,C ; 2nd byte of name has bit 7 on +2812 1231 4F LD C,A ; Resave second byte on name +2813 1232 CD 9A 0B CALL GETCHR ; Get next character +2814 1235 3A 7B 31 NOTSTR: LD A,(FORFLG) ; Array name needed ? +2815 1238 3D DEC A +2816 1239 CA E2 12 JP Z,ARLDSV ; Yes - Get array name +2817 123C F2 45 12 JP P,NSCFOR ; No array with "FOR" or "FN" +2818 123F 7E LD A,(HL) ; Get byte again +2819 1240 D6 28 SUB '(' ; Subscripted variable? +2820 1242 CA BA 12 JP Z,SBSCPT ; Yes - Sort out subscript +2821 1245 +2822 1245 AF NSCFOR: XOR A ; Simple variable +2823 1246 32 7B 31 LD (FORFLG),A ; Clear "FOR" flag +2824 1249 E5 PUSH HL ; Save code string address +2825 124A 50 LD D,B ; DE = Variable name to find +2826 124B 59 LD E,C +2827 124C 2A 8E 31 LD HL,(FNRGNM) ; FN argument name +2828 124F CD 0A 0A CALL CPDEHL ; Is it the FN argument? +2829 1252 11 90 31 LD DE,FNARG ; Point to argument value +2830 1255 CA 2A 19 JP Z,POPHRT ; Yes - Return FN argument value +2831 1258 2A 88 31 LD HL,(VAREND) ; End of variables +2832 125B EB EX DE,HL ; Address of end of search +2833 125C 2A 86 31 LD HL,(PROGND) ; Start of variables address +2834 125F CD 0A 0A FNDVAR: CALL CPDEHL ; End of variable list table? +2835 1262 CA 78 12 JP Z,CFEVAL ; Yes - Called from EVAL? +2836 1265 79 LD A,C ; Get second byte of name +2837 1266 96 SUB (HL) ; Compare with name in list +2838 1267 23 INC HL ; Move on to first byte +2839 1268 C2 6D 12 JP NZ,FNTHR ; Different - Find another +2840 126B 78 LD A,B ; Get first byte of name +2841 126C 96 SUB (HL) ; Compare with name in list +2842 126D 23 FNTHR: INC HL ; Move on to LSB of value +2843 126E CA AC 12 JP Z,RETADR ; Found - Return address +2844 1271 23 INC HL ; <- Skip +2845 1272 23 INC HL ; <- over +2846 1273 23 INC HL ; <- F.P. +2847 1274 23 INC HL ; <- value +2848 1275 C3 5F 12 JP FNDVAR ; Keep looking +2849 1278 +2850 1278 E1 CFEVAL: POP HL ; Restore code string address +2851 1279 E3 EX (SP),HL ; Get return address +2852 127A D5 PUSH DE ; Save address of variable +2853 127B 11 FA 10 LD DE,FRMEVL ; Return address in EVAL +2854 127E CD 0A 0A CALL CPDEHL ; Called from EVAL ? +2855 1281 D1 POP DE ; Restore address of variable +2856 1282 CA AF 12 JP Z,RETNUL ; Yes - Return null variable +2857 1285 E3 EX (SP),HL ; Put back return +2858 1286 E5 PUSH HL ; Save code string address +2859 1287 C5 PUSH BC ; Save variable name +2860 1288 01 06 00 LD BC,6 ; 2 byte name plus 4 byte data +2861 128B 2A 8A 31 LD HL,(ARREND) ; End of arrays +2862 128E E5 PUSH HL ; Save end of arrays +2863 128F 09 ADD HL,BC ; Move up 6 bytes +2864 1290 C1 POP BC ; Source address in BC +2865 1291 E5 PUSH HL ; Save new end address +2866 1292 CD 0E 07 CALL MOVUP ; Move arrays up +2867 1295 E1 POP HL ; Restore new end address +2868 1296 22 8A 31 LD (ARREND),HL ; Set new end address +2869 1299 60 LD H,B ; End of variables to HL +2870 129A 69 LD L,C +2871 129B 22 88 31 LD (VAREND),HL ; Set new end address +2872 129E +2873 129E 2B ZEROLP: DEC HL ; Back through to zero variable +2874 129F 36 00 LD (HL),0 ; Zero byte in variable +2875 12A1 CD 0A 0A CALL CPDEHL ; Done them all? +2876 12A4 C2 9E 12 JP NZ,ZEROLP ; No - Keep on going +2877 12A7 D1 POP DE ; Get variable name +2878 12A8 73 LD (HL),E ; Store second character +2879 12A9 23 INC HL +2880 12AA 72 LD (HL),D ; Store first character +2881 12AB 23 INC HL +2882 12AC EB RETADR: EX DE,HL ; Address of variable in DE +2883 12AD E1 POP HL ; Restore code string address +2884 12AE C9 RET +2885 12AF +2886 12AF 32 97 31 RETNUL: LD (FPEXP),A ; Set result to zero +2887 12B2 21 DE 06 LD HL,ZERBYT ; Also set a null string +2888 12B5 22 94 31 LD (FPREG),HL ; Save for EVAL +2889 12B8 E1 POP HL ; Restore code string address +2890 12B9 C9 RET +2891 12BA +2892 12BA E5 SBSCPT: PUSH HL ; Save code string address +2893 12BB 2A 5C 31 LD HL,(LCRFLG) ; Locate/Create and Type +2894 12BE E3 EX (SP),HL ; Save and get code string +2895 12BF 57 LD D,A ; Zero number of dimensions +2896 12C0 D5 SCPTLP: PUSH DE ; Save number of dimensions +2897 12C1 C5 PUSH BC ; Save array name +2898 12C2 CD 40 0C CALL FPSINT ; Get subscript (0-32767) +2899 12C5 C1 POP BC ; Restore array name +2900 12C6 F1 POP AF ; Get number of dimensions +2901 12C7 EB EX DE,HL +2902 12C8 E3 EX (SP),HL ; Save subscript value +2903 12C9 E5 PUSH HL ; Save LCRFLG and TYPE +2904 12CA EB EX DE,HL +2905 12CB 3C INC A ; Count dimensions +2906 12CC 57 LD D,A ; Save in D +2907 12CD 7E LD A,(HL) ; Get next byte in code string +2908 12CE FE 2C CP ',' ; Comma (more to come)? +2909 12D0 CA C0 12 JP Z,SCPTLP ; Yes - More subscripts +2910 12D3 CD 10 0A CALL CHKSYN ; Make sure ")" follows +2911 12D6 29 .BYTE ")" +2912 12D7 22 80 31 LD (NXTOPR),HL ; Save code string address +2913 12DA E1 POP HL ; Get LCRFLG and TYPE +2914 12DB 22 5C 31 LD (LCRFLG),HL ; Restore Locate/create & type +2915 12DE 1E 00 LD E,0 ; Flag not CSAVE* or CLOAD* +2916 12E0 D5 PUSH DE ; Save number of dimensions (D) +2917 12E1 11 .BYTE 11H ; Skip "PUSH HL" and "PUSH AF' +2918 12E2 +2919 12E2 E5 ARLDSV: PUSH HL ; Save code string address +2920 12E3 F5 PUSH AF ; A = 00 , Flags set = Z,N +2921 12E4 2A 88 31 LD HL,(VAREND) ; Start of arrays +2922 12E7 3E .BYTE 3EH ; Skip "ADD HL,DE" +2923 12E8 19 FNDARY: ADD HL,DE ; Move to next array start +2924 12E9 EB EX DE,HL +2925 12EA 2A 8A 31 LD HL,(ARREND) ; End of arrays +2926 12ED EB EX DE,HL ; Current array pointer +2927 12EE CD 0A 0A CALL CPDEHL ; End of arrays found? +2928 12F1 CA 1A 13 JP Z,CREARY ; Yes - Create array +2929 12F4 7E LD A,(HL) ; Get second byte of name +2930 12F5 B9 CP C ; Compare with name given +2931 12F6 23 INC HL ; Move on +2932 12F7 C2 FC 12 JP NZ,NXTARY ; Different - Find next array +2933 12FA 7E LD A,(HL) ; Get first byte of name +2934 12FB B8 CP B ; Compare with name given +2935 12FC 23 NXTARY: INC HL ; Move on +2936 12FD 5E LD E,(HL) ; Get LSB of next array address +2937 12FE 23 INC HL +2938 12FF 56 LD D,(HL) ; Get MSB of next array address +2939 1300 23 INC HL +2940 1301 C2 E8 12 JP NZ,FNDARY ; Not found - Keep looking +2941 1304 3A 5C 31 LD A,(LCRFLG) ; Found Locate or Create it? +2942 1307 B7 OR A +2943 1308 C2 4B 07 JP NZ,DDERR ; Create - ?DD Error +2944 130B F1 POP AF ; Locate - Get number of dim'ns +2945 130C 44 LD B,H ; BC Points to array dim'ns +2946 130D 4D LD C,L +2947 130E CA 2A 19 JP Z,POPHRT ; Jump if array load/save +2948 1311 96 SUB (HL) ; Same number of dimensions? +2949 1312 CA 78 13 JP Z,FINDEL ; Yes - Find element +2950 1315 1E 10 BSERR: LD E,BS ; ?BS Error +2951 1317 C3 56 07 JP ERROR ; Output error +2952 131A +2953 131A 11 04 00 CREARY: LD DE,4 ; 4 Bytes per entry +2954 131D F1 POP AF ; Array to save or 0 dim'ns? +2955 131E CA 61 0C JP Z,FCERR ; Yes - ?FC Error +2956 1321 71 LD (HL),C ; Save second byte of name +2957 1322 23 INC HL +2958 1323 70 LD (HL),B ; Save first byte of name +2959 1324 23 INC HL +2960 1325 4F LD C,A ; Number of dimensions to C +2961 1326 CD 1F 07 CALL CHKSTK ; Check if enough memory +2962 1329 23 INC HL ; Point to number of dimensions +2963 132A 23 INC HL +2964 132B 22 75 31 LD (CUROPR),HL ; Save address of pointer +2965 132E 71 LD (HL),C ; Set number of dimensions +2966 132F 23 INC HL +2967 1330 3A 5C 31 LD A,(LCRFLG) ; Locate of Create? +2968 1333 17 RLA ; Carry set = Create +2969 1334 79 LD A,C ; Get number of dimensions +2970 1335 01 0B 00 CRARLP: LD BC,10+1 ; Default dimension size 10 +2971 1338 D2 3D 13 JP NC,DEFSIZ ; Locate - Set default size +2972 133B C1 POP BC ; Get specified dimension size +2973 133C 03 INC BC ; Include zero element +2974 133D 71 DEFSIZ: LD (HL),C ; Save LSB of dimension size +2975 133E 23 INC HL +2976 133F 70 LD (HL),B ; Save MSB of dimension size +2977 1340 23 INC HL +2978 1341 F5 PUSH AF ; Save num' of dim'ns an status +2979 1342 E5 PUSH HL ; Save address of dim'n size +2980 1343 CD D5 1A CALL MLDEBC ; Multiply DE by BC to find +2981 1346 EB EX DE,HL ; amount of mem needed (to DE) +2982 1347 E1 POP HL ; Restore address of dimension +2983 1348 F1 POP AF ; Restore number of dimensions +2984 1349 3D DEC A ; Count them +2985 134A C2 35 13 JP NZ,CRARLP ; Do next dimension if more +2986 134D F5 PUSH AF ; Save locate/create flag +2987 134E 42 LD B,D ; MSB of memory needed +2988 134F 4B LD C,E ; LSB of memory needed +2989 1350 EB EX DE,HL +2990 1351 19 ADD HL,DE ; Add bytes to array start +2991 1352 DA 37 07 JP C,OMERR ; Too big - Error +2992 1355 CD 28 07 CALL ENFMEM ; See if enough memory +2993 1358 22 8A 31 LD (ARREND),HL ; Save new end of array +2994 135B +2995 135B 2B ZERARY: DEC HL ; Back through array data +2996 135C 36 00 LD (HL),0 ; Set array element to zero +2997 135E CD 0A 0A CALL CPDEHL ; All elements zeroed? +2998 1361 C2 5B 13 JP NZ,ZERARY ; No - Keep on going +2999 1364 03 INC BC ; Number of bytes + 1 +3000 1365 57 LD D,A ; A=0 +3001 1366 2A 75 31 LD HL,(CUROPR) ; Get address of array +3002 1369 5E LD E,(HL) ; Number of dimensions +3003 136A EB EX DE,HL ; To HL +3004 136B 29 ADD HL,HL ; Two bytes per dimension size +3005 136C 09 ADD HL,BC ; Add number of bytes +3006 136D EB EX DE,HL ; Bytes needed to DE +3007 136E 2B DEC HL +3008 136F 2B DEC HL +3009 1370 73 LD (HL),E ; Save LSB of bytes needed +3010 1371 23 INC HL +3011 1372 72 LD (HL),D ; Save MSB of bytes needed +3012 1373 23 INC HL +3013 1374 F1 POP AF ; Locate / Create? +3014 1375 DA 9C 13 JP C,ENDDIM ; A is 0 , End if create +3015 1378 47 FINDEL: LD B,A ; Find array element +3016 1379 4F LD C,A +3017 137A 7E LD A,(HL) ; Number of dimensions +3018 137B 23 INC HL +3019 137C 16 .BYTE 16H ; Skip "POP HL" +3020 137D E1 FNDELP: POP HL ; Address of next dim' size +3021 137E 5E LD E,(HL) ; Get LSB of dim'n size +3022 137F 23 INC HL +3023 1380 56 LD D,(HL) ; Get MSB of dim'n size +3024 1381 23 INC HL +3025 1382 E3 EX (SP),HL ; Save address - Get index +3026 1383 F5 PUSH AF ; Save number of dim'ns +3027 1384 CD 0A 0A CALL CPDEHL ; Dimension too large? +3028 1387 D2 15 13 JP NC,BSERR ; Yes - ?BS Error +3029 138A E5 PUSH HL ; Save index +3030 138B CD D5 1A CALL MLDEBC ; Multiply previous by size +3031 138E D1 POP DE ; Index supplied to DE +3032 138F 19 ADD HL,DE ; Add index to pointer +3033 1390 F1 POP AF ; Number of dimensions +3034 1391 3D DEC A ; Count them +3035 1392 44 LD B,H ; MSB of pointer +3036 1393 4D LD C,L ; LSB of pointer +3037 1394 C2 7D 13 JP NZ,FNDELP ; More - Keep going +3038 1397 29 ADD HL,HL ; 4 Bytes per element +3039 1398 29 ADD HL,HL +3040 1399 C1 POP BC ; Start of array +3041 139A 09 ADD HL,BC ; Point to element +3042 139B EB EX DE,HL ; Address of element to DE +3043 139C 2A 80 31 ENDDIM: LD HL,(NXTOPR) ; Got code string address +3044 139F C9 RET +3045 13A0 +3046 13A0 2A 8A 31 FRE: LD HL,(ARREND) ; Start of free memory +3047 13A3 EB EX DE,HL ; To DE +3048 13A4 21 00 00 LD HL,0 ; End of free memory +3049 13A7 39 ADD HL,SP ; Current stack value +3050 13A8 3A 5D 31 LD A,(TYPE) ; Dummy argument type +3051 13AB B7 OR A +3052 13AC CA BC 13 JP Z,FRENUM ; Numeric - Free variable space +3053 13AF CD 23 16 CALL GSTRCU ; Current string to pool +3054 13B2 CD 23 15 CALL GARBGE ; Garbage collection +3055 13B5 2A 0A 31 LD HL,(STRSPC) ; Bottom of string space in use +3056 13B8 EB EX DE,HL ; To DE +3057 13B9 2A 73 31 LD HL,(STRBOT) ; Bottom of string space +3058 13BC 7D FRENUM: LD A,L ; Get LSB of end +3059 13BD 93 SUB E ; Subtract LSB of beginning +3060 13BE 4F LD C,A ; Save difference if C +3061 13BF 7C LD A,H ; Get MSB of end +3062 13C0 9A SBC A,D ; Subtract MSB of beginning +3063 13C1 41 ACPASS: LD B,C ; Return integer AC +3064 13C2 50 ABPASS: LD D,B ; Return integer AB +3065 13C3 1E 00 LD E,0 +3066 13C5 21 5D 31 LD HL,TYPE ; Point to type +3067 13C8 73 LD (HL),E ; Set type to numeric +3068 13C9 06 90 LD B,80H+16 ; 16 bit integer +3069 13CB C3 00 1A JP RETINT ; Return the integr +3070 13CE +3071 13CE 3A 5B 31 POS: LD A,(CURPOS) ; Get cursor position +3072 13D1 47 PASSA: LD B,A ; Put A into AB +3073 13D2 AF XOR A ; Zero A +3074 13D3 C3 C2 13 JP ABPASS ; Return integer AB +3075 13D6 +3076 13D6 CD 59 14 DEF: CALL CHEKFN ; Get "FN" and name +3077 13D9 CD 4B 14 CALL IDTEST ; Test for illegal direct +3078 13DC 01 31 0D LD BC,DATA ; To get next statement +3079 13DF C5 PUSH BC ; Save address for RETurn +3080 13E0 D5 PUSH DE ; Save address of function ptr +3081 13E1 CD 10 0A CALL CHKSYN ; Make sure "(" follows +3082 13E4 28 .BYTE "(" +3083 13E5 CD FD 11 CALL GETVAR ; Get argument variable name +3084 13E8 E5 PUSH HL ; Save code string address +3085 13E9 EB EX DE,HL ; Argument address to HL +3086 13EA 2B DEC HL +3087 13EB 56 LD D,(HL) ; Get first byte of arg name +3088 13EC 2B DEC HL +3089 13ED 5E LD E,(HL) ; Get second byte of arg name +3090 13EE E1 POP HL ; Restore code string address +3091 13EF CD 0A 10 CALL TSTNUM ; Make sure numeric argument +3092 13F2 CD 10 0A CALL CHKSYN ; Make sure ")" follows +3093 13F5 29 .BYTE ")" +3094 13F6 CD 10 0A CALL CHKSYN ; Make sure "=" follows +3095 13F9 B4 .BYTE ZEQUAL ; "=" token +3096 13FA 44 LD B,H ; Code string address to BC +3097 13FB 4D LD C,L +3098 13FC E3 EX (SP),HL ; Save code str , Get FN ptr +3099 13FD 71 LD (HL),C ; Save LSB of FN code string +3100 13FE 23 INC HL +3101 13FF 70 LD (HL),B ; Save MSB of FN code string +3102 1400 C3 98 14 JP SVSTAD ; Save address and do function +3103 1403 +3104 1403 CD 59 14 DOFN: CALL CHEKFN ; Make sure FN follows +3105 1406 D5 PUSH DE ; Save function pointer address +3106 1407 CD DE 10 CALL EVLPAR ; Evaluate expression in "()" +3107 140A CD 0A 10 CALL TSTNUM ; Make sure numeric result +3108 140D E3 EX (SP),HL ; Save code str , Get FN ptr +3109 140E 5E LD E,(HL) ; Get LSB of FN code string +3110 140F 23 INC HL +3111 1410 56 LD D,(HL) ; Get MSB of FN code string +3112 1411 23 INC HL +3113 1412 7A LD A,D ; And function DEFined? +3114 1413 B3 OR E +3115 1414 CA 4E 07 JP Z,UFERR ; No - ?UF Error +3116 1417 7E LD A,(HL) ; Get LSB of argument address +3117 1418 23 INC HL +3118 1419 66 LD H,(HL) ; Get MSB of argument address +3119 141A 6F LD L,A ; HL = Arg variable address +3120 141B E5 PUSH HL ; Save it +3121 141C 2A 8E 31 LD HL,(FNRGNM) ; Get old argument name +3122 141F E3 EX (SP),HL ; ; Save old , Get new +3123 1420 22 8E 31 LD (FNRGNM),HL ; Set new argument name +3124 1423 2A 92 31 LD HL,(FNARG+2) ; Get LSB,NLSB of old arg value +3125 1426 E5 PUSH HL ; Save it +3126 1427 2A 90 31 LD HL,(FNARG) ; Get MSB,EXP of old arg value +3127 142A E5 PUSH HL ; Save it +3128 142B 21 90 31 LD HL,FNARG ; HL = Value of argument +3129 142E D5 PUSH DE ; Save FN code string address +3130 142F CD 41 1A CALL FPTHL ; Move FPREG to argument +3131 1432 E1 POP HL ; Get FN code string address +3132 1433 CD 07 10 CALL GETNUM ; Get value from function +3133 1436 2B DEC HL ; DEC 'cos GETCHR INCs +3134 1437 CD 9A 0B CALL GETCHR ; Get next character +3135 143A C2 42 07 JP NZ,SNERR ; Bad character in FN - Error +3136 143D E1 POP HL ; Get MSB,EXP of old arg +3137 143E 22 90 31 LD (FNARG),HL ; Restore it +3138 1441 E1 POP HL ; Get LSB,NLSB of old arg +3139 1442 22 92 31 LD (FNARG+2),HL ; Restore it +3140 1445 E1 POP HL ; Get name of old arg +3141 1446 22 8E 31 LD (FNRGNM),HL ; Restore it +3142 1449 E1 POP HL ; Restore code string address +3143 144A C9 RET +3144 144B +3145 144B E5 IDTEST: PUSH HL ; Save code string address +3146 144C 2A 0C 31 LD HL,(LINEAT) ; Get current line number +3147 144F 23 INC HL ; -1 means direct statement +3148 1450 7C LD A,H +3149 1451 B5 OR L +3150 1452 E1 POP HL ; Restore code string address +3151 1453 C0 RET NZ ; Return if in program +3152 1454 1E 16 LD E,ID ; ?ID Error +3153 1456 C3 56 07 JP ERROR +3154 1459 +3155 1459 CD 10 0A CHEKFN: CALL CHKSYN ; Make sure FN follows +3156 145C A7 .BYTE ZFN ; "FN" token +3157 145D 3E 80 LD A,80H +3158 145F 32 7B 31 LD (FORFLG),A ; Flag FN name to find +3159 1462 B6 OR (HL) ; FN name has bit 7 set +3160 1463 47 LD B,A ; in first byte of name +3161 1464 CD 02 12 CALL GTFNAM ; Get FN name +3162 1467 C3 0A 10 JP TSTNUM ; Make sure numeric function +3163 146A +3164 146A CD 0A 10 STR: CALL TSTNUM ; Make sure it's a number +3165 146D CD 8E 1B CALL NUMASC ; Turn number into text +3166 1470 CD 9E 14 STR1: CALL CRTST ; Create string entry for it +3167 1473 CD 23 16 CALL GSTRCU ; Current string to pool +3168 1476 01 7E 16 LD BC,TOPOOL ; Save in string pool +3169 1479 C5 PUSH BC ; Save address on stack +3170 147A +3171 147A 7E SAVSTR: LD A,(HL) ; Get string length +3172 147B 23 INC HL +3173 147C 23 INC HL +3174 147D E5 PUSH HL ; Save pointer to string +3175 147E CD F9 14 CALL TESTR ; See if enough string space +3176 1481 E1 POP HL ; Restore pointer to string +3177 1482 4E LD C,(HL) ; Get LSB of address +3178 1483 23 INC HL +3179 1484 46 LD B,(HL) ; Get MSB of address +3180 1485 CD 92 14 CALL CRTMST ; Create string entry +3181 1488 E5 PUSH HL ; Save pointer to MSB of addr +3182 1489 6F LD L,A ; Length of string +3183 148A CD 16 16 CALL TOSTRA ; Move to string area +3184 148D D1 POP DE ; Restore pointer to MSB +3185 148E C9 RET +3186 148F +3187 148F CD F9 14 MKTMST: CALL TESTR ; See if enough string space +3188 1492 21 6F 31 CRTMST: LD HL,TMPSTR ; Temporary string +3189 1495 E5 PUSH HL ; Save it +3190 1496 77 LD (HL),A ; Save length of string +3191 1497 23 INC HL +3192 1498 23 SVSTAD: INC HL +3193 1499 73 LD (HL),E ; Save LSB of address +3194 149A 23 INC HL +3195 149B 72 LD (HL),D ; Save MSB of address +3196 149C E1 POP HL ; Restore pointer +3197 149D C9 RET +3198 149E +3199 149E 2B CRTST: DEC HL ; DEC - INCed after +3200 149F 06 22 QTSTR: LD B,'"' ; Terminating quote +3201 14A1 50 LD D,B ; Quote to D +3202 14A2 E5 DTSTR: PUSH HL ; Save start +3203 14A3 0E FF LD C,-1 ; Set counter to -1 +3204 14A5 23 QTSTLP: INC HL ; Move on +3205 14A6 7E LD A,(HL) ; Get byte +3206 14A7 0C INC C ; Count bytes +3207 14A8 B7 OR A ; End of line? +3208 14A9 CA B4 14 JP Z,CRTSTE ; Yes - Create string entry +3209 14AC BA CP D ; Terminator D found? +3210 14AD CA B4 14 JP Z,CRTSTE ; Yes - Create string entry +3211 14B0 B8 CP B ; Terminator B found? +3212 14B1 C2 A5 14 JP NZ,QTSTLP ; No - Keep looking +3213 14B4 FE 22 CRTSTE: CP '"' ; End with '"'? +3214 14B6 CC 9A 0B CALL Z,GETCHR ; Yes - Get next character +3215 14B9 E3 EX (SP),HL ; Starting quote +3216 14BA 23 INC HL ; First byte of string +3217 14BB EB EX DE,HL ; To DE +3218 14BC 79 LD A,C ; Get length +3219 14BD CD 92 14 CALL CRTMST ; Create string entry +3220 14C0 11 6F 31 TSTOPL: LD DE,TMPSTR ; Temporary string +3221 14C3 2A 61 31 LD HL,(TMSTPT) ; Temporary string pool pointer +3222 14C6 22 94 31 LD (FPREG),HL ; Save address of string ptr +3223 14C9 3E 01 LD A,1 +3224 14CB 32 5D 31 LD (TYPE),A ; Set type to string +3225 14CE CD 44 1A CALL DETHL4 ; Move string to pool +3226 14D1 CD 0A 0A CALL CPDEHL ; Out of string pool? +3227 14D4 22 61 31 LD (TMSTPT),HL ; Save new pointer +3228 14D7 E1 POP HL ; Restore code string address +3229 14D8 7E LD A,(HL) ; Get next code byte +3230 14D9 C0 RET NZ ; Return if pool OK +3231 14DA 1E 1E LD E,ST ; ?ST Error +3232 14DC C3 56 07 JP ERROR ; String pool overflow +3233 14DF +3234 14DF 23 PRNUMS: INC HL ; Skip leading space +3235 14E0 CD 9E 14 PRS: CALL CRTST ; Create string entry for it +3236 14E3 CD 23 16 PRS1: CALL GSTRCU ; Current string to pool +3237 14E6 CD 38 1A CALL LOADFP ; Move string block to BCDE +3238 14E9 1C INC E ; Length + 1 +3239 14EA 1D PRSLP: DEC E ; Count characters +3240 14EB C8 RET Z ; End of string +3241 14EC 0A LD A,(BC) ; Get byte to output +3242 14ED CD 1B 0A CALL OUTC ; Output character in A +3243 14F0 FE 0D CP CR ; Return? +3244 14F2 CC 4C 0E CALL Z,DONULL ; Yes - Do nulls +3245 14F5 03 INC BC ; Next byte in string +3246 14F6 C3 EA 14 JP PRSLP ; More characters to output +3247 14F9 +3248 14F9 B7 TESTR: OR A ; Test if enough room +3249 14FA 0E .BYTE 0EH ; No garbage collection done +3250 14FB F1 GRBDON: POP AF ; Garbage collection done +3251 14FC F5 PUSH AF ; Save status +3252 14FD 2A 0A 31 LD HL,(STRSPC) ; Bottom of string space in use +3253 1500 EB EX DE,HL ; To DE +3254 1501 2A 73 31 LD HL,(STRBOT) ; Bottom of string area +3255 1504 2F CPL ; Negate length (Top down) +3256 1505 4F LD C,A ; -Length to BC +3257 1506 06 FF LD B,-1 ; BC = -ve length of string +3258 1508 09 ADD HL,BC ; Add to bottom of space in use +3259 1509 23 INC HL ; Plus one for 2's complement +3260 150A CD 0A 0A CALL CPDEHL ; Below string RAM area? +3261 150D DA 17 15 JP C,TESTOS ; Tidy up if not done else err +3262 1510 22 73 31 LD (STRBOT),HL ; Save new bottom of area +3263 1513 23 INC HL ; Point to first byte of string +3264 1514 EB EX DE,HL ; Address to DE +3265 1515 F1 POPAF: POP AF ; Throw away status push +3266 1516 C9 RET +3267 1517 +3268 1517 F1 TESTOS: POP AF ; Garbage collect been done? +3269 1518 1E 1A LD E,OS ; ?OS Error +3270 151A CA 56 07 JP Z,ERROR ; Yes - Not enough string apace +3271 151D BF CP A ; Flag garbage collect done +3272 151E F5 PUSH AF ; Save status +3273 151F 01 FB 14 LD BC,GRBDON ; Garbage collection done +3274 1522 C5 PUSH BC ; Save for RETurn +3275 1523 2A 5F 31 GARBGE: LD HL,(LSTRAM) ; Get end of RAM pointer +3276 1526 22 73 31 GARBLP: LD (STRBOT),HL ; Reset string pointer +3277 1529 21 00 00 LD HL,0 +3278 152C E5 PUSH HL ; Flag no string found +3279 152D 2A 0A 31 LD HL,(STRSPC) ; Get bottom of string space +3280 1530 E5 PUSH HL ; Save bottom of string space +3281 1531 21 63 31 LD HL,TMSTPL ; Temporary string pool +3282 1534 EB GRBLP: EX DE,HL +3283 1535 2A 61 31 LD HL,(TMSTPT) ; Temporary string pool pointer +3284 1538 EB EX DE,HL +3285 1539 CD 0A 0A CALL CPDEHL ; Temporary string pool done? +3286 153C 01 34 15 LD BC,GRBLP ; Loop until string pool done +3287 153F C2 88 15 JP NZ,STPOOL ; No - See if in string area +3288 1542 2A 86 31 LD HL,(PROGND) ; Start of simple variables +3289 1545 EB SMPVAR: EX DE,HL +3290 1546 2A 88 31 LD HL,(VAREND) ; End of simple variables +3291 1549 EB EX DE,HL +3292 154A CD 0A 0A CALL CPDEHL ; All simple strings done? +3293 154D CA 5B 15 JP Z,ARRLP ; Yes - Do string arrays +3294 1550 7E LD A,(HL) ; Get type of variable +3295 1551 23 INC HL +3296 1552 23 INC HL +3297 1553 B7 OR A ; "S" flag set if string +3298 1554 CD 8B 15 CALL STRADD ; See if string in string area +3299 1557 C3 45 15 JP SMPVAR ; Loop until simple ones done +3300 155A +3301 155A C1 GNXARY: POP BC ; Scrap address of this array +3302 155B EB ARRLP: EX DE,HL +3303 155C 2A 8A 31 LD HL,(ARREND) ; End of string arrays +3304 155F EB EX DE,HL +3305 1560 CD 0A 0A CALL CPDEHL ; All string arrays done? +3306 1563 CA B1 15 JP Z,SCNEND ; Yes - Move string if found +3307 1566 CD 38 1A CALL LOADFP ; Get array name to BCDE +3308 1569 7B LD A,E ; Get type of array +3309 156A E5 PUSH HL ; Save address of num of dim'ns +3310 156B 09 ADD HL,BC ; Start of next array +3311 156C B7 OR A ; Test type of array +3312 156D F2 5A 15 JP P,GNXARY ; Numeric array - Ignore it +3313 1570 22 75 31 LD (CUROPR),HL ; Save address of next array +3314 1573 E1 POP HL ; Get address of num of dim'ns +3315 1574 4E LD C,(HL) ; BC = Number of dimensions +3316 1575 06 00 LD B,0 +3317 1577 09 ADD HL,BC ; Two bytes per dimension size +3318 1578 09 ADD HL,BC +3319 1579 23 INC HL ; Plus one for number of dim'ns +3320 157A EB GRBARY: EX DE,HL +3321 157B 2A 75 31 LD HL,(CUROPR) ; Get address of next array +3322 157E EB EX DE,HL +3323 157F CD 0A 0A CALL CPDEHL ; Is this array finished? +3324 1582 CA 5B 15 JP Z,ARRLP ; Yes - Get next one +3325 1585 01 7A 15 LD BC,GRBARY ; Loop until array all done +3326 1588 C5 STPOOL: PUSH BC ; Save return address +3327 1589 F6 80 OR 80H ; Flag string type +3328 158B 7E STRADD: LD A,(HL) ; Get string length +3329 158C 23 INC HL +3330 158D 23 INC HL +3331 158E 5E LD E,(HL) ; Get LSB of string address +3332 158F 23 INC HL +3333 1590 56 LD D,(HL) ; Get MSB of string address +3334 1591 23 INC HL +3335 1592 F0 RET P ; Not a string - Return +3336 1593 B7 OR A ; Set flags on string length +3337 1594 C8 RET Z ; Null string - Return +3338 1595 44 LD B,H ; Save variable pointer +3339 1596 4D LD C,L +3340 1597 2A 73 31 LD HL,(STRBOT) ; Bottom of new area +3341 159A CD 0A 0A CALL CPDEHL ; String been done? +3342 159D 60 LD H,B ; Restore variable pointer +3343 159E 69 LD L,C +3344 159F D8 RET C ; String done - Ignore +3345 15A0 E1 POP HL ; Return address +3346 15A1 E3 EX (SP),HL ; Lowest available string area +3347 15A2 CD 0A 0A CALL CPDEHL ; String within string area? +3348 15A5 E3 EX (SP),HL ; Lowest available string area +3349 15A6 E5 PUSH HL ; Re-save return address +3350 15A7 60 LD H,B ; Restore variable pointer +3351 15A8 69 LD L,C +3352 15A9 D0 RET NC ; Outside string area - Ignore +3353 15AA C1 POP BC ; Get return , Throw 2 away +3354 15AB F1 POP AF ; +3355 15AC F1 POP AF ; +3356 15AD E5 PUSH HL ; Save variable pointer +3357 15AE D5 PUSH DE ; Save address of current +3358 15AF C5 PUSH BC ; Put back return address +3359 15B0 C9 RET ; Go to it +3360 15B1 +3361 15B1 D1 SCNEND: POP DE ; Addresses of strings +3362 15B2 E1 POP HL ; +3363 15B3 7D LD A,L ; HL = 0 if no more to do +3364 15B4 B4 OR H +3365 15B5 C8 RET Z ; No more to do - Return +3366 15B6 2B DEC HL +3367 15B7 46 LD B,(HL) ; MSB of address of string +3368 15B8 2B DEC HL +3369 15B9 4E LD C,(HL) ; LSB of address of string +3370 15BA E5 PUSH HL ; Save variable address +3371 15BB 2B DEC HL +3372 15BC 2B DEC HL +3373 15BD 6E LD L,(HL) ; HL = Length of string +3374 15BE 26 00 LD H,0 +3375 15C0 09 ADD HL,BC ; Address of end of string+1 +3376 15C1 50 LD D,B ; String address to DE +3377 15C2 59 LD E,C +3378 15C3 2B DEC HL ; Last byte in string +3379 15C4 44 LD B,H ; Address to BC +3380 15C5 4D LD C,L +3381 15C6 2A 73 31 LD HL,(STRBOT) ; Current bottom of string area +3382 15C9 CD 11 07 CALL MOVSTR ; Move string to new address +3383 15CC E1 POP HL ; Restore variable address +3384 15CD 71 LD (HL),C ; Save new LSB of address +3385 15CE 23 INC HL +3386 15CF 70 LD (HL),B ; Save new MSB of address +3387 15D0 69 LD L,C ; Next string area+1 to HL +3388 15D1 60 LD H,B +3389 15D2 2B DEC HL ; Next string area address +3390 15D3 C3 26 15 JP GARBLP ; Look for more strings +3391 15D6 +3392 15D6 C5 CONCAT: PUSH BC ; Save prec' opr & code string +3393 15D7 E5 PUSH HL ; +3394 15D8 2A 94 31 LD HL,(FPREG) ; Get first string +3395 15DB E3 EX (SP),HL ; Save first string +3396 15DC CD 90 10 CALL OPRND ; Get second string +3397 15DF E3 EX (SP),HL ; Restore first string +3398 15E0 CD 0B 10 CALL TSTSTR ; Make sure it's a string +3399 15E3 7E LD A,(HL) ; Get length of second string +3400 15E4 E5 PUSH HL ; Save first string +3401 15E5 2A 94 31 LD HL,(FPREG) ; Get second string +3402 15E8 E5 PUSH HL ; Save second string +3403 15E9 86 ADD A,(HL) ; Add length of second string +3404 15EA 1E 1C LD E,LS ; ?LS Error +3405 15EC DA 56 07 JP C,ERROR ; String too long - Error +3406 15EF CD 8F 14 CALL MKTMST ; Make temporary string +3407 15F2 D1 POP DE ; Get second string to DE +3408 15F3 CD 27 16 CALL GSTRDE ; Move to string pool if needed +3409 15F6 E3 EX (SP),HL ; Get first string +3410 15F7 CD 26 16 CALL GSTRHL ; Move to string pool if needed +3411 15FA E5 PUSH HL ; Save first string +3412 15FB 2A 71 31 LD HL,(TMPSTR+2) ; Temporary string address +3413 15FE EB EX DE,HL ; To DE +3414 15FF CD 0D 16 CALL SSTSA ; First string to string area +3415 1602 CD 0D 16 CALL SSTSA ; Second string to string area +3416 1605 21 25 10 LD HL,EVAL2 ; Return to evaluation loop +3417 1608 E3 EX (SP),HL ; Save return,get code string +3418 1609 E5 PUSH HL ; Save code string address +3419 160A C3 C0 14 JP TSTOPL ; To temporary string to pool +3420 160D +3421 160D E1 SSTSA: POP HL ; Return address +3422 160E E3 EX (SP),HL ; Get string block,save return +3423 160F 7E LD A,(HL) ; Get length of string +3424 1610 23 INC HL +3425 1611 23 INC HL +3426 1612 4E LD C,(HL) ; Get LSB of string address +3427 1613 23 INC HL +3428 1614 46 LD B,(HL) ; Get MSB of string address +3429 1615 6F LD L,A ; Length to L +3430 1616 2C TOSTRA: INC L ; INC - DECed after +3431 1617 2D TSALP: DEC L ; Count bytes moved +3432 1618 C8 RET Z ; End of string - Return +3433 1619 0A LD A,(BC) ; Get source +3434 161A 12 LD (DE),A ; Save destination +3435 161B 03 INC BC ; Next source +3436 161C 13 INC DE ; Next destination +3437 161D C3 17 16 JP TSALP ; Loop until string moved +3438 1620 +3439 1620 CD 0B 10 GETSTR: CALL TSTSTR ; Make sure it's a string +3440 1623 2A 94 31 GSTRCU: LD HL,(FPREG) ; Get current string +3441 1626 EB GSTRHL: EX DE,HL ; Save DE +3442 1627 CD 41 16 GSTRDE: CALL BAKTMP ; Was it last tmp-str? +3443 162A EB EX DE,HL ; Restore DE +3444 162B C0 RET NZ ; No - Return +3445 162C D5 PUSH DE ; Save string +3446 162D 50 LD D,B ; String block address to DE +3447 162E 59 LD E,C +3448 162F 1B DEC DE ; Point to length +3449 1630 4E LD C,(HL) ; Get string length +3450 1631 2A 73 31 LD HL,(STRBOT) ; Current bottom of string area +3451 1634 CD 0A 0A CALL CPDEHL ; Last one in string area? +3452 1637 C2 3F 16 JP NZ,POPHL ; No - Return +3453 163A 47 LD B,A ; Clear B (A=0) +3454 163B 09 ADD HL,BC ; Remove string from str' area +3455 163C 22 73 31 LD (STRBOT),HL ; Save new bottom of str' area +3456 163F E1 POPHL: POP HL ; Restore string +3457 1640 C9 RET +3458 1641 +3459 1641 2A 61 31 BAKTMP: LD HL,(TMSTPT) ; Get temporary string pool top +3460 1644 2B DEC HL ; Back +3461 1645 46 LD B,(HL) ; Get MSB of address +3462 1646 2B DEC HL ; Back +3463 1647 4E LD C,(HL) ; Get LSB of address +3464 1648 2B DEC HL ; Back +3465 1649 2B DEC HL ; Back +3466 164A CD 0A 0A CALL CPDEHL ; String last in string pool? +3467 164D C0 RET NZ ; Yes - Leave it +3468 164E 22 61 31 LD (TMSTPT),HL ; Save new string pool top +3469 1651 C9 RET +3470 1652 +3471 1652 01 D1 13 LEN: LD BC,PASSA ; To return integer A +3472 1655 C5 PUSH BC ; Save address +3473 1656 CD 20 16 GETLEN: CALL GETSTR ; Get string and its length +3474 1659 AF XOR A +3475 165A 57 LD D,A ; Clear D +3476 165B 32 5D 31 LD (TYPE),A ; Set type to numeric +3477 165E 7E LD A,(HL) ; Get length of string +3478 165F B7 OR A ; Set status flags +3479 1660 C9 RET +3480 1661 +3481 1661 01 D1 13 ASC: LD BC,PASSA ; To return integer A +3482 1664 C5 PUSH BC ; Save address +3483 1665 CD 56 16 GTFLNM: CALL GETLEN ; Get length of string +3484 1668 CA 61 0C JP Z,FCERR ; Null string - Error +3485 166B 23 INC HL +3486 166C 23 INC HL +3487 166D 5E LD E,(HL) ; Get LSB of address +3488 166E 23 INC HL +3489 166F 56 LD D,(HL) ; Get MSB of address +3490 1670 1A LD A,(DE) ; Get first byte of string +3491 1671 C9 RET +3492 1672 +3493 1672 3E 01 CHR: LD A,1 ; One character string +3494 1674 CD 8F 14 CALL MKTMST ; Make a temporary string +3495 1677 CD 6B 17 CALL MAKINT ; Make it integer A +3496 167A 2A 71 31 LD HL,(TMPSTR+2) ; Get address of string +3497 167D 73 LD (HL),E ; Save character +3498 167E C1 TOPOOL: POP BC ; Clean up stack +3499 167F C3 C0 14 JP TSTOPL ; Temporary string to pool +3500 1682 +3501 1682 CD 1B 17 LEFT: CALL LFRGNM ; Get number and ending ")" +3502 1685 AF XOR A ; Start at first byte in string +3503 1686 E3 RIGHT1: EX (SP),HL ; Save code string,Get string +3504 1687 4F LD C,A ; Starting position in string +3505 1688 E5 MID1: PUSH HL ; Save string block address +3506 1689 7E LD A,(HL) ; Get length of string +3507 168A B8 CP B ; Compare with number given +3508 168B DA 90 16 JP C,ALLFOL ; All following bytes required +3509 168E 78 LD A,B ; Get new length +3510 168F 11 .BYTE 11H ; Skip "LD C,0" +3511 1690 0E 00 ALLFOL: LD C,0 ; First byte of string +3512 1692 C5 PUSH BC ; Save position in string +3513 1693 CD F9 14 CALL TESTR ; See if enough string space +3514 1696 C1 POP BC ; Get position in string +3515 1697 E1 POP HL ; Restore string block address +3516 1698 E5 PUSH HL ; And re-save it +3517 1699 23 INC HL +3518 169A 23 INC HL +3519 169B 46 LD B,(HL) ; Get LSB of address +3520 169C 23 INC HL +3521 169D 66 LD H,(HL) ; Get MSB of address +3522 169E 68 LD L,B ; HL = address of string +3523 169F 06 00 LD B,0 ; BC = starting address +3524 16A1 09 ADD HL,BC ; Point to that byte +3525 16A2 44 LD B,H ; BC = source string +3526 16A3 4D LD C,L +3527 16A4 CD 92 14 CALL CRTMST ; Create a string entry +3528 16A7 6F LD L,A ; Length of new string +3529 16A8 CD 16 16 CALL TOSTRA ; Move string to string area +3530 16AB D1 POP DE ; Clear stack +3531 16AC CD 27 16 CALL GSTRDE ; Move to string pool if needed +3532 16AF C3 C0 14 JP TSTOPL ; Temporary string to pool +3533 16B2 +3534 16B2 CD 1B 17 RIGHT: CALL LFRGNM ; Get number and ending ")" +3535 16B5 D1 POP DE ; Get string length +3536 16B6 D5 PUSH DE ; And re-save +3537 16B7 1A LD A,(DE) ; Get length +3538 16B8 90 SUB B ; Move back N bytes +3539 16B9 C3 86 16 JP RIGHT1 ; Go and get sub-string +3540 16BC +3541 16BC EB MID: EX DE,HL ; Get code string address +3542 16BD 7E LD A,(HL) ; Get next byte ',' or ")" +3543 16BE CD 20 17 CALL MIDNUM ; Get number supplied +3544 16C1 04 INC B ; Is it character zero? +3545 16C2 05 DEC B +3546 16C3 CA 61 0C JP Z,FCERR ; Yes - Error +3547 16C6 C5 PUSH BC ; Save starting position +3548 16C7 1E FF LD E,255 ; All of string +3549 16C9 FE 29 CP ')' ; Any length given? +3550 16CB CA D5 16 JP Z,RSTSTR ; No - Rest of string +3551 16CE CD 10 0A CALL CHKSYN ; Make sure ',' follows +3552 16D1 2C .BYTE ',' +3553 16D2 CD 68 17 CALL GETINT ; Get integer 0-255 +3554 16D5 CD 10 0A RSTSTR: CALL CHKSYN ; Make sure ")" follows +3555 16D8 29 .BYTE ")" +3556 16D9 F1 POP AF ; Restore starting position +3557 16DA E3 EX (SP),HL ; Get string,8ave code string +3558 16DB 01 88 16 LD BC,MID1 ; Continuation of MID$ routine +3559 16DE C5 PUSH BC ; Save for return +3560 16DF 3D DEC A ; Starting position-1 +3561 16E0 BE CP (HL) ; Compare with length +3562 16E1 06 00 LD B,0 ; Zero bytes length +3563 16E3 D0 RET NC ; Null string if start past end +3564 16E4 4F LD C,A ; Save starting position-1 +3565 16E5 7E LD A,(HL) ; Get length of string +3566 16E6 91 SUB C ; Subtract start +3567 16E7 BB CP E ; Enough string for it? +3568 16E8 47 LD B,A ; Save maximum length available +3569 16E9 D8 RET C ; Truncate string if needed +3570 16EA 43 LD B,E ; Set specified length +3571 16EB C9 RET ; Go and create string +3572 16EC +3573 16EC CD 56 16 VAL: CALL GETLEN ; Get length of string +3574 16EF CA 09 18 JP Z,RESZER ; Result zero +3575 16F2 5F LD E,A ; Save length +3576 16F3 23 INC HL +3577 16F4 23 INC HL +3578 16F5 7E LD A,(HL) ; Get LSB of address +3579 16F6 23 INC HL +3580 16F7 66 LD H,(HL) ; Get MSB of address +3581 16F8 6F LD L,A ; HL = String address +3582 16F9 E5 PUSH HL ; Save string address +3583 16FA 19 ADD HL,DE +3584 16FB 46 LD B,(HL) ; Get end of string+1 byte +3585 16FC 72 LD (HL),D ; Zero it to terminate +3586 16FD E3 EX (SP),HL ; Save string end,get start +3587 16FE C5 PUSH BC ; Save end+1 byte +3588 16FF 7E LD A,(HL) ; Get starting byte +3589 1700 FE 24 CP '$' ; Hex number indicated? [function added] +3590 1702 C2 0A 17 JP NZ,VAL1 +3591 1705 CD 34 1F CALL HEXTFP ; Convert Hex to FPREG +3592 1708 18 0D JR VAL3 +3593 170A FE 25 VAL1: CP '%' ; Binary number indicated? [function added] +3594 170C C2 14 17 JP NZ,VAL2 +3595 170F CD A4 1F CALL BINTFP ; Convert Bin to FPREG +3596 1712 18 03 JR VAL3 +3597 1714 CD F0 1A VAL2: CALL ASCTFP ; Convert ASCII string to FP +3598 1717 C1 VAL3: POP BC ; Restore end+1 byte +3599 1718 E1 POP HL ; Restore end+1 address +3600 1719 70 LD (HL),B ; Put back original byte +3601 171A C9 RET +3602 171B +3603 171B EB LFRGNM: EX DE,HL ; Code string address to HL +3604 171C CD 10 0A CALL CHKSYN ; Make sure ")" follows +3605 171F 29 .BYTE ")" +3606 1720 C1 MIDNUM: POP BC ; Get return address +3607 1721 D1 POP DE ; Get number supplied +3608 1722 C5 PUSH BC ; Re-save return address +3609 1723 43 LD B,E ; Number to B +3610 1724 C9 RET +3611 1725 +3612 1725 CD 6B 17 INP: CALL MAKINT ; Make it integer A +3613 1728 32 EF 30 LD (INPORT),A ; Set input port +3614 172B CD EE 30 CALL INPSUB ; Get input from port +3615 172E C3 D1 13 JP PASSA ; Return integer A +3616 1731 +3617 1731 CD 55 17 POUT: CALL SETIO ; Set up port number +3618 1734 C3 B6 30 JP OUTSUB ; Output data and return +3619 1737 +3620 1737 CD 55 17 WAIT: CALL SETIO ; Set up port number +3621 173A F5 PUSH AF ; Save AND mask +3622 173B 1E 00 LD E,0 ; Assume zero if none given +3623 173D 2B DEC HL ; DEC 'cos GETCHR INCs +3624 173E CD 9A 0B CALL GETCHR ; Get next character +3625 1741 CA 4B 17 JP Z,NOXOR ; No XOR byte given +3626 1744 CD 10 0A CALL CHKSYN ; Make sure ',' follows +3627 1747 2C .BYTE ',' +3628 1748 CD 68 17 CALL GETINT ; Get integer 0-255 to XOR with +3629 174B C1 NOXOR: POP BC ; Restore AND mask +3630 174C CD EE 30 WAITLP: CALL INPSUB ; Get input +3631 174F AB XOR E ; Flip selected bits +3632 1750 A0 AND B ; Result non-zero? +3633 1751 CA 4C 17 JP Z,WAITLP ; No = keep waiting +3634 1754 C9 RET +3635 1755 +3636 1755 CD 68 17 SETIO: CALL GETINT ; Get integer 0-255 +3637 1758 32 EF 30 LD (INPORT),A ; Set input port +3638 175B 32 B7 30 LD (OTPORT),A ; Set output port +3639 175E CD 10 0A CALL CHKSYN ; Make sure ',' follows +3640 1761 2C .BYTE ',' +3641 1762 C3 68 17 JP GETINT ; Get integer 0-255 and return +3642 1765 +3643 1765 CD 9A 0B FNDNUM: CALL GETCHR ; Get next character +3644 1768 CD 07 10 GETINT: CALL GETNUM ; Get a number from 0 to 255 +3645 176B CD 46 0C MAKINT: CALL DEPINT ; Make sure value 0 - 255 +3646 176E 7A LD A,D ; Get MSB of number +3647 176F B7 OR A ; Zero? +3648 1770 C2 61 0C JP NZ,FCERR ; No - Error +3649 1773 2B DEC HL ; DEC 'cos GETCHR INCs +3650 1774 CD 9A 0B CALL GETCHR ; Get next character +3651 1777 7B LD A,E ; Get number to A +3652 1778 C9 RET +3653 1779 +3654 1779 CD 4C 0C PEEK: CALL DEINT ; Get memory address +3655 177C 1A LD A,(DE) ; Get byte in memory +3656 177D C3 D1 13 JP PASSA ; Return integer A +3657 1780 +3658 1780 CD 07 10 POKE: CALL GETNUM ; Get memory address +3659 1783 CD 4C 0C CALL DEINT ; Get integer -32768 to 3276 +3660 1786 D5 PUSH DE ; Save memory address +3661 1787 CD 10 0A CALL CHKSYN ; Make sure ',' follows +3662 178A 2C .BYTE ',' +3663 178B CD 68 17 CALL GETINT ; Get integer 0-255 +3664 178E D1 POP DE ; Restore memory address +3665 178F 12 LD (DE),A ; Load it into memory +3666 1790 C9 RET +3667 1791 +3668 1791 21 67 1C ROUND: LD HL,HALF ; Add 0.5 to FPREG +3669 1794 CD 38 1A ADDPHL: CALL LOADFP ; Load FP at (HL) to BCDE +3670 1797 C3 A3 17 JP FPADD ; Add BCDE to FPREG +3671 179A +3672 179A CD 38 1A SUBPHL: CALL LOADFP ; FPREG = -FPREG + number at HL +3673 179D 21 .BYTE 21H ; Skip "POP BC" and "POP DE" +3674 179E C1 PSUB: POP BC ; Get FP number from stack +3675 179F D1 POP DE +3676 17A0 CD 12 1A SUBCDE: CALL INVSGN ; Negate FPREG +3677 17A3 78 FPADD: LD A,B ; Get FP exponent +3678 17A4 B7 OR A ; Is number zero? +3679 17A5 C8 RET Z ; Yes - Nothing to add +3680 17A6 3A 97 31 LD A,(FPEXP) ; Get FPREG exponent +3681 17A9 B7 OR A ; Is this number zero? +3682 17AA CA 2A 1A JP Z,FPBCDE ; Yes - Move BCDE to FPREG +3683 17AD 90 SUB B ; BCDE number larger? +3684 17AE D2 BD 17 JP NC,NOSWAP ; No - Don't swap them +3685 17B1 2F CPL ; Two's complement +3686 17B2 3C INC A ; FP exponent +3687 17B3 EB EX DE,HL +3688 17B4 CD 1A 1A CALL STAKFP ; Put FPREG on stack +3689 17B7 EB EX DE,HL +3690 17B8 CD 2A 1A CALL FPBCDE ; Move BCDE to FPREG +3691 17BB C1 POP BC ; Restore number from stack +3692 17BC D1 POP DE +3693 17BD FE 19 NOSWAP: CP 24+1 ; Second number insignificant? +3694 17BF D0 RET NC ; Yes - First number is result +3695 17C0 F5 PUSH AF ; Save number of bits to scale +3696 17C1 CD 4F 1A CALL SIGNS ; Set MSBs & sign of result +3697 17C4 67 LD H,A ; Save sign of result +3698 17C5 F1 POP AF ; Restore scaling factor +3699 17C6 CD 68 18 CALL SCALE ; Scale BCDE to same exponent +3700 17C9 B4 OR H ; Result to be positive? +3701 17CA 21 94 31 LD HL,FPREG ; Point to FPREG +3702 17CD F2 E3 17 JP P,MINCDE ; No - Subtract FPREG from CDE +3703 17D0 CD 48 18 CALL PLUCDE ; Add FPREG to CDE +3704 17D3 D2 29 18 JP NC,RONDUP ; No overflow - Round it up +3705 17D6 23 INC HL ; Point to exponent +3706 17D7 34 INC (HL) ; Increment it +3707 17D8 CA 51 07 JP Z,OVERR ; Number overflowed - Error +3708 17DB 2E 01 LD L,1 ; 1 bit to shift right +3709 17DD CD 7E 18 CALL SHRT1 ; Shift result right +3710 17E0 C3 29 18 JP RONDUP ; Round it up +3711 17E3 +3712 17E3 AF MINCDE: XOR A ; Clear A and carry +3713 17E4 90 SUB B ; Negate exponent +3714 17E5 47 LD B,A ; Re-save exponent +3715 17E6 7E LD A,(HL) ; Get LSB of FPREG +3716 17E7 9B SBC A, E ; Subtract LSB of BCDE +3717 17E8 5F LD E,A ; Save LSB of BCDE +3718 17E9 23 INC HL +3719 17EA 7E LD A,(HL) ; Get NMSB of FPREG +3720 17EB 9A SBC A,D ; Subtract NMSB of BCDE +3721 17EC 57 LD D,A ; Save NMSB of BCDE +3722 17ED 23 INC HL +3723 17EE 7E LD A,(HL) ; Get MSB of FPREG +3724 17EF 99 SBC A,C ; Subtract MSB of BCDE +3725 17F0 4F LD C,A ; Save MSB of BCDE +3726 17F1 DC 54 18 CONPOS: CALL C,COMPL ; Overflow - Make it positive +3727 17F4 +3728 17F4 68 BNORM: LD L,B ; L = Exponent +3729 17F5 63 LD H,E ; H = LSB +3730 17F6 AF XOR A +3731 17F7 47 BNRMLP: LD B,A ; Save bit count +3732 17F8 79 LD A,C ; Get MSB +3733 17F9 B7 OR A ; Is it zero? +3734 17FA C2 16 18 JP NZ,PNORM ; No - Do it bit at a time +3735 17FD 4A LD C,D ; MSB = NMSB +3736 17FE 54 LD D,H ; NMSB= LSB +3737 17FF 65 LD H,L ; LSB = VLSB +3738 1800 6F LD L,A ; VLSB= 0 +3739 1801 78 LD A,B ; Get exponent +3740 1802 D6 08 SUB 8 ; Count 8 bits +3741 1804 FE E0 CP -24-8 ; Was number zero? +3742 1806 C2 F7 17 JP NZ,BNRMLP ; No - Keep normalising +3743 1809 AF RESZER: XOR A ; Result is zero +3744 180A 32 97 31 SAVEXP: LD (FPEXP),A ; Save result as zero +3745 180D C9 RET +3746 180E +3747 180E 05 NORMAL: DEC B ; Count bits +3748 180F 29 ADD HL,HL ; Shift HL left +3749 1810 7A LD A,D ; Get NMSB +3750 1811 17 RLA ; Shift left with last bit +3751 1812 57 LD D,A ; Save NMSB +3752 1813 79 LD A,C ; Get MSB +3753 1814 8F ADC A,A ; Shift left with last bit +3754 1815 4F LD C,A ; Save MSB +3755 1816 F2 0E 18 PNORM: JP P,NORMAL ; Not done - Keep going +3756 1819 78 LD A,B ; Number of bits shifted +3757 181A 5C LD E,H ; Save HL in EB +3758 181B 45 LD B,L +3759 181C B7 OR A ; Any shifting done? +3760 181D CA 29 18 JP Z,RONDUP ; No - Round it up +3761 1820 21 97 31 LD HL,FPEXP ; Point to exponent +3762 1823 86 ADD A,(HL) ; Add shifted bits +3763 1824 77 LD (HL),A ; Re-save exponent +3764 1825 D2 09 18 JP NC,RESZER ; Underflow - Result is zero +3765 1828 C8 RET Z ; Result is zero +3766 1829 78 RONDUP: LD A,B ; Get VLSB of number +3767 182A 21 97 31 RONDB: LD HL,FPEXP ; Point to exponent +3768 182D B7 OR A ; Any rounding? +3769 182E FC 3B 18 CALL M,FPROND ; Yes - Round number up +3770 1831 46 LD B,(HL) ; B = Exponent +3771 1832 23 INC HL +3772 1833 7E LD A,(HL) ; Get sign of result +3773 1834 E6 80 AND 10000000B ; Only bit 7 needed +3774 1836 A9 XOR C ; Set correct sign +3775 1837 4F LD C,A ; Save correct sign in number +3776 1838 C3 2A 1A JP FPBCDE ; Move BCDE to FPREG +3777 183B +3778 183B 1C FPROND: INC E ; Round LSB +3779 183C C0 RET NZ ; Return if ok +3780 183D 14 INC D ; Round NMSB +3781 183E C0 RET NZ ; Return if ok +3782 183F 0C INC C ; Round MSB +3783 1840 C0 RET NZ ; Return if ok +3784 1841 0E 80 LD C,80H ; Set normal value +3785 1843 34 INC (HL) ; Increment exponent +3786 1844 C0 RET NZ ; Return if ok +3787 1845 C3 51 07 JP OVERR ; Overflow error +3788 1848 +3789 1848 7E PLUCDE: LD A,(HL) ; Get LSB of FPREG +3790 1849 83 ADD A,E ; Add LSB of BCDE +3791 184A 5F LD E,A ; Save LSB of BCDE +3792 184B 23 INC HL +3793 184C 7E LD A,(HL) ; Get NMSB of FPREG +3794 184D 8A ADC A,D ; Add NMSB of BCDE +3795 184E 57 LD D,A ; Save NMSB of BCDE +3796 184F 23 INC HL +3797 1850 7E LD A,(HL) ; Get MSB of FPREG +3798 1851 89 ADC A,C ; Add MSB of BCDE +3799 1852 4F LD C,A ; Save MSB of BCDE +3800 1853 C9 RET +3801 1854 +3802 1854 21 98 31 COMPL: LD HL,SGNRES ; Sign of result +3803 1857 7E LD A,(HL) ; Get sign of result +3804 1858 2F CPL ; Negate it +3805 1859 77 LD (HL),A ; Put it back +3806 185A AF XOR A +3807 185B 6F LD L,A ; Set L to zero +3808 185C 90 SUB B ; Negate exponent,set carry +3809 185D 47 LD B,A ; Re-save exponent +3810 185E 7D LD A,L ; Load zero +3811 185F 9B SBC A,E ; Negate LSB +3812 1860 5F LD E,A ; Re-save LSB +3813 1861 7D LD A,L ; Load zero +3814 1862 9A SBC A,D ; Negate NMSB +3815 1863 57 LD D,A ; Re-save NMSB +3816 1864 7D LD A,L ; Load zero +3817 1865 99 SBC A,C ; Negate MSB +3818 1866 4F LD C,A ; Re-save MSB +3819 1867 C9 RET +3820 1868 +3821 1868 06 00 SCALE: LD B,0 ; Clear underflow +3822 186A D6 08 SCALLP: SUB 8 ; 8 bits (a whole byte)? +3823 186C DA 77 18 JP C,SHRITE ; No - Shift right A bits +3824 186F 43 LD B,E ; <- Shift +3825 1870 5A LD E,D ; <- right +3826 1871 51 LD D,C ; <- eight +3827 1872 0E 00 LD C,0 ; <- bits +3828 1874 C3 6A 18 JP SCALLP ; More bits to shift +3829 1877 +3830 1877 C6 09 SHRITE: ADD A,8+1 ; Adjust count +3831 1879 6F LD L,A ; Save bits to shift +3832 187A AF SHRLP: XOR A ; Flag for all done +3833 187B 2D DEC L ; All shifting done? +3834 187C C8 RET Z ; Yes - Return +3835 187D 79 LD A,C ; Get MSB +3836 187E 1F SHRT1: RRA ; Shift it right +3837 187F 4F LD C,A ; Re-save +3838 1880 7A LD A,D ; Get NMSB +3839 1881 1F RRA ; Shift right with last bit +3840 1882 57 LD D,A ; Re-save it +3841 1883 7B LD A,E ; Get LSB +3842 1884 1F RRA ; Shift right with last bit +3843 1885 5F LD E,A ; Re-save it +3844 1886 78 LD A,B ; Get underflow +3845 1887 1F RRA ; Shift right with last bit +3846 1888 47 LD B,A ; Re-save underflow +3847 1889 C3 7A 18 JP SHRLP ; More bits to do +3848 188C +3849 188C 00 00 00 81 UNITY: .BYTE 000H,000H,000H,081H ; 1.00000 +3850 1890 +3851 1890 03 LOGTAB: .BYTE 3 ; Table used by LOG +3852 1891 AA 56 19 80 .BYTE 0AAH,056H,019H,080H ; 0.59898 +3853 1895 F1 22 76 80 .BYTE 0F1H,022H,076H,080H ; 0.96147 +3854 1899 45 AA 38 82 .BYTE 045H,0AAH,038H,082H ; 2.88539 +3855 189D +3856 189D CD E9 19 LOG: CALL TSTSGN ; Test sign of value +3857 18A0 B7 OR A +3858 18A1 EA 61 0C JP PE,FCERR ; ?FC Error if <= zero +3859 18A4 21 97 31 LD HL,FPEXP ; Point to exponent +3860 18A7 7E LD A,(HL) ; Get exponent +3861 18A8 01 35 80 LD BC,8035H ; BCDE = SQR(1/2) +3862 18AB 11 F3 04 LD DE,04F3H +3863 18AE 90 SUB B ; Scale value to be < 1 +3864 18AF F5 PUSH AF ; Save scale factor +3865 18B0 70 LD (HL),B ; Save new exponent +3866 18B1 D5 PUSH DE ; Save SQR(1/2) +3867 18B2 C5 PUSH BC +3868 18B3 CD A3 17 CALL FPADD ; Add SQR(1/2) to value +3869 18B6 C1 POP BC ; Restore SQR(1/2) +3870 18B7 D1 POP DE +3871 18B8 04 INC B ; Make it SQR(2) +3872 18B9 CD 3F 19 CALL DVBCDE ; Divide by SQR(2) +3873 18BC 21 8C 18 LD HL,UNITY ; Point to 1. +3874 18BF CD 9A 17 CALL SUBPHL ; Subtract FPREG from 1 +3875 18C2 21 90 18 LD HL,LOGTAB ; Coefficient table +3876 18C5 CD 31 1D CALL SUMSER ; Evaluate sum of series +3877 18C8 01 80 80 LD BC,8080H ; BCDE = -0.5 +3878 18CB 11 00 00 LD DE,0000H +3879 18CE CD A3 17 CALL FPADD ; Subtract 0.5 from FPREG +3880 18D1 F1 POP AF ; Restore scale factor +3881 18D2 CD 64 1B CALL RSCALE ; Re-scale number +3882 18D5 01 31 80 MULLN2: LD BC,8031H ; BCDE = Ln(2) +3883 18D8 11 18 72 LD DE,7218H +3884 18DB 21 .BYTE 21H ; Skip "POP BC" and "POP DE" +3885 18DC +3886 18DC C1 MULT: POP BC ; Get number from stack +3887 18DD D1 POP DE +3888 18DE CD E9 19 FPMULT: CALL TSTSGN ; Test sign of FPREG +3889 18E1 C8 RET Z ; Return zero if zero +3890 18E2 2E 00 LD L,0 ; Flag add exponents +3891 18E4 CD A7 19 CALL ADDEXP ; Add exponents +3892 18E7 79 LD A,C ; Get MSB of multiplier +3893 18E8 32 A6 31 LD (MULVAL),A ; Save MSB of multiplier +3894 18EB EB EX DE,HL +3895 18EC 22 A7 31 LD (MULVAL+1),HL ; Save rest of multiplier +3896 18EF 01 00 00 LD BC,0 ; Partial product (BCDE) = zero +3897 18F2 50 LD D,B +3898 18F3 58 LD E,B +3899 18F4 21 F4 17 LD HL,BNORM ; Address of normalise +3900 18F7 E5 PUSH HL ; Save for return +3901 18F8 21 00 19 LD HL,MULT8 ; Address of 8 bit multiply +3902 18FB E5 PUSH HL ; Save for NMSB,MSB +3903 18FC E5 PUSH HL ; +3904 18FD 21 94 31 LD HL,FPREG ; Point to number +3905 1900 7E MULT8: LD A,(HL) ; Get LSB of number +3906 1901 23 INC HL ; Point to NMSB +3907 1902 B7 OR A ; Test LSB +3908 1903 CA 2C 19 JP Z,BYTSFT ; Zero - shift to next byte +3909 1906 E5 PUSH HL ; Save address of number +3910 1907 2E 08 LD L,8 ; 8 bits to multiply by +3911 1909 1F MUL8LP: RRA ; Shift LSB right +3912 190A 67 LD H,A ; Save LSB +3913 190B 79 LD A,C ; Get MSB +3914 190C D2 1A 19 JP NC,NOMADD ; Bit was zero - Don't add +3915 190F E5 PUSH HL ; Save LSB and count +3916 1910 2A A7 31 LD HL,(MULVAL+1) ; Get LSB and NMSB +3917 1913 19 ADD HL,DE ; Add NMSB and LSB +3918 1914 EB EX DE,HL ; Leave sum in DE +3919 1915 E1 POP HL ; Restore MSB and count +3920 1916 3A A6 31 LD A,(MULVAL) ; Get MSB of multiplier +3921 1919 89 ADC A,C ; Add MSB +3922 191A 1F NOMADD: RRA ; Shift MSB right +3923 191B 4F LD C,A ; Re-save MSB +3924 191C 7A LD A,D ; Get NMSB +3925 191D 1F RRA ; Shift NMSB right +3926 191E 57 LD D,A ; Re-save NMSB +3927 191F 7B LD A,E ; Get LSB +3928 1920 1F RRA ; Shift LSB right +3929 1921 5F LD E,A ; Re-save LSB +3930 1922 78 LD A,B ; Get VLSB +3931 1923 1F RRA ; Shift VLSB right +3932 1924 47 LD B,A ; Re-save VLSB +3933 1925 2D DEC L ; Count bits multiplied +3934 1926 7C LD A,H ; Get LSB of multiplier +3935 1927 C2 09 19 JP NZ,MUL8LP ; More - Do it +3936 192A E1 POPHRT: POP HL ; Restore address of number +3937 192B C9 RET +3938 192C +3939 192C 43 BYTSFT: LD B,E ; Shift partial product left +3940 192D 5A LD E,D +3941 192E 51 LD D,C +3942 192F 4F LD C,A +3943 1930 C9 RET +3944 1931 +3945 1931 CD 1A 1A DIV10: CALL STAKFP ; Save FPREG on stack +3946 1934 01 20 84 LD BC,8420H ; BCDE = 10. +3947 1937 11 00 00 LD DE,0000H +3948 193A CD 2A 1A CALL FPBCDE ; Move 10 to FPREG +3949 193D +3950 193D C1 DIV: POP BC ; Get number from stack +3951 193E D1 POP DE +3952 193F CD E9 19 DVBCDE: CALL TSTSGN ; Test sign of FPREG +3953 1942 CA 45 07 JP Z,DZERR ; Error if division by zero +3954 1945 2E FF LD L,-1 ; Flag subtract exponents +3955 1947 CD A7 19 CALL ADDEXP ; Subtract exponents +3956 194A 34 INC (HL) ; Add 2 to exponent to adjust +3957 194B 34 INC (HL) +3958 194C 2B DEC HL ; Point to MSB +3959 194D 7E LD A,(HL) ; Get MSB of dividend +3960 194E 32 C2 30 LD (DIV3),A ; Save for subtraction +3961 1951 2B DEC HL +3962 1952 7E LD A,(HL) ; Get NMSB of dividend +3963 1953 32 BE 30 LD (DIV2),A ; Save for subtraction +3964 1956 2B DEC HL +3965 1957 7E LD A,(HL) ; Get MSB of dividend +3966 1958 32 BA 30 LD (DIV1),A ; Save for subtraction +3967 195B 41 LD B,C ; Get MSB +3968 195C EB EX DE,HL ; NMSB,LSB to HL +3969 195D AF XOR A +3970 195E 4F LD C,A ; Clear MSB of quotient +3971 195F 57 LD D,A ; Clear NMSB of quotient +3972 1960 5F LD E,A ; Clear LSB of quotient +3973 1961 32 C5 30 LD (DIV4),A ; Clear overflow count +3974 1964 E5 DIVLP: PUSH HL ; Save divisor +3975 1965 C5 PUSH BC +3976 1966 7D LD A,L ; Get LSB of number +3977 1967 CD B9 30 CALL DIVSUP ; Subt' divisor from dividend +3978 196A DE 00 SBC A,0 ; Count for overflows +3979 196C 3F CCF +3980 196D D2 77 19 JP NC,RESDIV ; Restore divisor if borrow +3981 1970 32 C5 30 LD (DIV4),A ; Re-save overflow count +3982 1973 F1 POP AF ; Scrap divisor +3983 1974 F1 POP AF +3984 1975 37 SCF ; Set carry to +3985 1976 D2 .BYTE 0D2H ; Skip "POP BC" and "POP HL" +3986 1977 +3987 1977 C1 RESDIV: POP BC ; Restore divisor +3988 1978 E1 POP HL +3989 1979 79 LD A,C ; Get MSB of quotient +3990 197A 3C INC A +3991 197B 3D DEC A +3992 197C 1F RRA ; Bit 0 to bit 7 +3993 197D FA 2A 18 JP M,RONDB ; Done - Normalise result +3994 1980 17 RLA ; Restore carry +3995 1981 7B LD A,E ; Get LSB of quotient +3996 1982 17 RLA ; Double it +3997 1983 5F LD E,A ; Put it back +3998 1984 7A LD A,D ; Get NMSB of quotient +3999 1985 17 RLA ; Double it +4000 1986 57 LD D,A ; Put it back +4001 1987 79 LD A,C ; Get MSB of quotient +4002 1988 17 RLA ; Double it +4003 1989 4F LD C,A ; Put it back +4004 198A 29 ADD HL,HL ; Double NMSB,LSB of divisor +4005 198B 78 LD A,B ; Get MSB of divisor +4006 198C 17 RLA ; Double it +4007 198D 47 LD B,A ; Put it back +4008 198E 3A C5 30 LD A,(DIV4) ; Get VLSB of quotient +4009 1991 17 RLA ; Double it +4010 1992 32 C5 30 LD (DIV4),A ; Put it back +4011 1995 79 LD A,C ; Get MSB of quotient +4012 1996 B2 OR D ; Merge NMSB +4013 1997 B3 OR E ; Merge LSB +4014 1998 C2 64 19 JP NZ,DIVLP ; Not done - Keep dividing +4015 199B E5 PUSH HL ; Save divisor +4016 199C 21 97 31 LD HL,FPEXP ; Point to exponent +4017 199F 35 DEC (HL) ; Divide by 2 +4018 19A0 E1 POP HL ; Restore divisor +4019 19A1 C2 64 19 JP NZ,DIVLP ; Ok - Keep going +4020 19A4 C3 51 07 JP OVERR ; Overflow error +4021 19A7 +4022 19A7 78 ADDEXP: LD A,B ; Get exponent of dividend +4023 19A8 B7 OR A ; Test it +4024 19A9 CA CB 19 JP Z,OVTST3 ; Zero - Result zero +4025 19AC 7D LD A,L ; Get add/subtract flag +4026 19AD 21 97 31 LD HL,FPEXP ; Point to exponent +4027 19B0 AE XOR (HL) ; Add or subtract it +4028 19B1 80 ADD A,B ; Add the other exponent +4029 19B2 47 LD B,A ; Save new exponent +4030 19B3 1F RRA ; Test exponent for overflow +4031 19B4 A8 XOR B +4032 19B5 78 LD A,B ; Get exponent +4033 19B6 F2 CA 19 JP P,OVTST2 ; Positive - Test for overflow +4034 19B9 C6 80 ADD A,80H ; Add excess 128 +4035 19BB 77 LD (HL),A ; Save new exponent +4036 19BC CA 2A 19 JP Z,POPHRT ; Zero - Result zero +4037 19BF CD 4F 1A CALL SIGNS ; Set MSBs and sign of result +4038 19C2 77 LD (HL),A ; Save new exponent +4039 19C3 2B DEC HL ; Point to MSB +4040 19C4 C9 RET +4041 19C5 +4042 19C5 CD E9 19 OVTST1: CALL TSTSGN ; Test sign of FPREG +4043 19C8 2F CPL ; Invert sign +4044 19C9 E1 POP HL ; Clean up stack +4045 19CA B7 OVTST2: OR A ; Test if new exponent zero +4046 19CB E1 OVTST3: POP HL ; Clear off return address +4047 19CC F2 09 18 JP P,RESZER ; Result zero +4048 19CF C3 51 07 JP OVERR ; Overflow error +4049 19D2 +4050 19D2 CD 35 1A MLSP10: CALL BCDEFP ; Move FPREG to BCDE +4051 19D5 78 LD A,B ; Get exponent +4052 19D6 B7 OR A ; Is it zero? +4053 19D7 C8 RET Z ; Yes - Result is zero +4054 19D8 C6 02 ADD A,2 ; Multiply by 4 +4055 19DA DA 51 07 JP C,OVERR ; Overflow - ?OV Error +4056 19DD 47 LD B,A ; Re-save exponent +4057 19DE CD A3 17 CALL FPADD ; Add BCDE to FPREG (Times 5) +4058 19E1 21 97 31 LD HL,FPEXP ; Point to exponent +4059 19E4 34 INC (HL) ; Double number (Times 10) +4060 19E5 C0 RET NZ ; Ok - Return +4061 19E6 C3 51 07 JP OVERR ; Overflow error +4062 19E9 +4063 19E9 3A 97 31 TSTSGN: LD A,(FPEXP) ; Get sign of FPREG +4064 19EC B7 OR A +4065 19ED C8 RET Z ; RETurn if number is zero +4066 19EE 3A 96 31 LD A,(FPREG+2) ; Get MSB of FPREG +4067 19F1 FE .BYTE 0FEH ; Test sign +4068 19F2 2F RETREL: CPL ; Invert sign +4069 19F3 17 RLA ; Sign bit to carry +4070 19F4 9F FLGDIF: SBC A,A ; Carry to all bits of A +4071 19F5 C0 RET NZ ; Return -1 if negative +4072 19F6 3C INC A ; Bump to +1 +4073 19F7 C9 RET ; Positive - Return +1 +4074 19F8 +4075 19F8 CD E9 19 SGN: CALL TSTSGN ; Test sign of FPREG +4076 19FB 06 88 FLGREL: LD B,80H+8 ; 8 bit integer in exponent +4077 19FD 11 00 00 LD DE,0 ; Zero NMSB and LSB +4078 1A00 21 97 31 RETINT: LD HL,FPEXP ; Point to exponent +4079 1A03 4F LD C,A ; CDE = MSB,NMSB and LSB +4080 1A04 70 LD (HL),B ; Save exponent +4081 1A05 06 00 LD B,0 ; CDE = integer to normalise +4082 1A07 23 INC HL ; Point to sign of result +4083 1A08 36 80 LD (HL),80H ; Set sign of result +4084 1A0A 17 RLA ; Carry = sign of integer +4085 1A0B C3 F1 17 JP CONPOS ; Set sign of result +4086 1A0E +4087 1A0E CD E9 19 ABS: CALL TSTSGN ; Test sign of FPREG +4088 1A11 F0 RET P ; Return if positive +4089 1A12 21 96 31 INVSGN: LD HL,FPREG+2 ; Point to MSB +4090 1A15 7E LD A,(HL) ; Get sign of mantissa +4091 1A16 EE 80 XOR 80H ; Invert sign of mantissa +4092 1A18 77 LD (HL),A ; Re-save sign of mantissa +4093 1A19 C9 RET +4094 1A1A +4095 1A1A EB STAKFP: EX DE,HL ; Save code string address +4096 1A1B 2A 94 31 LD HL,(FPREG) ; LSB,NLSB of FPREG +4097 1A1E E3 EX (SP),HL ; Stack them,get return +4098 1A1F E5 PUSH HL ; Re-save return +4099 1A20 2A 96 31 LD HL,(FPREG+2) ; MSB and exponent of FPREG +4100 1A23 E3 EX (SP),HL ; Stack them,get return +4101 1A24 E5 PUSH HL ; Re-save return +4102 1A25 EB EX DE,HL ; Restore code string address +4103 1A26 C9 RET +4104 1A27 +4105 1A27 CD 38 1A PHLTFP: CALL LOADFP ; Number at HL to BCDE +4106 1A2A EB FPBCDE: EX DE,HL ; Save code string address +4107 1A2B 22 94 31 LD (FPREG),HL ; Save LSB,NLSB of number +4108 1A2E 60 LD H,B ; Exponent of number +4109 1A2F 69 LD L,C ; MSB of number +4110 1A30 22 96 31 LD (FPREG+2),HL ; Save MSB and exponent +4111 1A33 EB EX DE,HL ; Restore code string address +4112 1A34 C9 RET +4113 1A35 +4114 1A35 21 94 31 BCDEFP: LD HL,FPREG ; Point to FPREG +4115 1A38 5E LOADFP: LD E,(HL) ; Get LSB of number +4116 1A39 23 INC HL +4117 1A3A 56 LD D,(HL) ; Get NMSB of number +4118 1A3B 23 INC HL +4119 1A3C 4E LD C,(HL) ; Get MSB of number +4120 1A3D 23 INC HL +4121 1A3E 46 LD B,(HL) ; Get exponent of number +4122 1A3F 23 INCHL: INC HL ; Used for conditional "INC HL" +4123 1A40 C9 RET +4124 1A41 +4125 1A41 11 94 31 FPTHL: LD DE,FPREG ; Point to FPREG +4126 1A44 06 04 DETHL4: LD B,4 ; 4 bytes to move +4127 1A46 1A DETHLB: LD A,(DE) ; Get source +4128 1A47 77 LD (HL),A ; Save destination +4129 1A48 13 INC DE ; Next source +4130 1A49 23 INC HL ; Next destination +4131 1A4A 05 DEC B ; Count bytes +4132 1A4B C2 46 1A JP NZ,DETHLB ; Loop if more +4133 1A4E C9 RET +4134 1A4F +4135 1A4F 21 96 31 SIGNS: LD HL,FPREG+2 ; Point to MSB of FPREG +4136 1A52 7E LD A,(HL) ; Get MSB +4137 1A53 07 RLCA ; Old sign to carry +4138 1A54 37 SCF ; Set MSBit +4139 1A55 1F RRA ; Set MSBit of MSB +4140 1A56 77 LD (HL),A ; Save new MSB +4141 1A57 3F CCF ; Complement sign +4142 1A58 1F RRA ; Old sign to carry +4143 1A59 23 INC HL +4144 1A5A 23 INC HL +4145 1A5B 77 LD (HL),A ; Set sign of result +4146 1A5C 79 LD A,C ; Get MSB +4147 1A5D 07 RLCA ; Old sign to carry +4148 1A5E 37 SCF ; Set MSBit +4149 1A5F 1F RRA ; Set MSBit of MSB +4150 1A60 4F LD C,A ; Save MSB +4151 1A61 1F RRA +4152 1A62 AE XOR (HL) ; New sign of result +4153 1A63 C9 RET +4154 1A64 +4155 1A64 78 CMPNUM: LD A,B ; Get exponent of number +4156 1A65 B7 OR A +4157 1A66 CA E9 19 JP Z,TSTSGN ; Zero - Test sign of FPREG +4158 1A69 21 F2 19 LD HL,RETREL ; Return relation routine +4159 1A6C E5 PUSH HL ; Save for return +4160 1A6D CD E9 19 CALL TSTSGN ; Test sign of FPREG +4161 1A70 79 LD A,C ; Get MSB of number +4162 1A71 C8 RET Z ; FPREG zero - Number's MSB +4163 1A72 21 96 31 LD HL,FPREG+2 ; MSB of FPREG +4164 1A75 AE XOR (HL) ; Combine signs +4165 1A76 79 LD A,C ; Get MSB of number +4166 1A77 F8 RET M ; Exit if signs different +4167 1A78 CD 7E 1A CALL CMPFP ; Compare FP numbers +4168 1A7B 1F RRA ; Get carry to sign +4169 1A7C A9 XOR C ; Combine with MSB of number +4170 1A7D C9 RET +4171 1A7E +4172 1A7E 23 CMPFP: INC HL ; Point to exponent +4173 1A7F 78 LD A,B ; Get exponent +4174 1A80 BE CP (HL) ; Compare exponents +4175 1A81 C0 RET NZ ; Different +4176 1A82 2B DEC HL ; Point to MBS +4177 1A83 79 LD A,C ; Get MSB +4178 1A84 BE CP (HL) ; Compare MSBs +4179 1A85 C0 RET NZ ; Different +4180 1A86 2B DEC HL ; Point to NMSB +4181 1A87 7A LD A,D ; Get NMSB +4182 1A88 BE CP (HL) ; Compare NMSBs +4183 1A89 C0 RET NZ ; Different +4184 1A8A 2B DEC HL ; Point to LSB +4185 1A8B 7B LD A,E ; Get LSB +4186 1A8C 96 SUB (HL) ; Compare LSBs +4187 1A8D C0 RET NZ ; Different +4188 1A8E E1 POP HL ; Drop RETurn +4189 1A8F E1 POP HL ; Drop another RETurn +4190 1A90 C9 RET +4191 1A91 +4192 1A91 47 FPINT: LD B,A ; <- Move +4193 1A92 4F LD C,A ; <- exponent +4194 1A93 57 LD D,A ; <- to all +4195 1A94 5F LD E,A ; <- bits +4196 1A95 B7 OR A ; Test exponent +4197 1A96 C8 RET Z ; Zero - Return zero +4198 1A97 E5 PUSH HL ; Save pointer to number +4199 1A98 CD 35 1A CALL BCDEFP ; Move FPREG to BCDE +4200 1A9B CD 4F 1A CALL SIGNS ; Set MSBs & sign of result +4201 1A9E AE XOR (HL) ; Combine with sign of FPREG +4202 1A9F 67 LD H,A ; Save combined signs +4203 1AA0 FC B5 1A CALL M,DCBCDE ; Negative - Decrement BCDE +4204 1AA3 3E 98 LD A,80H+24 ; 24 bits +4205 1AA5 90 SUB B ; Bits to shift +4206 1AA6 CD 68 18 CALL SCALE ; Shift BCDE +4207 1AA9 7C LD A,H ; Get combined sign +4208 1AAA 17 RLA ; Sign to carry +4209 1AAB DC 3B 18 CALL C,FPROND ; Negative - Round number up +4210 1AAE 06 00 LD B,0 ; Zero exponent +4211 1AB0 DC 54 18 CALL C,COMPL ; If negative make positive +4212 1AB3 E1 POP HL ; Restore pointer to number +4213 1AB4 C9 RET +4214 1AB5 +4215 1AB5 1B DCBCDE: DEC DE ; Decrement BCDE +4216 1AB6 7A LD A,D ; Test LSBs +4217 1AB7 A3 AND E +4218 1AB8 3C INC A +4219 1AB9 C0 RET NZ ; Exit if LSBs not FFFF +4220 1ABA 0B DEC BC ; Decrement MSBs +4221 1ABB C9 RET +4222 1ABC +4223 1ABC 21 97 31 INT: LD HL,FPEXP ; Point to exponent +4224 1ABF 7E LD A,(HL) ; Get exponent +4225 1AC0 FE 98 CP 80H+24 ; Integer accuracy only? +4226 1AC2 3A 94 31 LD A,(FPREG) ; Get LSB +4227 1AC5 D0 RET NC ; Yes - Already integer +4228 1AC6 7E LD A,(HL) ; Get exponent +4229 1AC7 CD 91 1A CALL FPINT ; F.P to integer +4230 1ACA 36 98 LD (HL),80H+24 ; Save 24 bit integer +4231 1ACC 7B LD A,E ; Get LSB of number +4232 1ACD F5 PUSH AF ; Save LSB +4233 1ACE 79 LD A,C ; Get MSB of number +4234 1ACF 17 RLA ; Sign to carry +4235 1AD0 CD F1 17 CALL CONPOS ; Set sign of result +4236 1AD3 F1 POP AF ; Restore LSB of number +4237 1AD4 C9 RET +4238 1AD5 +4239 1AD5 21 00 00 MLDEBC: LD HL,0 ; Clear partial product +4240 1AD8 78 LD A,B ; Test multiplier +4241 1AD9 B1 OR C +4242 1ADA C8 RET Z ; Return zero if zero +4243 1ADB 3E 10 LD A,16 ; 16 bits +4244 1ADD 29 MLDBLP: ADD HL,HL ; Shift P.P left +4245 1ADE DA 15 13 JP C,BSERR ; ?BS Error if overflow +4246 1AE1 EB EX DE,HL +4247 1AE2 29 ADD HL,HL ; Shift multiplier left +4248 1AE3 EB EX DE,HL +4249 1AE4 D2 EB 1A JP NC,NOMLAD ; Bit was zero - No add +4250 1AE7 09 ADD HL,BC ; Add multiplicand +4251 1AE8 DA 15 13 JP C,BSERR ; ?BS Error if overflow +4252 1AEB 3D NOMLAD: DEC A ; Count bits +4253 1AEC C2 DD 1A JP NZ,MLDBLP ; More +4254 1AEF C9 RET +4255 1AF0 +4256 1AF0 FE 2D ASCTFP: CP '-' ; Negative? +4257 1AF2 F5 PUSH AF ; Save it and flags +4258 1AF3 CA FC 1A JP Z,CNVNUM ; Yes - Convert number +4259 1AF6 FE 2B CP '+' ; Positive? +4260 1AF8 CA FC 1A JP Z,CNVNUM ; Yes - Convert number +4261 1AFB 2B DEC HL ; DEC 'cos GETCHR INCs +4262 1AFC CD 09 18 CNVNUM: CALL RESZER ; Set result to zero +4263 1AFF 47 LD B,A ; Digits after point counter +4264 1B00 57 LD D,A ; Sign of exponent +4265 1B01 5F LD E,A ; Exponent of ten +4266 1B02 2F CPL +4267 1B03 4F LD C,A ; Before or after point flag +4268 1B04 CD 9A 0B MANLP: CALL GETCHR ; Get next character +4269 1B07 DA 4D 1B JP C,ADDIG ; Digit - Add to number +4270 1B0A FE 2E CP '.' +4271 1B0C CA 28 1B JP Z,DPOINT ; '.' - Flag point +4272 1B0F FE 45 CP 'E' +4273 1B11 C2 2C 1B JP NZ,CONEXP ; Not 'E' - Scale number +4274 1B14 CD 9A 0B CALL GETCHR ; Get next character +4275 1B17 CD 40 11 CALL SGNEXP ; Get sign of exponent +4276 1B1A CD 9A 0B EXPLP: CALL GETCHR ; Get next character +4277 1B1D DA 6F 1B JP C,EDIGIT ; Digit - Add to exponent +4278 1B20 14 INC D ; Is sign negative? +4279 1B21 C2 2C 1B JP NZ,CONEXP ; No - Scale number +4280 1B24 AF XOR A +4281 1B25 93 SUB E ; Negate exponent +4282 1B26 5F LD E,A ; And re-save it +4283 1B27 0C INC C ; Flag end of number +4284 1B28 0C DPOINT: INC C ; Flag point passed +4285 1B29 CA 04 1B JP Z,MANLP ; Zero - Get another digit +4286 1B2C E5 CONEXP: PUSH HL ; Save code string address +4287 1B2D 7B LD A,E ; Get exponent +4288 1B2E 90 SUB B ; Subtract digits after point +4289 1B2F F4 45 1B SCALMI: CALL P,SCALPL ; Positive - Multiply number +4290 1B32 F2 3B 1B JP P,ENDCON ; Positive - All done +4291 1B35 F5 PUSH AF ; Save number of times to /10 +4292 1B36 CD 31 19 CALL DIV10 ; Divide by 10 +4293 1B39 F1 POP AF ; Restore count +4294 1B3A 3C INC A ; Count divides +4295 1B3B +4296 1B3B C2 2F 1B ENDCON: JP NZ,SCALMI ; More to do +4297 1B3E D1 POP DE ; Restore code string address +4298 1B3F F1 POP AF ; Restore sign of number +4299 1B40 CC 12 1A CALL Z,INVSGN ; Negative - Negate number +4300 1B43 EB EX DE,HL ; Code string address to HL +4301 1B44 C9 RET +4302 1B45 +4303 1B45 C8 SCALPL: RET Z ; Exit if no scaling needed +4304 1B46 F5 MULTEN: PUSH AF ; Save count +4305 1B47 CD D2 19 CALL MLSP10 ; Multiply number by 10 +4306 1B4A F1 POP AF ; Restore count +4307 1B4B 3D DEC A ; Count multiplies +4308 1B4C C9 RET +4309 1B4D +4310 1B4D D5 ADDIG: PUSH DE ; Save sign of exponent +4311 1B4E 57 LD D,A ; Save digit +4312 1B4F 78 LD A,B ; Get digits after point +4313 1B50 89 ADC A,C ; Add one if after point +4314 1B51 47 LD B,A ; Re-save counter +4315 1B52 C5 PUSH BC ; Save point flags +4316 1B53 E5 PUSH HL ; Save code string address +4317 1B54 D5 PUSH DE ; Save digit +4318 1B55 CD D2 19 CALL MLSP10 ; Multiply number by 10 +4319 1B58 F1 POP AF ; Restore digit +4320 1B59 D6 30 SUB '0' ; Make it absolute +4321 1B5B CD 64 1B CALL RSCALE ; Re-scale number +4322 1B5E E1 POP HL ; Restore code string address +4323 1B5F C1 POP BC ; Restore point flags +4324 1B60 D1 POP DE ; Restore sign of exponent +4325 1B61 C3 04 1B JP MANLP ; Get another digit +4326 1B64 +4327 1B64 CD 1A 1A RSCALE: CALL STAKFP ; Put number on stack +4328 1B67 CD FB 19 CALL FLGREL ; Digit to add to FPREG +4329 1B6A C1 PADD: POP BC ; Restore number +4330 1B6B D1 POP DE +4331 1B6C C3 A3 17 JP FPADD ; Add BCDE to FPREG and return +4332 1B6F +4333 1B6F 7B EDIGIT: LD A,E ; Get digit +4334 1B70 07 RLCA ; Times 2 +4335 1B71 07 RLCA ; Times 4 +4336 1B72 83 ADD A,E ; Times 5 +4337 1B73 07 RLCA ; Times 10 +4338 1B74 86 ADD A,(HL) ; Add next digit +4339 1B75 D6 30 SUB '0' ; Make it absolute +4340 1B77 5F LD E,A ; Save new digit +4341 1B78 C3 1A 1B JP EXPLP ; Look for another digit +4342 1B7B +4343 1B7B E5 LINEIN: PUSH HL ; Save code string address +4344 1B7C 21 DA 06 LD HL,INMSG ; Output " in " +4345 1B7F CD E0 14 CALL PRS ; Output string at HL +4346 1B82 E1 POP HL ; Restore code string address +4347 1B83 EB PRNTHL: EX DE,HL ; Code string address to DE +4348 1B84 AF XOR A +4349 1B85 06 98 LD B,80H+24 ; 24 bits +4350 1B87 CD 00 1A CALL RETINT ; Return the integer +4351 1B8A 21 DF 14 LD HL,PRNUMS ; Print number string +4352 1B8D E5 PUSH HL ; Save for return +4353 1B8E 21 99 31 NUMASC: LD HL,PBUFF ; Convert number to ASCII +4354 1B91 E5 PUSH HL ; Save for return +4355 1B92 CD E9 19 CALL TSTSGN ; Test sign of FPREG +4356 1B95 36 20 LD (HL),' ' ; Space at start +4357 1B97 F2 9C 1B JP P,SPCFST ; Positive - Space to start +4358 1B9A 36 2D LD (HL),'-' ; '-' sign at start +4359 1B9C 23 SPCFST: INC HL ; First byte of number +4360 1B9D 36 30 LD (HL),'0' ; '0' if zero +4361 1B9F CA 52 1C JP Z,JSTZER ; Return '0' if zero +4362 1BA2 E5 PUSH HL ; Save buffer address +4363 1BA3 FC 12 1A CALL M,INVSGN ; Negate FPREG if negative +4364 1BA6 AF XOR A ; Zero A +4365 1BA7 F5 PUSH AF ; Save it +4366 1BA8 CD 58 1C CALL RNGTST ; Test number is in range +4367 1BAB 01 43 91 SIXDIG: LD BC,9143H ; BCDE - 99999.9 +4368 1BAE 11 F8 4F LD DE,4FF8H +4369 1BB1 CD 64 1A CALL CMPNUM ; Compare numbers +4370 1BB4 B7 OR A +4371 1BB5 E2 C9 1B JP PO,INRNG ; > 99999.9 - Sort it out +4372 1BB8 F1 POP AF ; Restore count +4373 1BB9 CD 46 1B CALL MULTEN ; Multiply by ten +4374 1BBC F5 PUSH AF ; Re-save count +4375 1BBD C3 AB 1B JP SIXDIG ; Test it again +4376 1BC0 +4377 1BC0 CD 31 19 GTSIXD: CALL DIV10 ; Divide by 10 +4378 1BC3 F1 POP AF ; Get count +4379 1BC4 3C INC A ; Count divides +4380 1BC5 F5 PUSH AF ; Re-save count +4381 1BC6 CD 58 1C CALL RNGTST ; Test number is in range +4382 1BC9 CD 91 17 INRNG: CALL ROUND ; Add 0.5 to FPREG +4383 1BCC 3C INC A +4384 1BCD CD 91 1A CALL FPINT ; F.P to integer +4385 1BD0 CD 2A 1A CALL FPBCDE ; Move BCDE to FPREG +4386 1BD3 01 06 03 LD BC,0306H ; 1E+06 to 1E-03 range +4387 1BD6 F1 POP AF ; Restore count +4388 1BD7 81 ADD A,C ; 6 digits before point +4389 1BD8 3C INC A ; Add one +4390 1BD9 FA E5 1B JP M,MAKNUM ; Do it in 'E' form if < 1E-02 +4391 1BDC FE 08 CP 6+1+1 ; More than 999999 ? +4392 1BDE D2 E5 1B JP NC,MAKNUM ; Yes - Do it in 'E' form +4393 1BE1 3C INC A ; Adjust for exponent +4394 1BE2 47 LD B,A ; Exponent of number +4395 1BE3 3E 02 LD A,2 ; Make it zero after +4396 1BE5 +4397 1BE5 3D MAKNUM: DEC A ; Adjust for digits to do +4398 1BE6 3D DEC A +4399 1BE7 E1 POP HL ; Restore buffer address +4400 1BE8 F5 PUSH AF ; Save count +4401 1BE9 11 6B 1C LD DE,POWERS ; Powers of ten +4402 1BEC 05 DEC B ; Count digits before point +4403 1BED C2 F6 1B JP NZ,DIGTXT ; Not zero - Do number +4404 1BF0 36 2E LD (HL),'.' ; Save point +4405 1BF2 23 INC HL ; Move on +4406 1BF3 36 30 LD (HL),'0' ; Save zero +4407 1BF5 23 INC HL ; Move on +4408 1BF6 05 DIGTXT: DEC B ; Count digits before point +4409 1BF7 36 2E LD (HL),'.' ; Save point in case +4410 1BF9 CC 3F 1A CALL Z,INCHL ; Last digit - move on +4411 1BFC C5 PUSH BC ; Save digits before point +4412 1BFD E5 PUSH HL ; Save buffer address +4413 1BFE D5 PUSH DE ; Save powers of ten +4414 1BFF CD 35 1A CALL BCDEFP ; Move FPREG to BCDE +4415 1C02 E1 POP HL ; Powers of ten table +4416 1C03 06 2F LD B, '0'-1 ; ASCII '0' - 1 +4417 1C05 04 TRYAGN: INC B ; Count subtractions +4418 1C06 7B LD A,E ; Get LSB +4419 1C07 96 SUB (HL) ; Subtract LSB +4420 1C08 5F LD E,A ; Save LSB +4421 1C09 23 INC HL +4422 1C0A 7A LD A,D ; Get NMSB +4423 1C0B 9E SBC A,(HL) ; Subtract NMSB +4424 1C0C 57 LD D,A ; Save NMSB +4425 1C0D 23 INC HL +4426 1C0E 79 LD A,C ; Get MSB +4427 1C0F 9E SBC A,(HL) ; Subtract MSB +4428 1C10 4F LD C,A ; Save MSB +4429 1C11 2B DEC HL ; Point back to start +4430 1C12 2B DEC HL +4431 1C13 D2 05 1C JP NC,TRYAGN ; No overflow - Try again +4432 1C16 CD 48 18 CALL PLUCDE ; Restore number +4433 1C19 23 INC HL ; Start of next number +4434 1C1A CD 2A 1A CALL FPBCDE ; Move BCDE to FPREG +4435 1C1D EB EX DE,HL ; Save point in table +4436 1C1E E1 POP HL ; Restore buffer address +4437 1C1F 70 LD (HL),B ; Save digit in buffer +4438 1C20 23 INC HL ; And move on +4439 1C21 C1 POP BC ; Restore digit count +4440 1C22 0D DEC C ; Count digits +4441 1C23 C2 F6 1B JP NZ,DIGTXT ; More - Do them +4442 1C26 05 DEC B ; Any decimal part? +4443 1C27 CA 36 1C JP Z,DOEBIT ; No - Do 'E' bit +4444 1C2A 2B SUPTLZ: DEC HL ; Move back through buffer +4445 1C2B 7E LD A,(HL) ; Get character +4446 1C2C FE 30 CP '0' ; '0' character? +4447 1C2E CA 2A 1C JP Z,SUPTLZ ; Yes - Look back for more +4448 1C31 FE 2E CP '.' ; A decimal point? +4449 1C33 C4 3F 1A CALL NZ,INCHL ; Move back over digit +4450 1C36 +4451 1C36 F1 DOEBIT: POP AF ; Get 'E' flag +4452 1C37 CA 55 1C JP Z,NOENED ; No 'E' needed - End buffer +4453 1C3A 36 45 LD (HL),'E' ; Put 'E' in buffer +4454 1C3C 23 INC HL ; And move on +4455 1C3D 36 2B LD (HL),'+' ; Put '+' in buffer +4456 1C3F F2 46 1C JP P,OUTEXP ; Positive - Output exponent +4457 1C42 36 2D LD (HL),'-' ; Put '-' in buffer +4458 1C44 2F CPL ; Negate exponent +4459 1C45 3C INC A +4460 1C46 06 2F OUTEXP: LD B,'0'-1 ; ASCII '0' - 1 +4461 1C48 04 EXPTEN: INC B ; Count subtractions +4462 1C49 D6 0A SUB 10 ; Tens digit +4463 1C4B D2 48 1C JP NC,EXPTEN ; More to do +4464 1C4E C6 3A ADD A,'0'+10 ; Restore and make ASCII +4465 1C50 23 INC HL ; Move on +4466 1C51 70 LD (HL),B ; Save MSB of exponent +4467 1C52 23 JSTZER: INC HL ; +4468 1C53 77 LD (HL),A ; Save LSB of exponent +4469 1C54 23 INC HL +4470 1C55 71 NOENED: LD (HL),C ; Mark end of buffer +4471 1C56 E1 POP HL ; Restore code string address +4472 1C57 C9 RET +4473 1C58 +4474 1C58 01 74 94 RNGTST: LD BC,9474H ; BCDE = 999999. +4475 1C5B 11 F7 23 LD DE,23F7H +4476 1C5E CD 64 1A CALL CMPNUM ; Compare numbers +4477 1C61 B7 OR A +4478 1C62 E1 POP HL ; Return address to HL +4479 1C63 E2 C0 1B JP PO,GTSIXD ; Too big - Divide by ten +4480 1C66 E9 JP (HL) ; Otherwise return to caller +4481 1C67 +4482 1C67 00 00 00 80 HALF: .BYTE 00H,00H,00H,80H ; 0.5 +4483 1C6B +4484 1C6B A0 86 01 POWERS: .BYTE 0A0H,086H,001H ; 100000 +4485 1C6E 10 27 00 .BYTE 010H,027H,000H ; 10000 +4486 1C71 E8 03 00 .BYTE 0E8H,003H,000H ; 1000 +4487 1C74 64 00 00 .BYTE 064H,000H,000H ; 100 +4488 1C77 0A 00 00 .BYTE 00AH,000H,000H ; 10 +4489 1C7A 01 00 00 .BYTE 001H,000H,000H ; 1 +4490 1C7D +4491 1C7D 21 12 1A NEGAFT: LD HL,INVSGN ; Negate result +4492 1C80 E3 EX (SP),HL ; To be done after caller +4493 1C81 E9 JP (HL) ; Return to caller +4494 1C82 +4495 1C82 CD 1A 1A SQR: CALL STAKFP ; Put value on stack +4496 1C85 21 67 1C LD HL,HALF ; Set power to 1/2 +4497 1C88 CD 27 1A CALL PHLTFP ; Move 1/2 to FPREG +4498 1C8B +4499 1C8B C1 POWER: POP BC ; Get base +4500 1C8C D1 POP DE +4501 1C8D CD E9 19 CALL TSTSGN ; Test sign of power +4502 1C90 78 LD A,B ; Get exponent of base +4503 1C91 CA D0 1C JP Z,EXP ; Make result 1 if zero +4504 1C94 F2 9B 1C JP P,POWER1 ; Positive base - Ok +4505 1C97 B7 OR A ; Zero to negative power? +4506 1C98 CA 45 07 JP Z,DZERR ; Yes - ?/0 Error +4507 1C9B B7 POWER1: OR A ; Base zero? +4508 1C9C CA 0A 18 JP Z,SAVEXP ; Yes - Return zero +4509 1C9F D5 PUSH DE ; Save base +4510 1CA0 C5 PUSH BC +4511 1CA1 79 LD A,C ; Get MSB of base +4512 1CA2 F6 7F OR 01111111B ; Get sign status +4513 1CA4 CD 35 1A CALL BCDEFP ; Move power to BCDE +4514 1CA7 F2 B8 1C JP P,POWER2 ; Positive base - Ok +4515 1CAA D5 PUSH DE ; Save power +4516 1CAB C5 PUSH BC +4517 1CAC CD BC 1A CALL INT ; Get integer of power +4518 1CAF C1 POP BC ; Restore power +4519 1CB0 D1 POP DE +4520 1CB1 F5 PUSH AF ; MSB of base +4521 1CB2 CD 64 1A CALL CMPNUM ; Power an integer? +4522 1CB5 E1 POP HL ; Restore MSB of base +4523 1CB6 7C LD A,H ; but don't affect flags +4524 1CB7 1F RRA ; Exponent odd or even? +4525 1CB8 E1 POWER2: POP HL ; Restore MSB and exponent +4526 1CB9 22 96 31 LD (FPREG+2),HL ; Save base in FPREG +4527 1CBC E1 POP HL ; LSBs of base +4528 1CBD 22 94 31 LD (FPREG),HL ; Save in FPREG +4529 1CC0 DC 7D 1C CALL C,NEGAFT ; Odd power - Negate result +4530 1CC3 CC 12 1A CALL Z,INVSGN ; Negative base - Negate it +4531 1CC6 D5 PUSH DE ; Save power +4532 1CC7 C5 PUSH BC +4533 1CC8 CD 9D 18 CALL LOG ; Get LOG of base +4534 1CCB C1 POP BC ; Restore power +4535 1CCC D1 POP DE +4536 1CCD CD DE 18 CALL FPMULT ; Multiply LOG by power +4537 1CD0 +4538 1CD0 CD 1A 1A EXP: CALL STAKFP ; Put value on stack +4539 1CD3 01 38 81 LD BC,08138H ; BCDE = 1/Ln(2) +4540 1CD6 11 3B AA LD DE,0AA3BH +4541 1CD9 CD DE 18 CALL FPMULT ; Multiply value by 1/LN(2) +4542 1CDC 3A 97 31 LD A,(FPEXP) ; Get exponent +4543 1CDF FE 88 CP 80H+8 ; Is it in range? +4544 1CE1 D2 C5 19 JP NC,OVTST1 ; No - Test for overflow +4545 1CE4 CD BC 1A CALL INT ; Get INT of FPREG +4546 1CE7 C6 80 ADD A,80H ; For excess 128 +4547 1CE9 C6 02 ADD A,2 ; Exponent > 126? +4548 1CEB DA C5 19 JP C,OVTST1 ; Yes - Test for overflow +4549 1CEE F5 PUSH AF ; Save scaling factor +4550 1CEF 21 8C 18 LD HL,UNITY ; Point to 1. +4551 1CF2 CD 94 17 CALL ADDPHL ; Add 1 to FPREG +4552 1CF5 CD D5 18 CALL MULLN2 ; Multiply by LN(2) +4553 1CF8 F1 POP AF ; Restore scaling factor +4554 1CF9 C1 POP BC ; Restore exponent +4555 1CFA D1 POP DE +4556 1CFB F5 PUSH AF ; Save scaling factor +4557 1CFC CD A0 17 CALL SUBCDE ; Subtract exponent from FPREG +4558 1CFF CD 12 1A CALL INVSGN ; Negate result +4559 1D02 21 10 1D LD HL,EXPTAB ; Coefficient table +4560 1D05 CD 40 1D CALL SMSER1 ; Sum the series +4561 1D08 11 00 00 LD DE,0 ; Zero LSBs +4562 1D0B C1 POP BC ; Scaling factor +4563 1D0C 4A LD C,D ; Zero MSB +4564 1D0D C3 DE 18 JP FPMULT ; Scale result to correct value +4565 1D10 +4566 1D10 08 EXPTAB: .BYTE 8 ; Table used by EXP +4567 1D11 40 2E 94 74 .BYTE 040H,02EH,094H,074H ; -1/7! (-1/5040) +4568 1D15 70 4F 2E 77 .BYTE 070H,04FH,02EH,077H ; 1/6! ( 1/720) +4569 1D19 6E 02 88 7A .BYTE 06EH,002H,088H,07AH ; -1/5! (-1/120) +4570 1D1D E6 A0 2A 7C .BYTE 0E6H,0A0H,02AH,07CH ; 1/4! ( 1/24) +4571 1D21 50 AA AA 7E .BYTE 050H,0AAH,0AAH,07EH ; -1/3! (-1/6) +4572 1D25 FF FF 7F 7F .BYTE 0FFH,0FFH,07FH,07FH ; 1/2! ( 1/2) +4573 1D29 00 00 80 81 .BYTE 000H,000H,080H,081H ; -1/1! (-1/1) +4574 1D2D 00 00 00 81 .BYTE 000H,000H,000H,081H ; 1/0! ( 1/1) +4575 1D31 +4576 1D31 CD 1A 1A SUMSER: CALL STAKFP ; Put FPREG on stack +4577 1D34 11 DC 18 LD DE,MULT ; Multiply by "X" +4578 1D37 D5 PUSH DE ; To be done after +4579 1D38 E5 PUSH HL ; Save address of table +4580 1D39 CD 35 1A CALL BCDEFP ; Move FPREG to BCDE +4581 1D3C CD DE 18 CALL FPMULT ; Square the value +4582 1D3F E1 POP HL ; Restore address of table +4583 1D40 CD 1A 1A SMSER1: CALL STAKFP ; Put value on stack +4584 1D43 7E LD A,(HL) ; Get number of coefficients +4585 1D44 23 INC HL ; Point to start of table +4586 1D45 CD 27 1A CALL PHLTFP ; Move coefficient to FPREG +4587 1D48 06 .BYTE 06H ; Skip "POP AF" +4588 1D49 F1 SUMLP: POP AF ; Restore count +4589 1D4A C1 POP BC ; Restore number +4590 1D4B D1 POP DE +4591 1D4C 3D DEC A ; Cont coefficients +4592 1D4D C8 RET Z ; All done +4593 1D4E D5 PUSH DE ; Save number +4594 1D4F C5 PUSH BC +4595 1D50 F5 PUSH AF ; Save count +4596 1D51 E5 PUSH HL ; Save address in table +4597 1D52 CD DE 18 CALL FPMULT ; Multiply FPREG by BCDE +4598 1D55 E1 POP HL ; Restore address in table +4599 1D56 CD 38 1A CALL LOADFP ; Number at HL to BCDE +4600 1D59 E5 PUSH HL ; Save address in table +4601 1D5A CD A3 17 CALL FPADD ; Add coefficient to FPREG +4602 1D5D E1 POP HL ; Restore address in table +4603 1D5E C3 49 1D JP SUMLP ; More coefficients +4604 1D61 +4605 1D61 CD E9 19 RND: CALL TSTSGN ; Test sign of FPREG +4606 1D64 21 C9 30 LD HL,SEED+2 ; Random number seed +4607 1D67 FA C2 1D JP M,RESEED ; Negative - Re-seed +4608 1D6A 21 EA 30 LD HL,LSTRND ; Last random number +4609 1D6D CD 27 1A CALL PHLTFP ; Move last RND to FPREG +4610 1D70 21 C9 30 LD HL,SEED+2 ; Random number seed +4611 1D73 C8 RET Z ; Return if RND(0) +4612 1D74 86 ADD A,(HL) ; Add (SEED)+2) +4613 1D75 E6 07 AND 00000111B ; 0 to 7 +4614 1D77 06 00 LD B,0 +4615 1D79 77 LD (HL),A ; Re-save seed +4616 1D7A 23 INC HL ; Move to coefficient table +4617 1D7B 87 ADD A,A ; 4 bytes +4618 1D7C 87 ADD A,A ; per entry +4619 1D7D 4F LD C,A ; BC = Offset into table +4620 1D7E 09 ADD HL,BC ; Point to coefficient +4621 1D7F CD 38 1A CALL LOADFP ; Coefficient to BCDE +4622 1D82 CD DE 18 CALL FPMULT ; ; Multiply FPREG by coefficient +4623 1D85 3A C8 30 LD A,(SEED+1) ; Get (SEED+1) +4624 1D88 3C INC A ; Add 1 +4625 1D89 E6 03 AND 00000011B ; 0 to 3 +4626 1D8B 06 00 LD B,0 +4627 1D8D FE 01 CP 1 ; Is it zero? +4628 1D8F 88 ADC A,B ; Yes - Make it 1 +4629 1D90 32 C8 30 LD (SEED+1),A ; Re-save seed +4630 1D93 21 C6 1D LD HL,RNDTAB-4 ; Addition table +4631 1D96 87 ADD A,A ; 4 bytes +4632 1D97 87 ADD A,A ; per entry +4633 1D98 4F LD C,A ; BC = Offset into table +4634 1D99 09 ADD HL,BC ; Point to value +4635 1D9A CD 94 17 CALL ADDPHL ; Add value to FPREG +4636 1D9D CD 35 1A RND1: CALL BCDEFP ; Move FPREG to BCDE +4637 1DA0 7B LD A,E ; Get LSB +4638 1DA1 59 LD E,C ; LSB = MSB +4639 1DA2 EE 4F XOR 01001111B ; Fiddle around +4640 1DA4 4F LD C,A ; New MSB +4641 1DA5 36 80 LD (HL),80H ; Set exponent +4642 1DA7 2B DEC HL ; Point to MSB +4643 1DA8 46 LD B,(HL) ; Get MSB +4644 1DA9 36 80 LD (HL),80H ; Make value -0.5 +4645 1DAB 21 C7 30 LD HL,SEED ; Random number seed +4646 1DAE 34 INC (HL) ; Count seed +4647 1DAF 7E LD A,(HL) ; Get seed +4648 1DB0 D6 AB SUB 171 ; Do it modulo 171 +4649 1DB2 C2 B9 1D JP NZ,RND2 ; Non-zero - Ok +4650 1DB5 77 LD (HL),A ; Zero seed +4651 1DB6 0C INC C ; Fillde about +4652 1DB7 15 DEC D ; with the +4653 1DB8 1C INC E ; number +4654 1DB9 CD F4 17 RND2: CALL BNORM ; Normalise number +4655 1DBC 21 EA 30 LD HL,LSTRND ; Save random number +4656 1DBF C3 41 1A JP FPTHL ; Move FPREG to last and return +4657 1DC2 +4658 1DC2 77 RESEED: LD (HL),A ; Re-seed random numbers +4659 1DC3 2B DEC HL +4660 1DC4 77 LD (HL),A +4661 1DC5 2B DEC HL +4662 1DC6 77 LD (HL),A +4663 1DC7 C3 9D 1D JP RND1 ; Return RND seed +4664 1DCA +4665 1DCA 68 B1 46 68 RNDTAB: .BYTE 068H,0B1H,046H,068H ; Table used by RND +4666 1DCE 99 E9 92 69 .BYTE 099H,0E9H,092H,069H +4667 1DD2 10 D1 75 68 .BYTE 010H,0D1H,075H,068H +4668 1DD6 +4669 1DD6 21 20 1E COS: LD HL,HALFPI ; Point to PI/2 +4670 1DD9 CD 94 17 CALL ADDPHL ; Add it to PPREG +4671 1DDC CD 1A 1A SIN: CALL STAKFP ; Put angle on stack +4672 1DDF 01 49 83 LD BC,8349H ; BCDE = 2 PI +4673 1DE2 11 DB 0F LD DE,0FDBH +4674 1DE5 CD 2A 1A CALL FPBCDE ; Move 2 PI to FPREG +4675 1DE8 C1 POP BC ; Restore angle +4676 1DE9 D1 POP DE +4677 1DEA CD 3F 19 CALL DVBCDE ; Divide angle by 2 PI +4678 1DED CD 1A 1A CALL STAKFP ; Put it on stack +4679 1DF0 CD BC 1A CALL INT ; Get INT of result +4680 1DF3 C1 POP BC ; Restore number +4681 1DF4 D1 POP DE +4682 1DF5 CD A0 17 CALL SUBCDE ; Make it 0 <= value < 1 +4683 1DF8 21 24 1E LD HL,QUARTR ; Point to 0.25 +4684 1DFB CD 9A 17 CALL SUBPHL ; Subtract value from 0.25 +4685 1DFE CD E9 19 CALL TSTSGN ; Test sign of value +4686 1E01 37 SCF ; Flag positive +4687 1E02 F2 0C 1E JP P,SIN1 ; Positive - Ok +4688 1E05 CD 91 17 CALL ROUND ; Add 0.5 to value +4689 1E08 CD E9 19 CALL TSTSGN ; Test sign of value +4690 1E0B B7 OR A ; Flag negative +4691 1E0C F5 SIN1: PUSH AF ; Save sign +4692 1E0D F4 12 1A CALL P,INVSGN ; Negate value if positive +4693 1E10 21 24 1E LD HL,QUARTR ; Point to 0.25 +4694 1E13 CD 94 17 CALL ADDPHL ; Add 0.25 to value +4695 1E16 F1 POP AF ; Restore sign +4696 1E17 D4 12 1A CALL NC,INVSGN ; Negative - Make positive +4697 1E1A 21 28 1E LD HL,SINTAB ; Coefficient table +4698 1E1D C3 31 1D JP SUMSER ; Evaluate sum of series +4699 1E20 +4700 1E20 DB 0F 49 81 HALFPI: .BYTE 0DBH,00FH,049H,081H ; 1.5708 (PI/2) +4701 1E24 +4702 1E24 00 00 00 7F QUARTR: .BYTE 000H,000H,000H,07FH ; 0.25 +4703 1E28 +4704 1E28 05 SINTAB: .BYTE 5 ; Table used by SIN +4705 1E29 BA D7 1E 86 .BYTE 0BAH,0D7H,01EH,086H ; 39.711 +4706 1E2D 64 26 99 87 .BYTE 064H,026H,099H,087H ;-76.575 +4707 1E31 58 34 23 87 .BYTE 058H,034H,023H,087H ; 81.602 +4708 1E35 E0 5D A5 86 .BYTE 0E0H,05DH,0A5H,086H ;-41.342 +4709 1E39 DA 0F 49 83 .BYTE 0DAH,00FH,049H,083H ; 6.2832 +4710 1E3D +4711 1E3D CD 1A 1A TAN: CALL STAKFP ; Put angle on stack +4712 1E40 CD DC 1D CALL SIN ; Get SIN of angle +4713 1E43 C1 POP BC ; Restore angle +4714 1E44 E1 POP HL +4715 1E45 CD 1A 1A CALL STAKFP ; Save SIN of angle +4716 1E48 EB EX DE,HL ; BCDE = Angle +4717 1E49 CD 2A 1A CALL FPBCDE ; Angle to FPREG +4718 1E4C CD D6 1D CALL COS ; Get COS of angle +4719 1E4F C3 3D 19 JP DIV ; TAN = SIN / COS +4720 1E52 +4721 1E52 CD E9 19 ATN: CALL TSTSGN ; Test sign of value +4722 1E55 FC 7D 1C CALL M,NEGAFT ; Negate result after if -ve +4723 1E58 FC 12 1A CALL M,INVSGN ; Negate value if -ve +4724 1E5B 3A 97 31 LD A,(FPEXP) ; Get exponent +4725 1E5E FE 81 CP 81H ; Number less than 1? +4726 1E60 DA 6F 1E JP C,ATN1 ; Yes - Get arc tangnt +4727 1E63 01 00 81 LD BC,8100H ; BCDE = 1 +4728 1E66 51 LD D,C +4729 1E67 59 LD E,C +4730 1E68 CD 3F 19 CALL DVBCDE ; Get reciprocal of number +4731 1E6B 21 9A 17 LD HL,SUBPHL ; Sub angle from PI/2 +4732 1E6E E5 PUSH HL ; Save for angle > 1 +4733 1E6F 21 79 1E ATN1: LD HL,ATNTAB ; Coefficient table +4734 1E72 CD 31 1D CALL SUMSER ; Evaluate sum of series +4735 1E75 21 20 1E LD HL,HALFPI ; PI/2 - angle in case > 1 +4736 1E78 C9 RET ; Number > 1 - Sub from PI/2 +4737 1E79 +4738 1E79 09 ATNTAB: .BYTE 9 ; Table used by ATN +4739 1E7A 4A D7 3B 78 .BYTE 04AH,0D7H,03BH,078H ; 1/17 +4740 1E7E 02 6E 84 7B .BYTE 002H,06EH,084H,07BH ;-1/15 +4741 1E82 FE C1 2F 7C .BYTE 0FEH,0C1H,02FH,07CH ; 1/13 +4742 1E86 74 31 9A 7D .BYTE 074H,031H,09AH,07DH ;-1/11 +4743 1E8A 84 3D 5A 7D .BYTE 084H,03DH,05AH,07DH ; 1/9 +4744 1E8E C8 7F 91 7E .BYTE 0C8H,07FH,091H,07EH ;-1/7 +4745 1E92 E4 BB 4C 7E .BYTE 0E4H,0BBH,04CH,07EH ; 1/5 +4746 1E96 6C AA AA 7F .BYTE 06CH,0AAH,0AAH,07FH ;-1/3 +4747 1E9A 00 00 00 81 .BYTE 000H,000H,000H,081H ; 1/1 +4748 1E9E +4749 1E9E +4750 1E9E C9 ARET: RET ; A RETurn instruction +4751 1E9F +4752 1E9F D7 GETINP: RST 10H ;input a character +4753 1EA0 C9 RET +4754 1EA1 +4755 1EA1 CLS: +4756 1EA1 3E 0C LD A,CS ; ASCII Clear screen +4757 1EA3 C3 DB 1F JP MONOUT ; Output character +4758 1EA6 +4759 1EA6 CD 68 17 WIDTH: CALL GETINT ; Get integer 0-255 +4760 1EA9 7B LD A,E ; Width to A +4761 1EAA 32 F2 30 LD (LWIDTH),A ; Set width +4762 1EAD C9 RET +4763 1EAE +4764 1EAE CD 07 10 LINES: CALL GETNUM ; Get a number +4765 1EB1 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 +4766 1EB4 ED 53 F6 30 LD (LINESC),DE ; Set lines counter +4767 1EB8 ED 53 F8 30 LD (LINESN),DE ; Set lines number +4768 1EBC C9 RET +4769 1EBD +4770 1EBD CD 4C 0C DEEK: CALL DEINT ; Get integer -32768 to 32767 +4771 1EC0 D5 PUSH DE ; Save number +4772 1EC1 E1 POP HL ; Number to HL +4773 1EC2 46 LD B,(HL) ; Get LSB of contents +4774 1EC3 23 INC HL +4775 1EC4 7E LD A,(HL) ; Get MSB of contents +4776 1EC5 C3 C2 13 JP ABPASS ; Return integer AB +4777 1EC8 +4778 1EC8 CD 07 10 DOKE: CALL GETNUM ; Get a number +4779 1ECB CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 +4780 1ECE D5 PUSH DE ; Save address +4781 1ECF CD 10 0A CALL CHKSYN ; Make sure ',' follows +4782 1ED2 2C .BYTE ',' +4783 1ED3 CD 07 10 CALL GETNUM ; Get a number +4784 1ED6 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 +4785 1ED9 E3 EX (SP),HL ; Save value,get address +4786 1EDA 73 LD (HL),E ; Save LSB of value +4787 1EDB 23 INC HL +4788 1EDC 72 LD (HL),D ; Save MSB of value +4789 1EDD E1 POP HL ; Restore code string address +4790 1EDE C9 RET +4791 1EDF +4792 1EDF +4793 1EDF ; HEX$(nn) Convert 16 bit number to Hexadecimal string +4794 1EDF +4795 1EDF CD 0A 10 HEX: CALL TSTNUM ; Verify it's a number +4796 1EE2 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 +4797 1EE5 C5 PUSH BC ; Save contents of BC +4798 1EE6 21 99 31 LD HL,PBUFF +4799 1EE9 7A LD A,D ; Get high order into A +4800 1EEA FE 00 CP $0 +4801 1EEC 28 0C JR Z,HEX2 ; Skip output if both high digits are zero +4802 1EEE CD 17 1F CALL BYT2ASC ; Convert D to ASCII +4803 1EF1 78 LD A,B +4804 1EF2 FE 30 CP '0' +4805 1EF4 28 02 JR Z,HEX1 ; Don't store high digit if zero +4806 1EF6 70 LD (HL),B ; Store it to PBUFF +4807 1EF7 23 INC HL ; Next location +4808 1EF8 71 HEX1: LD (HL),C ; Store C to PBUFF+1 +4809 1EF9 23 INC HL ; Next location +4810 1EFA 7B HEX2: LD A,E ; Get lower byte +4811 1EFB CD 17 1F CALL BYT2ASC ; Convert E to ASCII +4812 1EFE 7A LD A,D +4813 1EFF FE 00 CP $0 +4814 1F01 20 05 JR NZ,HEX3 ; If upper byte was not zero then always print lower byte +4815 1F03 78 LD A,B +4816 1F04 FE 30 CP '0' ; If high digit of lower byte is zero then don't print +4817 1F06 28 02 JR Z,HEX4 +4818 1F08 70 HEX3: LD (HL),B ; to PBUFF+2 +4819 1F09 23 INC HL ; Next location +4820 1F0A 71 HEX4: LD (HL),C ; to PBUFF+3 +4821 1F0B 23 INC HL ; PBUFF+4 to zero +4822 1F0C AF XOR A ; Terminating character +4823 1F0D 77 LD (HL),A ; Store zero to terminate +4824 1F0E 23 INC HL ; Make sure PBUFF is terminated +4825 1F0F 77 LD (HL),A ; Store the double zero there +4826 1F10 C1 POP BC ; Get BC back +4827 1F11 21 99 31 LD HL,PBUFF ; Reset to start of PBUFF +4828 1F14 C3 70 14 JP STR1 ; Convert the PBUFF to a string and return it +4829 1F17 +4830 1F17 47 BYT2ASC LD B,A ; Save original value +4831 1F18 E6 0F AND $0F ; Strip off upper nybble +4832 1F1A FE 0A CP $0A ; 0-9? +4833 1F1C 38 02 JR C,ADD30 ; If A-F, add 7 more +4834 1F1E C6 07 ADD A,$07 ; Bring value up to ASCII A-F +4835 1F20 C6 30 ADD30 ADD A,$30 ; And make ASCII +4836 1F22 4F LD C,A ; Save converted char to C +4837 1F23 78 LD A,B ; Retrieve original value +4838 1F24 0F RRCA ; and Rotate it right +4839 1F25 0F RRCA +4840 1F26 0F RRCA +4841 1F27 0F RRCA +4842 1F28 E6 0F AND $0F ; Mask off upper nybble +4843 1F2A FE 0A CP $0A ; 0-9? < A hex? +4844 1F2C 38 02 JR C,ADD301 ; Skip Add 7 +4845 1F2E C6 07 ADD A,$07 ; Bring it up to ASCII A-F +4846 1F30 C6 30 ADD301 ADD A,$30 ; And make it full ASCII +4847 1F32 47 LD B,A ; Store high order byte +4848 1F33 C9 RET +4849 1F34 +4850 1F34 ; Convert "&Hnnnn" to FPREG +4851 1F34 ; Gets a character from (HL) checks for Hexadecimal ASCII numbers "&Hnnnn" +4852 1F34 ; Char is in A, NC if char is ;<=>?@ A-z, CY is set if 0-9 +4853 1F34 EB HEXTFP EX DE,HL ; Move code string pointer to DE +4854 1F35 21 00 00 LD HL,$0000 ; Zero out the value +4855 1F38 CD 4D 1F CALL GETHEX ; Check the number for valid hex +4856 1F3B DA 6D 1F JP C,HXERR ; First value wasn't hex, HX error +4857 1F3E 18 05 JR HEXLP1 ; Convert first character +4858 1F40 CD 4D 1F HEXLP CALL GETHEX ; Get second and addtional characters +4859 1F43 38 1F JR C,HEXIT ; Exit if not a hex character +4860 1F45 29 HEXLP1 ADD HL,HL ; Rotate 4 bits to the left +4861 1F46 29 ADD HL,HL +4862 1F47 29 ADD HL,HL +4863 1F48 29 ADD HL,HL +4864 1F49 B5 OR L ; Add in D0-D3 into L +4865 1F4A 6F LD L,A ; Save new value +4866 1F4B 18 F3 JR HEXLP ; And continue until all hex characters are in +4867 1F4D +4868 1F4D 13 GETHEX INC DE ; Next location +4869 1F4E 1A LD A,(DE) ; Load character at pointer +4870 1F4F FE 20 CP ' ' +4871 1F51 CA 4D 1F JP Z,GETHEX ; Skip spaces +4872 1F54 D6 30 SUB $30 ; Get absolute value +4873 1F56 D8 RET C ; < "0", error +4874 1F57 FE 0A CP $0A +4875 1F59 38 05 JR C,NOSUB7 ; Is already in the range 0-9 +4876 1F5B D6 07 SUB $07 ; Reduce to A-F +4877 1F5D FE 0A CP $0A ; Value should be $0A-$0F at this point +4878 1F5F D8 RET C ; CY set if was : ; < = > ? @ +4879 1F60 FE 10 NOSUB7 CP $10 ; > Greater than "F"? +4880 1F62 3F CCF +4881 1F63 C9 RET ; CY set if it wasn't valid hex +4882 1F64 +4883 1F64 EB HEXIT EX DE,HL ; Value into DE, Code string into HL +4884 1F65 7A LD A,D ; Load DE into AC +4885 1F66 4B LD C,E ; For prep to +4886 1F67 E5 PUSH HL +4887 1F68 CD C1 13 CALL ACPASS ; ACPASS to set AC as integer into FPREG +4888 1F6B E1 POP HL +4889 1F6C C9 RET +4890 1F6D +4891 1F6D 1E 26 HXERR: LD E,HX ; ?HEX Error +4892 1F6F C3 56 07 JP ERROR +4893 1F72 +4894 1F72 ; BIN$(NN) Convert integer to a 1-16 char binary string +4895 1F72 CD 0A 10 BIN: CALL TSTNUM ; Verify it's a number +4896 1F75 CD 4C 0C CALL DEINT ; Get integer -32768 to 32767 +4897 1F78 C5 BIN2: PUSH BC ; Save contents of BC +4898 1F79 21 99 31 LD HL,PBUFF +4899 1F7C 06 11 LD B,17 ; One higher than max char count +4900 1F7E ZEROSUP: ; Suppress leading zeros +4901 1F7E 05 DEC B ; Max 16 chars +4902 1F7F 78 LD A,B +4903 1F80 FE 01 CP $01 +4904 1F82 28 08 JR Z,BITOUT ; Always output at least one character +4905 1F84 CB 13 RL E +4906 1F86 CB 12 RL D +4907 1F88 30 F4 JR NC,ZEROSUP +4908 1F8A 18 04 JR BITOUT2 +4909 1F8C BITOUT: +4910 1F8C CB 13 RL E +4911 1F8E CB 12 RL D ; Top bit now in carry +4912 1F90 BITOUT2: +4913 1F90 3E 30 LD A,'0' ; Char for '0' +4914 1F92 CE 00 ADC A,0 ; If carry set then '0' --> '1' +4915 1F94 77 LD (HL),A +4916 1F95 23 INC HL +4917 1F96 05 DEC B +4918 1F97 20 F3 JR NZ,BITOUT +4919 1F99 AF XOR A ; Terminating character +4920 1F9A 77 LD (HL),A ; Store zero to terminate +4921 1F9B 23 INC HL ; Make sure PBUFF is terminated +4922 1F9C 77 LD (HL),A ; Store the double zero there +4923 1F9D C1 POP BC +4924 1F9E 21 99 31 LD HL,PBUFF +4925 1FA1 C3 70 14 JP STR1 +4926 1FA4 +4927 1FA4 ; Convert "&Bnnnn" to FPREG +4928 1FA4 ; Gets a character from (HL) checks for Binary ASCII numbers "&Bnnnn" +4929 1FA4 EB BINTFP: EX DE,HL ; Move code string pointer to DE +4930 1FA5 21 00 00 LD HL,$0000 ; Zero out the value +4931 1FA8 CD C1 1F CALL CHKBIN ; Check the number for valid bin +4932 1FAB DA CF 1F JP C,BINERR ; First value wasn't bin, HX error +4933 1FAE D6 30 BINIT: SUB '0' +4934 1FB0 29 ADD HL,HL ; Rotate HL left +4935 1FB1 B5 OR L +4936 1FB2 6F LD L,A +4937 1FB3 CD C1 1F CALL CHKBIN ; Get second and addtional characters +4938 1FB6 30 F6 JR NC,BINIT ; Process if a bin character +4939 1FB8 EB EX DE,HL ; Value into DE, Code string into HL +4940 1FB9 7A LD A,D ; Load DE into AC +4941 1FBA 4B LD C,E ; For prep to +4942 1FBB E5 PUSH HL +4943 1FBC CD C1 13 CALL ACPASS ; ACPASS to set AC as integer into FPREG +4944 1FBF E1 POP HL +4945 1FC0 C9 RET +4946 1FC1 +4947 1FC1 ; Char is in A, NC if char is 0 or 1 +4948 1FC1 13 CHKBIN: INC DE +4949 1FC2 1A LD A,(DE) +4950 1FC3 FE 20 CP ' ' +4951 1FC5 CA C1 1F JP Z,CHKBIN ; Skip spaces +4952 1FC8 FE 30 CP '0' ; Set C if < '0' +4953 1FCA D8 RET C +4954 1FCB FE 32 CP '2' +4955 1FCD 3F CCF ; Set C if > '1' +4956 1FCE C9 RET +4957 1FCF +4958 1FCF 1E 28 BINERR: LD E,BN ; ?BIN Error +4959 1FD1 C3 56 07 JP ERROR +4960 1FD4 +4961 1FD4 +4962 1FD4 JJUMP1: +4963 1FD4 DD 21 FF FF LD IX,-1 ; Flag cold start +4964 1FD8 C3 A6 03 JP CSTART ; Go and initialise +4965 1FDB +4966 1FDB MONOUT: +4967 1FDB C3 08 00 JP $0008 ; output a char +4968 1FDE +4969 1FDE +4970 1FDE MONITR: +4971 1FDE C3 00 00 JP $0000 ; Restart (Normally Monitor Start) +4972 1FE1 +4973 1FE1 +4974 1FE1 3E 00 INITST: LD A,0 ; Clear break flag +4975 1FE3 32 FD 30 LD (BRKFLG),A +4976 1FE6 C3 AD 03 JP INIT +4977 1FE9 +4978 1FE9 ED 45 ARETN: RETN ; Return from NMI +4979 1FEB +4980 1FEB +4981 1FEB F5 TSTBIT: PUSH AF ; Save bit mask +4982 1FEC A0 AND B ; Get common bits +4983 1FED C1 POP BC ; Restore bit mask +4984 1FEE B8 CP B ; Same bit set? +4985 1FEF 3E 00 LD A,0 ; Return 0 in A +4986 1FF1 C9 RET +4987 1FF2 +4988 1FF2 CD 1B 0A OUTNCR: CALL OUTC ; Output character in A +4989 1FF5 C3 42 0E JP PRNTCRLF ; Output CRLF +4990 1FF8 +4991 1FF8 .end +4992 1FF8 +tasm: Number of errors = 0 diff --git a/Z80 CPM and bootloader (basmon)/source/CBIOS128.LST b/Z80 CPM and bootloader (basmon)/source/CBIOS128.LST index 250e562..6c9e157 100644 --- a/Z80 CPM and bootloader (basmon)/source/CBIOS128.LST +++ b/Z80 CPM and bootloader (basmon)/source/CBIOS128.LST @@ -1,947 +1,1031 @@ -0001 0000 ;================================================================================== -0002 0000 ; Contents of this file are copyright Grant Searle -0003 0000 ; Blocking/unblocking routines are the published version by Digital Research -0004 0000 ; (bugfixed, as found on the web) -0005 0000 ; -0006 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY -0007 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. -0008 0000 ; -0009 0000 ; http://searle.hostei.com/grant/index.html -0010 0000 ; -0011 0000 ; eMail: home.micros01@btinternet.com -0012 0000 ; -0013 0000 ; If the above don't work, please perform an Internet search to see if I have -0014 0000 ; updated the web page hosting service. -0015 0000 ; -0016 0000 ;================================================================================== -0017 0000 -0018 0000 ccp .EQU 0D000h ; Base of CCP. -0019 0000 bdos .EQU ccp + 0806h ; Base of BDOS. -0020 0000 bios .EQU ccp + 1600h ; Base of BIOS. -0021 0000 -0022 0000 ; Set CP/M low memory datA, vector and buffer addresses. -0023 0000 -0024 0000 iobyte .EQU 03h ; Intel standard I/O definition byte. -0025 0000 userdrv .EQU 04h ; Current user number and drive. -0026 0000 tpabuf .EQU 80h ; Default I/O buffer and command line storage. -0027 0000 -0028 0000 -0029 0000 SD_DATA .EQU 088H -0030 0000 SD_CONTROL .EQU 089H -0031 0000 SD_STATUS .EQU 089H -0032 0000 SD_LBA0 .EQU 08AH -0033 0000 SD_LBA1 .EQU 08BH -0034 0000 SD_LBA2 .EQU 08CH -0035 0000 -0036 0000 RTS_HIGH .EQU 0D5H -0037 0000 RTS_LOW .EQU 095H -0038 0000 -0039 0000 ACIA0_D .EQU $81 -0040 0000 ACIA0_C .EQU $80 -0041 0000 ACIA1_D .EQU $83 -0042 0000 ACIA1_C .EQU $82 -0043 0000 -0044 0000 nmi .EQU 66H -0045 0000 -0046 0000 blksiz .equ 4096 ;CP/M allocation size -0047 0000 hstsiz .equ 512 ;host disk sector size -0048 0000 hstspt .equ 32 ;host disk sectors/trk -0049 0000 hstblk .equ hstsiz/128 ;CP/M sects/host buff -0050 0000 cpmspt .equ hstblk * hstspt ;CP/M sectors/track -0051 0000 secmsk .equ hstblk-1 ;sector mask -0052 0000 ;compute sector mask -0053 0000 ;secshf .equ 2 ;log2(hstblk) -0054 0000 -0055 0000 wrall .equ 0 ;write to allocated -0056 0000 wrdir .equ 1 ;write to directory -0057 0000 wrual .equ 2 ;write to unallocated -0058 0000 -0059 0000 LF .EQU 0AH ;line feed -0060 0000 FF .EQU 0CH ;form feed -0061 0000 CR .EQU 0DH ;carriage RETurn -0062 0000 -0063 0000 ;================================================================================================ -0064 0000 -0065 E600 .ORG bios ; BIOS origin. -0066 E600 -0067 E600 ;================================================================================================ -0068 E600 ; BIOS jump table. -0069 E600 ;================================================================================================ -0070 E600 C3 51 E7 JP boot ; 0 Initialize. -0071 E603 C3 B5 E7 wboote: JP wboot ; 1 Warm boot. -0072 E606 C3 1D E8 JP const ; 2 Console status. -0073 E609 C3 58 E8 JP conin ; 3 Console input. -0074 E60C C3 96 E8 JP conout ; 4 Console OUTput. -0075 E60F C3 7E E8 JP list ; 5 List OUTput. -0076 E612 C3 8A E8 JP punch ; 6 punch OUTput. -0077 E615 C3 4C E8 JP reader ; 7 Reader input. -0078 E618 C3 EF E8 JP home ; 8 Home disk. -0079 E61B C3 C7 E8 JP seldsk ; 9 Select disk. -0080 E61E C3 FB E8 JP settrk ; 10 Select track. -0081 E621 C3 00 E9 JP setsec ; 11 Select sector. -0082 E624 C3 05 E9 JP setdma ; 12 Set DMA ADDress. -0083 E627 C3 0D E9 JP read ; 13 Read 128 bytes. -0084 E62A C3 21 E9 JP write ; 14 Write 128 bytes. -0085 E62D C3 C4 E8 JP listst ; 15 List status. -0086 E630 C3 0A E9 JP sectran ; 16 Sector translate. -0087 E633 -0088 E633 ;================================================================================================ -0089 E633 ; Disk parameter headers for disk 0 to 15 -0090 E633 ;================================================================================================ -0091 E633 dpbase: -0092 E633 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb0,0000h,alv00 -0092 E639 00000DEB33E700008DEB -0093 E643 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv01 -0093 E649 00000DEB42E700008EEC -0094 E653 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv02 -0094 E659 00000DEB42E700008FED -0095 E663 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv03 -0095 E669 00000DEB42E7000090EE -0096 E673 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv04 -0096 E679 00000DEB42E7000091EF -0097 E683 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv05 -0097 E689 00000DEB42E7000092F0 -0098 E693 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv06 -0098 E699 00000DEB42E7000093F1 -0099 E6A3 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv07 -0099 E6A9 00000DEB42E7000094F2 -0100 E6B3 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv08 -0100 E6B9 00000DEB42E7000095F3 -0101 E6C3 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv09 -0101 E6C9 00000DEB42E7000096F4 -0102 E6D3 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv10 -0102 E6D9 00000DEB42E7000097F5 -0103 E6E3 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv11 -0103 E6E9 00000DEB42E7000098F6 -0104 E6F3 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv12 -0104 E6F9 00000DEB42E7000099F7 -0105 E703 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv13 -0105 E709 00000DEB42E700009AF8 -0106 E713 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv14 -0106 E719 00000DEB42E700009BF9 -0107 E723 000000000000 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv15 -0107 E729 00000DEB42E700009CFA -0108 E733 -0109 E733 ; First drive has a reserved track for CP/M -0110 E733 dpb0: -0111 E733 80 00 .DW 128 ;SPT - sectors per track -0112 E735 05 .DB 5 ;BSH - block shift factor -0113 E736 1F .DB 31 ;BLM - block mask -0114 E737 01 .DB 1 ;EXM - Extent mask -0115 E738 FB 07 .DW 2043 ; (2047-4) DSM - Storage size (blocks - 1) -0116 E73A FF 01 .DW 511 ;DRM - Number of directory entries - 1 -0117 E73C F0 .DB 240 ;AL0 - 1 bit set per directory block -0118 E73D 00 .DB 0 ;AL1 - " -0119 E73E 00 00 .DW 0 ;CKS - DIR check vector size (DRM+1)/4 (0=fixed disk) -0120 E740 01 00 .DW 1 ;OFF - Reserved tracks -0121 E742 -0122 E742 dpb: -0123 E742 80 00 .DW 128 ;SPT - sectors per track -0124 E744 05 .DB 5 ;BSH - block shift factor -0125 E745 1F .DB 31 ;BLM - block mask -0126 E746 01 .DB 1 ;EXM - Extent mask -0127 E747 FF 07 .DW 2047 ;DSM - Storage size (blocks - 1) -0128 E749 FF 01 .DW 511 ;DRM - Number of directory entries - 1 -0129 E74B F0 .DB 240 ;AL0 - 1 bit set per directory block -0130 E74C 00 .DB 0 ;AL1 - " -0131 E74D 00 00 .DW 0 ;CKS - DIR check vector size (DRM+1)/4 (0=fixed disk) -0132 E74F 00 00 .DW 0 ;OFF - Reserved tracks -0133 E751 -0134 E751 ;================================================================================================ -0135 E751 ; Cold boot -0136 E751 ;================================================================================================ -0137 E751 -0138 E751 boot: -0139 E751 F3 DI ; Disable interrupts. -0140 E752 31 C1 FB LD SP,biosstack ; Set default stack. -0141 E755 -0142 E755 ; Turn off ROM -0143 E755 -0144 E755 3E 01 LD A,$01 -0145 E757 D3 38 OUT ($38),A -0146 E759 -0147 E759 3E 95 LD A,RTS_LOW -0148 E75B D3 80 OUT (ACIA0_C),A ; Initialise ACIA0 -0149 E75D D3 82 OUT (ACIA1_C),A ; Initialise ACIA1 -0150 E75F -0151 E75F CD F9 EA CALL printInline -0152 E762 0C .DB FF -0153 E763 43502F4D2042 .TEXT "CP/M BIOS 2.0 by G. Searle 2013" -0153 E769 494F5320322E3020627920472E20536561726C652032303133 -0154 E782 0D 0A .DB CR,LF -0155 E784 0D 0A .DB CR,LF -0156 E786 43502F4D2032 .TEXT "CP/M 2.2 " -0156 E78C 2E3220 -0157 E78F 28 63 29 .TEXT "(c)" -0158 E792 203139373920 .TEXT " 1979 by Digital Research" -0158 E798 6279204469676974616C205265736561726368 -0159 E7AB 0D 0A 00 .DB CR,LF,0 -0160 E7AE -0161 E7AE ; CALL sdPreamble?? -0162 E7AE -0163 E7AE AF XOR a ; Clear I/O & drive bytes. -0164 E7AF 32 04 00 LD (userdrv),A -0165 E7B2 C3 F5 E7 JP gocpm -0166 E7B5 -0167 E7B5 ;================================================================================================ -0168 E7B5 ; Warm boot -0169 E7B5 ;================================================================================================ -0170 E7B5 -0171 E7B5 wboot: -0172 E7B5 F3 DI ; Disable interrupts. -0173 E7B6 31 C1 FB LD SP,biosstack ; Set default stack. -0174 E7B9 -0175 E7B9 06 0B LD B,11 ; Number of sectors to reload -0176 E7BB -0177 E7BB 3E 00 LD A,0 -0178 E7BD 32 C9 FB LD (hstsec),A -0179 E7C0 D3 8C OUT (SD_LBA2),A -0180 E7C2 D3 8B OUT (SD_LBA1),A -0181 E7C4 -0182 E7C4 21 00 D0 LD HL,ccp -0183 E7C7 -0184 E7C7 wbRdAllSecs: -0185 E7C7 -0186 E7C7 DB 89 wBrdWait1: IN A,(SD_STATUS) -0187 E7C9 FE 80 CP 128 -0188 E7CB 20 FA JR NZ,wBrdWait1 -0189 E7CD -0190 E7CD 3A C9 FB LD A,(hstsec) -0191 E7D0 D3 8A OUT (SD_LBA0),A -0192 E7D2 -0193 E7D2 3E 00 LD A,$00 ; 00 = Read block -0194 E7D4 D3 89 OUT (SD_CONTROL),A -0195 E7D6 C5 PUSH BC -0196 E7D7 -0197 E7D7 0E 04 LD c,4 -0198 E7D9 wBrd4secs: -0199 E7D9 06 80 LD b,128 -0200 E7DB wBrdByte: -0201 E7DB -0202 E7DB DB 89 wBrdWait2: IN A,(SD_STATUS) -0203 E7DD FE E0 CP 224 ; Read byte waiting -0204 E7DF 20 FA JR NZ,wBrdWait2 -0205 E7E1 -0206 E7E1 DB 88 IN A,(SD_DATA) -0207 E7E3 -0208 E7E3 77 LD (HL),A -0209 E7E4 23 INC HL -0210 E7E5 05 dec b -0211 E7E6 20 F3 JR NZ, wBrdByte -0212 E7E8 -0213 E7E8 0D dec c -0214 E7E9 20 EE JR NZ,wBrd4secs -0215 E7EB -0216 E7EB 3A C9 FB LD A,(hstsec) -0217 E7EE 3C INC A -0218 E7EF 32 C9 FB LD (hstsec),A -0219 E7F2 -0220 E7F2 C1 POP BC -0221 E7F3 -0222 E7F3 10 D2 DJNZ wbRdAllSecs -0223 E7F5 ;================================================================================================ -0224 E7F5 ; Common code for cold and warm boot -0225 E7F5 ;================================================================================================ -0226 E7F5 -0227 E7F5 gocpm: -0228 E7F5 AF xor a ;0 to accumulator -0229 E7F6 32 CB FB ld (hstact),a ;host buffer inactive -0230 E7F9 32 CD FB ld (unacnt),a ;clear unalloc count -0231 E7FC -0232 E7FC 21 80 00 LD HL,tpabuf ; Address of BIOS DMA buffer. -0233 E7FF 22 D6 FB LD (dmaAddr),HL -0234 E802 3E C3 LD A,0C3h ; Opcode for 'JP'. -0235 E804 32 00 00 LD (00h),A ; Load at start of RAM. -0236 E807 21 03 E6 LD HL,wboote ; Address of jump for a warm boot. -0237 E80A 22 01 00 LD (01h),HL -0238 E80D 32 05 00 LD (05h),A ; Opcode for 'JP'. -0239 E810 21 06 D8 LD HL,bdos ; Address of jump for the BDOS. -0240 E813 22 06 00 LD (06h),HL -0241 E816 3A 04 00 LD A,(userdrv) ; Save new drive number (0). -0242 E819 4F LD c,A ; Pass drive number in C. -0243 E81A -0244 E81A C3 00 D0 JP ccp ; Start CP/M by jumping to the CCP. -0245 E81D -0246 E81D ;================================================================================================ -0247 E81D ; Console I/O routines -0248 E81D ;================================================================================================ -0249 E81D -0250 E81D -0251 E81D ;------------------------------------------------------------------------------------------------ -0252 E81D const: -0253 E81D 3A 03 00 LD A,(iobyte) -0254 E820 E6 0B AND 00001011b ; Mask off console and high bit of reader -0255 E822 FE 0A CP 00001010b ; redirected to reader on UR1/2 (Serial A) -0256 E824 28 0A JR Z,constA -0257 E826 FE 02 CP 00000010b ; redirected to reader on TTY/RDR (Serial B) -0258 E828 28 14 JR Z,constB -0259 E82A -0260 E82A E6 03 AND $03 ; remove the reader from the mask - only console bits then remain -0261 E82C FE 01 CP $01 -0262 E82E 20 0E JR NZ,constB -0263 E830 constA: -0264 E830 DB 80 IN A,(ACIA0_C) ; Status byte -0265 E832 E6 01 AND $01 -0266 E834 FE 00 CP $0 ; Z flag set if no char -0267 E836 28 03 JR Z, dataAEmpty -0268 E838 3E FF LD A,0FFH -0269 E83A C9 RET -0270 E83B dataAEmpty: -0271 E83B 3E 00 LD A,0 -0272 E83D C9 RET -0273 E83E -0274 E83E -0275 E83E constB: -0276 E83E DB 82 IN A,(ACIA1_C) ; Status byte -0277 E840 E6 01 AND $01 -0278 E842 FE 00 CP $0 ; Z flag set if no char -0279 E844 28 03 JR Z, dataBEmpty -0280 E846 3E FF LD A,0FFH -0281 E848 C9 RET -0282 E849 dataBEmpty: -0283 E849 3E 00 LD A,0 -0284 E84B C9 RET -0285 E84C -0286 E84C ;------------------------------------------------------------------------------------------------ -0287 E84C reader: -0288 E84C F5 PUSH AF -0289 E84D 3A 03 00 reader2: LD A,(iobyte) -0290 E850 E6 08 AND $08 -0291 E852 FE 08 CP $08 -0292 E854 20 1C JR NZ,coninB -0293 E856 18 0E JR coninA -0294 E858 ;------------------------------------------------------------------------------------------------ -0295 E858 conin: -0296 E858 F5 PUSH AF -0297 E859 3A 03 00 LD A,(iobyte) -0298 E85C E6 03 AND $03 -0299 E85E FE 02 CP $02 -0300 E860 28 EB JR Z,reader2 ; "BAT:" redirect -0301 E862 FE 01 CP $01 -0302 E864 20 0C JR NZ,coninB -0303 E866 -0304 E866 -0305 E866 coninA: -0306 E866 F1 POP AF -0307 E867 waitForCharA: -0308 E867 DB 80 IN A,(ACIA0_C) ; Status byte -0309 E869 E6 01 AND $01 -0310 E86B FE 00 CP $0 ; Z flag set if no char -0311 E86D 28 F8 JR Z, waitForCharA -0312 E86F DB 81 IN A,(ACIA0_D) -0313 E871 -0314 E871 C9 RET ; Char ready in A -0315 E872 -0316 E872 -0317 E872 coninB: -0318 E872 F1 POP AF -0319 E873 waitForCharB: -0320 E873 DB 82 IN A,(ACIA1_C) ; Status byte -0321 E875 E6 01 AND $01 -0322 E877 FE 00 CP $0 ; Z flag set if no char -0323 E879 28 F8 JR Z, waitForCharB -0324 E87B DB 83 IN A,(ACIA1_D) -0325 E87D -0326 E87D C9 RET ; Char ready in A -0327 E87E -0328 E87E ;------------------------------------------------------------------------------------------------ -0329 E87E F5 list: PUSH AF ; Store character -0330 E87F 3A 03 00 list2: LD A,(iobyte) -0331 E882 E6 C0 AND $C0 -0332 E884 FE 40 CP $40 -0333 E886 20 26 JR NZ,conoutB1 -0334 E888 18 1A JR conoutA1 -0335 E88A -0336 E88A ;------------------------------------------------------------------------------------------------ -0337 E88A F5 punch: PUSH AF ; Store character -0338 E88B 3A 03 00 LD A,(iobyte) -0339 E88E E6 20 AND $20 -0340 E890 FE 20 CP $20 -0341 E892 20 1A JR NZ,conoutB1 -0342 E894 18 0E JR conoutA1 -0343 E896 -0344 E896 ;------------------------------------------------------------------------------------------------ -0345 E896 F5 conout: PUSH AF -0346 E897 3A 03 00 LD A,(iobyte) -0347 E89A E6 03 AND $03 -0348 E89C FE 02 CP $02 -0349 E89E 28 DF JR Z,list2 ; "BAT:" redirect -0350 E8A0 FE 01 CP $01 -0351 E8A2 20 0A JR NZ,conoutB1 -0352 E8A4 -0353 E8A4 CD B8 E8 conoutA1: CALL CKACIA0 ; See if ACIA channel A is finished transmitting -0354 E8A7 28 FB JR Z,conoutA1 ; Loop until ACIA flag signals ready -0355 E8A9 79 LD A,C -0356 E8AA D3 81 OUT (ACIA0_D),A ; OUTput the character -0357 E8AC F1 POP AF -0358 E8AD C9 RET -0359 E8AE -0360 E8AE CD BE E8 conoutB1: CALL CKACIA1 ; See if ACIA channel B is finished transmitting -0361 E8B1 28 FB JR Z,conoutB1 ; Loop until ACIA flag signals ready -0362 E8B3 79 LD A,C -0363 E8B4 D3 83 OUT (ACIA1_D),A ; OUTput the character -0364 E8B6 F1 POP AF -0365 E8B7 C9 RET -0366 E8B8 -0367 E8B8 ;------------------------------------------------------------------------------------------------ -0368 E8B8 CKACIA0 -0369 E8B8 DB 80 IN A,(ACIA0_C) ; Status byte D1=TX Buff Empty, D0=RX char ready -0370 E8BA 0F RRCA ; Rotates RX status into Carry Flag, -0371 E8BB CB 47 BIT 0,A ; Set Zero flag if still transmitting character -0372 E8BD C9 RET -0373 E8BE -0374 E8BE CKACIA1 -0375 E8BE DB 82 IN A,(ACIA1_C) ; Status byte D1=TX Buff Empty, D0=RX char ready -0376 E8C0 0F RRCA ; Rotates RX status into Carry Flag, -0377 E8C1 CB 47 BIT 0,A ; Set Zero flag if still transmitting character -0378 E8C3 C9 RET -0379 E8C4 -0380 E8C4 ;------------------------------------------------------------------------------------------------ -0381 E8C4 3E FF listst: LD A,$FF ; Return list status of 0xFF (ready). -0382 E8C6 C9 RET -0383 E8C7 -0384 E8C7 ;================================================================================================ -0385 E8C7 ; Disk processing entry points -0386 E8C7 ;================================================================================================ -0387 E8C7 -0388 E8C7 seldsk: -0389 E8C7 21 00 00 LD HL,$0000 -0390 E8CA 79 LD A,C -0391 E8CB FE 10 CP 16 ; 16 for 128MB disk, 8 for 64MB disk -0392 E8CD 38 0D jr C,chgdsk ; if invalid drive will give BDOS error -0393 E8CF 3A 04 00 LD A,(userdrv) ; so set the drive back to a: -0394 E8D2 B9 CP C ; If the default disk is not the same as the -0395 E8D3 C0 RET NZ ; selected drive then return, -0396 E8D4 AF XOR A ; else reset default back to a: -0397 E8D5 32 04 00 LD (userdrv),A ; otherwise will be stuck in a loop -0398 E8D8 32 C1 FB LD (sekdsk),A -0399 E8DB C9 ret -0400 E8DC -0401 E8DC 32 C1 FB chgdsk: LD (sekdsk),A -0402 E8DF CB 07 RLC a ;*2 -0403 E8E1 CB 07 RLC a ;*4 -0404 E8E3 CB 07 RLC a ;*8 -0405 E8E5 CB 07 RLC a ;*16 -0406 E8E7 21 33 E6 LD HL,dpbase -0407 E8EA 06 00 LD b,0 -0408 E8EC 4F LD c,A -0409 E8ED 09 ADD HL,BC -0410 E8EE -0411 E8EE C9 RET -0412 E8EF -0413 E8EF ;------------------------------------------------------------------------------------------------ -0414 E8EF home: -0415 E8EF 3A CC FB ld a,(hstwrt) ;check for pending write -0416 E8F2 B7 or a -0417 E8F3 20 03 jr nz,homed -0418 E8F5 32 CB FB ld (hstact),a ;clear host active flag -0419 E8F8 homed: -0420 E8F8 01 00 00 LD BC,0000h -0421 E8FB -0422 E8FB ;------------------------------------------------------------------------------------------------ -0423 E8FB ED 43 C2 FB settrk: LD (sektrk),BC ; Set track passed from BDOS in register BC. -0424 E8FF C9 RET -0425 E900 -0426 E900 ;------------------------------------------------------------------------------------------------ -0427 E900 ED 43 C4 FB setsec: LD (seksec),BC ; Set sector passed from BDOS in register BC. -0428 E904 C9 RET -0429 E905 -0430 E905 ;------------------------------------------------------------------------------------------------ -0431 E905 ED 43 D6 FB setdma: LD (dmaAddr),BC ; Set DMA ADDress given by registers BC. -0432 E909 C9 RET -0433 E90A -0434 E90A ;------------------------------------------------------------------------------------------------ -0435 E90A C5 sectran: PUSH BC -0436 E90B E1 POP HL -0437 E90C C9 RET -0438 E90D -0439 E90D ;------------------------------------------------------------------------------------------------ -0440 E90D read: -0441 E90D ;read the selected CP/M sector -0442 E90D AF xor a -0443 E90E 32 CD FB ld (unacnt),a -0444 E911 3E 01 ld a,1 -0445 E913 32 D4 FB ld (readop),a ;read operation -0446 E916 32 D3 FB ld (rsflag),a ;must read data -0447 E919 3E 02 ld a,wrual -0448 E91B 32 D5 FB ld (wrtype),a ;treat as unalloc -0449 E91E C3 88 E9 jp rwoper ;to perform the read -0450 E921 -0451 E921 -0452 E921 ;------------------------------------------------------------------------------------------------ -0453 E921 write: -0454 E921 ;write the selected CP/M sector -0455 E921 AF xor a ;0 to accumulator -0456 E922 32 D4 FB ld (readop),a ;not a read operation -0457 E925 79 ld a,c ;write type in c -0458 E926 32 D5 FB ld (wrtype),a -0459 E929 FE 02 cp wrual ;write unallocated? -0460 E92B 20 17 jr nz,chkuna ;check for unalloc -0461 E92D ; -0462 E92D ; write to unallocated, set parameters -0463 E92D 3E 20 ld a,blksiz/128 ;next unalloc recs -0464 E92F 32 CD FB ld (unacnt),a -0465 E932 3A C1 FB ld a,(sekdsk) ;disk to seek -0466 E935 32 CE FB ld (unadsk),a ;unadsk = sekdsk -0467 E938 2A C2 FB ld hl,(sektrk) -0468 E93B 22 CF FB ld (unatrk),hl ;unatrk = sectrk -0469 E93E 3A C4 FB ld a,(seksec) -0470 E941 32 D1 FB ld (unasec),a ;unasec = seksec -0471 E944 ; -0472 E944 chkuna: -0473 E944 ; check for write to unallocated sector -0474 E944 3A CD FB ld a,(unacnt) ;any unalloc remain? -0475 E947 B7 or a -0476 E948 28 36 jr z,alloc ;skip if not -0477 E94A ; -0478 E94A ; more unallocated records remain -0479 E94A 3D dec a ;unacnt = unacnt-1 -0480 E94B 32 CD FB ld (unacnt),a -0481 E94E 3A C1 FB ld a,(sekdsk) ;same disk? -0482 E951 21 CE FB ld hl,unadsk -0483 E954 BE cp (hl) ;sekdsk = unadsk? -0484 E955 C2 80 E9 jp nz,alloc ;skip if not -0485 E958 ; -0486 E958 ; disks are the same -0487 E958 21 CF FB ld hl,unatrk -0488 E95B CD 1F EA call sektrkcmp ;sektrk = unatrk? -0489 E95E C2 80 E9 jp nz,alloc ;skip if not -0490 E961 ; -0491 E961 ; tracks are the same -0492 E961 3A C4 FB ld a,(seksec) ;same sector? -0493 E964 21 D1 FB ld hl,unasec -0494 E967 BE cp (hl) ;seksec = unasec? -0495 E968 C2 80 E9 jp nz,alloc ;skip if not -0496 E96B ; -0497 E96B ; match, move to next sector for future ref -0498 E96B 34 inc (hl) ;unasec = unasec+1 -0499 E96C 7E ld a,(hl) ;end of track? -0500 E96D FE 80 cp cpmspt ;count CP/M sectors -0501 E96F 38 09 jr c,noovf ;skip if no overflow -0502 E971 ; -0503 E971 ; overflow to next track -0504 E971 36 00 ld (hl),0 ;unasec = 0 -0505 E973 2A CF FB ld hl,(unatrk) -0506 E976 23 inc hl -0507 E977 22 CF FB ld (unatrk),hl ;unatrk = unatrk+1 -0508 E97A ; -0509 E97A noovf: -0510 E97A ;match found, mark as unnecessary read -0511 E97A AF xor a ;0 to accumulator -0512 E97B 32 D3 FB ld (rsflag),a ;rsflag = 0 -0513 E97E 18 08 jr rwoper ;to perform the write -0514 E980 ; -0515 E980 alloc: -0516 E980 ;not an unallocated record, requires pre-read -0517 E980 AF xor a ;0 to accum -0518 E981 32 CD FB ld (unacnt),a ;unacnt = 0 -0519 E984 3C inc a ;1 to accum -0520 E985 32 D3 FB ld (rsflag),a ;rsflag = 1 -0521 E988 -0522 E988 ;------------------------------------------------------------------------------------------------ -0523 E988 rwoper: -0524 E988 ;enter here to perform the read/write -0525 E988 AF xor a ;zero to accum -0526 E989 32 D2 FB ld (erflag),a ;no errors (yet) -0527 E98C 3A C4 FB ld a,(seksec) ;compute host sector -0528 E98F B7 or a ;carry = 0 -0529 E990 1F rra ;shift right -0530 E991 B7 or a ;carry = 0 -0531 E992 1F rra ;shift right -0532 E993 32 CA FB ld (sekhst),a ;host sector to seek -0533 E996 ; -0534 E996 ; active host sector? -0535 E996 21 CB FB ld hl,hstact ;host active flag -0536 E999 7E ld a,(hl) -0537 E99A 36 01 ld (hl),1 ;always becomes 1 -0538 E99C B7 or a ;was it already? -0539 E99D 28 21 jr z,filhst ;fill host if not -0540 E99F ; -0541 E99F ; host buffer active, same as seek buffer? -0542 E99F 3A C1 FB ld a,(sekdsk) -0543 E9A2 21 C6 FB ld hl,hstdsk ;same disk? -0544 E9A5 BE cp (hl) ;sekdsk = hstdsk? -0545 E9A6 20 11 jr nz,nomatch -0546 E9A8 ; -0547 E9A8 ; same disk, same track? -0548 E9A8 21 C7 FB ld hl,hsttrk -0549 E9AB CD 1F EA call sektrkcmp ;sektrk = hsttrk? -0550 E9AE 20 09 jr nz,nomatch -0551 E9B0 ; -0552 E9B0 ; same disk, same track, same buffer? -0553 E9B0 3A CA FB ld a,(sekhst) -0554 E9B3 21 C9 FB ld hl,hstsec ;sekhst = hstsec? -0555 E9B6 BE cp (hl) -0556 E9B7 28 24 jr z,match ;skip if match -0557 E9B9 ; -0558 E9B9 nomatch: -0559 E9B9 ;proper disk, but not correct sector -0560 E9B9 3A CC FB ld a,(hstwrt) ;host written? -0561 E9BC B7 or a -0562 E9BD C4 C4 EA call nz,writehst ;clear host buff -0563 E9C0 ; -0564 E9C0 filhst: -0565 E9C0 ;may have to fill the host buffer -0566 E9C0 3A C1 FB ld a,(sekdsk) -0567 E9C3 32 C6 FB ld (hstdsk),a -0568 E9C6 2A C2 FB ld hl,(sektrk) -0569 E9C9 22 C7 FB ld (hsttrk),hl -0570 E9CC 3A CA FB ld a,(sekhst) -0571 E9CF 32 C9 FB ld (hstsec),a -0572 E9D2 3A D3 FB ld a,(rsflag) ;need to read? -0573 E9D5 B7 or a -0574 E9D6 C4 95 EA call nz,readhst ;yes, if 1 -0575 E9D9 AF xor a ;0 to accum -0576 E9DA 32 CC FB ld (hstwrt),a ;no pending write -0577 E9DD ; -0578 E9DD match: -0579 E9DD ;copy data to or from buffer -0580 E9DD 3A C4 FB ld a,(seksec) ;mask buffer number -0581 E9E0 E6 03 and secmsk ;least signif bits -0582 E9E2 6F ld l,a ;ready to shift -0583 E9E3 26 00 ld h,0 ;double count -0584 E9E5 29 add hl,hl -0585 E9E6 29 add hl,hl -0586 E9E7 29 add hl,hl -0587 E9E8 29 add hl,hl -0588 E9E9 29 add hl,hl -0589 E9EA 29 add hl,hl -0590 E9EB 29 add hl,hl -0591 E9EC ; hl has relative host buffer address -0592 E9EC 11 D8 FB ld de,hstbuf -0593 E9EF 19 add hl,de ;hl = host address -0594 E9F0 EB ex de,hl ;now in DE -0595 E9F1 2A D6 FB ld hl,(dmaAddr) ;get/put CP/M data -0596 E9F4 0E 80 ld c,128 ;length of move -0597 E9F6 3A D4 FB ld a,(readop) ;which way? -0598 E9F9 B7 or a -0599 E9FA 20 06 jr nz,rwmove ;skip if read -0600 E9FC ; -0601 E9FC ; write operation, mark and switch direction -0602 E9FC 3E 01 ld a,1 -0603 E9FE 32 CC FB ld (hstwrt),a ;hstwrt = 1 -0604 EA01 EB ex de,hl ;source/dest swap -0605 EA02 ; -0606 EA02 rwmove: -0607 EA02 ;C initially 128, DE is source, HL is dest -0608 EA02 1A ld a,(de) ;source character -0609 EA03 13 inc de -0610 EA04 77 ld (hl),a ;to dest -0611 EA05 23 inc hl -0612 EA06 0D dec c ;loop 128 times -0613 EA07 20 F9 jr nz,rwmove -0614 EA09 ; -0615 EA09 ; data has been moved to/from host buffer -0616 EA09 3A D5 FB ld a,(wrtype) ;write type -0617 EA0C FE 01 cp wrdir ;to directory? -0618 EA0E 3A D2 FB ld a,(erflag) ;in case of errors -0619 EA11 C0 ret nz ;no further processing -0620 EA12 ; -0621 EA12 ; clear host buffer for directory write -0622 EA12 B7 or a ;errors? -0623 EA13 C0 ret nz ;skip if so -0624 EA14 AF xor a ;0 to accum -0625 EA15 32 CC FB ld (hstwrt),a ;buffer written -0626 EA18 CD C4 EA call writehst -0627 EA1B 3A D2 FB ld a,(erflag) -0628 EA1E C9 ret -0629 EA1F -0630 EA1F ;------------------------------------------------------------------------------------------------ -0631 EA1F ;Utility subroutine for 16-bit compare -0632 EA1F sektrkcmp: -0633 EA1F ;HL = .unatrk or .hsttrk, compare with sektrk -0634 EA1F EB ex de,hl -0635 EA20 21 C2 FB ld hl,sektrk -0636 EA23 1A ld a,(de) ;low byte compare -0637 EA24 BE cp (HL) ;same? -0638 EA25 C0 ret nz ;return if not -0639 EA26 ; low bytes equal, test high 1s -0640 EA26 13 inc de -0641 EA27 23 inc hl -0642 EA28 1A ld a,(de) -0643 EA29 BE cp (hl) ;sets flags -0644 EA2A C9 ret -0645 EA2B -0646 EA2B ;================================================================================================ -0647 EA2B ; Convert track/head/sector into LBA for physical access to the disk -0648 EA2B ;================================================================================================ -0649 EA2B setLBAaddr: -0650 EA2B 2A C7 FB LD HL,(hsttrk) -0651 EA2E CB 05 RLC L -0652 EA30 CB 05 RLC L -0653 EA32 CB 05 RLC L -0654 EA34 CB 05 RLC L -0655 EA36 CB 05 RLC L -0656 EA38 7D LD A,L -0657 EA39 E6 E0 AND 0E0H -0658 EA3B 6F LD L,A -0659 EA3C 3A C9 FB LD A,(hstsec) -0660 EA3F 85 ADD A,L -0661 EA40 32 9D FB LD (lba0),A -0662 EA43 -0663 EA43 2A C7 FB LD HL,(hsttrk) -0664 EA46 CB 0D RRC L -0665 EA48 CB 0D RRC L -0666 EA4A CB 0D RRC L -0667 EA4C 7D LD A,L -0668 EA4D E6 1F AND 01FH -0669 EA4F 6F LD L,A -0670 EA50 CB 04 RLC H -0671 EA52 CB 04 RLC H -0672 EA54 CB 04 RLC H -0673 EA56 CB 04 RLC H -0674 EA58 CB 04 RLC H -0675 EA5A 7C LD A,H -0676 EA5B E6 20 AND 020H -0677 EA5D 67 LD H,A -0678 EA5E 3A C6 FB LD A,(hstdsk) -0679 EA61 CB 07 RLC a -0680 EA63 CB 07 RLC a -0681 EA65 CB 07 RLC a -0682 EA67 CB 07 RLC a -0683 EA69 CB 07 RLC a -0684 EA6B CB 07 RLC a -0685 EA6D E6 C0 AND 0C0H -0686 EA6F 84 ADD A,H -0687 EA70 85 ADD A,L -0688 EA71 32 9E FB LD (lba1),A -0689 EA74 -0690 EA74 3A C6 FB LD A,(hstdsk) -0691 EA77 CB 0F RRC A -0692 EA79 CB 0F RRC A -0693 EA7B E6 03 AND 03H -0694 EA7D 32 9F FB LD (lba2),A -0695 EA80 -0696 EA80 3E 00 LD a,00H -0697 EA82 32 A0 FB LD (lba3),A -0698 EA85 -0699 EA85 ; Transfer LBA to disk (LBA3 not used on SD card) -0700 EA85 3A 9F FB LD A,(lba2) -0701 EA88 D3 8C OUT (SD_LBA2),A -0702 EA8A 3A 9E FB LD A,(lba1) -0703 EA8D D3 8B OUT (SD_LBA1),A -0704 EA8F 3A 9D FB LD A,(lba0) -0705 EA92 D3 8A OUT (SD_LBA0),A -0706 EA94 C9 RET -0707 EA95 -0708 EA95 ;================================================================================================ -0709 EA95 ; Read physical sector from host -0710 EA95 ;================================================================================================ -0711 EA95 -0712 EA95 readhst: -0713 EA95 F5 PUSH AF -0714 EA96 C5 PUSH BC -0715 EA97 E5 PUSH HL -0716 EA98 -0717 EA98 DB 89 rdWait1: IN A,(SD_STATUS) -0718 EA9A FE 80 CP 128 -0719 EA9C 20 FA JR NZ,rdWait1 -0720 EA9E -0721 EA9E CD 2B EA CALL setLBAaddr -0722 EAA1 -0723 EAA1 3E 00 LD A,$00 ; 00 = Read block -0724 EAA3 D3 89 OUT (SD_CONTROL),A -0725 EAA5 -0726 EAA5 0E 04 LD c,4 -0727 EAA7 21 D8 FB LD HL,hstbuf -0728 EAAA rd4secs: -0729 EAAA 06 80 LD b,128 -0730 EAAC rdByte: -0731 EAAC -0732 EAAC DB 89 rdWait2: IN A,(SD_STATUS) -0733 EAAE FE E0 CP 224 ; Read byte waiting -0734 EAB0 20 FA JR NZ,rdWait2 -0735 EAB2 -0736 EAB2 DB 88 IN A,(SD_DATA) -0737 EAB4 -0738 EAB4 77 LD (HL),A -0739 EAB5 23 INC HL -0740 EAB6 05 dec b -0741 EAB7 20 F3 JR NZ, rdByte -0742 EAB9 0D dec c -0743 EABA 20 EE JR NZ,rd4secs -0744 EABC -0745 EABC E1 POP HL -0746 EABD C1 POP BC -0747 EABE F1 POP AF -0748 EABF -0749 EABF AF XOR a -0750 EAC0 32 D2 FB ld (erflag),a -0751 EAC3 C9 RET -0752 EAC4 -0753 EAC4 -0754 EAC4 ;================================================================================================ -0755 EAC4 ; Write physical sector to host -0756 EAC4 ;================================================================================================ -0757 EAC4 -0758 EAC4 writehst: -0759 EAC4 F5 PUSH AF -0760 EAC5 C5 PUSH BC -0761 EAC6 E5 PUSH HL -0762 EAC7 -0763 EAC7 DB 89 wrWait1: IN A,(SD_STATUS) -0764 EAC9 FE 80 CP 128 -0765 EACB 20 FA JR NZ,wrWait1 -0766 EACD -0767 EACD CD 2B EA CALL setLBAaddr -0768 EAD0 -0769 EAD0 3E 01 LD A,$01 ; 01 = Write block -0770 EAD2 D3 89 OUT (SD_CONTROL),A -0771 EAD4 -0772 EAD4 0E 04 LD c,4 -0773 EAD6 21 D8 FB LD HL,hstbuf -0774 EAD9 wr4secs: -0775 EAD9 06 80 LD b,128 -0776 EADB wrByte: -0777 EADB -0778 EADB DB 89 wrWait2: IN A,(SD_STATUS) -0779 EADD FE A0 CP 160 ; Write buffer empty -0780 EADF 20 FA JR NZ,wrWait2 -0781 EAE1 -0782 EAE1 ; UPDATE S0urceror, inserted wait cycle between IN and OUT -0783 EAE1 ; to resolve unknown write issue in sd_controller.vhd in combination -0784 EAE1 ; with MISTer virtual SD interface sys/sd_card.sv -0785 EAE1 ; which results in hangs or write errors. -0786 EAE1 C5 push bc -0787 EAE2 06 32 ld b,50 -0788 EAE4 _again: -0789 EAE4 10 FE djnz _again -0790 EAE6 C1 pop bc -0791 EAE7 ; END UPDATE -0792 EAE7 -0793 EAE7 7E LD A,(HL) -0794 EAE8 D3 88 OUT (SD_DATA),A -0795 EAEA 23 INC HL -0796 EAEB 05 dec b -0797 EAEC 20 ED JR NZ, wrByte -0798 EAEE -0799 EAEE 0D dec c -0800 EAEF 20 E8 JR NZ,wr4secs -0801 EAF1 -0802 EAF1 E1 POP HL -0803 EAF2 C1 POP BC -0804 EAF3 F1 POP AF -0805 EAF4 -0806 EAF4 AF XOR a -0807 EAF5 32 D2 FB ld (erflag),a -0808 EAF8 C9 RET -0809 EAF9 -0810 EAF9 ;================================================================================================ -0811 EAF9 ; Utilities -0812 EAF9 ;================================================================================================ -0813 EAF9 -0814 EAF9 printInline: -0815 EAF9 E3 EX (SP),HL ; PUSH HL and put RET ADDress into HL -0816 EAFA F5 PUSH AF -0817 EAFB C5 PUSH BC -0818 EAFC 7E nextILChar: LD A,(HL) -0819 EAFD FE 00 CP 0 -0820 EAFF 28 07 JR Z,endOfPrint -0821 EB01 4F LD C,A -0822 EB02 CD 96 E8 CALL conout ; Print to TTY -0823 EB05 23 iNC HL -0824 EB06 18 F4 JR nextILChar -0825 EB08 23 endOfPrint: INC HL ; Get past "null" terminator -0826 EB09 C1 POP BC -0827 EB0A F1 POP AF -0828 EB0B E3 EX (SP),HL ; PUSH new RET ADDress on stack and restore HL -0829 EB0C C9 RET -0830 EB0D -0831 EB0D ;================================================================================================ -0832 EB0D ; Data storage -0833 EB0D ;================================================================================================ -0834 EB0D -0835 EB0D dirbuf: .ds 128 ;scratch directory area -0836 EB8D alv00: .ds 257 ;allocation vector 0 -0837 EC8E alv01: .ds 257 ;allocation vector 1 -0838 ED8F alv02: .ds 257 ;allocation vector 2 -0839 EE90 alv03: .ds 257 ;allocation vector 3 -0840 EF91 alv04: .ds 257 ;allocation vector 4 -0841 F092 alv05: .ds 257 ;allocation vector 5 -0842 F193 alv06: .ds 257 ;allocation vector 6 -0843 F294 alv07: .ds 257 ;allocation vector 7 -0844 F395 alv08: .ds 257 ;allocation vector 8 -0845 F496 alv09: .ds 257 ;allocation vector 9 -0846 F597 alv10: .ds 257 ;allocation vector 10 -0847 F698 alv11: .ds 257 ;allocation vector 11 -0848 F799 alv12: .ds 257 ;allocation vector 12 -0849 F89A alv13: .ds 257 ;allocation vector 13 -0850 F99B alv14: .ds 257 ;allocation vector 14 -0851 FA9C alv15: .ds 257 ;allocation vector 15 -0852 FB9D -0853 FB9D 00 lba0 .DB 00h -0854 FB9E 00 lba1 .DB 00h -0855 FB9F 00 lba2 .DB 00h -0856 FBA0 00 lba3 .DB 00h -0857 FBA1 -0858 FBA1 .DS 020h ; Start of BIOS stack area. -0859 FBC1 biosstack: .EQU $ -0860 FBC1 -0861 FBC1 sekdsk: .ds 1 ;seek disk number -0862 FBC2 sektrk: .ds 2 ;seek track number -0863 FBC4 seksec: .ds 2 ;seek sector number -0864 FBC6 ; -0865 FBC6 hstdsk: .ds 1 ;host disk number -0866 FBC7 hsttrk: .ds 2 ;host track number -0867 FBC9 hstsec: .ds 1 ;host sector number -0868 FBCA ; -0869 FBCA sekhst: .ds 1 ;seek shr secshf -0870 FBCB hstact: .ds 1 ;host active flag -0871 FBCC hstwrt: .ds 1 ;host written flag -0872 FBCD ; -0873 FBCD unacnt: .ds 1 ;unalloc rec cnt -0874 FBCE unadsk: .ds 1 ;last unalloc disk -0875 FBCF unatrk: .ds 2 ;last unalloc track -0876 FBD1 unasec: .ds 1 ;last unalloc sector -0877 FBD2 ; -0878 FBD2 erflag: .ds 1 ;error reporting -0879 FBD3 rsflag: .ds 1 ;read sector flag -0880 FBD4 readop: .ds 1 ;1 if read operation -0881 FBD5 wrtype: .ds 1 ;write operation type -0882 FBD6 dmaAddr: .ds 2 ;last dma address -0883 FBD8 hstbuf: .ds 512 ;host buffer -0884 FDD8 -0885 FDD8 hstBufEnd: .EQU $ -0886 FDD8 -0887 FDD8 biosEnd: .EQU $ -0888 FDD8 -0889 FDD8 ; Disable the ROM, pop the active IO port from the stack (supplied by monitor), -0890 FDD8 ; then start CP/M -0891 FDD8 popAndRun: -0892 FDD8 3E 01 LD A,$01 -0893 FDDA D3 38 OUT ($38),A -0894 FDDC -0895 FDDC F1 POP AF -0896 FDDD FE 01 CP $01 -0897 FDDF 28 04 JR Z,consoleAtB -0898 FDE1 3E 01 LD A,$01 ;(List is TTY:, Punch is TTY:, Reader is TTY:, Console is CRT:) -0899 FDE3 18 02 JR setIOByte -0900 FDE5 3E 00 consoleAtB: LD A,$00 ;(List is TTY:, Punch is TTY:, Reader is TTY:, Console is TTY:) -0901 FDE7 32 03 00 setIOByte: LD (iobyte),A -0902 FDEA C3 00 E6 JP bios -0903 FDED -0904 FDED -0905 FDED ;================================================================================= -0906 FDED ; Relocate TPA area from 4100 to 0100 then start CP/M -0907 FDED ; Used to manually transfer a loaded program after CP/M was previously loaded -0908 FDED ;================================================================================= -0909 FDED -0910 FFE8 .org 0FFE8H -0911 FFE8 3E 01 LD A,$01 -0912 FFEA D3 38 OUT ($38),A -0913 FFEC -0914 FFEC 21 00 41 LD HL,04100H -0915 FFEF 11 00 01 LD DE,00100H -0916 FFF2 01 00 8F LD BC,08F00H -0917 FFF5 ED B0 LDIR -0918 FFF7 C3 00 E6 JP bios -0919 FFFA -0920 FFFA ;================================================================================= -0921 FFFA ; Normal start CP/M vector -0922 FFFA ;================================================================================= -0923 FFFA -0924 FFFE .ORG 0FFFEH -0925 FFFE D8 FD .dw popAndRun -0926 0000 -0927 0000 .END -tasm: Number of errors = 0 +0001 0000 ;================================================================================== +0002 0000 ; Contents of this file are copyright Grant Searle +0003 0000 ; Blocking/unblocking routines are the published version by Digital Research +0004 0000 ; (bugfixed, as found on the web) +0005 0000 ; +0006 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY +0007 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. +0008 0000 ; +0009 0000 ; http://searle.hostei.com/grant/index.html +0010 0000 ; +0011 0000 ; eMail: home.micros01@btinternet.com +0012 0000 ; +0013 0000 ; If the above don't work, please perform an Internet search to see if I have +0014 0000 ; updated the web page hosting service. +0015 0000 ; +0016 0000 ;================================================================================== +0017 0000 +0018 0000 ccp .EQU 0D000h ; Base of CCP. +0019 0000 bdos .EQU ccp + 0806h ; Base of BDOS. +0020 0000 bios .EQU ccp + 1600h ; Base of BIOS. +0021 0000 +0022 0000 ; Set CP/M low memory datA, vector and buffer addresses. +0023 0000 +0024 0000 iobyte .EQU 03h ; Intel standard I/O definition byte. +0025 0000 userdrv .EQU 04h ; Current user number and drive. +0026 0000 tpabuf .EQU 80h ; Default I/O buffer and command line storage. +0027 0000 +0028 0000 +0029 0000 SD_DATA .EQU 088H +0030 0000 SD_CONTROL .EQU 089H +0031 0000 SD_STATUS .EQU 089H +0032 0000 SD_LBA0 .EQU 08AH +0033 0000 SD_LBA1 .EQU 08BH +0034 0000 SD_LBA2 .EQU 08CH +0035 0000 +0036 0000 RTS_HIGH .EQU 0D5H +0037 0000 RTS_LOW .EQU 095H +0038 0000 +0039 0000 ACIA0_D .EQU $81 +0040 0000 ACIA0_C .EQU $80 +0041 0000 ACIA1_D .EQU $83 +0042 0000 ACIA1_C .EQU $82 +0043 0000 +0044 0000 nmi .EQU 66H +0045 0000 +0046 0000 blksiz .equ 4096 ;CP/M allocation size +0047 0000 hstsiz .equ 512 ;host disk sector size +0048 0000 hstspt .equ 32 ;host disk sectors/trk +0049 0000 hstblk .equ hstsiz/128 ;CP/M sects/host buff +0050 0000 cpmspt .equ hstblk * hstspt ;CP/M sectors/track +0051 0000 secmsk .equ hstblk-1 ;sector mask +0052 0000 ;compute sector mask +0053 0000 ;secshf .equ 2 ;log2(hstblk) +0054 0000 +0055 0000 wrall .equ 0 ;write to allocated +0056 0000 wrdir .equ 1 ;write to directory +0057 0000 wrual .equ 2 ;write to unallocated +0058 0000 +0059 0000 LF .EQU 0AH ;line feed +0060 0000 FF .EQU 0CH ;form feed +0061 0000 CR .EQU 0DH ;carriage RETurn +0062 0000 +0063 0000 ;================================================================================================ +0064 0000 +0065 E600 .ORG bios ; BIOS origin. +0066 E600 +0067 E600 ;================================================================================================ +0068 E600 ; BIOS jump table. +0069 E600 ;================================================================================================ +0070 E600 C3 51 E7 JP boot ; 0 Initialize. +0071 E603 C3 B5 E7 wboote: JP wboot ; 1 Warm boot. +0072 E606 C3 1D E8 JP const ; 2 Console status. +0073 E609 C3 58 E8 JP conin ; 3 Console input. +0074 E60C C3 96 E8 JP conout ; 4 Console OUTput. +0075 E60F C3 7E E8 JP list ; 5 List OUTput. +0076 E612 C3 8A E8 JP punch ; 6 punch OUTput. +0077 E615 C3 4C E8 JP reader ; 7 Reader input. +0078 E618 C3 EF E8 JP home ; 8 Home disk. +0079 E61B C3 C7 E8 JP seldsk ; 9 Select disk. +0080 E61E C3 FB E8 JP settrk ; 10 Select track. +0081 E621 C3 00 E9 JP setsec ; 11 Select sector. +0082 E624 C3 05 E9 JP setdma ; 12 Set DMA ADDress. +0083 E627 C3 0D E9 JP read ; 13 Read 128 bytes. +0084 E62A C3 21 E9 JP write ; 14 Write 128 bytes. +0085 E62D C3 C4 E8 JP listst ; 15 List status. +0086 E630 C3 0A E9 JP sectran ; 16 Sector translate. +0087 E633 +0088 E633 ;================================================================================================ +0089 E633 ; Disk parameter headers for disk 0 to 15 +0090 E633 ;================================================================================================ +0091 E633 dpbase: +0092 E633 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb0,0000h,alv00 +0092 E637 00 00 00 00 +0092 E63B 43 EB 33 E7 +0092 E63F 00 00 C3 EB +0093 E643 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv01 +0093 E647 00 00 00 00 +0093 E64B 43 EB 42 E7 +0093 E64F 00 00 C4 EC +0094 E653 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv02 +0094 E657 00 00 00 00 +0094 E65B 43 EB 42 E7 +0094 E65F 00 00 C5 ED +0095 E663 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv03 +0095 E667 00 00 00 00 +0095 E66B 43 EB 42 E7 +0095 E66F 00 00 C6 EE +0096 E673 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv04 +0096 E677 00 00 00 00 +0096 E67B 43 EB 42 E7 +0096 E67F 00 00 C7 EF +0097 E683 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv05 +0097 E687 00 00 00 00 +0097 E68B 43 EB 42 E7 +0097 E68F 00 00 C8 F0 +0098 E693 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv06 +0098 E697 00 00 00 00 +0098 E69B 43 EB 42 E7 +0098 E69F 00 00 C9 F1 +0099 E6A3 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv07 +0099 E6A7 00 00 00 00 +0099 E6AB 43 EB 42 E7 +0099 E6AF 00 00 CA F2 +0100 E6B3 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv08 +0100 E6B7 00 00 00 00 +0100 E6BB 43 EB 42 E7 +0100 E6BF 00 00 CB F3 +0101 E6C3 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv09 +0101 E6C7 00 00 00 00 +0101 E6CB 43 EB 42 E7 +0101 E6CF 00 00 CC F4 +0102 E6D3 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv10 +0102 E6D7 00 00 00 00 +0102 E6DB 43 EB 42 E7 +0102 E6DF 00 00 CD F5 +0103 E6E3 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv11 +0103 E6E7 00 00 00 00 +0103 E6EB 43 EB 42 E7 +0103 E6EF 00 00 CE F6 +0104 E6F3 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv12 +0104 E6F7 00 00 00 00 +0104 E6FB 43 EB 42 E7 +0104 E6FF 00 00 CF F7 +0105 E703 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv13 +0105 E707 00 00 00 00 +0105 E70B 43 EB 42 E7 +0105 E70F 00 00 D0 F8 +0106 E713 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv14 +0106 E717 00 00 00 00 +0106 E71B 43 EB 42 E7 +0106 E71F 00 00 D1 F9 +0107 E723 00 00 00 00 .DW 0000h,0000h,0000h,0000h,dirbuf,dpb,0000h,alv15 +0107 E727 00 00 00 00 +0107 E72B 43 EB 42 E7 +0107 E72F 00 00 D2 FA +0108 E733 +0109 E733 ; First drive has a reserved track for CP/M +0110 E733 dpb0: +0111 E733 80 00 .DW 128 ;SPT - sectors per track +0112 E735 05 .DB 5 ;BSH - block shift factor +0113 E736 1F .DB 31 ;BLM - block mask +0114 E737 01 .DB 1 ;EXM - Extent mask +0115 E738 FB 07 .DW 2043 ; (2047-4) DSM - Storage size (blocks - 1) +0116 E73A FF 01 .DW 511 ;DRM - Number of directory entries - 1 +0117 E73C F0 .DB 240 ;AL0 - 1 bit set per directory block +0118 E73D 00 .DB 0 ;AL1 - " +0119 E73E 00 00 .DW 0 ;CKS - DIR check vector size (DRM+1)/4 (0=fixed disk) +0120 E740 01 00 .DW 1 ;OFF - Reserved tracks +0121 E742 +0122 E742 dpb: +0123 E742 80 00 .DW 128 ;SPT - sectors per track +0124 E744 05 .DB 5 ;BSH - block shift factor +0125 E745 1F .DB 31 ;BLM - block mask +0126 E746 01 .DB 1 ;EXM - Extent mask +0127 E747 FF 07 .DW 2047 ;DSM - Storage size (blocks - 1) +0128 E749 FF 01 .DW 511 ;DRM - Number of directory entries - 1 +0129 E74B F0 .DB 240 ;AL0 - 1 bit set per directory block +0130 E74C 00 .DB 0 ;AL1 - " +0131 E74D 00 00 .DW 0 ;CKS - DIR check vector size (DRM+1)/4 (0=fixed disk) +0132 E74F 00 00 .DW 0 ;OFF - Reserved tracks +0133 E751 +0134 E751 ;================================================================================================ +0135 E751 ; Cold boot +0136 E751 ;================================================================================================ +0137 E751 +0138 E751 boot: +0139 E751 F3 DI ; Disable interrupts. +0140 E752 31 F7 FB LD SP,biosstack ; Set default stack. +0141 E755 +0142 E755 ; Turn off ROM +0143 E755 +0144 E755 3E 01 LD A,$01 +0145 E757 D3 38 OUT ($38),A +0146 E759 +0147 E759 3E 95 LD A,RTS_LOW +0148 E75B D3 80 OUT (ACIA0_C),A ; Initialise ACIA0 +0149 E75D D3 82 OUT (ACIA1_C),A ; Initialise ACIA1 +0150 E75F +0151 E75F CD 2F EB CALL printInline +0152 E762 0C .DB FF +0153 E763 43 50 2F 4D .TEXT "CP/M BIOS 2.0 by G. Searle 2013" +0153 E767 20 42 49 4F +0153 E76B 53 20 32 2E +0153 E76F 30 20 62 79 +0153 E773 20 47 2E 20 +0153 E777 53 65 61 72 +0153 E77B 6C 65 20 32 +0153 E77F 30 31 33 +0154 E782 0D 0A .DB CR,LF +0155 E784 0D 0A .DB CR,LF +0156 E786 43 50 2F 4D .TEXT "CP/M 2.2 " +0156 E78A 20 32 2E 32 +0156 E78E 20 +0157 E78F 28 63 29 .TEXT "(c)" +0158 E792 20 31 39 37 .TEXT " 1979 by Digital Research" +0158 E796 39 20 62 79 +0158 E79A 20 44 69 67 +0158 E79E 69 74 61 6C +0158 E7A2 20 52 65 73 +0158 E7A6 65 61 72 63 +0158 E7AA 68 +0159 E7AB 0D 0A 00 .DB CR,LF,0 +0160 E7AE +0161 E7AE ; CALL sdPreamble?? +0162 E7AE +0163 E7AE AF XOR a ; Clear I/O & drive bytes. +0164 E7AF 32 04 00 LD (userdrv),A +0165 E7B2 C3 F5 E7 JP gocpm +0166 E7B5 +0167 E7B5 ;================================================================================================ +0168 E7B5 ; Warm boot +0169 E7B5 ;================================================================================================ +0170 E7B5 +0171 E7B5 wboot: +0172 E7B5 F3 DI ; Disable interrupts. +0173 E7B6 31 F7 FB LD SP,biosstack ; Set default stack. +0174 E7B9 +0175 E7B9 06 0B LD B,11 ; Number of sectors to reload +0176 E7BB +0177 E7BB 3E 00 LD A,0 +0178 E7BD 32 FF FB LD (hstsec),A +0179 E7C0 D3 8C OUT (SD_LBA2),A +0180 E7C2 D3 8B OUT (SD_LBA1),A +0181 E7C4 +0182 E7C4 21 00 D0 LD HL,ccp +0183 E7C7 +0184 E7C7 wbRdAllSecs: +0185 E7C7 +0186 E7C7 DB 89 wBrdWait1: IN A,(SD_STATUS) +0187 E7C9 FE 80 CP 128 +0188 E7CB 20 FA JR NZ,wBrdWait1 +0189 E7CD +0190 E7CD 3A FF FB LD A,(hstsec) +0191 E7D0 D3 8A OUT (SD_LBA0),A +0192 E7D2 +0193 E7D2 3E 00 LD A,$00 ; 00 = Read block +0194 E7D4 D3 89 OUT (SD_CONTROL),A +0195 E7D6 C5 PUSH BC +0196 E7D7 +0197 E7D7 0E 04 LD c,4 +0198 E7D9 wBrd4secs: +0199 E7D9 06 80 LD b,128 +0200 E7DB wBrdByte: +0201 E7DB +0202 E7DB DB 89 wBrdWait2: IN A,(SD_STATUS) +0203 E7DD FE E0 CP 224 ; Read byte waiting +0204 E7DF 20 FA JR NZ,wBrdWait2 +0205 E7E1 +0206 E7E1 DB 88 IN A,(SD_DATA) +0207 E7E3 +0208 E7E3 77 LD (HL),A +0209 E7E4 23 INC HL +0210 E7E5 05 dec b +0211 E7E6 20 F3 JR NZ, wBrdByte +0212 E7E8 +0213 E7E8 0D dec c +0214 E7E9 20 EE JR NZ,wBrd4secs +0215 E7EB +0216 E7EB 3A FF FB LD A,(hstsec) +0217 E7EE 3C INC A +0218 E7EF 32 FF FB LD (hstsec),A +0219 E7F2 +0220 E7F2 C1 POP BC +0221 E7F3 +0222 E7F3 10 D2 DJNZ wbRdAllSecs +0223 E7F5 ;================================================================================================ +0224 E7F5 ; Common code for cold and warm boot +0225 E7F5 ;================================================================================================ +0226 E7F5 +0227 E7F5 gocpm: +0228 E7F5 AF xor a ;0 to accumulator +0229 E7F6 32 01 FC ld (hstact),a ;host buffer inactive +0230 E7F9 32 03 FC ld (unacnt),a ;clear unalloc count +0231 E7FC +0232 E7FC 21 80 00 LD HL,tpabuf ; Address of BIOS DMA buffer. +0233 E7FF 22 0C FC LD (dmaAddr),HL +0234 E802 3E C3 LD A,0C3h ; Opcode for 'JP'. +0235 E804 32 00 00 LD (00h),A ; Load at start of RAM. +0236 E807 21 03 E6 LD HL,wboote ; Address of jump for a warm boot. +0237 E80A 22 01 00 LD (01h),HL +0238 E80D 32 05 00 LD (05h),A ; Opcode for 'JP'. +0239 E810 21 06 D8 LD HL,bdos ; Address of jump for the BDOS. +0240 E813 22 06 00 LD (06h),HL +0241 E816 3A 04 00 LD A,(userdrv) ; Save new drive number (0). +0242 E819 4F LD c,A ; Pass drive number in C. +0243 E81A +0244 E81A C3 00 D0 JP ccp ; Start CP/M by jumping to the CCP. +0245 E81D +0246 E81D ;================================================================================================ +0247 E81D ; Console I/O routines +0248 E81D ;================================================================================================ +0249 E81D +0250 E81D +0251 E81D ;------------------------------------------------------------------------------------------------ +0252 E81D const: +0253 E81D 3A 03 00 LD A,(iobyte) +0254 E820 E6 0B AND 00001011b ; Mask off console and high bit of reader +0255 E822 FE 0A CP 00001010b ; redirected to reader on UR1/2 (Serial A) +0256 E824 28 0A JR Z,constA +0257 E826 FE 02 CP 00000010b ; redirected to reader on TTY/RDR (Serial B) +0258 E828 28 14 JR Z,constB +0259 E82A +0260 E82A E6 03 AND $03 ; remove the reader from the mask - only console bits then remain +0261 E82C FE 01 CP $01 +0262 E82E 20 0E JR NZ,constB +0263 E830 constA: +0264 E830 DB 80 IN A,(ACIA0_C) ; Status byte +0265 E832 E6 01 AND $01 +0266 E834 FE 00 CP $0 ; Z flag set if no char +0267 E836 28 03 JR Z, dataAEmpty +0268 E838 3E FF LD A,0FFH +0269 E83A C9 RET +0270 E83B dataAEmpty: +0271 E83B 3E 00 LD A,0 +0272 E83D C9 RET +0273 E83E +0274 E83E +0275 E83E constB: +0276 E83E DB 82 IN A,(ACIA1_C) ; Status byte +0277 E840 E6 01 AND $01 +0278 E842 FE 00 CP $0 ; Z flag set if no char +0279 E844 28 03 JR Z, dataBEmpty +0280 E846 3E FF LD A,0FFH +0281 E848 C9 RET +0282 E849 dataBEmpty: +0283 E849 3E 00 LD A,0 +0284 E84B C9 RET +0285 E84C +0286 E84C ;------------------------------------------------------------------------------------------------ +0287 E84C reader: +0288 E84C F5 PUSH AF +0289 E84D 3A 03 00 reader2: LD A,(iobyte) +0290 E850 E6 08 AND $08 +0291 E852 FE 08 CP $08 +0292 E854 20 1C JR NZ,coninB +0293 E856 18 0E JR coninA +0294 E858 ;------------------------------------------------------------------------------------------------ +0295 E858 conin: +0296 E858 F5 PUSH AF +0297 E859 3A 03 00 LD A,(iobyte) +0298 E85C E6 03 AND $03 +0299 E85E FE 02 CP $02 +0300 E860 28 EB JR Z,reader2 ; "BAT:" redirect +0301 E862 FE 01 CP $01 +0302 E864 20 0C JR NZ,coninB +0303 E866 +0304 E866 +0305 E866 coninA: +0306 E866 F1 POP AF +0307 E867 waitForCharA: +0308 E867 DB 80 IN A,(ACIA0_C) ; Status byte +0309 E869 E6 01 AND $01 +0310 E86B FE 00 CP $0 ; Z flag set if no char +0311 E86D 28 F8 JR Z, waitForCharA +0312 E86F DB 81 IN A,(ACIA0_D) +0313 E871 +0314 E871 C9 RET ; Char ready in A +0315 E872 +0316 E872 +0317 E872 coninB: +0318 E872 F1 POP AF +0319 E873 waitForCharB: +0320 E873 DB 82 IN A,(ACIA1_C) ; Status byte +0321 E875 E6 01 AND $01 +0322 E877 FE 00 CP $0 ; Z flag set if no char +0323 E879 28 F8 JR Z, waitForCharB +0324 E87B DB 83 IN A,(ACIA1_D) +0325 E87D +0326 E87D C9 RET ; Char ready in A +0327 E87E +0328 E87E ;------------------------------------------------------------------------------------------------ +0329 E87E F5 list: PUSH AF ; Store character +0330 E87F 3A 03 00 list2: LD A,(iobyte) +0331 E882 E6 C0 AND $C0 +0332 E884 FE 40 CP $40 +0333 E886 20 26 JR NZ,conoutB1 +0334 E888 18 1A JR conoutA1 +0335 E88A +0336 E88A ;------------------------------------------------------------------------------------------------ +0337 E88A F5 punch: PUSH AF ; Store character +0338 E88B 3A 03 00 LD A,(iobyte) +0339 E88E E6 20 AND $20 +0340 E890 FE 20 CP $20 +0341 E892 20 1A JR NZ,conoutB1 +0342 E894 18 0E JR conoutA1 +0343 E896 +0344 E896 ;------------------------------------------------------------------------------------------------ +0345 E896 F5 conout: PUSH AF +0346 E897 3A 03 00 LD A,(iobyte) +0347 E89A E6 03 AND $03 +0348 E89C FE 02 CP $02 +0349 E89E 28 DF JR Z,list2 ; "BAT:" redirect +0350 E8A0 FE 01 CP $01 +0351 E8A2 20 0A JR NZ,conoutB1 +0352 E8A4 +0353 E8A4 CD B8 E8 conoutA1: CALL CKACIA0 ; See if ACIA channel A is finished transmitting +0354 E8A7 28 FB JR Z,conoutA1 ; Loop until ACIA flag signals ready +0355 E8A9 79 LD A,C +0356 E8AA D3 81 OUT (ACIA0_D),A ; OUTput the character +0357 E8AC F1 POP AF +0358 E8AD C9 RET +0359 E8AE +0360 E8AE CD BE E8 conoutB1: CALL CKACIA1 ; See if ACIA channel B is finished transmitting +0361 E8B1 28 FB JR Z,conoutB1 ; Loop until ACIA flag signals ready +0362 E8B3 79 LD A,C +0363 E8B4 D3 83 OUT (ACIA1_D),A ; OUTput the character +0364 E8B6 F1 POP AF +0365 E8B7 C9 RET +0366 E8B8 +0367 E8B8 ;------------------------------------------------------------------------------------------------ +0368 E8B8 CKACIA0 +0369 E8B8 DB 80 IN A,(ACIA0_C) ; Status byte D1=TX Buff Empty, D0=RX char ready +0370 E8BA 0F RRCA ; Rotates RX status into Carry Flag, +0371 E8BB CB 47 BIT 0,A ; Set Zero flag if still transmitting character +0372 E8BD C9 RET +0373 E8BE +0374 E8BE CKACIA1 +0375 E8BE DB 82 IN A,(ACIA1_C) ; Status byte D1=TX Buff Empty, D0=RX char ready +0376 E8C0 0F RRCA ; Rotates RX status into Carry Flag, +0377 E8C1 CB 47 BIT 0,A ; Set Zero flag if still transmitting character +0378 E8C3 C9 RET +0379 E8C4 +0380 E8C4 ;------------------------------------------------------------------------------------------------ +0381 E8C4 3E FF listst: LD A,$FF ; Return list status of 0xFF (ready). +0382 E8C6 C9 RET +0383 E8C7 +0384 E8C7 ;================================================================================================ +0385 E8C7 ; Disk processing entry points +0386 E8C7 ;================================================================================================ +0387 E8C7 +0388 E8C7 seldsk: +0389 E8C7 21 00 00 LD HL,$0000 +0390 E8CA 79 LD A,C +0391 E8CB FE 10 CP 16 ; 16 for 128MB disk, 8 for 64MB disk +0392 E8CD 38 0D jr C,chgdsk ; if invalid drive will give BDOS error +0393 E8CF 3A 04 00 LD A,(userdrv) ; so set the drive back to a: +0394 E8D2 B9 CP C ; If the default disk is not the same as the +0395 E8D3 C0 RET NZ ; selected drive then return, +0396 E8D4 AF XOR A ; else reset default back to a: +0397 E8D5 32 04 00 LD (userdrv),A ; otherwise will be stuck in a loop +0398 E8D8 32 F7 FB LD (sekdsk),A +0399 E8DB C9 ret +0400 E8DC +0401 E8DC 32 F7 FB chgdsk: LD (sekdsk),A +0402 E8DF CB 07 RLC a ;*2 +0403 E8E1 CB 07 RLC a ;*4 +0404 E8E3 CB 07 RLC a ;*8 +0405 E8E5 CB 07 RLC a ;*16 +0406 E8E7 21 33 E6 LD HL,dpbase +0407 E8EA 06 00 LD b,0 +0408 E8EC 4F LD c,A +0409 E8ED 09 ADD HL,BC +0410 E8EE +0411 E8EE C9 RET +0412 E8EF +0413 E8EF ;------------------------------------------------------------------------------------------------ +0414 E8EF home: +0415 E8EF 3A 02 FC ld a,(hstwrt) ;check for pending write +0416 E8F2 B7 or a +0417 E8F3 20 03 jr nz,homed +0418 E8F5 32 01 FC ld (hstact),a ;clear host active flag +0419 E8F8 homed: +0420 E8F8 01 00 00 LD BC,0000h +0421 E8FB +0422 E8FB ;------------------------------------------------------------------------------------------------ +0423 E8FB ED 43 F8 FB settrk: LD (sektrk),BC ; Set track passed from BDOS in register BC. +0424 E8FF C9 RET +0425 E900 +0426 E900 ;------------------------------------------------------------------------------------------------ +0427 E900 ED 43 FA FB setsec: LD (seksec),BC ; Set sector passed from BDOS in register BC. +0428 E904 C9 RET +0429 E905 +0430 E905 ;------------------------------------------------------------------------------------------------ +0431 E905 ED 43 0C FC setdma: LD (dmaAddr),BC ; Set DMA ADDress given by registers BC. +0432 E909 C9 RET +0433 E90A +0434 E90A ;------------------------------------------------------------------------------------------------ +0435 E90A C5 sectran: PUSH BC +0436 E90B E1 POP HL +0437 E90C C9 RET +0438 E90D +0439 E90D ;------------------------------------------------------------------------------------------------ +0440 E90D read: +0441 E90D ;read the selected CP/M sector +0442 E90D AF xor a +0443 E90E 32 03 FC ld (unacnt),a +0444 E911 3E 01 ld a,1 +0445 E913 32 0A FC ld (readop),a ;read operation +0446 E916 32 09 FC ld (rsflag),a ;must read data +0447 E919 3E 02 ld a,wrual +0448 E91B 32 0B FC ld (wrtype),a ;treat as unalloc +0449 E91E C3 88 E9 jp rwoper ;to perform the read +0450 E921 +0451 E921 +0452 E921 ;------------------------------------------------------------------------------------------------ +0453 E921 write: +0454 E921 ;write the selected CP/M sector +0455 E921 AF xor a ;0 to accumulator +0456 E922 32 0A FC ld (readop),a ;not a read operation +0457 E925 79 ld a,c ;write type in c +0458 E926 32 0B FC ld (wrtype),a +0459 E929 FE 02 cp wrual ;write unallocated? +0460 E92B 20 17 jr nz,chkuna ;check for unalloc +0461 E92D ; +0462 E92D ; write to unallocated, set parameters +0463 E92D 3E 20 ld a,blksiz/128 ;next unalloc recs +0464 E92F 32 03 FC ld (unacnt),a +0465 E932 3A F7 FB ld a,(sekdsk) ;disk to seek +0466 E935 32 04 FC ld (unadsk),a ;unadsk = sekdsk +0467 E938 2A F8 FB ld hl,(sektrk) +0468 E93B 22 05 FC ld (unatrk),hl ;unatrk = sectrk +0469 E93E 3A FA FB ld a,(seksec) +0470 E941 32 07 FC ld (unasec),a ;unasec = seksec +0471 E944 ; +0472 E944 chkuna: +0473 E944 ; check for write to unallocated sector +0474 E944 3A 03 FC ld a,(unacnt) ;any unalloc remain? +0475 E947 B7 or a +0476 E948 28 36 jr z,alloc ;skip if not +0477 E94A ; +0478 E94A ; more unallocated records remain +0479 E94A 3D dec a ;unacnt = unacnt-1 +0480 E94B 32 03 FC ld (unacnt),a +0481 E94E 3A F7 FB ld a,(sekdsk) ;same disk? +0482 E951 21 04 FC ld hl,unadsk +0483 E954 BE cp (hl) ;sekdsk = unadsk? +0484 E955 C2 80 E9 jp nz,alloc ;skip if not +0485 E958 ; +0486 E958 ; disks are the same +0487 E958 21 05 FC ld hl,unatrk +0488 E95B CD 1F EA call sektrkcmp ;sektrk = unatrk? +0489 E95E C2 80 E9 jp nz,alloc ;skip if not +0490 E961 ; +0491 E961 ; tracks are the same +0492 E961 3A FA FB ld a,(seksec) ;same sector? +0493 E964 21 07 FC ld hl,unasec +0494 E967 BE cp (hl) ;seksec = unasec? +0495 E968 C2 80 E9 jp nz,alloc ;skip if not +0496 E96B ; +0497 E96B ; match, move to next sector for future ref +0498 E96B 34 inc (hl) ;unasec = unasec+1 +0499 E96C 7E ld a,(hl) ;end of track? +0500 E96D FE 80 cp cpmspt ;count CP/M sectors +0501 E96F 38 09 jr c,noovf ;skip if no overflow +0502 E971 ; +0503 E971 ; overflow to next track +0504 E971 36 00 ld (hl),0 ;unasec = 0 +0505 E973 2A 05 FC ld hl,(unatrk) +0506 E976 23 inc hl +0507 E977 22 05 FC ld (unatrk),hl ;unatrk = unatrk+1 +0508 E97A ; +0509 E97A noovf: +0510 E97A ;match found, mark as unnecessary read +0511 E97A AF xor a ;0 to accumulator +0512 E97B 32 09 FC ld (rsflag),a ;rsflag = 0 +0513 E97E 18 08 jr rwoper ;to perform the write +0514 E980 ; +0515 E980 alloc: +0516 E980 ;not an unallocated record, requires pre-read +0517 E980 AF xor a ;0 to accum +0518 E981 32 03 FC ld (unacnt),a ;unacnt = 0 +0519 E984 3C inc a ;1 to accum +0520 E985 32 09 FC ld (rsflag),a ;rsflag = 1 +0521 E988 +0522 E988 ;------------------------------------------------------------------------------------------------ +0523 E988 rwoper: +0524 E988 ;enter here to perform the read/write +0525 E988 AF xor a ;zero to accum +0526 E989 32 08 FC ld (erflag),a ;no errors (yet) +0527 E98C 3A FA FB ld a,(seksec) ;compute host sector +0528 E98F B7 or a ;carry = 0 +0529 E990 1F rra ;shift right +0530 E991 B7 or a ;carry = 0 +0531 E992 1F rra ;shift right +0532 E993 32 00 FC ld (sekhst),a ;host sector to seek +0533 E996 ; +0534 E996 ; active host sector? +0535 E996 21 01 FC ld hl,hstact ;host active flag +0536 E999 7E ld a,(hl) +0537 E99A 36 01 ld (hl),1 ;always becomes 1 +0538 E99C B7 or a ;was it already? +0539 E99D 28 21 jr z,filhst ;fill host if not +0540 E99F ; +0541 E99F ; host buffer active, same as seek buffer? +0542 E99F 3A F7 FB ld a,(sekdsk) +0543 E9A2 21 FC FB ld hl,hstdsk ;same disk? +0544 E9A5 BE cp (hl) ;sekdsk = hstdsk? +0545 E9A6 20 11 jr nz,nomatch +0546 E9A8 ; +0547 E9A8 ; same disk, same track? +0548 E9A8 21 FD FB ld hl,hsttrk +0549 E9AB CD 1F EA call sektrkcmp ;sektrk = hsttrk? +0550 E9AE 20 09 jr nz,nomatch +0551 E9B0 ; +0552 E9B0 ; same disk, same track, same buffer? +0553 E9B0 3A 00 FC ld a,(sekhst) +0554 E9B3 21 FF FB ld hl,hstsec ;sekhst = hstsec? +0555 E9B6 BE cp (hl) +0556 E9B7 28 24 jr z,match ;skip if match +0557 E9B9 ; +0558 E9B9 nomatch: +0559 E9B9 ;proper disk, but not correct sector +0560 E9B9 3A 02 FC ld a,(hstwrt) ;host written? +0561 E9BC B7 or a +0562 E9BD C4 EA EA call nz,writehst ;clear host buff +0563 E9C0 ; +0564 E9C0 filhst: +0565 E9C0 ;may have to fill the host buffer +0566 E9C0 3A F7 FB ld a,(sekdsk) +0567 E9C3 32 FC FB ld (hstdsk),a +0568 E9C6 2A F8 FB ld hl,(sektrk) +0569 E9C9 22 FD FB ld (hsttrk),hl +0570 E9CC 3A 00 FC ld a,(sekhst) +0571 E9CF 32 FF FB ld (hstsec),a +0572 E9D2 3A 09 FC ld a,(rsflag) ;need to read? +0573 E9D5 B7 or a +0574 E9D6 C4 95 EA call nz,readhst ;yes, if 1 +0575 E9D9 AF xor a ;0 to accum +0576 E9DA 32 02 FC ld (hstwrt),a ;no pending write +0577 E9DD ; +0578 E9DD match: +0579 E9DD ;copy data to or from buffer +0580 E9DD 3A FA FB ld a,(seksec) ;mask buffer number +0581 E9E0 E6 03 and secmsk ;least signif bits +0582 E9E2 6F ld l,a ;ready to shift +0583 E9E3 26 00 ld h,0 ;double count +0584 E9E5 29 add hl,hl +0585 E9E6 29 add hl,hl +0586 E9E7 29 add hl,hl +0587 E9E8 29 add hl,hl +0588 E9E9 29 add hl,hl +0589 E9EA 29 add hl,hl +0590 E9EB 29 add hl,hl +0591 E9EC ; hl has relative host buffer address +0592 E9EC 11 0E FC ld de,hstbuf +0593 E9EF 19 add hl,de ;hl = host address +0594 E9F0 EB ex de,hl ;now in DE +0595 E9F1 2A 0C FC ld hl,(dmaAddr) ;get/put CP/M data +0596 E9F4 0E 80 ld c,128 ;length of move +0597 E9F6 3A 0A FC ld a,(readop) ;which way? +0598 E9F9 B7 or a +0599 E9FA 20 06 jr nz,rwmove ;skip if read +0600 E9FC ; +0601 E9FC ; write operation, mark and switch direction +0602 E9FC 3E 01 ld a,1 +0603 E9FE 32 02 FC ld (hstwrt),a ;hstwrt = 1 +0604 EA01 EB ex de,hl ;source/dest swap +0605 EA02 ; +0606 EA02 rwmove: +0607 EA02 ;C initially 128, DE is source, HL is dest +0608 EA02 1A ld a,(de) ;source character +0609 EA03 13 inc de +0610 EA04 77 ld (hl),a ;to dest +0611 EA05 23 inc hl +0612 EA06 0D dec c ;loop 128 times +0613 EA07 20 F9 jr nz,rwmove +0614 EA09 ; +0615 EA09 ; data has been moved to/from host buffer +0616 EA09 3A 0B FC ld a,(wrtype) ;write type +0617 EA0C FE 01 cp wrdir ;to directory? +0618 EA0E 3A 08 FC ld a,(erflag) ;in case of errors +0619 EA11 C0 ret nz ;no further processing +0620 EA12 ; +0621 EA12 ; clear host buffer for directory write +0622 EA12 B7 or a ;errors? +0623 EA13 C0 ret nz ;skip if so +0624 EA14 AF xor a ;0 to accum +0625 EA15 32 02 FC ld (hstwrt),a ;buffer written +0626 EA18 CD EA EA call writehst +0627 EA1B 3A 08 FC ld a,(erflag) +0628 EA1E C9 ret +0629 EA1F +0630 EA1F ;------------------------------------------------------------------------------------------------ +0631 EA1F ;Utility subroutine for 16-bit compare +0632 EA1F sektrkcmp: +0633 EA1F ;HL = .unatrk or .hsttrk, compare with sektrk +0634 EA1F EB ex de,hl +0635 EA20 21 F8 FB ld hl,sektrk +0636 EA23 1A ld a,(de) ;low byte compare +0637 EA24 BE cp (HL) ;same? +0638 EA25 C0 ret nz ;return if not +0639 EA26 ; low bytes equal, test high 1s +0640 EA26 13 inc de +0641 EA27 23 inc hl +0642 EA28 1A ld a,(de) +0643 EA29 BE cp (hl) ;sets flags +0644 EA2A C9 ret +0645 EA2B +0646 EA2B ;================================================================================================ +0647 EA2B ; Convert track/head/sector into LBA for physical access to the disk +0648 EA2B ;================================================================================================ +0649 EA2B setLBAaddr: +0650 EA2B 2A FD FB LD HL,(hsttrk) +0651 EA2E CB 05 RLC L +0652 EA30 CB 05 RLC L +0653 EA32 CB 05 RLC L +0654 EA34 CB 05 RLC L +0655 EA36 CB 05 RLC L +0656 EA38 7D LD A,L +0657 EA39 E6 E0 AND 0E0H +0658 EA3B 6F LD L,A +0659 EA3C 3A FF FB LD A,(hstsec) +0660 EA3F 85 ADD A,L +0661 EA40 32 D3 FB LD (lba0),A +0662 EA43 +0663 EA43 2A FD FB LD HL,(hsttrk) +0664 EA46 CB 0D RRC L +0665 EA48 CB 0D RRC L +0666 EA4A CB 0D RRC L +0667 EA4C 7D LD A,L +0668 EA4D E6 1F AND 01FH +0669 EA4F 6F LD L,A +0670 EA50 CB 04 RLC H +0671 EA52 CB 04 RLC H +0672 EA54 CB 04 RLC H +0673 EA56 CB 04 RLC H +0674 EA58 CB 04 RLC H +0675 EA5A 7C LD A,H +0676 EA5B E6 20 AND 020H +0677 EA5D 67 LD H,A +0678 EA5E 3A FC FB LD A,(hstdsk) +0679 EA61 CB 07 RLC a +0680 EA63 CB 07 RLC a +0681 EA65 CB 07 RLC a +0682 EA67 CB 07 RLC a +0683 EA69 CB 07 RLC a +0684 EA6B CB 07 RLC a +0685 EA6D E6 C0 AND 0C0H +0686 EA6F 84 ADD A,H +0687 EA70 85 ADD A,L +0688 EA71 32 D4 FB LD (lba1),A +0689 EA74 +0690 EA74 3A FC FB LD A,(hstdsk) +0691 EA77 CB 0F RRC A +0692 EA79 CB 0F RRC A +0693 EA7B E6 03 AND 03H +0694 EA7D 32 D5 FB LD (lba2),A +0695 EA80 +0696 EA80 3E 00 LD a,00H +0697 EA82 32 D6 FB LD (lba3),A +0698 EA85 +0699 EA85 ; Transfer LBA to disk (LBA3 not used on SD card) +0700 EA85 3A D5 FB LD A,(lba2) +0701 EA88 D3 8C OUT (SD_LBA2),A +0702 EA8A 3A D4 FB LD A,(lba1) +0703 EA8D D3 8B OUT (SD_LBA1),A +0704 EA8F 3A D3 FB LD A,(lba0) +0705 EA92 D3 8A OUT (SD_LBA0),A +0706 EA94 C9 RET +0707 EA95 +0708 EA95 ;================================================================================================ +0709 EA95 ; Read physical sector from host +0710 EA95 ;================================================================================================ +0711 EA95 +0712 EA95 readhst: +0713 EA95 F5 PUSH AF +0714 EA96 C5 PUSH BC +0715 EA97 E5 PUSH HL +0716 EA98 +0717 EA98 DB 89 rdWait1: IN A,(SD_STATUS) +0718 EA9A FE 80 CP 128 ; Check for ready status +0719 EA9C 20 FA JR NZ,rdWait1 +0720 EA9E +0721 EA9E ; Add multiple status checks before starting read +0722 EA9E 06 03 LD B,3 ; Check status 3 times +0723 EAA0 rdCheck1: +0724 EAA0 DB 89 IN A,(SD_STATUS) +0725 EAA2 FE 80 CP 128 +0726 EAA4 20 FA JR NZ,rdCheck1 +0727 EAA6 10 F8 DJNZ rdCheck1 +0728 EAA8 +0729 EAA8 CD 2B EA CALL setLBAaddr +0730 EAAB +0731 EAAB 3E 00 LD A,$00 ; 00 = Read block +0732 EAAD D3 89 OUT (SD_CONTROL),A +0733 EAAF +0734 EAAF 0E 04 LD c,4 +0735 EAB1 21 0E FC LD HL,hstbuf +0736 EAB4 rd4secs: +0737 EAB4 06 80 LD b,128 +0738 EAB6 rdByte: +0739 EAB6 +0740 EAB6 DB 89 rdWait2: IN A,(SD_STATUS) +0741 EAB8 FE E0 CP 224 ; Read byte waiting +0742 EABA 20 FA JR NZ,rdWait2 +0743 EABC +0744 EABC ; Add extra validation checks before each read +0745 EABC C5 PUSH BC ; Save main counters +0746 EABD 06 02 LD B,2 ; Check status twice +0747 EABF rdCheck2: +0748 EABF DB 89 IN A,(SD_STATUS) +0749 EAC1 FE E0 CP 224 +0750 EAC3 20 FA JR NZ,rdCheck2 +0751 EAC5 10 F8 DJNZ rdCheck2 +0752 EAC7 C1 POP BC ; Restore main counters +0753 EAC8 +0754 EAC8 DB 88 IN A,(SD_DATA) +0755 EACA +0756 EACA ; Add small delay after read before store +0757 EACA C5 PUSH BC +0758 EACB 06 0A LD B,10 +0759 EACD rdDelay: +0760 EACD 10 FE DJNZ rdDelay +0761 EACF C1 POP BC +0762 EAD0 +0763 EAD0 77 LD (HL),A +0764 EAD1 23 INC HL +0765 EAD2 05 dec b +0766 EAD3 20 E1 JR NZ, rdByte +0767 EAD5 0D dec c +0768 EAD6 20 DC JR NZ,rd4secs +0769 EAD8 +0770 EAD8 ; Add final wait before returning +0771 EAD8 06 00 LD B,0 +0772 EADA rdWaitFinal: +0773 EADA DB 89 IN A,(SD_STATUS) +0774 EADC FE 80 CP 128 ; Wait for ready status +0775 EADE 20 FA JR NZ,rdWaitFinal +0776 EAE0 10 F8 DJNZ rdWaitFinal +0777 EAE2 +0778 EAE2 E1 POP HL +0779 EAE3 C1 POP BC +0780 EAE4 F1 POP AF +0781 EAE5 +0782 EAE5 AF XOR a +0783 EAE6 32 08 FC ld (erflag),a +0784 EAE9 C9 RET +0785 EAEA +0786 EAEA +0787 EAEA ;================================================================================================ +0788 EAEA ; Write physical sector to host +0789 EAEA ;================================================================================================ +0790 EAEA +0791 EAEA writehst: +0792 EAEA F5 PUSH AF +0793 EAEB C5 PUSH BC +0794 EAEC E5 PUSH HL +0795 EAED +0796 EAED DB 89 wrWait1: IN A,(SD_STATUS) +0797 EAEF FE 80 CP 128 +0798 EAF1 20 FA JR NZ,wrWait1 +0799 EAF3 +0800 EAF3 CD 2B EA CALL setLBAaddr +0801 EAF6 +0802 EAF6 3E 01 LD A,$01 ; 01 = Write block +0803 EAF8 D3 89 OUT (SD_CONTROL),A +0804 EAFA +0805 EAFA 0E 04 LD c,4 +0806 EAFC 21 0E FC LD HL,hstbuf +0807 EAFF wr4secs: +0808 EAFF 06 80 LD b,128 +0809 EB01 wrByte: +0810 EB01 +0811 EB01 DB 89 wrWait2: IN A,(SD_STATUS) +0812 EB03 FE A0 CP 160 ; Write buffer empty +0813 EB05 20 FA JR NZ,wrWait2 +0814 EB07 +0815 EB07 ; Add multiple status checks before proceeding with write +0816 EB07 C5 PUSH BC ; Save main counters +0817 EB08 06 03 LD B,3 ; Check status 3 times +0818 EB0A wrCheck: +0819 EB0A DB 89 IN A,(SD_STATUS) +0820 EB0C FE A0 CP 160 +0821 EB0E 20 FA JR NZ,wrCheck +0822 EB10 10 F8 DJNZ wrCheck +0823 EB12 C1 POP BC ; Restore main counters +0824 EB13 +0825 EB13 7E LD A,(HL) +0826 EB14 D3 88 OUT (SD_DATA),A +0827 EB16 23 INC HL +0828 EB17 05 dec b +0829 EB18 20 E7 JR NZ,wrByte +0830 EB1A +0831 EB1A 0D dec c +0832 EB1B 20 E2 JR NZ,wr4secs +0833 EB1D +0834 EB1D ; Add final wait before returning +0835 EB1D 06 00 LD B,0 +0836 EB1F wrWaitFinal: +0837 EB1F DB 89 IN A,(SD_STATUS) +0838 EB21 FE 80 CP 128 ; Wait for ready status +0839 EB23 20 FA JR NZ,wrWaitFinal +0840 EB25 10 F8 DJNZ wrWaitFinal +0841 EB27 +0842 EB27 E1 POP HL +0843 EB28 C1 POP BC +0844 EB29 F1 POP AF +0845 EB2A +0846 EB2A AF XOR a +0847 EB2B 32 08 FC ld (erflag),a +0848 EB2E C9 RET +0849 EB2F +0850 EB2F ;================================================================================================ +0851 EB2F ; Utilities +0852 EB2F ;================================================================================================ +0853 EB2F +0854 EB2F printInline: +0855 EB2F E3 EX (SP),HL ; PUSH HL and put RET ADDress into HL +0856 EB30 F5 PUSH AF +0857 EB31 C5 PUSH BC +0858 EB32 7E nextILChar: LD A,(HL) +0859 EB33 FE 00 CP 0 +0860 EB35 28 07 JR Z,endOfPrint +0861 EB37 4F LD C,A +0862 EB38 CD 96 E8 CALL conout ; Print to TTY +0863 EB3B 23 iNC HL +0864 EB3C 18 F4 JR nextILChar +0865 EB3E 23 endOfPrint: INC HL ; Get past "null" terminator +0866 EB3F C1 POP BC +0867 EB40 F1 POP AF +0868 EB41 E3 EX (SP),HL ; PUSH new RET ADDress on stack and restore HL +0869 EB42 C9 RET +0870 EB43 +0871 EB43 ;================================================================================================ +0872 EB43 ; Data storage +0873 EB43 ;================================================================================================ +0874 EB43 +0875 EB43 dirbuf: .ds 128 ;scratch directory area +0876 EBC3 alv00: .ds 257 ;allocation vector 0 +0877 ECC4 alv01: .ds 257 ;allocation vector 1 +0878 EDC5 alv02: .ds 257 ;allocation vector 2 +0879 EEC6 alv03: .ds 257 ;allocation vector 3 +0880 EFC7 alv04: .ds 257 ;allocation vector 4 +0881 F0C8 alv05: .ds 257 ;allocation vector 5 +0882 F1C9 alv06: .ds 257 ;allocation vector 6 +0883 F2CA alv07: .ds 257 ;allocation vector 7 +0884 F3CB alv08: .ds 257 ;allocation vector 8 +0885 F4CC alv09: .ds 257 ;allocation vector 9 +0886 F5CD alv10: .ds 257 ;allocation vector 10 +0887 F6CE alv11: .ds 257 ;allocation vector 11 +0888 F7CF alv12: .ds 257 ;allocation vector 12 +0889 F8D0 alv13: .ds 257 ;allocation vector 13 +0890 F9D1 alv14: .ds 257 ;allocation vector 14 +0891 FAD2 alv15: .ds 257 ;allocation vector 15 +0892 FBD3 +0893 FBD3 00 lba0 .DB 00h +0894 FBD4 00 lba1 .DB 00h +0895 FBD5 00 lba2 .DB 00h +0896 FBD6 00 lba3 .DB 00h +0897 FBD7 +0898 FBD7 .DS 020h ; Start of BIOS stack area. +0899 FBF7 biosstack: .EQU $ +0900 FBF7 +0901 FBF7 sekdsk: .ds 1 ;seek disk number +0902 FBF8 sektrk: .ds 2 ;seek track number +0903 FBFA seksec: .ds 2 ;seek sector number +0904 FBFC ; +0905 FBFC hstdsk: .ds 1 ;host disk number +0906 FBFD hsttrk: .ds 2 ;host track number +0907 FBFF hstsec: .ds 1 ;host sector number +0908 FC00 ; +0909 FC00 sekhst: .ds 1 ;seek shr secshf +0910 FC01 hstact: .ds 1 ;host active flag +0911 FC02 hstwrt: .ds 1 ;host written flag +0912 FC03 ; +0913 FC03 unacnt: .ds 1 ;unalloc rec cnt +0914 FC04 unadsk: .ds 1 ;last unalloc disk +0915 FC05 unatrk: .ds 2 ;last unalloc track +0916 FC07 unasec: .ds 1 ;last unalloc sector +0917 FC08 ; +0918 FC08 erflag: .ds 1 ;error reporting +0919 FC09 rsflag: .ds 1 ;read sector flag +0920 FC0A readop: .ds 1 ;1 if read operation +0921 FC0B wrtype: .ds 1 ;write operation type +0922 FC0C dmaAddr: .ds 2 ;last dma address +0923 FC0E hstbuf: .ds 512 ;host buffer +0924 FE0E +0925 FE0E hstBufEnd: .EQU $ +0926 FE0E +0927 FE0E biosEnd: .EQU $ +0928 FE0E +0929 FE0E ; Disable the ROM, pop the active IO port from the stack (supplied by monitor), +0930 FE0E ; then start CP/M +0931 FE0E popAndRun: +0932 FE0E 3E 01 LD A,$01 +0933 FE10 D3 38 OUT ($38),A +0934 FE12 +0935 FE12 F1 POP AF +0936 FE13 FE 01 CP $01 +0937 FE15 28 04 JR Z,consoleAtB +0938 FE17 3E 01 LD A,$01 ;(List is TTY:, Punch is TTY:, Reader is TTY:, Console is CRT:) +0939 FE19 18 02 JR setIOByte +0940 FE1B 3E 00 consoleAtB: LD A,$00 ;(List is TTY:, Punch is TTY:, Reader is TTY:, Console is TTY:) +0941 FE1D 32 03 00 setIOByte: LD (iobyte),A +0942 FE20 C3 00 E6 JP bios +0943 FE23 +0944 FE23 +0945 FE23 ;================================================================================= +0946 FE23 ; Relocate TPA area from 4100 to 0100 then start CP/M +0947 FE23 ; Used to manually transfer a loaded program after CP/M was previously loaded +0948 FE23 ;================================================================================= +0949 FE23 +0950 FFE8 .org 0FFE8H +0951 FFE8 3E 01 LD A,$01 +0952 FFEA D3 38 OUT ($38),A +0953 FFEC +0954 FFEC 21 00 41 LD HL,04100H +0955 FFEF 11 00 01 LD DE,00100H +0956 FFF2 01 00 8F LD BC,08F00H +0957 FFF5 ED B0 LDIR +0958 FFF7 C3 00 E6 JP bios +0959 FFFA +0960 FFFA ;================================================================================= +0961 FFFA ; Normal start CP/M vector +0962 FFFA ;================================================================================= +0963 FFFA +0964 FFFE .ORG 0FFFEH +0965 FFFE 0E FE .dw popAndRun +0966 10000 +0967 10000 .END +tasm: Number of errors = 0 diff --git a/Z80 CPM and bootloader (basmon)/source/CPM22.LST b/Z80 CPM and bootloader (basmon)/source/CPM22.LST index 8bcb096..3981708 100644 --- a/Z80 CPM and bootloader (basmon)/source/CPM22.LST +++ b/Z80 CPM and bootloader (basmon)/source/CPM22.LST @@ -1,3781 +1,3845 @@ -0001 0000 ;************************************************************** -0002 0000 ;* -0003 0000 ;* C P / M version 2 . 2 -0004 0000 ;* -0005 0000 ;* Reconstructed from memory image on February 27, 1981 -0006 0000 ;* -0007 0000 ;* by Clark A. Calkins -0008 0000 ;* -0009 0000 ;************************************************************** -0010 0000 ; -0011 0000 ; Set memory limit here. This is the amount of contigeous -0012 0000 ; ram starting from 0000. CP/M will reside at the end of this space. -0013 0000 ; -0014 0000 -0015 0000 IOBYTE .EQU 3 ;i/o definition byte. -0016 0000 TDRIVE .EQU 4 ;current drive name and user number. -0017 0000 ENTRY .EQU 5 ;entry point for the cp/m bdos. -0018 0000 TFCB .EQU 5CH ;default file control block. -0019 0000 TBUFF .EQU 80H ;i/o buffer and command line storage. -0020 0000 TBASE .EQU 100H ;transiant program storage area. -0021 0000 ; -0022 0000 ; Set control character equates. -0023 0000 ; -0024 0000 CNTRLC .EQU 3 ;control-c -0025 0000 CNTRLE .EQU 05H ;control-e -0026 0000 BS .EQU 08H ;backspace -0027 0000 TAB .EQU 09H ;tab -0028 0000 LF .EQU 0AH ;line feed -0029 0000 FF .EQU 0CH ;form feed -0030 0000 CR .EQU 0DH ;carriage return -0031 0000 CNTRLP .EQU 10H ;control-p -0032 0000 CNTRLR .EQU 12H ;control-r -0033 0000 CNTRLS .EQU 13H ;control-s -0034 0000 CNTRLU .EQU 15H ;control-u -0035 0000 CNTRLX .EQU 18H ;control-x -0036 0000 CNTRLZ .EQU 1AH ;control-z (end-of-file mark) -0037 0000 DEL .EQU 7FH ;rubout -0038 0000 ; -0039 0000 ; Set origin for CP/M -0040 0000 ; -0041 D000 .ORG 0D000H -0042 D000 ; -0043 D000 C3 5C D3 CBASE: JP COMMAND ;execute command processor (ccp). -0044 D003 C3 58 D3 JP CLEARBUF ;entry to empty input buffer before starting ccp. -0045 D006 -0046 D006 ; -0047 D006 ; Standard cp/m ccp input buffer. Format is (max length), -0048 D006 ; (actual length), (char #1), (char #2), (char #3), etc. -0049 D006 ; -0050 D006 7F INBUFF: .DB 127 ;length of input buffer. -0051 D007 00 .DB 0 ;current length of contents. -0052 D008 436F70797269 .TEXT "Copyright" -0052 D00E 676874 -0053 D011 203139373920 .TEXT " 1979 (c) by Digital Research " -0053 D017 286329206279204469676974616C205265736561726368202020202020 -0054 D034 000000000000 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -0054 D03A 0000000000000000000000000000000000 -0055 D04B 000000000000 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -0055 D051 0000000000000000000000000000000000 -0056 D062 000000000000 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -0056 D068 0000000000000000000000000000000000 -0057 D079 000000000000 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -0057 D07F 000000000000000000 -0058 D088 08 D0 INPOINT:.DW INBUFF+2 ;input line pointer -0059 D08A 00 00 NAMEPNT:.DW 0 ;input line pointer used for error message. Points to -0060 D08C ; ;start of name in error. -0061 D08C ; -0062 D08C ; Routine to print (A) on the console. All registers used. -0063 D08C ; -0064 D08C 5F PRINT: LD E,A ;setup bdos call. -0065 D08D 0E 02 LD C,2 -0066 D08F C3 05 00 JP ENTRY -0067 D092 ; -0068 D092 ; Routine to print (A) on the console and to save (BC). -0069 D092 ; -0070 D092 C5 PRINTB: PUSH BC -0071 D093 CD 8C D0 CALL PRINT -0072 D096 C1 POP BC -0073 D097 C9 RET -0074 D098 ; -0075 D098 ; Routine to send a carriage return, line feed combination -0076 D098 ; to the console. -0077 D098 ; -0078 D098 3E 0D CRLF: LD A,CR -0079 D09A CD 92 D0 CALL PRINTB -0080 D09D 3E 0A LD A,LF -0081 D09F C3 92 D0 JP PRINTB -0082 D0A2 ; -0083 D0A2 ; Routine to send one space to the console and save (BC). -0084 D0A2 ; -0085 D0A2 3E 20 SPACE: LD A,' ' -0086 D0A4 C3 92 D0 JP PRINTB -0087 D0A7 ; -0088 D0A7 ; Routine to print character string pointed to be (BC) on the -0089 D0A7 ; console. It must terminate with a null byte. -0090 D0A7 ; -0091 D0A7 C5 PLINE: PUSH BC -0092 D0A8 CD 98 D0 CALL CRLF -0093 D0AB E1 POP HL -0094 D0AC 7E PLINE2: LD A,(HL) -0095 D0AD B7 OR A -0096 D0AE C8 RET Z -0097 D0AF 23 INC HL -0098 D0B0 E5 PUSH HL -0099 D0B1 CD 8C D0 CALL PRINT -0100 D0B4 E1 POP HL -0101 D0B5 C3 AC D0 JP PLINE2 -0102 D0B8 ; -0103 D0B8 ; Routine to reset the disk system. -0104 D0B8 ; -0105 D0B8 0E 0D RESDSK: LD C,13 -0106 D0BA C3 05 00 JP ENTRY -0107 D0BD ; -0108 D0BD ; Routine to select disk (A). -0109 D0BD ; -0110 D0BD 5F DSKSEL: LD E,A -0111 D0BE 0E 0E LD C,14 -0112 D0C0 C3 05 00 JP ENTRY -0113 D0C3 ; -0114 D0C3 ; Routine to call bdos and save the return code. The zero -0115 D0C3 ; flag is set on a return of 0ffh. -0116 D0C3 ; -0117 D0C3 CD 05 00 ENTRY1: CALL ENTRY -0118 D0C6 32 EE D7 LD (RTNCODE),A ;save return code. -0119 D0C9 3C INC A ;set zero if 0ffh returned. -0120 D0CA C9 RET -0121 D0CB ; -0122 D0CB ; Routine to open a file. (DE) must point to the FCB. -0123 D0CB ; -0124 D0CB 0E 0F OPEN: LD C,15 -0125 D0CD C3 C3 D0 JP ENTRY1 -0126 D0D0 ; -0127 D0D0 ; Routine to open file at (FCB). -0128 D0D0 ; -0129 D0D0 AF OPENFCB:XOR A ;clear the record number byte at fcb+32 -0130 D0D1 32 ED D7 LD (FCB+32),A -0131 D0D4 11 CD D7 LD DE,FCB -0132 D0D7 C3 CB D0 JP OPEN -0133 D0DA ; -0134 D0DA ; Routine to close a file. (DE) points to FCB. -0135 D0DA ; -0136 D0DA 0E 10 CLOSE: LD C,16 -0137 D0DC C3 C3 D0 JP ENTRY1 -0138 D0DF ; -0139 D0DF ; Routine to search for the first file with ambigueous name -0140 D0DF ; (DE). -0141 D0DF ; -0142 D0DF 0E 11 SRCHFST:LD C,17 -0143 D0E1 C3 C3 D0 JP ENTRY1 -0144 D0E4 ; -0145 D0E4 ; Search for the next ambigeous file name. -0146 D0E4 ; -0147 D0E4 0E 12 SRCHNXT:LD C,18 -0148 D0E6 C3 C3 D0 JP ENTRY1 -0149 D0E9 ; -0150 D0E9 ; Search for file at (FCB). -0151 D0E9 ; -0152 D0E9 11 CD D7 SRCHFCB:LD DE,FCB -0153 D0EC C3 DF D0 JP SRCHFST -0154 D0EF ; -0155 D0EF ; Routine to delete a file pointed to by (DE). -0156 D0EF ; -0157 D0EF 0E 13 DELETE: LD C,19 -0158 D0F1 C3 05 00 JP ENTRY -0159 D0F4 ; -0160 D0F4 ; Routine to call the bdos and set the zero flag if a zero -0161 D0F4 ; status is returned. -0162 D0F4 ; -0163 D0F4 CD 05 00 ENTRY2: CALL ENTRY -0164 D0F7 B7 OR A ;set zero flag if appropriate. -0165 D0F8 C9 RET -0166 D0F9 ; -0167 D0F9 ; Routine to read the next record from a sequential file. -0168 D0F9 ; (DE) points to the FCB. -0169 D0F9 ; -0170 D0F9 0E 14 RDREC: LD C,20 -0171 D0FB C3 F4 D0 JP ENTRY2 -0172 D0FE ; -0173 D0FE ; Routine to read file at (FCB). -0174 D0FE ; -0175 D0FE 11 CD D7 READFCB:LD DE,FCB -0176 D101 C3 F9 D0 JP RDREC -0177 D104 ; -0178 D104 ; Routine to write the next record of a sequential file. -0179 D104 ; (DE) points to the FCB. -0180 D104 ; -0181 D104 0E 15 WRTREC: LD C,21 -0182 D106 C3 F4 D0 JP ENTRY2 -0183 D109 ; -0184 D109 ; Routine to create the file pointed to by (DE). -0185 D109 ; -0186 D109 0E 16 CREATE: LD C,22 -0187 D10B C3 C3 D0 JP ENTRY1 -0188 D10E ; -0189 D10E ; Routine to rename the file pointed to by (DE). Note that -0190 D10E ; the new name starts at (DE+16). -0191 D10E ; -0192 D10E 0E 17 RENAM: LD C,23 -0193 D110 C3 05 00 JP ENTRY -0194 D113 ; -0195 D113 ; Get the current user code. -0196 D113 ; -0197 D113 1E FF GETUSR: LD E,0FFH -0198 D115 ; -0199 D115 ; Routne to get or set the current user code. -0200 D115 ; If (E) is FF then this is a GET, else it is a SET. -0201 D115 ; -0202 D115 0E 20 GETSETUC: LD C,32 -0203 D117 C3 05 00 JP ENTRY -0204 D11A ; -0205 D11A ; Routine to set the current drive byte at (TDRIVE). -0206 D11A ; -0207 D11A CD 13 D1 SETCDRV:CALL GETUSR ;get user number -0208 D11D 87 ADD A,A ;and shift into the upper 4 bits. -0209 D11E 87 ADD A,A -0210 D11F 87 ADD A,A -0211 D120 87 ADD A,A -0212 D121 21 EF D7 LD HL,CDRIVE ;now add in the current drive number. -0213 D124 B6 OR (HL) -0214 D125 32 04 00 LD (TDRIVE),A ;and save. -0215 D128 C9 RET -0216 D129 ; -0217 D129 ; Move currently active drive down to (TDRIVE). -0218 D129 ; -0219 D129 3A EF D7 MOVECD: LD A,(CDRIVE) -0220 D12C 32 04 00 LD (TDRIVE),A -0221 D12F C9 RET -0222 D130 ; -0223 D130 ; Routine to convert (A) into upper case ascii. Only letters -0224 D130 ; are affected. -0225 D130 ; -0226 D130 FE 61 UPPER: CP 'a' ;check for letters in the range of 'a' to 'z'. -0227 D132 D8 RET C -0228 D133 FE 7B CP '{' -0229 D135 D0 RET NC -0230 D136 E6 5F AND 5FH ;convert it if found. -0231 D138 C9 RET -0232 D139 ; -0233 D139 ; Routine to get a line of input. We must check to see if the -0234 D139 ; user is in (BATCH) mode. If so, then read the input from file -0235 D139 ; ($$$.SUB). At the end, reset to console input. -0236 D139 ; -0237 D139 3A AB D7 GETINP: LD A,(BATCH) ;if =0, then use console input. -0238 D13C B7 OR A -0239 D13D CA 96 D1 JP Z,GETINP1 -0240 D140 ; -0241 D140 ; Use the submit file ($$$.sub) which is prepared by a -0242 D140 ; SUBMIT run. It must be on drive (A) and it will be deleted -0243 D140 ; if and error occures (like eof). -0244 D140 ; -0245 D140 3A EF D7 LD A,(CDRIVE) ;select drive 0 if need be. -0246 D143 B7 OR A -0247 D144 3E 00 LD A,0 ;always use drive A for submit. -0248 D146 C4 BD D0 CALL NZ,DSKSEL ;select it if required. -0249 D149 11 AC D7 LD DE,BATCHFCB -0250 D14C CD CB D0 CALL OPEN ;look for it. -0251 D14F CA 96 D1 JP Z,GETINP1 ;if not there, use normal input. -0252 D152 3A BB D7 LD A,(BATCHFCB+15) ;get last record number+1. -0253 D155 3D DEC A -0254 D156 32 CC D7 LD (BATCHFCB+32),A -0255 D159 11 AC D7 LD DE,BATCHFCB -0256 D15C CD F9 D0 CALL RDREC ;read last record. -0257 D15F C2 96 D1 JP NZ,GETINP1 ;quit on end of file. -0258 D162 ; -0259 D162 ; Move this record into input buffer. -0260 D162 ; -0261 D162 11 07 D0 LD DE,INBUFF+1 -0262 D165 21 80 00 LD HL,TBUFF ;data was read into buffer here. -0263 D168 06 80 LD B,128 ;all 128 characters may be used. -0264 D16A CD 42 D4 CALL HL2DE ;(HL) to (DE), (B) bytes. -0265 D16D 21 BA D7 LD HL,BATCHFCB+14 -0266 D170 36 00 LD (HL),0 ;zero out the 's2' byte. -0267 D172 23 INC HL ;and decrement the record count. -0268 D173 35 DEC (HL) -0269 D174 11 AC D7 LD DE,BATCHFCB ;close the batch file now. -0270 D177 CD DA D0 CALL CLOSE -0271 D17A CA 96 D1 JP Z,GETINP1 ;quit on an error. -0272 D17D 3A EF D7 LD A,(CDRIVE) ;re-select previous drive if need be. -0273 D180 B7 OR A -0274 D181 C4 BD D0 CALL NZ,DSKSEL ;don't do needless selects. -0275 D184 ; -0276 D184 ; Print line just read on console. -0277 D184 ; -0278 D184 21 08 D0 LD HL,INBUFF+2 -0279 D187 CD AC D0 CALL PLINE2 -0280 D18A CD C2 D1 CALL CHKCON ;check console, quit on a key. -0281 D18D CA A7 D1 JP Z,GETINP2 ;jump if no key is pressed. -0282 D190 ; -0283 D190 ; Terminate the submit job on any keyboard input. Delete this -0284 D190 ; file such that it is not re-started and jump to normal keyboard -0285 D190 ; input section. -0286 D190 ; -0287 D190 CD DD D1 CALL DELBATCH ;delete the batch file. -0288 D193 C3 82 D3 JP CMMND1 ;and restart command input. -0289 D196 ; -0290 D196 ; Get here for normal keyboard input. Delete the submit file -0291 D196 ; incase there was one. -0292 D196 ; -0293 D196 CD DD D1 GETINP1:CALL DELBATCH ;delete file ($$$.sub). -0294 D199 CD 1A D1 CALL SETCDRV ;reset active disk. -0295 D19C 0E 0A LD C,10 ;get line from console device. -0296 D19E 11 06 D0 LD DE,INBUFF -0297 D1A1 CD 05 00 CALL ENTRY -0298 D1A4 CD 29 D1 CALL MOVECD ;reset current drive (again). -0299 D1A7 ; -0300 D1A7 ; Convert input line to upper case. -0301 D1A7 ; -0302 D1A7 21 07 D0 GETINP2:LD HL,INBUFF+1 -0303 D1AA 46 LD B,(HL) ;(B)=character counter. -0304 D1AB 23 GETINP3:INC HL -0305 D1AC 78 LD A,B ;end of the line? -0306 D1AD B7 OR A -0307 D1AE CA BA D1 JP Z,GETINP4 -0308 D1B1 7E LD A,(HL) ;convert to upper case. -0309 D1B2 CD 30 D1 CALL UPPER -0310 D1B5 77 LD (HL),A -0311 D1B6 05 DEC B ;adjust character count. -0312 D1B7 C3 AB D1 JP GETINP3 -0313 D1BA 77 GETINP4:LD (HL),A ;add trailing null. -0314 D1BB 21 08 D0 LD HL,INBUFF+2 -0315 D1BE 22 88 D0 LD (INPOINT),HL ;reset input line pointer. -0316 D1C1 C9 RET -0317 D1C2 ; -0318 D1C2 ; Routine to check the console for a key pressed. The zero -0319 D1C2 ; flag is set is none, else the character is returned in (A). -0320 D1C2 ; -0321 D1C2 0E 0B CHKCON: LD C,11 ;check console. -0322 D1C4 CD 05 00 CALL ENTRY -0323 D1C7 B7 OR A -0324 D1C8 C8 RET Z ;return if nothing. -0325 D1C9 0E 01 LD C,1 ;else get character. -0326 D1CB CD 05 00 CALL ENTRY -0327 D1CE B7 OR A ;clear zero flag and return. -0328 D1CF C9 RET -0329 D1D0 ; -0330 D1D0 ; Routine to get the currently active drive number. -0331 D1D0 ; -0332 D1D0 0E 19 GETDSK: LD C,25 -0333 D1D2 C3 05 00 JP ENTRY -0334 D1D5 ; -0335 D1D5 ; Set the stabdard dma address. -0336 D1D5 ; -0337 D1D5 11 80 00 STDDMA: LD DE,TBUFF -0338 D1D8 ; -0339 D1D8 ; Routine to set the dma address to (DE). -0340 D1D8 ; -0341 D1D8 0E 1A DMASET: LD C,26 -0342 D1DA C3 05 00 JP ENTRY -0343 D1DD ; -0344 D1DD ; Delete the batch file created by SUBMIT. -0345 D1DD ; -0346 D1DD 21 AB D7 DELBATCH: LD HL,BATCH ;is batch active? -0347 D1E0 7E LD A,(HL) -0348 D1E1 B7 OR A -0349 D1E2 C8 RET Z -0350 D1E3 36 00 LD (HL),0 ;yes, de-activate it. -0351 D1E5 AF XOR A -0352 D1E6 CD BD D0 CALL DSKSEL ;select drive 0 for sure. -0353 D1E9 11 AC D7 LD DE,BATCHFCB ;and delete this file. -0354 D1EC CD EF D0 CALL DELETE -0355 D1EF 3A EF D7 LD A,(CDRIVE) ;reset current drive. -0356 D1F2 C3 BD D0 JP DSKSEL -0357 D1F5 ; -0358 D1F5 ; Check to two strings at (PATTRN1) and (PATTRN2). They must be -0359 D1F5 ; the same or we halt.... -0360 D1F5 ; -0361 D1F5 11 28 D3 VERIFY: LD DE,PATTRN1 ;these are the serial number bytes. -0362 D1F8 21 00 D8 LD HL,PATTRN2 ;ditto, but how could they be different? -0363 D1FB 06 06 LD B,6 ;6 bytes each. -0364 D1FD 1A VERIFY1:LD A,(DE) -0365 D1FE BE CP (HL) -0366 D1FF C2 CF D3 JP NZ,HALT ;jump to halt routine. -0367 D202 13 INC DE -0368 D203 23 INC HL -0369 D204 05 DEC B -0370 D205 C2 FD D1 JP NZ,VERIFY1 -0371 D208 C9 RET -0372 D209 ; -0373 D209 ; Print back file name with a '?' to indicate a syntax error. -0374 D209 ; -0375 D209 CD 98 D0 SYNERR: CALL CRLF ;end current line. -0376 D20C 2A 8A D0 LD HL,(NAMEPNT) ;this points to name in error. -0377 D20F 7E SYNERR1:LD A,(HL) ;print it until a space or null is found. -0378 D210 FE 20 CP ' ' -0379 D212 CA 22 D2 JP Z,SYNERR2 -0380 D215 B7 OR A -0381 D216 CA 22 D2 JP Z,SYNERR2 -0382 D219 E5 PUSH HL -0383 D21A CD 8C D0 CALL PRINT -0384 D21D E1 POP HL -0385 D21E 23 INC HL -0386 D21F C3 0F D2 JP SYNERR1 -0387 D222 3E 3F SYNERR2:LD A,'?' ;add trailing '?'. -0388 D224 CD 8C D0 CALL PRINT -0389 D227 CD 98 D0 CALL CRLF -0390 D22A CD DD D1 CALL DELBATCH ;delete any batch file. -0391 D22D C3 82 D3 JP CMMND1 ;and restart from console input. -0392 D230 ; -0393 D230 ; Check character at (DE) for legal command input. Note that the -0394 D230 ; zero flag is set if the character is a delimiter. -0395 D230 ; -0396 D230 1A CHECK: LD A,(DE) -0397 D231 B7 OR A -0398 D232 C8 RET Z -0399 D233 FE 20 CP ' ' ;control characters are not legal here. -0400 D235 DA 09 D2 JP C,SYNERR -0401 D238 C8 RET Z ;check for valid delimiter. -0402 D239 FE 3D CP '=' -0403 D23B C8 RET Z -0404 D23C FE 5F CP '_' -0405 D23E C8 RET Z -0406 D23F FE 2E CP '.' -0407 D241 C8 RET Z -0408 D242 FE 3A CP ':' -0409 D244 C8 RET Z -0410 D245 FE 3B CP 03BH ; ';' -0411 D247 C8 RET Z -0412 D248 FE 3C CP '<' -0413 D24A C8 RET Z -0414 D24B FE 3E CP '>' -0415 D24D C8 RET Z -0416 D24E C9 RET -0417 D24F ; -0418 D24F ; Get the next non-blank character from (DE). -0419 D24F ; -0420 D24F 1A NONBLANK: LD A,(DE) -0421 D250 B7 OR A ;string ends with a null. -0422 D251 C8 RET Z -0423 D252 FE 20 CP ' ' -0424 D254 C0 RET NZ -0425 D255 13 INC DE -0426 D256 C3 4F D2 JP NONBLANK -0427 D259 ; -0428 D259 ; Add (HL)=(HL)+(A) -0429 D259 ; -0430 D259 85 ADDHL: ADD A,L -0431 D25A 6F LD L,A -0432 D25B D0 RET NC ;take care of any carry. -0433 D25C 24 INC H -0434 D25D C9 RET -0435 D25E ; -0436 D25E ; Convert the first name in (FCB). -0437 D25E ; -0438 D25E 3E 00 CONVFST:LD A,0 -0439 D260 ; -0440 D260 ; Format a file name (convert * to '?', etc.). On return, -0441 D260 ; (A)=0 is an unambigeous name was specified. Enter with (A) equal to -0442 D260 ; the position within the fcb for the name (either 0 or 16). -0443 D260 ; -0444 D260 21 CD D7 CONVERT:LD HL,FCB -0445 D263 CD 59 D2 CALL ADDHL -0446 D266 E5 PUSH HL -0447 D267 E5 PUSH HL -0448 D268 AF XOR A -0449 D269 32 F0 D7 LD (CHGDRV),A ;initialize drive change flag. -0450 D26C 2A 88 D0 LD HL,(INPOINT) ;set (HL) as pointer into input line. -0451 D26F EB EX DE,HL -0452 D270 CD 4F D2 CALL NONBLANK ;get next non-blank character. -0453 D273 EB EX DE,HL -0454 D274 22 8A D0 LD (NAMEPNT),HL ;save pointer here for any error message. -0455 D277 EB EX DE,HL -0456 D278 E1 POP HL -0457 D279 1A LD A,(DE) ;get first character. -0458 D27A B7 OR A -0459 D27B CA 89 D2 JP Z,CONVRT1 -0460 D27E DE 40 SBC A,'A'-1 ;might be a drive name, convert to binary. -0461 D280 47 LD B,A ;and save. -0462 D281 13 INC DE ;check next character for a ':'. -0463 D282 1A LD A,(DE) -0464 D283 FE 3A CP ':' -0465 D285 CA 90 D2 JP Z,CONVRT2 -0466 D288 1B DEC DE ;nope, move pointer back to the start of the line. -0467 D289 3A EF D7 CONVRT1:LD A,(CDRIVE) -0468 D28C 77 LD (HL),A -0469 D28D C3 96 D2 JP CONVRT3 -0470 D290 78 CONVRT2:LD A,B -0471 D291 32 F0 D7 LD (CHGDRV),A ;set change in drives flag. -0472 D294 70 LD (HL),B -0473 D295 13 INC DE -0474 D296 ; -0475 D296 ; Convert the basic file name. -0476 D296 ; -0477 D296 06 08 CONVRT3:LD B,08H -0478 D298 CD 30 D2 CONVRT4:CALL CHECK -0479 D29B CA B9 D2 JP Z,CONVRT8 -0480 D29E 23 INC HL -0481 D29F FE 2A CP '*' ;note that an '*' will fill the remaining -0482 D2A1 C2 A9 D2 JP NZ,CONVRT5 ;field with '?'. -0483 D2A4 36 3F LD (HL),'?' -0484 D2A6 C3 AB D2 JP CONVRT6 -0485 D2A9 77 CONVRT5:LD (HL),A -0486 D2AA 13 INC DE -0487 D2AB 05 CONVRT6:DEC B -0488 D2AC C2 98 D2 JP NZ,CONVRT4 -0489 D2AF CD 30 D2 CONVRT7:CALL CHECK ;get next delimiter. -0490 D2B2 CA C0 D2 JP Z,GETEXT -0491 D2B5 13 INC DE -0492 D2B6 C3 AF D2 JP CONVRT7 -0493 D2B9 23 CONVRT8:INC HL ;blank fill the file name. -0494 D2BA 36 20 LD (HL),' ' -0495 D2BC 05 DEC B -0496 D2BD C2 B9 D2 JP NZ,CONVRT8 -0497 D2C0 ; -0498 D2C0 ; Get the extension and convert it. -0499 D2C0 ; -0500 D2C0 06 03 GETEXT: LD B,03H -0501 D2C2 FE 2E CP '.' -0502 D2C4 C2 E9 D2 JP NZ,GETEXT5 -0503 D2C7 13 INC DE -0504 D2C8 CD 30 D2 GETEXT1:CALL CHECK -0505 D2CB CA E9 D2 JP Z,GETEXT5 -0506 D2CE 23 INC HL -0507 D2CF FE 2A CP '*' -0508 D2D1 C2 D9 D2 JP NZ,GETEXT2 -0509 D2D4 36 3F LD (HL),'?' -0510 D2D6 C3 DB D2 JP GETEXT3 -0511 D2D9 77 GETEXT2:LD (HL),A -0512 D2DA 13 INC DE -0513 D2DB 05 GETEXT3:DEC B -0514 D2DC C2 C8 D2 JP NZ,GETEXT1 -0515 D2DF CD 30 D2 GETEXT4:CALL CHECK -0516 D2E2 CA F0 D2 JP Z,GETEXT6 -0517 D2E5 13 INC DE -0518 D2E6 C3 DF D2 JP GETEXT4 -0519 D2E9 23 GETEXT5:INC HL -0520 D2EA 36 20 LD (HL),' ' -0521 D2EC 05 DEC B -0522 D2ED C2 E9 D2 JP NZ,GETEXT5 -0523 D2F0 06 03 GETEXT6:LD B,3 -0524 D2F2 23 GETEXT7:INC HL -0525 D2F3 36 00 LD (HL),0 -0526 D2F5 05 DEC B -0527 D2F6 C2 F2 D2 JP NZ,GETEXT7 -0528 D2F9 EB EX DE,HL -0529 D2FA 22 88 D0 LD (INPOINT),HL ;save input line pointer. -0530 D2FD E1 POP HL -0531 D2FE ; -0532 D2FE ; Check to see if this is an ambigeous file name specification. -0533 D2FE ; Set the (A) register to non zero if it is. -0534 D2FE ; -0535 D2FE 01 0B 00 LD BC,11 ;set name length. -0536 D301 23 GETEXT8:INC HL -0537 D302 7E LD A,(HL) -0538 D303 FE 3F CP '?' ;any question marks? -0539 D305 C2 09 D3 JP NZ,GETEXT9 -0540 D308 04 INC B ;count them. -0541 D309 0D GETEXT9:DEC C -0542 D30A C2 01 D3 JP NZ,GETEXT8 -0543 D30D 78 LD A,B -0544 D30E B7 OR A -0545 D30F C9 RET -0546 D310 ; -0547 D310 ; CP/M command table. Note commands can be either 3 or 4 characters long. -0548 D310 ; -0549 D310 NUMCMDS .EQU 6 ;number of commands -0550 D310 44 49 52 20 CMDTBL: .TEXT "DIR " -0551 D314 45 52 41 20 .TEXT "ERA " -0552 D318 54 59 50 45 .TEXT "TYPE" -0553 D31C 53 41 56 45 .TEXT "SAVE" -0554 D320 52 45 4E 20 .TEXT "REN " -0555 D324 55 53 45 52 .TEXT "USER" -0556 D328 ; -0557 D328 ; The following six bytes must agree with those at (PATTRN2) -0558 D328 ; or cp/m will HALT. Why? -0559 D328 ; -0560 D328 001600000000PATTRN1:.DB 0,22,0,0,0,0 ;(* serial number bytes *). -0561 D32E ; -0562 D32E ; Search the command table for a match with what has just -0563 D32E ; been entered. If a match is found, then we jump to the -0564 D32E ; proper section. Else jump to (UNKNOWN). -0565 D32E ; On return, the (C) register is set to the command number -0566 D32E ; that matched (or NUMCMDS+1 if no match). -0567 D32E ; -0568 D32E 21 10 D3 SEARCH: LD HL,CMDTBL -0569 D331 0E 00 LD C,0 -0570 D333 79 SEARCH1:LD A,C -0571 D334 FE 06 CP NUMCMDS ;this commands exists. -0572 D336 D0 RET NC -0573 D337 11 CE D7 LD DE,FCB+1 ;check this one. -0574 D33A 06 04 LD B,4 ;max command length. -0575 D33C 1A SEARCH2:LD A,(DE) -0576 D33D BE CP (HL) -0577 D33E C2 4F D3 JP NZ,SEARCH3 ;not a match. -0578 D341 13 INC DE -0579 D342 23 INC HL -0580 D343 05 DEC B -0581 D344 C2 3C D3 JP NZ,SEARCH2 -0582 D347 1A LD A,(DE) ;allow a 3 character command to match. -0583 D348 FE 20 CP ' ' -0584 D34A C2 54 D3 JP NZ,SEARCH4 -0585 D34D 79 LD A,C ;set return register for this command. -0586 D34E C9 RET -0587 D34F 23 SEARCH3:INC HL -0588 D350 05 DEC B -0589 D351 C2 4F D3 JP NZ,SEARCH3 -0590 D354 0C SEARCH4:INC C -0591 D355 C3 33 D3 JP SEARCH1 -0592 D358 ; -0593 D358 ; Set the input buffer to empty and then start the command -0594 D358 ; processor (ccp). -0595 D358 ; -0596 D358 AF CLEARBUF: XOR A -0597 D359 32 07 D0 LD (INBUFF+1),A ;second byte is actual length. -0598 D35C ; -0599 D35C ;************************************************************** -0600 D35C ;* -0601 D35C ;* -0602 D35C ;* C C P - C o n s o l e C o m m a n d P r o c e s s o r -0603 D35C ;* -0604 D35C ;************************************************************** -0605 D35C ;* -0606 D35C 31 AB D7 COMMAND:LD SP,CCPSTACK ;setup stack area. -0607 D35F C5 PUSH BC ;note that (C) should be equal to: -0608 D360 79 LD A,C ;(uuuudddd) where 'uuuu' is the user number -0609 D361 1F RRA ;and 'dddd' is the drive number. -0610 D362 1F RRA -0611 D363 1F RRA -0612 D364 1F RRA -0613 D365 E6 0F AND 0FH ;isolate the user number. -0614 D367 5F LD E,A -0615 D368 CD 15 D1 CALL GETSETUC ;and set it. -0616 D36B CD B8 D0 CALL RESDSK ;reset the disk system. -0617 D36E 32 AB D7 LD (BATCH),A ;clear batch mode flag. -0618 D371 C1 POP BC -0619 D372 79 LD A,C -0620 D373 E6 0F AND 0FH ;isolate the drive number. -0621 D375 32 EF D7 LD (CDRIVE),A ;and save. -0622 D378 CD BD D0 CALL DSKSEL ;...and select. -0623 D37B 3A 07 D0 LD A,(INBUFF+1) -0624 D37E B7 OR A ;anything in input buffer already? -0625 D37F C2 98 D3 JP NZ,CMMND2 ;yes, we just process it. -0626 D382 ; -0627 D382 ; Entry point to get a command line from the console. -0628 D382 ; -0629 D382 31 AB D7 CMMND1: LD SP,CCPSTACK ;set stack straight. -0630 D385 CD 98 D0 CALL CRLF ;start a new line on the screen. -0631 D388 CD D0 D1 CALL GETDSK ;get current drive. -0632 D38B C6 41 ADD A,'A' -0633 D38D CD 8C D0 CALL PRINT ;print current drive. -0634 D390 3E 3E LD A,'>' -0635 D392 CD 8C D0 CALL PRINT ;and add prompt. -0636 D395 CD 39 D1 CALL GETINP ;get line from user. -0637 D398 ; -0638 D398 ; Process command line here. -0639 D398 ; -0640 D398 11 80 00 CMMND2: LD DE,TBUFF -0641 D39B CD D8 D1 CALL DMASET ;set standard dma address. -0642 D39E CD D0 D1 CALL GETDSK -0643 D3A1 32 EF D7 LD (CDRIVE),A ;set current drive. -0644 D3A4 CD 5E D2 CALL CONVFST ;convert name typed in. -0645 D3A7 C4 09 D2 CALL NZ,SYNERR ;wild cards are not allowed. -0646 D3AA 3A F0 D7 LD A,(CHGDRV) ;if a change in drives was indicated, -0647 D3AD B7 OR A ;then treat this as an unknown command -0648 D3AE C2 A5 D6 JP NZ,UNKNOWN ;which gets executed. -0649 D3B1 CD 2E D3 CALL SEARCH ;else search command table for a match. -0650 D3B4 ; -0651 D3B4 ; Note that an unknown command returns -0652 D3B4 ; with (A) pointing to the last address -0653 D3B4 ; in our table which is (UNKNOWN). -0654 D3B4 ; -0655 D3B4 21 C1 D3 LD HL,CMDADR ;now, look thru our address table for command (A). -0656 D3B7 5F LD E,A ;set (DE) to command number. -0657 D3B8 16 00 LD D,0 -0658 D3BA 19 ADD HL,DE -0659 D3BB 19 ADD HL,DE ;(HL)=(CMDADR)+2*(command number). -0660 D3BC 7E LD A,(HL) ;now pick out this address. -0661 D3BD 23 INC HL -0662 D3BE 66 LD H,(HL) -0663 D3BF 6F LD L,A -0664 D3C0 E9 JP (HL) ;now execute it. -0665 D3C1 ; -0666 D3C1 ; CP/M command address table. -0667 D3C1 ; -0668 D3C1 77D41FD55DD5CMDADR: .DW DIRECT,ERASE,TYPE,SAVE -0668 D3C7 ADD5 -0669 D3C9 10D68ED6A5D6 .DW RENAME,USER,UNKNOWN -0670 D3CF ; -0671 D3CF ; Halt the system. Reason for this is unknown at present. -0672 D3CF ; -0673 D3CF 21 F3 76 HALT: LD HL,76F3H ;'DI HLT' instructions. -0674 D3D2 22 00 D0 LD (CBASE),HL -0675 D3D5 21 00 D0 LD HL,CBASE -0676 D3D8 E9 JP (HL) -0677 D3D9 ; -0678 D3D9 ; Read error while TYPEing a file. -0679 D3D9 ; -0680 D3D9 01 DF D3 RDERROR:LD BC,RDERR -0681 D3DC C3 A7 D0 JP PLINE -0682 D3DF 526561642065RDERR: .TEXT "Read error" -0682 D3E5 72726F72 -0683 D3E9 00 .DB 0 -0684 D3EA ; -0685 D3EA ; Required file was not located. -0686 D3EA ; -0687 D3EA 01 F0 D3 NONE: LD BC,NOFILE -0688 D3ED C3 A7 D0 JP PLINE -0689 D3F0 4E6F2066696CNOFILE: .TEXT "No file" -0689 D3F6 65 -0690 D3F7 00 .DB 0 -0691 D3F8 ; -0692 D3F8 ; Decode a command of the form 'A>filename number{ filename}. -0693 D3F8 ; Note that a drive specifier is not allowed on the first file -0694 D3F8 ; name. On return, the number is in register (A). Any error -0695 D3F8 ; causes 'filename?' to be printed and the command is aborted. -0696 D3F8 ; -0697 D3F8 CD 5E D2 DECODE: CALL CONVFST ;convert filename. -0698 D3FB 3A F0 D7 LD A,(CHGDRV) ;do not allow a drive to be specified. -0699 D3FE B7 OR A -0700 D3FF C2 09 D2 JP NZ,SYNERR -0701 D402 21 CE D7 LD HL,FCB+1 ;convert number now. -0702 D405 01 0B 00 LD BC,11 ;(B)=sum register, (C)=max digit count. -0703 D408 7E DECODE1:LD A,(HL) -0704 D409 FE 20 CP ' ' ;a space terminates the numeral. -0705 D40B CA 33 D4 JP Z,DECODE3 -0706 D40E 23 INC HL -0707 D40F D6 30 SUB '0' ;make binary from ascii. -0708 D411 FE 0A CP 10 ;legal digit? -0709 D413 D2 09 D2 JP NC,SYNERR -0710 D416 57 LD D,A ;yes, save it in (D). -0711 D417 78 LD A,B ;compute (B)=(B)*10 and check for overflow. -0712 D418 E6 E0 AND 0E0H -0713 D41A C2 09 D2 JP NZ,SYNERR -0714 D41D 78 LD A,B -0715 D41E 07 RLCA -0716 D41F 07 RLCA -0717 D420 07 RLCA ;(A)=(B)*8 -0718 D421 80 ADD A,B ;.......*9 -0719 D422 DA 09 D2 JP C,SYNERR -0720 D425 80 ADD A,B ;.......*10 -0721 D426 DA 09 D2 JP C,SYNERR -0722 D429 82 ADD A,D ;add in new digit now. -0723 D42A DA 09 D2 DECODE2:JP C,SYNERR -0724 D42D 47 LD B,A ;and save result. -0725 D42E 0D DEC C ;only look at 11 digits. -0726 D42F C2 08 D4 JP NZ,DECODE1 -0727 D432 C9 RET -0728 D433 7E DECODE3:LD A,(HL) ;spaces must follow (why?). -0729 D434 FE 20 CP ' ' -0730 D436 C2 09 D2 JP NZ,SYNERR -0731 D439 23 INC HL -0732 D43A 0D DECODE4:DEC C -0733 D43B C2 33 D4 JP NZ,DECODE3 -0734 D43E 78 LD A,B ;set (A)=the numeric value entered. -0735 D43F C9 RET -0736 D440 ; -0737 D440 ; Move 3 bytes from (HL) to (DE). Note that there is only -0738 D440 ; one reference to this at (A2D5h). -0739 D440 ; -0740 D440 06 03 MOVE3: LD B,3 -0741 D442 ; -0742 D442 ; Move (B) bytes from (HL) to (DE). -0743 D442 ; -0744 D442 7E HL2DE: LD A,(HL) -0745 D443 12 LD (DE),A -0746 D444 23 INC HL -0747 D445 13 INC DE -0748 D446 05 DEC B -0749 D447 C2 42 D4 JP NZ,HL2DE -0750 D44A C9 RET -0751 D44B ; -0752 D44B ; Compute (HL)=(TBUFF)+(A)+(C) and get the byte that's here. -0753 D44B ; -0754 D44B 21 80 00 EXTRACT:LD HL,TBUFF -0755 D44E 81 ADD A,C -0756 D44F CD 59 D2 CALL ADDHL -0757 D452 7E LD A,(HL) -0758 D453 C9 RET -0759 D454 ; -0760 D454 ; Check drive specified. If it means a change, then the new -0761 D454 ; drive will be selected. In any case, the drive byte of the -0762 D454 ; fcb will be set to null (means use current drive). -0763 D454 ; -0764 D454 AF DSELECT:XOR A ;null out first byte of fcb. -0765 D455 32 CD D7 LD (FCB),A -0766 D458 3A F0 D7 LD A,(CHGDRV) ;a drive change indicated? -0767 D45B B7 OR A -0768 D45C C8 RET Z -0769 D45D 3D DEC A ;yes, is it the same as the current drive? -0770 D45E 21 EF D7 LD HL,CDRIVE -0771 D461 BE CP (HL) -0772 D462 C8 RET Z -0773 D463 C3 BD D0 JP DSKSEL ;no. Select it then. -0774 D466 ; -0775 D466 ; Check the drive selection and reset it to the previous -0776 D466 ; drive if it was changed for the preceeding command. -0777 D466 ; -0778 D466 3A F0 D7 RESETDR:LD A,(CHGDRV) ;drive change indicated? -0779 D469 B7 OR A -0780 D46A C8 RET Z -0781 D46B 3D DEC A ;yes, was it a different drive? -0782 D46C 21 EF D7 LD HL,CDRIVE -0783 D46F BE CP (HL) -0784 D470 C8 RET Z -0785 D471 3A EF D7 LD A,(CDRIVE) ;yes, re-select our old drive. -0786 D474 C3 BD D0 JP DSKSEL -0787 D477 ; -0788 D477 ;************************************************************** -0789 D477 ;* -0790 D477 ;* D I R E C T O R Y C O M M A N D -0791 D477 ;* -0792 D477 ;************************************************************** -0793 D477 ; -0794 D477 CD 5E D2 DIRECT: CALL CONVFST ;convert file name. -0795 D47A CD 54 D4 CALL DSELECT ;select indicated drive. -0796 D47D 21 CE D7 LD HL,FCB+1 ;was any file indicated? -0797 D480 7E LD A,(HL) -0798 D481 FE 20 CP ' ' -0799 D483 C2 8F D4 JP NZ,DIRECT2 -0800 D486 06 0B LD B,11 ;no. Fill field with '?' - same as *.*. -0801 D488 36 3F DIRECT1:LD (HL),'?' -0802 D48A 23 INC HL -0803 D48B 05 DEC B -0804 D48C C2 88 D4 JP NZ,DIRECT1 -0805 D48F 1E 00 DIRECT2:LD E,0 ;set initial cursor position. -0806 D491 D5 PUSH DE -0807 D492 CD E9 D0 CALL SRCHFCB ;get first file name. -0808 D495 CC EA D3 CALL Z,NONE ;none found at all? -0809 D498 CA 1B D5 DIRECT3:JP Z,DIRECT9 ;terminate if no more names. -0810 D49B 3A EE D7 LD A,(RTNCODE) ;get file's position in segment (0-3). -0811 D49E 0F RRCA -0812 D49F 0F RRCA -0813 D4A0 0F RRCA -0814 D4A1 E6 60 AND 60H ;(A)=position*32 -0815 D4A3 4F LD C,A -0816 D4A4 3E 0A LD A,10 -0817 D4A6 CD 4B D4 CALL EXTRACT ;extract the tenth entry in fcb. -0818 D4A9 17 RLA ;check system file status bit. -0819 D4AA DA 0F D5 JP C,DIRECT8 ;we don't list them. -0820 D4AD D1 POP DE -0821 D4AE 7B LD A,E ;bump name count. -0822 D4AF 1C INC E -0823 D4B0 D5 PUSH DE -0824 D4B1 E6 03 AND 03H ;at end of line? -0825 D4B3 F5 PUSH AF -0826 D4B4 C2 CC D4 JP NZ,DIRECT4 -0827 D4B7 CD 98 D0 CALL CRLF ;yes, end this line and start another. -0828 D4BA C5 PUSH BC -0829 D4BB CD D0 D1 CALL GETDSK ;start line with ('A:'). -0830 D4BE C1 POP BC -0831 D4BF C6 41 ADD A,'A' -0832 D4C1 CD 92 D0 CALL PRINTB -0833 D4C4 3E 3A LD A,':' -0834 D4C6 CD 92 D0 CALL PRINTB -0835 D4C9 C3 D4 D4 JP DIRECT5 -0836 D4CC CD A2 D0 DIRECT4:CALL SPACE ;add seperator between file names. -0837 D4CF 3E 3A LD A,':' -0838 D4D1 CD 92 D0 CALL PRINTB -0839 D4D4 CD A2 D0 DIRECT5:CALL SPACE -0840 D4D7 06 01 LD B,1 ;'extract' each file name character at a time. -0841 D4D9 78 DIRECT6:LD A,B -0842 D4DA CD 4B D4 CALL EXTRACT -0843 D4DD E6 7F AND 7FH ;strip bit 7 (status bit). -0844 D4DF FE 20 CP ' ' ;are we at the end of the name? -0845 D4E1 C2 F9 D4 JP NZ,DRECT65 -0846 D4E4 F1 POP AF ;yes, don't print spaces at the end of a line. -0847 D4E5 F5 PUSH AF -0848 D4E6 FE 03 CP 3 -0849 D4E8 C2 F7 D4 JP NZ,DRECT63 -0850 D4EB 3E 09 LD A,9 ;first check for no extension. -0851 D4ED CD 4B D4 CALL EXTRACT -0852 D4F0 E6 7F AND 7FH -0853 D4F2 FE 20 CP ' ' -0854 D4F4 CA 0E D5 JP Z,DIRECT7 ;don't print spaces. -0855 D4F7 3E 20 DRECT63:LD A,' ' ;else print them. -0856 D4F9 CD 92 D0 DRECT65:CALL PRINTB -0857 D4FC 04 INC B ;bump to next character psoition. -0858 D4FD 78 LD A,B -0859 D4FE FE 0C CP 12 ;end of the name? -0860 D500 D2 0E D5 JP NC,DIRECT7 -0861 D503 FE 09 CP 9 ;nope, starting extension? -0862 D505 C2 D9 D4 JP NZ,DIRECT6 -0863 D508 CD A2 D0 CALL SPACE ;yes, add seperating space. -0864 D50B C3 D9 D4 JP DIRECT6 -0865 D50E F1 DIRECT7:POP AF ;get the next file name. -0866 D50F CD C2 D1 DIRECT8:CALL CHKCON ;first check console, quit on anything. -0867 D512 C2 1B D5 JP NZ,DIRECT9 -0868 D515 CD E4 D0 CALL SRCHNXT ;get next name. -0869 D518 C3 98 D4 JP DIRECT3 ;and continue with our list. -0870 D51B D1 DIRECT9:POP DE ;restore the stack and return to command level. -0871 D51C C3 86 D7 JP GETBACK -0872 D51F ; -0873 D51F ;************************************************************** -0874 D51F ;* -0875 D51F ;* E R A S E C O M M A N D -0876 D51F ;* -0877 D51F ;************************************************************** -0878 D51F ; -0879 D51F CD 5E D2 ERASE: CALL CONVFST ;convert file name. -0880 D522 FE 0B CP 11 ;was '*.*' entered? -0881 D524 C2 42 D5 JP NZ,ERASE1 -0882 D527 01 52 D5 LD BC,YESNO ;yes, ask for confirmation. -0883 D52A CD A7 D0 CALL PLINE -0884 D52D CD 39 D1 CALL GETINP -0885 D530 21 07 D0 LD HL,INBUFF+1 -0886 D533 35 DEC (HL) ;must be exactly 'y'. -0887 D534 C2 82 D3 JP NZ,CMMND1 -0888 D537 23 INC HL -0889 D538 7E LD A,(HL) -0890 D539 FE 59 CP 'Y' -0891 D53B C2 82 D3 JP NZ,CMMND1 -0892 D53E 23 INC HL -0893 D53F 22 88 D0 LD (INPOINT),HL ;save input line pointer. -0894 D542 CD 54 D4 ERASE1: CALL DSELECT ;select desired disk. -0895 D545 11 CD D7 LD DE,FCB -0896 D548 CD EF D0 CALL DELETE ;delete the file. -0897 D54B 3C INC A -0898 D54C CC EA D3 CALL Z,NONE ;not there? -0899 D54F C3 86 D7 JP GETBACK ;return to command level now. -0900 D552 416C6C202879YESNO: .TEXT "All (y/n)?" -0900 D558 2F6E293F -0901 D55C 00 .DB 0 -0902 D55D ; -0903 D55D ;************************************************************** -0904 D55D ;* -0905 D55D ;* T Y P E C O M M A N D -0906 D55D ;* -0907 D55D ;************************************************************** -0908 D55D ; -0909 D55D CD 5E D2 TYPE: CALL CONVFST ;convert file name. -0910 D560 C2 09 D2 JP NZ,SYNERR ;wild cards not allowed. -0911 D563 CD 54 D4 CALL DSELECT ;select indicated drive. -0912 D566 CD D0 D0 CALL OPENFCB ;open the file. -0913 D569 CA A7 D5 JP Z,TYPE5 ;not there? -0914 D56C CD 98 D0 CALL CRLF ;ok, start a new line on the screen. -0915 D56F 21 F1 D7 LD HL,NBYTES ;initialize byte counter. -0916 D572 36 FF LD (HL),0FFH ;set to read first sector. -0917 D574 21 F1 D7 TYPE1: LD HL,NBYTES -0918 D577 7E TYPE2: LD A,(HL) ;have we written the entire sector? -0919 D578 FE 80 CP 128 -0920 D57A DA 87 D5 JP C,TYPE3 -0921 D57D E5 PUSH HL ;yes, read in the next one. -0922 D57E CD FE D0 CALL READFCB -0923 D581 E1 POP HL -0924 D582 C2 A0 D5 JP NZ,TYPE4 ;end or error? -0925 D585 AF XOR A ;ok, clear byte counter. -0926 D586 77 LD (HL),A -0927 D587 34 TYPE3: INC (HL) ;count this byte. -0928 D588 21 80 00 LD HL,TBUFF ;and get the (A)th one from the buffer (TBUFF). -0929 D58B CD 59 D2 CALL ADDHL -0930 D58E 7E LD A,(HL) -0931 D58F FE 1A CP CNTRLZ ;end of file mark? -0932 D591 CA 86 D7 JP Z,GETBACK -0933 D594 CD 8C D0 CALL PRINT ;no, print it. -0934 D597 CD C2 D1 CALL CHKCON ;check console, quit if anything ready. -0935 D59A C2 86 D7 JP NZ,GETBACK -0936 D59D C3 74 D5 JP TYPE1 -0937 D5A0 ; -0938 D5A0 ; Get here on an end of file or read error. -0939 D5A0 ; -0940 D5A0 3D TYPE4: DEC A ;read error? -0941 D5A1 CA 86 D7 JP Z,GETBACK -0942 D5A4 CD D9 D3 CALL RDERROR ;yes, print message. -0943 D5A7 CD 66 D4 TYPE5: CALL RESETDR ;and reset proper drive -0944 D5AA C3 09 D2 JP SYNERR ;now print file name with problem. -0945 D5AD ; -0946 D5AD ;************************************************************** -0947 D5AD ;* -0948 D5AD ;* S A V E C O M M A N D -0949 D5AD ;* -0950 D5AD ;************************************************************** -0951 D5AD ; -0952 D5AD CD F8 D3 SAVE: CALL DECODE ;get numeric number that follows SAVE. -0953 D5B0 F5 PUSH AF ;save number of pages to write. -0954 D5B1 CD 5E D2 CALL CONVFST ;convert file name. -0955 D5B4 C2 09 D2 JP NZ,SYNERR ;wild cards not allowed. -0956 D5B7 CD 54 D4 CALL DSELECT ;select specified drive. -0957 D5BA 11 CD D7 LD DE,FCB ;now delete this file. -0958 D5BD D5 PUSH DE -0959 D5BE CD EF D0 CALL DELETE -0960 D5C1 D1 POP DE -0961 D5C2 CD 09 D1 CALL CREATE ;and create it again. -0962 D5C5 CA FB D5 JP Z,SAVE3 ;can't create? -0963 D5C8 AF XOR A ;clear record number byte. -0964 D5C9 32 ED D7 LD (FCB+32),A -0965 D5CC F1 POP AF ;convert pages to sectors. -0966 D5CD 6F LD L,A -0967 D5CE 26 00 LD H,0 -0968 D5D0 29 ADD HL,HL ;(HL)=number of sectors to write. -0969 D5D1 11 00 01 LD DE,TBASE ;and we start from here. -0970 D5D4 7C SAVE1: LD A,H ;done yet? -0971 D5D5 B5 OR L -0972 D5D6 CA F1 D5 JP Z,SAVE2 -0973 D5D9 2B DEC HL ;nope, count this and compute the start -0974 D5DA E5 PUSH HL ;of the next 128 byte sector. -0975 D5DB 21 80 00 LD HL,128 -0976 D5DE 19 ADD HL,DE -0977 D5DF E5 PUSH HL ;save it and set the transfer address. -0978 D5E0 CD D8 D1 CALL DMASET -0979 D5E3 11 CD D7 LD DE,FCB ;write out this sector now. -0980 D5E6 CD 04 D1 CALL WRTREC -0981 D5E9 D1 POP DE ;reset (DE) to the start of the last sector. -0982 D5EA E1 POP HL ;restore sector count. -0983 D5EB C2 FB D5 JP NZ,SAVE3 ;write error? -0984 D5EE C3 D4 D5 JP SAVE1 -0985 D5F1 ; -0986 D5F1 ; Get here after writing all of the file. -0987 D5F1 ; -0988 D5F1 11 CD D7 SAVE2: LD DE,FCB ;now close the file. -0989 D5F4 CD DA D0 CALL CLOSE -0990 D5F7 3C INC A ;did it close ok? -0991 D5F8 C2 01 D6 JP NZ,SAVE4 -0992 D5FB ; -0993 D5FB ; Print out error message (no space). -0994 D5FB ; -0995 D5FB 01 07 D6 SAVE3: LD BC,NOSPACE -0996 D5FE CD A7 D0 CALL PLINE -0997 D601 CD D5 D1 SAVE4: CALL STDDMA ;reset the standard dma address. -0998 D604 C3 86 D7 JP GETBACK -0999 D607 4E6F20737061NOSPACE:.TEXT "No space" -0999 D60D 6365 -1000 D60F 00 .DB 0 -1001 D610 ; -1002 D610 ;************************************************************** -1003 D610 ;* -1004 D610 ;* R E N A M E C O M M A N D -1005 D610 ;* -1006 D610 ;************************************************************** -1007 D610 ; -1008 D610 CD 5E D2 RENAME: CALL CONVFST ;convert first file name. -1009 D613 C2 09 D2 JP NZ,SYNERR ;wild cards not allowed. -1010 D616 3A F0 D7 LD A,(CHGDRV) ;remember any change in drives specified. -1011 D619 F5 PUSH AF -1012 D61A CD 54 D4 CALL DSELECT ;and select this drive. -1013 D61D CD E9 D0 CALL SRCHFCB ;is this file present? -1014 D620 C2 79 D6 JP NZ,RENAME6 ;yes, print error message. -1015 D623 21 CD D7 LD HL,FCB ;yes, move this name into second slot. -1016 D626 11 DD D7 LD DE,FCB+16 -1017 D629 06 10 LD B,16 -1018 D62B CD 42 D4 CALL HL2DE -1019 D62E 2A 88 D0 LD HL,(INPOINT) ;get input pointer. -1020 D631 EB EX DE,HL -1021 D632 CD 4F D2 CALL NONBLANK ;get next non blank character. -1022 D635 FE 3D CP '=' ;only allow an '=' or '_' seperator. -1023 D637 CA 3F D6 JP Z,RENAME1 -1024 D63A FE 5F CP '_' -1025 D63C C2 73 D6 JP NZ,RENAME5 -1026 D63F EB RENAME1:EX DE,HL -1027 D640 23 INC HL ;ok, skip seperator. -1028 D641 22 88 D0 LD (INPOINT),HL ;save input line pointer. -1029 D644 CD 5E D2 CALL CONVFST ;convert this second file name now. -1030 D647 C2 73 D6 JP NZ,RENAME5 ;again, no wild cards. -1031 D64A F1 POP AF ;if a drive was specified, then it -1032 D64B 47 LD B,A ;must be the same as before. -1033 D64C 21 F0 D7 LD HL,CHGDRV -1034 D64F 7E LD A,(HL) -1035 D650 B7 OR A -1036 D651 CA 59 D6 JP Z,RENAME2 -1037 D654 B8 CP B -1038 D655 70 LD (HL),B -1039 D656 C2 73 D6 JP NZ,RENAME5 ;they were different, error. -1040 D659 70 RENAME2:LD (HL),B ; reset as per the first file specification. -1041 D65A AF XOR A -1042 D65B 32 CD D7 LD (FCB),A ;clear the drive byte of the fcb. -1043 D65E CD E9 D0 RENAME3:CALL SRCHFCB ;and go look for second file. -1044 D661 CA 6D D6 JP Z,RENAME4 ;doesn't exist? -1045 D664 11 CD D7 LD DE,FCB -1046 D667 CD 0E D1 CALL RENAM ;ok, rename the file. -1047 D66A C3 86 D7 JP GETBACK -1048 D66D ; -1049 D66D ; Process rename errors here. -1050 D66D ; -1051 D66D CD EA D3 RENAME4:CALL NONE ;file not there. -1052 D670 C3 86 D7 JP GETBACK -1053 D673 CD 66 D4 RENAME5:CALL RESETDR ;bad command format. -1054 D676 C3 09 D2 JP SYNERR -1055 D679 01 82 D6 RENAME6:LD BC,EXISTS ;destination file already exists. -1056 D67C CD A7 D0 CALL PLINE -1057 D67F C3 86 D7 JP GETBACK -1058 D682 46696C652065EXISTS: .TEXT "File exists" -1058 D688 7869737473 -1059 D68D 00 .DB 0 -1060 D68E ; -1061 D68E ;************************************************************** -1062 D68E ;* -1063 D68E ;* U S E R C O M M A N D -1064 D68E ;* -1065 D68E ;************************************************************** -1066 D68E ; -1067 D68E CD F8 D3 USER: CALL DECODE ;get numeric value following command. -1068 D691 FE 10 CP 16 ;legal user number? -1069 D693 D2 09 D2 JP NC,SYNERR -1070 D696 5F LD E,A ;yes but is there anything else? -1071 D697 3A CE D7 LD A,(FCB+1) -1072 D69A FE 20 CP ' ' -1073 D69C CA 09 D2 JP Z,SYNERR ;yes, that is not allowed. -1074 D69F CD 15 D1 CALL GETSETUC ;ok, set user code. -1075 D6A2 C3 89 D7 JP GETBACK1 -1076 D6A5 ; -1077 D6A5 ;************************************************************** -1078 D6A5 ;* -1079 D6A5 ;* T R A N S I A N T P R O G R A M C O M M A N D -1080 D6A5 ;* -1081 D6A5 ;************************************************************** -1082 D6A5 ; -1083 D6A5 CD F5 D1 UNKNOWN:CALL VERIFY ;check for valid system (why?). -1084 D6A8 3A CE D7 LD A,(FCB+1) ;anything to execute? -1085 D6AB FE 20 CP ' ' -1086 D6AD C2 C4 D6 JP NZ,UNKWN1 -1087 D6B0 3A F0 D7 LD A,(CHGDRV) ;nope, only a drive change? -1088 D6B3 B7 OR A -1089 D6B4 CA 89 D7 JP Z,GETBACK1 ;neither??? -1090 D6B7 3D DEC A -1091 D6B8 32 EF D7 LD (CDRIVE),A ;ok, store new drive. -1092 D6BB CD 29 D1 CALL MOVECD ;set (TDRIVE) also. -1093 D6BE CD BD D0 CALL DSKSEL ;and select this drive. -1094 D6C1 C3 89 D7 JP GETBACK1 ;then return. -1095 D6C4 ; -1096 D6C4 ; Here a file name was typed. Prepare to execute it. -1097 D6C4 ; -1098 D6C4 11 D6 D7 UNKWN1: LD DE,FCB+9 ;an extension specified? -1099 D6C7 1A LD A,(DE) -1100 D6C8 FE 20 CP ' ' -1101 D6CA C2 09 D2 JP NZ,SYNERR ;yes, not allowed. -1102 D6CD D5 UNKWN2: PUSH DE -1103 D6CE CD 54 D4 CALL DSELECT ;select specified drive. -1104 D6D1 D1 POP DE -1105 D6D2 21 83 D7 LD HL,COMFILE ;set the extension to 'COM'. -1106 D6D5 CD 40 D4 CALL MOVE3 -1107 D6D8 CD D0 D0 CALL OPENFCB ;and open this file. -1108 D6DB CA 6B D7 JP Z,UNKWN9 ;not present? -1109 D6DE ; -1110 D6DE ; Load in the program. -1111 D6DE ; -1112 D6DE 21 00 01 LD HL,TBASE ;store the program starting here. -1113 D6E1 E5 UNKWN3: PUSH HL -1114 D6E2 EB EX DE,HL -1115 D6E3 CD D8 D1 CALL DMASET ;set transfer address. -1116 D6E6 11 CD D7 LD DE,FCB ;and read the next record. -1117 D6E9 CD F9 D0 CALL RDREC -1118 D6EC C2 01 D7 JP NZ,UNKWN4 ;end of file or read error? -1119 D6EF E1 POP HL ;nope, bump pointer for next sector. -1120 D6F0 11 80 00 LD DE,128 -1121 D6F3 19 ADD HL,DE -1122 D6F4 11 00 D0 LD DE,CBASE ;enough room for the whole file? -1123 D6F7 7D LD A,L -1124 D6F8 93 SUB E -1125 D6F9 7C LD A,H -1126 D6FA 9A SBC A,D -1127 D6FB D2 71 D7 JP NC,UNKWN0 ;no, it can't fit. -1128 D6FE C3 E1 D6 JP UNKWN3 -1129 D701 ; -1130 D701 ; Get here after finished reading. -1131 D701 ; -1132 D701 E1 UNKWN4: POP HL -1133 D702 3D DEC A ;normal end of file? -1134 D703 C2 71 D7 JP NZ,UNKWN0 -1135 D706 CD 66 D4 CALL RESETDR ;yes, reset previous drive. -1136 D709 CD 5E D2 CALL CONVFST ;convert the first file name that follows -1137 D70C 21 F0 D7 LD HL,CHGDRV ;command name. -1138 D70F E5 PUSH HL -1139 D710 7E LD A,(HL) ;set drive code in default fcb. -1140 D711 32 CD D7 LD (FCB),A -1141 D714 3E 10 LD A,16 ;put second name 16 bytes later. -1142 D716 CD 60 D2 CALL CONVERT ;convert second file name. -1143 D719 E1 POP HL -1144 D71A 7E LD A,(HL) ;and set the drive for this second file. -1145 D71B 32 DD D7 LD (FCB+16),A -1146 D71E AF XOR A ;clear record byte in fcb. -1147 D71F 32 ED D7 LD (FCB+32),A -1148 D722 11 5C 00 LD DE,TFCB ;move it into place at(005Ch). -1149 D725 21 CD D7 LD HL,FCB -1150 D728 06 21 LD B,33 -1151 D72A CD 42 D4 CALL HL2DE -1152 D72D 21 08 D0 LD HL,INBUFF+2 ;now move the remainder of the input -1153 D730 7E UNKWN5: LD A,(HL) ;line down to (0080h). Look for a non blank. -1154 D731 B7 OR A ;or a null. -1155 D732 CA 3E D7 JP Z,UNKWN6 -1156 D735 FE 20 CP ' ' -1157 D737 CA 3E D7 JP Z,UNKWN6 -1158 D73A 23 INC HL -1159 D73B C3 30 D7 JP UNKWN5 -1160 D73E ; -1161 D73E ; Do the line move now. It ends in a null byte. -1162 D73E ; -1163 D73E 06 00 UNKWN6: LD B,0 ;keep a character count. -1164 D740 11 81 00 LD DE,TBUFF+1 ;data gets put here. -1165 D743 7E UNKWN7: LD A,(HL) ;move it now. -1166 D744 12 LD (DE),A -1167 D745 B7 OR A -1168 D746 CA 4F D7 JP Z,UNKWN8 -1169 D749 04 INC B -1170 D74A 23 INC HL -1171 D74B 13 INC DE -1172 D74C C3 43 D7 JP UNKWN7 -1173 D74F 78 UNKWN8: LD A,B ;now store the character count. -1174 D750 32 80 00 LD (TBUFF),A -1175 D753 CD 98 D0 CALL CRLF ;clean up the screen. -1176 D756 CD D5 D1 CALL STDDMA ;set standard transfer address. -1177 D759 CD 1A D1 CALL SETCDRV ;reset current drive. -1178 D75C CD 00 01 CALL TBASE ;and execute the program. -1179 D75F ; -1180 D75F ; Transiant programs return here (or reboot). -1181 D75F ; -1182 D75F 31 AB D7 LD SP,BATCH ;set stack first off. -1183 D762 CD 29 D1 CALL MOVECD ;move current drive into place (TDRIVE). -1184 D765 CD BD D0 CALL DSKSEL ;and reselect it. -1185 D768 C3 82 D3 JP CMMND1 ;back to comand mode. -1186 D76B ; -1187 D76B ; Get here if some error occured. -1188 D76B ; -1189 D76B CD 66 D4 UNKWN9: CALL RESETDR ;inproper format. -1190 D76E C3 09 D2 JP SYNERR -1191 D771 01 7A D7 UNKWN0: LD BC,BADLOAD ;read error or won't fit. -1192 D774 CD A7 D0 CALL PLINE -1193 D777 C3 86 D7 JP GETBACK -1194 D77A 426164206C6FBADLOAD:.TEXT "Bad load" -1194 D780 6164 -1195 D782 00 .DB 0 -1196 D783 43 4F 4D COMFILE:.TEXT "COM" ;command file extension. -1197 D786 ; -1198 D786 ; Get here to return to command level. We will reset the -1199 D786 ; previous active drive and then either return to command -1200 D786 ; level directly or print error message and then return. -1201 D786 ; -1202 D786 CD 66 D4 GETBACK:CALL RESETDR ;reset previous drive. -1203 D789 CD 5E D2 GETBACK1: CALL CONVFST ;convert first name in (FCB). -1204 D78C 3A CE D7 LD A,(FCB+1) ;if this was just a drive change request, -1205 D78F D6 20 SUB ' ' ;make sure it was valid. -1206 D791 21 F0 D7 LD HL,CHGDRV -1207 D794 B6 OR (HL) -1208 D795 C2 09 D2 JP NZ,SYNERR -1209 D798 C3 82 D3 JP CMMND1 ;ok, return to command level. -1210 D79B ; -1211 D79B ; ccp stack area. -1212 D79B ; -1213 D79B 000000000000 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -1213 D7A1 00000000000000000000 -1214 D7AB CCPSTACK .EQU $ ;end of ccp stack area. -1215 D7AB ; -1216 D7AB ; Batch (or SUBMIT) processing information storage. -1217 D7AB ; -1218 D7AB 00 BATCH: .DB 0 ;batch mode flag (0=not active). -1219 D7AC 00 BATCHFCB: .DB 0, -1220 D7AD 242424202020 .TEXT "$$$ SUB" -1220 D7B3 2020535542 -1221 D7B8 000000000000 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -1221 D7BE 000000000000000000000000000000 -1222 D7CD ; -1223 D7CD ; File control block setup by the CCP. -1224 D7CD ; -1225 D7CD 00 FCB: .DB 0 -1226 D7CE 202020202020 .TEXT " " -1226 D7D4 2020202020 -1227 D7D9 0000000000 .DB 0,0,0,0,0 -1228 D7DE 202020202020 .TEXT " " -1228 D7E4 2020202020 -1229 D7E9 0000000000 .DB 0,0,0,0,0 -1230 D7EE 00 RTNCODE:.DB 0 ;status returned from bdos call. -1231 D7EF 00 CDRIVE: .DB 0 ;currently active drive. -1232 D7F0 00 CHGDRV: .DB 0 ;change in drives flag (0=no change). -1233 D7F1 00 00 NBYTES: .DW 0 ;byte counter used by TYPE. -1234 D7F3 ; -1235 D7F3 ; Room for expansion? -1236 D7F3 ; -1237 D7F3 000000000000 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0 -1237 D7F9 00000000000000 -1238 D800 ; -1239 D800 ; Note that the following six bytes must match those at -1240 D800 ; (PATTRN1) or cp/m will HALT. Why? -1241 D800 ; -1242 D800 001600000000PATTRN2:.DB 0,22,0,0,0,0 ;(* serial number bytes *). -1243 D806 ; -1244 D806 ;************************************************************** -1245 D806 ;* -1246 D806 ;* B D O S E N T R Y -1247 D806 ;* -1248 D806 ;************************************************************** -1249 D806 ; -1250 D806 C3 11 D8 FBASE: JP FBASE1 -1251 D809 ; -1252 D809 ; Bdos error table. -1253 D809 ; -1254 D809 99 D8 BADSCTR:.DW ERROR1 ;bad sector on read or write. -1255 D80B A5 D8 BADSLCT:.DW ERROR2 ;bad disk select. -1256 D80D AB D8 RODISK: .DW ERROR3 ;disk is read only. -1257 D80F B1 D8 ROFILE: .DW ERROR4 ;file is read only. -1258 D811 ; -1259 D811 ; Entry into bdos. (DE) or (E) are the parameters passed. The -1260 D811 ; function number desired is in register (C). -1261 D811 ; -1262 D811 EB FBASE1: EX DE,HL ;save the (DE) parameters. -1263 D812 22 43 DB LD (PARAMS),HL -1264 D815 EB EX DE,HL -1265 D816 7B LD A,E ;and save register (E) in particular. -1266 D817 32 D6 E5 LD (EPARAM),A -1267 D81A 21 00 00 LD HL,0 -1268 D81D 22 45 DB LD (STATUS),HL ;clear return status. -1269 D820 39 ADD HL,SP -1270 D821 22 0F DB LD (USRSTACK),HL ;save users stack pointer. -1271 D824 31 41 DB LD SP,STKAREA ;and set our own. -1272 D827 AF XOR A ;clear auto select storage space. -1273 D828 32 E0 E5 LD (AUTOFLAG),A -1274 D82B 32 DE E5 LD (AUTO),A -1275 D82E 21 74 E5 LD HL,GOBACK ;set return address. -1276 D831 E5 PUSH HL -1277 D832 79 LD A,C ;get function number. -1278 D833 FE 29 CP NFUNCTS ;valid function number? -1279 D835 D0 RET NC -1280 D836 4B LD C,E ;keep single register function here. -1281 D837 21 47 D8 LD HL,FUNCTNS ;now look thru the function table. -1282 D83A 5F LD E,A -1283 D83B 16 00 LD D,0 ;(DE)=function number. -1284 D83D 19 ADD HL,DE -1285 D83E 19 ADD HL,DE ;(HL)=(start of table)+2*(function number). -1286 D83F 5E LD E,(HL) -1287 D840 23 INC HL -1288 D841 56 LD D,(HL) ;now (DE)=address for this function. -1289 D842 2A 43 DB LD HL,(PARAMS) ;retrieve parameters. -1290 D845 EB EX DE,HL ;now (DE) has the original parameters. -1291 D846 E9 JP (HL) ;execute desired function. -1292 D847 ; -1293 D847 ; BDOS function jump table. -1294 D847 ; -1295 D847 NFUNCTS .EQU 41 ;number of functions in followin table. -1296 D847 ; -1297 D847 03E6C8DA90D9FUNCTNS:.DW WBOOT,GETCON,OUTCON,GETRDR,PUNCH,LIST,DIRCIO,GETIOB -1297 D84D CEDA12E60FE6D4DAEDDA -1298 D857 F3DAF8DAE1D9 .DW SETIOB,PRTSTR,RDBUFF,GETCSTS,GETVER,RSTDSK,SETDSK,OPENFIL -1298 D85D FEDA7EE483E445E49CE4 -1299 D867 A5E4ABE4C8E4 .DW CLOSEFIL,GETFST,GETNXT,DELFILE,READSEQ,WRTSEQ,FCREATE -1299 D86D D7E4E0E4E6E4ECE4 -1300 D875 F5E4FEE404E5 .DW RENFILE,GETLOG,GETCRNT,PUTDMA,GETALOC,WRTPRTD,GETROV,SETATTR -1300 D87B 0AE511E52CDD17E51DE5 -1301 D885 26E52DE541E5 .DW GETPARM,GETUSER,RDRANDOM,WTRANDOM,FILESIZE,SETRAN,LOGOFF,RTN -1301 D88B 47E54DE50EE453E504DB -1302 D895 04 DB 9B E5 .DW RTN,WTSPECL -1303 D899 ; -1304 D899 ; Bdos error message section. -1305 D899 ; -1306 D899 21 CA D8 ERROR1: LD HL,BADSEC ;bad sector message. -1307 D89C CD E5 D8 CALL PRTERR ;print it and get a 1 char responce. -1308 D89F FE 03 CP CNTRLC ;re-boot request (control-c)? -1309 D8A1 CA 00 00 JP Z,0 ;yes. -1310 D8A4 C9 RET ;no, return to retry i/o function. -1311 D8A5 ; -1312 D8A5 21 D5 D8 ERROR2: LD HL,BADSEL ;bad drive selected. -1313 D8A8 C3 B4 D8 JP ERROR5 -1314 D8AB ; -1315 D8AB 21 E1 D8 ERROR3: LD HL,DISKRO ;disk is read only. -1316 D8AE C3 B4 D8 JP ERROR5 -1317 D8B1 ; -1318 D8B1 21 DC D8 ERROR4: LD HL,FILERO ;file is read only. -1319 D8B4 ; -1320 D8B4 CD E5 D8 ERROR5: CALL PRTERR -1321 D8B7 C3 00 00 JP 0 ;always reboot on these errors. -1322 D8BA ; -1323 D8BA 42646F732045BDOSERR:.TEXT "Bdos Err On " -1323 D8C0 7272204F6E20 -1324 D8C6 20 3A 20 24 BDOSDRV:.TEXT " : $" -1325 D8CA 426164205365BADSEC: .TEXT "Bad Sector$" -1325 D8D0 63746F7224 -1326 D8D5 53656C656374BADSEL: .TEXT "Select$" -1326 D8DB 24 -1327 D8DC 46696C6520 FILERO: .TEXT "File " -1328 D8E1 52 2F 4F 24 DISKRO: .TEXT "R/O$" -1329 D8E5 ; -1330 D8E5 ; Print bdos error message. -1331 D8E5 ; -1332 D8E5 E5 PRTERR: PUSH HL ;save second message pointer. -1333 D8E6 CD C9 D9 CALL OUTCRLF ;send (cr)(lf). -1334 D8E9 3A 42 DB LD A,(ACTIVE) ;get active drive. -1335 D8EC C6 41 ADD A,'A' ;make ascii. -1336 D8EE 32 C6 D8 LD (BDOSDRV),A ;and put in message. -1337 D8F1 01 BA D8 LD BC,BDOSERR ;and print it. -1338 D8F4 CD D3 D9 CALL PRTMESG -1339 D8F7 C1 POP BC ;print second message line now. -1340 D8F8 CD D3 D9 CALL PRTMESG -1341 D8FB ; -1342 D8FB ; Get an input character. We will check our 1 character -1343 D8FB ; buffer first. This may be set by the console status routine. -1344 D8FB ; -1345 D8FB 21 0E DB GETCHAR:LD HL,CHARBUF ;check character buffer. -1346 D8FE 7E LD A,(HL) ;anything present already? -1347 D8FF 36 00 LD (HL),0 ;...either case clear it. -1348 D901 B7 OR A -1349 D902 C0 RET NZ ;yes, use it. -1350 D903 C3 09 E6 JP CONIN ;nope, go get a character responce. -1351 D906 ; -1352 D906 ; Input and echo a character. -1353 D906 ; -1354 D906 CD FB D8 GETECHO:CALL GETCHAR ;input a character. -1355 D909 CD 14 D9 CALL CHKCHAR ;carriage control? -1356 D90C D8 RET C ;no, a regular control char so don't echo. -1357 D90D F5 PUSH AF ;ok, save character now. -1358 D90E 4F LD C,A -1359 D90F CD 90 D9 CALL OUTCON ;and echo it. -1360 D912 F1 POP AF ;get character and return. -1361 D913 C9 RET -1362 D914 ; -1363 D914 ; Check character in (A). Set the zero flag on a carriage -1364 D914 ; control character and the carry flag on any other control -1365 D914 ; character. -1366 D914 ; -1367 D914 FE 0D CHKCHAR:CP CR ;check for carriage return, line feed, backspace, -1368 D916 C8 RET Z ;or a tab. -1369 D917 FE 0A CP LF -1370 D919 C8 RET Z -1371 D91A FE 09 CP TAB -1372 D91C C8 RET Z -1373 D91D FE 08 CP BS -1374 D91F C8 RET Z -1375 D920 FE 20 CP ' ' ;other control char? Set carry flag. -1376 D922 C9 RET -1377 D923 ; -1378 D923 ; Check the console during output. Halt on a control-s, then -1379 D923 ; reboot on a control-c. If anything else is ready, clear the -1380 D923 ; zero flag and return (the calling routine may want to do -1381 D923 ; something). -1382 D923 ; -1383 D923 3A 0E DB CKCONSOL: LD A,(CHARBUF) ;check buffer. -1384 D926 B7 OR A ;if anything, just return without checking. -1385 D927 C2 45 D9 JP NZ,CKCON2 -1386 D92A CD 06 E6 CALL CONST ;nothing in buffer. Check console. -1387 D92D E6 01 AND 01H ;look at bit 0. -1388 D92F C8 RET Z ;return if nothing. -1389 D930 CD 09 E6 CALL CONIN ;ok, get it. -1390 D933 FE 13 CP CNTRLS ;if not control-s, return with zero cleared. -1391 D935 C2 42 D9 JP NZ,CKCON1 -1392 D938 CD 09 E6 CALL CONIN ;halt processing until another char -1393 D93B FE 03 CP CNTRLC ;is typed. Control-c? -1394 D93D CA 00 00 JP Z,0 ;yes, reboot now. -1395 D940 AF XOR A ;no, just pretend nothing was ever ready. -1396 D941 C9 RET -1397 D942 32 0E DB CKCON1: LD (CHARBUF),A ;save character in buffer for later processing. -1398 D945 3E 01 CKCON2: LD A,1 ;set (A) to non zero to mean something is ready. -1399 D947 C9 RET -1400 D948 ; -1401 D948 ; Output (C) to the screen. If the printer flip-flop flag -1402 D948 ; is set, we will send character to printer also. The console -1403 D948 ; will be checked in the process. -1404 D948 ; -1405 D948 3A 0A DB OUTCHAR:LD A,(OUTFLAG) ;check output flag. -1406 D94B B7 OR A ;anything and we won't generate output. -1407 D94C C2 62 D9 JP NZ,OUTCHR1 -1408 D94F C5 PUSH BC -1409 D950 CD 23 D9 CALL CKCONSOL ;check console (we don't care whats there). -1410 D953 C1 POP BC -1411 D954 C5 PUSH BC -1412 D955 CD 0C E6 CALL CONOUT ;output (C) to the screen. -1413 D958 C1 POP BC -1414 D959 C5 PUSH BC -1415 D95A 3A 0D DB LD A,(PRTFLAG) ;check printer flip-flop flag. -1416 D95D B7 OR A -1417 D95E C4 0F E6 CALL NZ,LIST ;print it also if non-zero. -1418 D961 C1 POP BC -1419 D962 79 OUTCHR1:LD A,C ;update cursors position. -1420 D963 21 0C DB LD HL,CURPOS -1421 D966 FE 7F CP DEL ;rubouts don't do anything here. -1422 D968 C8 RET Z -1423 D969 34 INC (HL) ;bump line pointer. -1424 D96A FE 20 CP ' ' ;and return if a normal character. -1425 D96C D0 RET NC -1426 D96D 35 DEC (HL) ;restore and check for the start of the line. -1427 D96E 7E LD A,(HL) -1428 D96F B7 OR A -1429 D970 C8 RET Z ;ingnore control characters at the start of the line. -1430 D971 79 LD A,C -1431 D972 FE 08 CP BS ;is it a backspace? -1432 D974 C2 79 D9 JP NZ,OUTCHR2 -1433 D977 35 DEC (HL) ;yes, backup pointer. -1434 D978 C9 RET -1435 D979 FE 0A OUTCHR2:CP LF ;is it a line feed? -1436 D97B C0 RET NZ ;ignore anything else. -1437 D97C 36 00 LD (HL),0 ;reset pointer to start of line. -1438 D97E C9 RET -1439 D97F ; -1440 D97F ; Output (A) to the screen. If it is a control character -1441 D97F ; (other than carriage control), use ^x format. -1442 D97F ; -1443 D97F 79 SHOWIT: LD A,C -1444 D980 CD 14 D9 CALL CHKCHAR ;check character. -1445 D983 D2 90 D9 JP NC,OUTCON ;not a control, use normal output. -1446 D986 F5 PUSH AF -1447 D987 0E 5E LD C,'^' ;for a control character, preceed it with '^'. -1448 D989 CD 48 D9 CALL OUTCHAR -1449 D98C F1 POP AF -1450 D98D F6 40 OR '@' ;and then use the letter equivelant. -1451 D98F 4F LD C,A -1452 D990 ; -1453 D990 ; Function to output (C) to the console device and expand tabs -1454 D990 ; if necessary. -1455 D990 ; -1456 D990 79 OUTCON: LD A,C -1457 D991 FE 09 CP TAB ;is it a tab? -1458 D993 C2 48 D9 JP NZ,OUTCHAR ;use regular output. -1459 D996 0E 20 OUTCON1:LD C,' ' ;yes it is, use spaces instead. -1460 D998 CD 48 D9 CALL OUTCHAR -1461 D99B 3A 0C DB LD A,(CURPOS) ;go until the cursor is at a multiple of 8 -1462 D99E -1463 D99E E6 07 AND 07H ;position. -1464 D9A0 C2 96 D9 JP NZ,OUTCON1 -1465 D9A3 C9 RET -1466 D9A4 ; -1467 D9A4 ; Echo a backspace character. Erase the prevoius character -1468 D9A4 ; on the screen. -1469 D9A4 ; -1470 D9A4 CD AC D9 BACKUP: CALL BACKUP1 ;backup the screen 1 place. -1471 D9A7 0E 20 LD C,' ' ;then blank that character. -1472 D9A9 CD 0C E6 CALL CONOUT -1473 D9AC 0E 08 BACKUP1:LD C,BS ;then back space once more. -1474 D9AE C3 0C E6 JP CONOUT -1475 D9B1 ; -1476 D9B1 ; Signal a deleted line. Print a '#' at the end and start -1477 D9B1 ; over. -1478 D9B1 ; -1479 D9B1 0E 23 NEWLINE:LD C,'#' -1480 D9B3 CD 48 D9 CALL OUTCHAR ;print this. -1481 D9B6 CD C9 D9 CALL OUTCRLF ;start new line. -1482 D9B9 3A 0C DB NEWLN1: LD A,(CURPOS) ;move the cursor to the starting position. -1483 D9BC 21 0B DB LD HL,STARTING -1484 D9BF BE CP (HL) -1485 D9C0 D0 RET NC ;there yet? -1486 D9C1 0E 20 LD C,' ' -1487 D9C3 CD 48 D9 CALL OUTCHAR ;nope, keep going. -1488 D9C6 C3 B9 D9 JP NEWLN1 -1489 D9C9 ; -1490 D9C9 ; Output a (cr) (lf) to the console device (screen). -1491 D9C9 ; -1492 D9C9 0E 0D OUTCRLF:LD C,CR -1493 D9CB CD 48 D9 CALL OUTCHAR -1494 D9CE 0E 0A LD C,LF -1495 D9D0 C3 48 D9 JP OUTCHAR -1496 D9D3 ; -1497 D9D3 ; Print message pointed to by (BC). It will end with a '$'. -1498 D9D3 ; -1499 D9D3 0A PRTMESG:LD A,(BC) ;check for terminating character. -1500 D9D4 FE 24 CP '$' -1501 D9D6 C8 RET Z -1502 D9D7 03 INC BC -1503 D9D8 C5 PUSH BC ;otherwise, bump pointer and print it. -1504 D9D9 4F LD C,A -1505 D9DA CD 90 D9 CALL OUTCON -1506 D9DD C1 POP BC -1507 D9DE C3 D3 D9 JP PRTMESG -1508 D9E1 ; -1509 D9E1 ; Function to execute a buffered read. -1510 D9E1 ; -1511 D9E1 3A 0C DB RDBUFF: LD A,(CURPOS) ;use present location as starting one. -1512 D9E4 32 0B DB LD (STARTING),A -1513 D9E7 2A 43 DB LD HL,(PARAMS) ;get the maximum buffer space. -1514 D9EA 4E LD C,(HL) -1515 D9EB 23 INC HL ;point to first available space. -1516 D9EC E5 PUSH HL ;and save. -1517 D9ED 06 00 LD B,0 ;keep a character count. -1518 D9EF C5 RDBUF1: PUSH BC -1519 D9F0 E5 PUSH HL -1520 D9F1 CD FB D8 RDBUF2: CALL GETCHAR ;get the next input character. -1521 D9F4 E6 7F AND 7FH ;strip bit 7. -1522 D9F6 E1 POP HL ;reset registers. -1523 D9F7 C1 POP BC -1524 D9F8 FE 0D CP CR ;en of the line? -1525 D9FA CA C1 DA JP Z,RDBUF17 -1526 D9FD FE 0A CP LF -1527 D9FF CA C1 DA JP Z,RDBUF17 -1528 DA02 FE 08 CP BS ;how about a backspace? -1529 DA04 C2 16 DA JP NZ,RDBUF3 -1530 DA07 78 LD A,B ;yes, but ignore at the beginning of the line. -1531 DA08 B7 OR A -1532 DA09 CA EF D9 JP Z,RDBUF1 -1533 DA0C 05 DEC B ;ok, update counter. -1534 DA0D 3A 0C DB LD A,(CURPOS) ;if we backspace to the start of the line, -1535 DA10 32 0A DB LD (OUTFLAG),A ;treat as a cancel (control-x). -1536 DA13 C3 70 DA JP RDBUF10 -1537 DA16 FE 7F RDBUF3: CP DEL ;user typed a rubout? -1538 DA18 C2 26 DA JP NZ,RDBUF4 -1539 DA1B 78 LD A,B ;ignore at the start of the line. -1540 DA1C B7 OR A -1541 DA1D CA EF D9 JP Z,RDBUF1 -1542 DA20 7E LD A,(HL) ;ok, echo the prevoius character. -1543 DA21 05 DEC B ;and reset pointers (counters). -1544 DA22 2B DEC HL -1545 DA23 C3 A9 DA JP RDBUF15 -1546 DA26 FE 05 RDBUF4: CP CNTRLE ;physical end of line? -1547 DA28 C2 37 DA JP NZ,RDBUF5 -1548 DA2B C5 PUSH BC ;yes, do it. -1549 DA2C E5 PUSH HL -1550 DA2D CD C9 D9 CALL OUTCRLF -1551 DA30 AF XOR A ;and update starting position. -1552 DA31 32 0B DB LD (STARTING),A -1553 DA34 C3 F1 D9 JP RDBUF2 -1554 DA37 FE 10 RDBUF5: CP CNTRLP ;control-p? -1555 DA39 C2 48 DA JP NZ,RDBUF6 -1556 DA3C E5 PUSH HL ;yes, flip the print flag filp-flop byte. -1557 DA3D 21 0D DB LD HL,PRTFLAG -1558 DA40 3E 01 LD A,1 ;PRTFLAG=1-PRTFLAG -1559 DA42 96 SUB (HL) -1560 DA43 77 LD (HL),A -1561 DA44 E1 POP HL -1562 DA45 C3 EF D9 JP RDBUF1 -1563 DA48 FE 18 RDBUF6: CP CNTRLX ;control-x (cancel)? -1564 DA4A C2 5F DA JP NZ,RDBUF8 -1565 DA4D E1 POP HL -1566 DA4E 3A 0B DB RDBUF7: LD A,(STARTING) ;yes, backup the cursor to here. -1567 DA51 21 0C DB LD HL,CURPOS -1568 DA54 BE CP (HL) -1569 DA55 D2 E1 D9 JP NC,RDBUFF ;done yet? -1570 DA58 35 DEC (HL) ;no, decrement pointer and output back up one space. -1571 DA59 CD A4 D9 CALL BACKUP -1572 DA5C C3 4E DA JP RDBUF7 -1573 DA5F FE 15 RDBUF8: CP CNTRLU ;cntrol-u (cancel line)? -1574 DA61 C2 6B DA JP NZ,RDBUF9 -1575 DA64 CD B1 D9 CALL NEWLINE ;start a new line. -1576 DA67 E1 POP HL -1577 DA68 C3 E1 D9 JP RDBUFF -1578 DA6B FE 12 RDBUF9: CP CNTRLR ;control-r? -1579 DA6D C2 A6 DA JP NZ,RDBUF14 -1580 DA70 C5 RDBUF10:PUSH BC ;yes, start a new line and retype the old one. -1581 DA71 CD B1 D9 CALL NEWLINE -1582 DA74 C1 POP BC -1583 DA75 E1 POP HL -1584 DA76 E5 PUSH HL -1585 DA77 C5 PUSH BC -1586 DA78 78 RDBUF11:LD A,B ;done whole line yet? -1587 DA79 B7 OR A -1588 DA7A CA 8A DA JP Z,RDBUF12 -1589 DA7D 23 INC HL ;nope, get next character. -1590 DA7E 4E LD C,(HL) -1591 DA7F 05 DEC B ;count it. -1592 DA80 C5 PUSH BC -1593 DA81 E5 PUSH HL -1594 DA82 CD 7F D9 CALL SHOWIT ;and display it. -1595 DA85 E1 POP HL -1596 DA86 C1 POP BC -1597 DA87 C3 78 DA JP RDBUF11 -1598 DA8A E5 RDBUF12:PUSH HL ;done with line. If we were displaying -1599 DA8B 3A 0A DB LD A,(OUTFLAG) ;then update cursor position. -1600 DA8E B7 OR A -1601 DA8F CA F1 D9 JP Z,RDBUF2 -1602 DA92 21 0C DB LD HL,CURPOS ;because this line is shorter, we must -1603 DA95 96 SUB (HL) ;back up the cursor (not the screen however) -1604 DA96 32 0A DB LD (OUTFLAG),A ;some number of positions. -1605 DA99 CD A4 D9 RDBUF13:CALL BACKUP ;note that as long as (OUTFLAG) is non -1606 DA9C 21 0A DB LD HL,OUTFLAG ;zero, the screen will not be changed. -1607 DA9F 35 DEC (HL) -1608 DAA0 C2 99 DA JP NZ,RDBUF13 -1609 DAA3 C3 F1 D9 JP RDBUF2 ;now just get the next character. -1610 DAA6 ; -1611 DAA6 ; Just a normal character, put this in our buffer and echo. -1612 DAA6 ; -1613 DAA6 23 RDBUF14:INC HL -1614 DAA7 77 LD (HL),A ;store character. -1615 DAA8 04 INC B ;and count it. -1616 DAA9 C5 RDBUF15:PUSH BC -1617 DAAA E5 PUSH HL -1618 DAAB 4F LD C,A ;echo it now. -1619 DAAC CD 7F D9 CALL SHOWIT -1620 DAAF E1 POP HL -1621 DAB0 C1 POP BC -1622 DAB1 7E LD A,(HL) ;was it an abort request? -1623 DAB2 FE 03 CP CNTRLC ;control-c abort? -1624 DAB4 78 LD A,B -1625 DAB5 C2 BD DA JP NZ,RDBUF16 -1626 DAB8 FE 01 CP 1 ;only if at start of line. -1627 DABA CA 00 00 JP Z,0 -1628 DABD B9 RDBUF16:CP C ;nope, have we filled the buffer? -1629 DABE DA EF D9 JP C,RDBUF1 -1630 DAC1 E1 RDBUF17:POP HL ;yes end the line and return. -1631 DAC2 70 LD (HL),B -1632 DAC3 0E 0D LD C,CR -1633 DAC5 C3 48 D9 JP OUTCHAR ;output (cr) and return. -1634 DAC8 ; -1635 DAC8 ; Function to get a character from the console device. -1636 DAC8 ; -1637 DAC8 CD 06 D9 GETCON: CALL GETECHO ;get and echo. -1638 DACB C3 01 DB JP SETSTAT ;save status and return. -1639 DACE ; -1640 DACE ; Function to get a character from the tape reader device. -1641 DACE ; -1642 DACE CD 15 E6 GETRDR: CALL READER ;get a character from reader, set status and return. -1643 DAD1 C3 01 DB JP SETSTAT -1644 DAD4 ; -1645 DAD4 ; Function to perform direct console i/o. If (C) contains (FF) -1646 DAD4 ; then this is an input request. If (C) contains (FE) then -1647 DAD4 ; this is a status request. Otherwise we are to output (C). -1648 DAD4 ; -1649 DAD4 79 DIRCIO: LD A,C ;test for (FF). -1650 DAD5 3C INC A -1651 DAD6 CA E0 DA JP Z,DIRC1 -1652 DAD9 3C INC A ;test for (FE). -1653 DADA CA 06 E6 JP Z,CONST -1654 DADD C3 0C E6 JP CONOUT ;just output (C). -1655 DAE0 CD 06 E6 DIRC1: CALL CONST ;this is an input request. -1656 DAE3 B7 OR A -1657 DAE4 CA 91 E5 JP Z,GOBACK1 ;not ready? Just return (directly). -1658 DAE7 CD 09 E6 CALL CONIN ;yes, get character. -1659 DAEA C3 01 DB JP SETSTAT ;set status and return. -1660 DAED ; -1661 DAED ; Function to return the i/o byte. -1662 DAED ; -1663 DAED 3A 03 00 GETIOB: LD A,(IOBYTE) -1664 DAF0 C3 01 DB JP SETSTAT -1665 DAF3 ; -1666 DAF3 ; Function to set the i/o byte. -1667 DAF3 ; -1668 DAF3 21 03 00 SETIOB: LD HL,IOBYTE -1669 DAF6 71 LD (HL),C -1670 DAF7 C9 RET -1671 DAF8 ; -1672 DAF8 ; Function to print the character string pointed to by (DE) -1673 DAF8 ; on the console device. The string ends with a '$'. -1674 DAF8 ; -1675 DAF8 EB PRTSTR: EX DE,HL -1676 DAF9 4D LD C,L -1677 DAFA 44 LD B,H ;now (BC) points to it. -1678 DAFB C3 D3 D9 JP PRTMESG -1679 DAFE ; -1680 DAFE ; Function to interigate the console device. -1681 DAFE ; -1682 DAFE CD 23 D9 GETCSTS:CALL CKCONSOL -1683 DB01 ; -1684 DB01 ; Get here to set the status and return to the cleanup -1685 DB01 ; section. Then back to the user. -1686 DB01 ; -1687 DB01 32 45 DB SETSTAT:LD (STATUS),A -1688 DB04 C9 RTN: RET -1689 DB05 ; -1690 DB05 ; Set the status to 1 (read or write error code). -1691 DB05 ; -1692 DB05 3E 01 IOERR1: LD A,1 -1693 DB07 C3 01 DB JP SETSTAT -1694 DB0A ; -1695 DB0A 00 OUTFLAG:.DB 0 ;output flag (non zero means no output). -1696 DB0B 02 STARTING: .DB 2 ;starting position for cursor. -1697 DB0C 00 CURPOS: .DB 0 ;cursor position (0=start of line). -1698 DB0D 00 PRTFLAG:.DB 0 ;printer flag (control-p toggle). List if non zero. -1699 DB0E 00 CHARBUF:.DB 0 ;single input character buffer. -1700 DB0F ; -1701 DB0F ; Stack area for BDOS calls. -1702 DB0F ; -1703 DB0F 00 00 USRSTACK: .DW 0 ;save users stack pointer here. -1704 DB11 ; -1705 DB11 000000000000 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -1705 DB17 000000000000000000000000000000000000 -1706 DB29 000000000000 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -1706 DB2F 000000000000000000000000000000000000 -1707 DB41 STKAREA .EQU $ ;end of stack area. -1708 DB41 ; -1709 DB41 00 USERNO: .DB 0 ;current user number. -1710 DB42 00 ACTIVE: .DB 0 ;currently active drive. -1711 DB43 00 00 PARAMS: .DW 0 ;save (DE) parameters here on entry. -1712 DB45 00 00 STATUS: .DW 0 ;status returned from bdos function. -1713 DB47 ; -1714 DB47 ; Select error occured, jump to error routine. -1715 DB47 ; -1716 DB47 21 0B D8 SLCTERR:LD HL,BADSLCT -1717 DB4A ; -1718 DB4A ; Jump to (HL) indirectly. -1719 DB4A ; -1720 DB4A 5E JUMPHL: LD E,(HL) -1721 DB4B 23 INC HL -1722 DB4C 56 LD D,(HL) ;now (DE) contain the desired address. -1723 DB4D EB EX DE,HL -1724 DB4E E9 JP (HL) -1725 DB4F ; -1726 DB4F ; Block move. (DE) to (HL), (C) bytes total. -1727 DB4F ; -1728 DB4F 0C DE2HL: INC C ;is count down to zero? -1729 DB50 0D DE2HL1: DEC C -1730 DB51 C8 RET Z ;yes, we are done. -1731 DB52 1A LD A,(DE) ;no, move one more byte. -1732 DB53 77 LD (HL),A -1733 DB54 13 INC DE -1734 DB55 23 INC HL -1735 DB56 C3 50 DB JP DE2HL1 ;and repeat. -1736 DB59 ; -1737 DB59 ; Select the desired drive. -1738 DB59 ; -1739 DB59 3A 42 DB SELECT: LD A,(ACTIVE) ;get active disk. -1740 DB5C 4F LD C,A -1741 DB5D CD 1B E6 CALL SELDSK ;select it. -1742 DB60 7C LD A,H ;valid drive? -1743 DB61 B5 OR L ;valid drive? -1744 DB62 C8 RET Z ;return if not. -1745 DB63 ; -1746 DB63 ; Here, the BIOS returned the address of the parameter block -1747 DB63 ; in (HL). We will extract the necessary pointers and save them. -1748 DB63 ; -1749 DB63 5E LD E,(HL) ;yes, get address of translation table into (DE). -1750 DB64 23 INC HL -1751 DB65 56 LD D,(HL) -1752 DB66 23 INC HL -1753 DB67 22 B3 E5 LD (SCRATCH1),HL ;save pointers to scratch areas. -1754 DB6A 23 INC HL -1755 DB6B 23 INC HL -1756 DB6C 22 B5 E5 LD (SCRATCH2),HL ;ditto. -1757 DB6F 23 INC HL -1758 DB70 23 INC HL -1759 DB71 22 B7 E5 LD (SCRATCH3),HL ;ditto. -1760 DB74 23 INC HL -1761 DB75 23 INC HL -1762 DB76 EB EX DE,HL ;now save the translation table address. -1763 DB77 22 D0 E5 LD (XLATE),HL -1764 DB7A 21 B9 E5 LD HL,DIRBUF ;put the next 8 bytes here. -1765 DB7D 0E 08 LD C,8 ;they consist of the directory buffer -1766 DB7F CD 4F DB CALL DE2HL ;pointer, parameter block pointer, -1767 DB82 2A BB E5 LD HL,(DISKPB) ;check and allocation vectors. -1768 DB85 EB EX DE,HL -1769 DB86 21 C1 E5 LD HL,SECTORS ;move parameter block into our ram. -1770 DB89 0E 0F LD C,15 ;it is 15 bytes long. -1771 DB8B CD 4F DB CALL DE2HL -1772 DB8E 2A C6 E5 LD HL,(DSKSIZE) ;check disk size. -1773 DB91 7C LD A,H ;more than 256 blocks on this? -1774 DB92 21 DD E5 LD HL,BIGDISK -1775 DB95 36 FF LD (HL),0FFH ;set to samll. -1776 DB97 B7 OR A -1777 DB98 CA 9D DB JP Z,SELECT1 -1778 DB9B 36 00 LD (HL),0 ;wrong, set to large. -1779 DB9D 3E FF SELECT1:LD A,0FFH ;clear the zero flag. -1780 DB9F B7 OR A -1781 DBA0 C9 RET -1782 DBA1 ; -1783 DBA1 ; Routine to home the disk track head and clear pointers. -1784 DBA1 ; -1785 DBA1 CD 18 E6 HOMEDRV:CALL HOME ;home the head. -1786 DBA4 AF XOR A -1787 DBA5 2A B5 E5 LD HL,(SCRATCH2) ;set our track pointer also. -1788 DBA8 77 LD (HL),A -1789 DBA9 23 INC HL -1790 DBAA 77 LD (HL),A -1791 DBAB 2A B7 E5 LD HL,(SCRATCH3) ;and our sector pointer. -1792 DBAE 77 LD (HL),A -1793 DBAF 23 INC HL -1794 DBB0 77 LD (HL),A -1795 DBB1 C9 RET -1796 DBB2 ; -1797 DBB2 ; Do the actual disk read and check the error return status. -1798 DBB2 ; -1799 DBB2 CD 27 E6 DOREAD: CALL READ -1800 DBB5 C3 BB DB JP IORET -1801 DBB8 ; -1802 DBB8 ; Do the actual disk write and handle any bios error. -1803 DBB8 ; -1804 DBB8 CD 2A E6 DOWRITE:CALL WRITE -1805 DBBB B7 IORET: OR A -1806 DBBC C8 RET Z ;return unless an error occured. -1807 DBBD 21 09 D8 LD HL,BADSCTR ;bad read/write on this sector. -1808 DBC0 C3 4A DB JP JUMPHL -1809 DBC3 ; -1810 DBC3 ; Routine to select the track and sector that the desired -1811 DBC3 ; block number falls in. -1812 DBC3 ; -1813 DBC3 2A EA E5 TRKSEC: LD HL,(FILEPOS) ;get position of last accessed file -1814 DBC6 0E 02 LD C,2 ;in directory and compute sector #. -1815 DBC8 CD EA DC CALL SHIFTR ;sector #=file-position/4. -1816 DBCB 22 E5 E5 LD (BLKNMBR),HL ;save this as the block number of interest. -1817 DBCE 22 EC E5 LD (CKSUMTBL),HL ;what's it doing here too? -1818 DBD1 ; -1819 DBD1 ; if the sector number has already been set (BLKNMBR), enter -1820 DBD1 ; at this point. -1821 DBD1 ; -1822 DBD1 21 E5 E5 TRKSEC1:LD HL,BLKNMBR -1823 DBD4 4E LD C,(HL) ;move sector number into (BC). -1824 DBD5 23 INC HL -1825 DBD6 46 LD B,(HL) -1826 DBD7 2A B7 E5 LD HL,(SCRATCH3) ;get current sector number and -1827 DBDA 5E LD E,(HL) ;move this into (DE). -1828 DBDB 23 INC HL -1829 DBDC 56 LD D,(HL) -1830 DBDD 2A B5 E5 LD HL,(SCRATCH2) ;get current track number. -1831 DBE0 7E LD A,(HL) ;and this into (HL). -1832 DBE1 23 INC HL -1833 DBE2 66 LD H,(HL) -1834 DBE3 6F LD L,A -1835 DBE4 79 TRKSEC2:LD A,C ;is desired sector before current one? -1836 DBE5 93 SUB E -1837 DBE6 78 LD A,B -1838 DBE7 9A SBC A,D -1839 DBE8 D2 FA DB JP NC,TRKSEC3 -1840 DBEB E5 PUSH HL ;yes, decrement sectors by one track. -1841 DBEC 2A C1 E5 LD HL,(SECTORS) ;get sectors per track. -1842 DBEF 7B LD A,E -1843 DBF0 95 SUB L -1844 DBF1 5F LD E,A -1845 DBF2 7A LD A,D -1846 DBF3 9C SBC A,H -1847 DBF4 57 LD D,A ;now we have backed up one full track. -1848 DBF5 E1 POP HL -1849 DBF6 2B DEC HL ;adjust track counter. -1850 DBF7 C3 E4 DB JP TRKSEC2 -1851 DBFA E5 TRKSEC3:PUSH HL ;desired sector is after current one. -1852 DBFB 2A C1 E5 LD HL,(SECTORS) ;get sectors per track. -1853 DBFE 19 ADD HL,DE ;bump sector pointer to next track. -1854 DBFF DA 0F DC JP C,TRKSEC4 -1855 DC02 79 LD A,C ;is desired sector now before current one? -1856 DC03 95 SUB L -1857 DC04 78 LD A,B -1858 DC05 9C SBC A,H -1859 DC06 DA 0F DC JP C,TRKSEC4 -1860 DC09 EB EX DE,HL ;not yes, increment track counter -1861 DC0A E1 POP HL ;and continue until it is. -1862 DC0B 23 INC HL -1863 DC0C C3 FA DB JP TRKSEC3 -1864 DC0F ; -1865 DC0F ; here we have determined the track number that contains the -1866 DC0F ; desired sector. -1867 DC0F ; -1868 DC0F E1 TRKSEC4:POP HL ;get track number (HL). -1869 DC10 C5 PUSH BC -1870 DC11 D5 PUSH DE -1871 DC12 E5 PUSH HL -1872 DC13 EB EX DE,HL -1873 DC14 2A CE E5 LD HL,(OFFSET) ;adjust for first track offset. -1874 DC17 19 ADD HL,DE -1875 DC18 44 LD B,H -1876 DC19 4D LD C,L -1877 DC1A CD 1E E6 CALL SETTRK ;select this track. -1878 DC1D D1 POP DE ;reset current track pointer. -1879 DC1E 2A B5 E5 LD HL,(SCRATCH2) -1880 DC21 73 LD (HL),E -1881 DC22 23 INC HL -1882 DC23 72 LD (HL),D -1883 DC24 D1 POP DE -1884 DC25 2A B7 E5 LD HL,(SCRATCH3) ;reset the first sector on this track. -1885 DC28 73 LD (HL),E -1886 DC29 23 INC HL -1887 DC2A 72 LD (HL),D -1888 DC2B C1 POP BC -1889 DC2C 79 LD A,C ;now subtract the desired one. -1890 DC2D 93 SUB E ;to make it relative (1-# sectors/track). -1891 DC2E 4F LD C,A -1892 DC2F 78 LD A,B -1893 DC30 9A SBC A,D -1894 DC31 47 LD B,A -1895 DC32 2A D0 E5 LD HL,(XLATE) ;translate this sector according to this table. -1896 DC35 EB EX DE,HL -1897 DC36 CD 30 E6 CALL SECTRN ;let the bios translate it. -1898 DC39 4D LD C,L -1899 DC3A 44 LD B,H -1900 DC3B C3 21 E6 JP SETSEC ;and select it. -1901 DC3E ; -1902 DC3E ; Compute block number from record number (SAVNREC) and -1903 DC3E ; extent number (SAVEXT). -1904 DC3E ; -1905 DC3E 21 C3 E5 GETBLOCK: LD HL,BLKSHFT ;get logical to physical conversion. -1906 DC41 4E LD C,(HL) ;note that this is base 2 log of ratio. -1907 DC42 3A E3 E5 LD A,(SAVNREC) ;get record number. -1908 DC45 B7 GETBLK1:OR A ;compute (A)=(A)/2^BLKSHFT. -1909 DC46 1F RRA -1910 DC47 0D DEC C -1911 DC48 C2 45 DC JP NZ,GETBLK1 -1912 DC4B 47 LD B,A ;save result in (B). -1913 DC4C 3E 08 LD A,8 -1914 DC4E 96 SUB (HL) -1915 DC4F 4F LD C,A ;compute (C)=8-BLKSHFT. -1916 DC50 3A E2 E5 LD A,(SAVEXT) -1917 DC53 0D GETBLK2:DEC C ;compute (A)=SAVEXT*2^(8-BLKSHFT). -1918 DC54 CA 5C DC JP Z,GETBLK3 -1919 DC57 B7 OR A -1920 DC58 17 RLA -1921 DC59 C3 53 DC JP GETBLK2 -1922 DC5C 80 GETBLK3:ADD A,B -1923 DC5D C9 RET -1924 DC5E ; -1925 DC5E ; Routine to extract the (BC) block byte from the fcb pointed -1926 DC5E ; to by (PARAMS). If this is a big-disk, then these are 16 bit -1927 DC5E ; block numbers, else they are 8 bit numbers. -1928 DC5E ; Number is returned in (HL). -1929 DC5E ; -1930 DC5E 2A 43 DB EXTBLK: LD HL,(PARAMS) ;get fcb address. -1931 DC61 11 10 00 LD DE,16 ;block numbers start 16 bytes into fcb. -1932 DC64 19 ADD HL,DE -1933 DC65 09 ADD HL,BC -1934 DC66 3A DD E5 LD A,(BIGDISK) ;are we using a big-disk? -1935 DC69 B7 OR A -1936 DC6A CA 71 DC JP Z,EXTBLK1 -1937 DC6D 6E LD L,(HL) ;no, extract an 8 bit number from the fcb. -1938 DC6E 26 00 LD H,0 -1939 DC70 C9 RET -1940 DC71 09 EXTBLK1:ADD HL,BC ;yes, extract a 16 bit number. -1941 DC72 5E LD E,(HL) -1942 DC73 23 INC HL -1943 DC74 56 LD D,(HL) -1944 DC75 EB EX DE,HL ;return in (HL). -1945 DC76 C9 RET -1946 DC77 ; -1947 DC77 ; Compute block number. -1948 DC77 ; -1949 DC77 CD 3E DC COMBLK: CALL GETBLOCK -1950 DC7A 4F LD C,A -1951 DC7B 06 00 LD B,0 -1952 DC7D CD 5E DC CALL EXTBLK -1953 DC80 22 E5 E5 LD (BLKNMBR),HL -1954 DC83 C9 RET -1955 DC84 ; -1956 DC84 ; Check for a zero block number (unused). -1957 DC84 ; -1958 DC84 2A E5 E5 CHKBLK: LD HL,(BLKNMBR) -1959 DC87 7D LD A,L ;is it zero? -1960 DC88 B4 OR H -1961 DC89 C9 RET -1962 DC8A ; -1963 DC8A ; Adjust physical block (BLKNMBR) and convert to logical -1964 DC8A ; sector (LOGSECT). This is the starting sector of this block. -1965 DC8A ; The actual sector of interest is then added to this and the -1966 DC8A ; resulting sector number is stored back in (BLKNMBR). This -1967 DC8A ; will still have to be adjusted for the track number. -1968 DC8A ; -1969 DC8A 3A C3 E5 LOGICAL:LD A,(BLKSHFT) ;get log2(physical/logical sectors). -1970 DC8D 2A E5 E5 LD HL,(BLKNMBR) ;get physical sector desired. -1971 DC90 29 LOGICL1:ADD HL,HL ;compute logical sector number. -1972 DC91 3D DEC A ;note logical sectors are 128 bytes long. -1973 DC92 C2 90 DC JP NZ,LOGICL1 -1974 DC95 22 E7 E5 LD (LOGSECT),HL ;save logical sector. -1975 DC98 3A C4 E5 LD A,(BLKMASK) ;get block mask. -1976 DC9B 4F LD C,A -1977 DC9C 3A E3 E5 LD A,(SAVNREC) ;get next sector to access. -1978 DC9F A1 AND C ;extract the relative position within physical block. -1979 DCA0 B5 OR L ;and add it too logical sector. -1980 DCA1 6F LD L,A -1981 DCA2 22 E5 E5 LD (BLKNMBR),HL ;and store. -1982 DCA5 C9 RET -1983 DCA6 ; -1984 DCA6 ; Set (HL) to point to extent byte in fcb. -1985 DCA6 ; -1986 DCA6 2A 43 DB SETEXT: LD HL,(PARAMS) -1987 DCA9 11 0C 00 LD DE,12 ;it is the twelth byte. -1988 DCAC 19 ADD HL,DE -1989 DCAD C9 RET -1990 DCAE ; -1991 DCAE ; Set (HL) to point to record count byte in fcb and (DE) to -1992 DCAE ; next record number byte. -1993 DCAE ; -1994 DCAE 2A 43 DB SETHLDE:LD HL,(PARAMS) -1995 DCB1 11 0F 00 LD DE,15 ;record count byte (#15). -1996 DCB4 19 ADD HL,DE -1997 DCB5 EB EX DE,HL -1998 DCB6 21 11 00 LD HL,17 ;next record number (#32). -1999 DCB9 19 ADD HL,DE -2000 DCBA C9 RET -2001 DCBB ; -2002 DCBB ; Save current file data from fcb. -2003 DCBB ; -2004 DCBB CD AE DC STRDATA:CALL SETHLDE -2005 DCBE 7E LD A,(HL) ;get and store record count byte. -2006 DCBF 32 E3 E5 LD (SAVNREC),A -2007 DCC2 EB EX DE,HL -2008 DCC3 7E LD A,(HL) ;get and store next record number byte. -2009 DCC4 32 E1 E5 LD (SAVNXT),A -2010 DCC7 CD A6 DC CALL SETEXT ;point to extent byte. -2011 DCCA 3A C5 E5 LD A,(EXTMASK) ;get extent mask. -2012 DCCD A6 AND (HL) -2013 DCCE 32 E2 E5 LD (SAVEXT),A ;and save extent here. -2014 DCD1 C9 RET -2015 DCD2 ; -2016 DCD2 ; Set the next record to access. If (MODE) is set to 2, then -2017 DCD2 ; the last record byte (SAVNREC) has the correct number to access. -2018 DCD2 ; For sequential access, (MODE) will be equal to 1. -2019 DCD2 ; -2020 DCD2 CD AE DC SETNREC:CALL SETHLDE -2021 DCD5 3A D5 E5 LD A,(MODE) ;get sequential flag (=1). -2022 DCD8 FE 02 CP 2 ;a 2 indicates that no adder is needed. -2023 DCDA C2 DE DC JP NZ,STNREC1 -2024 DCDD AF XOR A ;clear adder (random access?). -2025 DCDE 4F STNREC1:LD C,A -2026 DCDF 3A E3 E5 LD A,(SAVNREC) ;get last record number. -2027 DCE2 81 ADD A,C ;increment record count. -2028 DCE3 77 LD (HL),A ;and set fcb's next record byte. -2029 DCE4 EB EX DE,HL -2030 DCE5 3A E1 E5 LD A,(SAVNXT) ;get next record byte from storage. -2031 DCE8 77 LD (HL),A ;and put this into fcb as number of records used. -2032 DCE9 C9 RET -2033 DCEA ; -2034 DCEA ; Shift (HL) right (C) bits. -2035 DCEA ; -2036 DCEA 0C SHIFTR: INC C -2037 DCEB 0D SHIFTR1:DEC C -2038 DCEC C8 RET Z -2039 DCED 7C LD A,H -2040 DCEE B7 OR A -2041 DCEF 1F RRA -2042 DCF0 67 LD H,A -2043 DCF1 7D LD A,L -2044 DCF2 1F RRA -2045 DCF3 6F LD L,A -2046 DCF4 C3 EB DC JP SHIFTR1 -2047 DCF7 ; -2048 DCF7 ; Compute the check-sum for the directory buffer. Return -2049 DCF7 ; integer sum in (A). -2050 DCF7 ; -2051 DCF7 0E 80 CHECKSUM: LD C,128 ;length of buffer. -2052 DCF9 2A B9 E5 LD HL,(DIRBUF) ;get its location. -2053 DCFC AF XOR A ;clear summation byte. -2054 DCFD 86 CHKSUM1:ADD A,(HL) ;and compute sum ignoring carries. -2055 DCFE 23 INC HL -2056 DCFF 0D DEC C -2057 DD00 C2 FD DC JP NZ,CHKSUM1 -2058 DD03 C9 RET -2059 DD04 ; -2060 DD04 ; Shift (HL) left (C) bits. -2061 DD04 ; -2062 DD04 0C SHIFTL: INC C -2063 DD05 0D SHIFTL1:DEC C -2064 DD06 C8 RET Z -2065 DD07 29 ADD HL,HL ;shift left 1 bit. -2066 DD08 C3 05 DD JP SHIFTL1 -2067 DD0B ; -2068 DD0B ; Routine to set a bit in a 16 bit value contained in (BC). -2069 DD0B ; The bit set depends on the current drive selection. -2070 DD0B ; -2071 DD0B C5 SETBIT: PUSH BC ;save 16 bit word. -2072 DD0C 3A 42 DB LD A,(ACTIVE) ;get active drive. -2073 DD0F 4F LD C,A -2074 DD10 21 01 00 LD HL,1 -2075 DD13 CD 04 DD CALL SHIFTL ;shift bit 0 into place. -2076 DD16 C1 POP BC ;now 'or' this with the original word. -2077 DD17 79 LD A,C -2078 DD18 B5 OR L -2079 DD19 6F LD L,A ;low byte done, do high byte. -2080 DD1A 78 LD A,B -2081 DD1B B4 OR H -2082 DD1C 67 LD H,A -2083 DD1D C9 RET -2084 DD1E ; -2085 DD1E ; Extract the write protect status bit for the current drive. -2086 DD1E ; The result is returned in (A), bit 0. -2087 DD1E ; -2088 DD1E 2A AD E5 GETWPRT:LD HL,(WRTPRT) ;get status bytes. -2089 DD21 3A 42 DB LD A,(ACTIVE) ;which drive is current? -2090 DD24 4F LD C,A -2091 DD25 CD EA DC CALL SHIFTR ;shift status such that bit 0 is the -2092 DD28 7D LD A,L ;one of interest for this drive. -2093 DD29 E6 01 AND 01H ;and isolate it. -2094 DD2B C9 RET -2095 DD2C ; -2096 DD2C ; Function to write protect the current disk. -2097 DD2C ; -2098 DD2C 21 AD E5 WRTPRTD:LD HL,WRTPRT ;point to status word. -2099 DD2F 4E LD C,(HL) ;set (BC) equal to the status. -2100 DD30 23 INC HL -2101 DD31 46 LD B,(HL) -2102 DD32 CD 0B DD CALL SETBIT ;and set this bit according to current drive. -2103 DD35 22 AD E5 LD (WRTPRT),HL ;then save. -2104 DD38 2A C8 E5 LD HL,(DIRSIZE) ;now save directory size limit. -2105 DD3B 23 INC HL ;remember the last one. -2106 DD3C EB EX DE,HL -2107 DD3D 2A B3 E5 LD HL,(SCRATCH1) ;and store it here. -2108 DD40 73 LD (HL),E ;put low byte. -2109 DD41 23 INC HL -2110 DD42 72 LD (HL),D ;then high byte. -2111 DD43 C9 RET -2112 DD44 ; -2113 DD44 ; Check for a read only file. -2114 DD44 ; -2115 DD44 CD 5E DD CHKROFL:CALL FCB2HL ;set (HL) to file entry in directory buffer. -2116 DD47 11 09 00 CKROF1: LD DE,9 ;look at bit 7 of the ninth byte. -2117 DD4A 19 ADD HL,DE -2118 DD4B 7E LD A,(HL) -2119 DD4C 17 RLA -2120 DD4D D0 RET NC ;return if ok. -2121 DD4E 21 0F D8 LD HL,ROFILE ;else, print error message and terminate. -2122 DD51 C3 4A DB JP JUMPHL -2123 DD54 ; -2124 DD54 ; Check the write protect status of the active disk. -2125 DD54 ; -2126 DD54 CD 1E DD CHKWPRT:CALL GETWPRT -2127 DD57 C8 RET Z ;return if ok. -2128 DD58 21 0D D8 LD HL,RODISK ;else print message and terminate. -2129 DD5B C3 4A DB JP JUMPHL -2130 DD5E ; -2131 DD5E ; Routine to set (HL) pointing to the proper entry in the -2132 DD5E ; directory buffer. -2133 DD5E ; -2134 DD5E 2A B9 E5 FCB2HL: LD HL,(DIRBUF) ;get address of buffer. -2135 DD61 3A E9 E5 LD A,(FCBPOS) ;relative position of file. -2136 DD64 ; -2137 DD64 ; Routine to add (A) to (HL). -2138 DD64 ; -2139 DD64 85 ADDA2HL:ADD A,L -2140 DD65 6F LD L,A -2141 DD66 D0 RET NC -2142 DD67 24 INC H ;take care of any carry. -2143 DD68 C9 RET -2144 DD69 ; -2145 DD69 ; Routine to get the 's2' byte from the fcb supplied in -2146 DD69 ; the initial parameter specification. -2147 DD69 ; -2148 DD69 2A 43 DB GETS2: LD HL,(PARAMS) ;get address of fcb. -2149 DD6C 11 0E 00 LD DE,14 ;relative position of 's2'. -2150 DD6F 19 ADD HL,DE -2151 DD70 7E LD A,(HL) ;extract this byte. -2152 DD71 C9 RET -2153 DD72 ; -2154 DD72 ; Clear the 's2' byte in the fcb. -2155 DD72 ; -2156 DD72 CD 69 DD CLEARS2:CALL GETS2 ;this sets (HL) pointing to it. -2157 DD75 36 00 LD (HL),0 ;now clear it. -2158 DD77 C9 RET -2159 DD78 ; -2160 DD78 ; Set bit 7 in the 's2' byte of the fcb. -2161 DD78 ; -2162 DD78 CD 69 DD SETS2B7:CALL GETS2 ;get the byte. -2163 DD7B F6 80 OR 80H ;and set bit 7. -2164 DD7D 77 LD (HL),A ;then store. -2165 DD7E C9 RET -2166 DD7F ; -2167 DD7F ; Compare (FILEPOS) with (SCRATCH1) and set flags based on -2168 DD7F ; the difference. This checks to see if there are more file -2169 DD7F ; names in the directory. We are at (FILEPOS) and there are -2170 DD7F ; (SCRATCH1) of them to check. -2171 DD7F ; -2172 DD7F 2A EA E5 MOREFLS:LD HL,(FILEPOS) ;we are here. -2173 DD82 EB EX DE,HL -2174 DD83 2A B3 E5 LD HL,(SCRATCH1) ;and don't go past here. -2175 DD86 7B LD A,E ;compute difference but don't keep. -2176 DD87 96 SUB (HL) -2177 DD88 23 INC HL -2178 DD89 7A LD A,D -2179 DD8A 9E SBC A,(HL) ;set carry if no more names. -2180 DD8B C9 RET -2181 DD8C ; -2182 DD8C ; Call this routine to prevent (SCRATCH1) from being greater -2183 DD8C ; than (FILEPOS). -2184 DD8C ; -2185 DD8C CD 7F DD CHKNMBR:CALL MOREFLS ;SCRATCH1 too big? -2186 DD8F D8 RET C -2187 DD90 13 INC DE ;yes, reset it to (FILEPOS). -2188 DD91 72 LD (HL),D -2189 DD92 2B DEC HL -2190 DD93 73 LD (HL),E -2191 DD94 C9 RET -2192 DD95 ; -2193 DD95 ; Compute (HL)=(DE)-(HL) -2194 DD95 ; -2195 DD95 7B SUBHL: LD A,E ;compute difference. -2196 DD96 95 SUB L -2197 DD97 6F LD L,A ;store low byte. -2198 DD98 7A LD A,D -2199 DD99 9C SBC A,H -2200 DD9A 67 LD H,A ;and then high byte. -2201 DD9B C9 RET -2202 DD9C ; -2203 DD9C ; Set the directory checksum byte. -2204 DD9C ; -2205 DD9C 0E FF SETDIR: LD C,0FFH -2206 DD9E ; -2207 DD9E ; Routine to set or compare the directory checksum byte. If -2208 DD9E ; (C)=0ffh, then this will set the checksum byte. Else the byte -2209 DD9E ; will be checked. If the check fails (the disk has been changed), -2210 DD9E ; then this disk will be write protected. -2211 DD9E ; -2212 DD9E 2A EC E5 CHECKDIR: LD HL,(CKSUMTBL) -2213 DDA1 EB EX DE,HL -2214 DDA2 2A CC E5 LD HL,(ALLOC1) -2215 DDA5 CD 95 DD CALL SUBHL -2216 DDA8 D0 RET NC ;ok if (CKSUMTBL) > (ALLOC1), so return. -2217 DDA9 C5 PUSH BC -2218 DDAA CD F7 DC CALL CHECKSUM ;else compute checksum. -2219 DDAD 2A BD E5 LD HL,(CHKVECT) ;get address of checksum table. -2220 DDB0 EB EX DE,HL -2221 DDB1 2A EC E5 LD HL,(CKSUMTBL) -2222 DDB4 19 ADD HL,DE ;set (HL) to point to byte for this drive. -2223 DDB5 C1 POP BC -2224 DDB6 0C INC C ;set or check ? -2225 DDB7 CA C4 DD JP Z,CHKDIR1 -2226 DDBA BE CP (HL) ;check them. -2227 DDBB C8 RET Z ;return if they are the same. -2228 DDBC CD 7F DD CALL MOREFLS ;not the same, do we care? -2229 DDBF D0 RET NC -2230 DDC0 CD 2C DD CALL WRTPRTD ;yes, mark this as write protected. -2231 DDC3 C9 RET -2232 DDC4 77 CHKDIR1:LD (HL),A ;just set the byte. -2233 DDC5 C9 RET -2234 DDC6 ; -2235 DDC6 ; Do a write to the directory of the current disk. -2236 DDC6 ; -2237 DDC6 CD 9C DD DIRWRITE: CALL SETDIR ;set checksum byte. -2238 DDC9 CD E0 DD CALL DIRDMA ;set directory dma address. -2239 DDCC 0E 01 LD C,1 ;tell the bios to actually write. -2240 DDCE CD B8 DB CALL DOWRITE ;then do the write. -2241 DDD1 C3 DA DD JP DEFDMA -2242 DDD4 ; -2243 DDD4 ; Read from the directory. -2244 DDD4 ; -2245 DDD4 CD E0 DD DIRREAD:CALL DIRDMA ;set the directory dma address. -2246 DDD7 CD B2 DB CALL DOREAD ;and read it. -2247 DDDA ; -2248 DDDA ; Routine to set the dma address to the users choice. -2249 DDDA ; -2250 DDDA 21 B1 E5 DEFDMA: LD HL,USERDMA ;reset the default dma address and return. -2251 DDDD C3 E3 DD JP DIRDMA1 -2252 DDE0 ; -2253 DDE0 ; Routine to set the dma address for directory work. -2254 DDE0 ; -2255 DDE0 21 B9 E5 DIRDMA: LD HL,DIRBUF -2256 DDE3 ; -2257 DDE3 ; Set the dma address. On entry, (HL) points to -2258 DDE3 ; word containing the desired dma address. -2259 DDE3 ; -2260 DDE3 4E DIRDMA1:LD C,(HL) -2261 DDE4 23 INC HL -2262 DDE5 46 LD B,(HL) ;setup (BC) and go to the bios to set it. -2263 DDE6 C3 24 E6 JP SETDMA -2264 DDE9 ; -2265 DDE9 ; Move the directory buffer into user's dma space. -2266 DDE9 ; -2267 DDE9 2A B9 E5 MOVEDIR:LD HL,(DIRBUF) ;buffer is located here, and -2268 DDEC EB EX DE,HL -2269 DDED 2A B1 E5 LD HL,(USERDMA) ; put it here. -2270 DDF0 0E 80 LD C,128 ;this is its length. -2271 DDF2 C3 4F DB JP DE2HL ;move it now and return. -2272 DDF5 ; -2273 DDF5 ; Check (FILEPOS) and set the zero flag if it equals 0ffffh. -2274 DDF5 ; -2275 DDF5 21 EA E5 CKFILPOS: LD HL,FILEPOS -2276 DDF8 7E LD A,(HL) -2277 DDF9 23 INC HL -2278 DDFA BE CP (HL) ;are both bytes the same? -2279 DDFB C0 RET NZ -2280 DDFC 3C INC A ;yes, but are they each 0ffh? -2281 DDFD C9 RET -2282 DDFE ; -2283 DDFE ; Set location (FILEPOS) to 0ffffh. -2284 DDFE ; -2285 DDFE 21 FF FF STFILPOS: LD HL,0FFFFH -2286 DE01 22 EA E5 LD (FILEPOS),HL -2287 DE04 C9 RET -2288 DE05 ; -2289 DE05 ; Move on to the next file position within the current -2290 DE05 ; directory buffer. If no more exist, set pointer to 0ffffh -2291 DE05 ; and the calling routine will check for this. Enter with (C) -2292 DE05 ; equal to 0ffh to cause the checksum byte to be set, else we -2293 DE05 ; will check this disk and set write protect if checksums are -2294 DE05 ; not the same (applies only if another directory sector must -2295 DE05 ; be read). -2296 DE05 ; -2297 DE05 2A C8 E5 NXENTRY:LD HL,(DIRSIZE) ;get directory entry size limit. -2298 DE08 EB EX DE,HL -2299 DE09 2A EA E5 LD HL,(FILEPOS) ;get current count. -2300 DE0C 23 INC HL ;go on to the next one. -2301 DE0D 22 EA E5 LD (FILEPOS),HL -2302 DE10 CD 95 DD CALL SUBHL ;(HL)=(DIRSIZE)-(FILEPOS) -2303 DE13 D2 19 DE JP NC,NXENT1 ;is there more room left? -2304 DE16 C3 FE DD JP STFILPOS ;no. Set this flag and return. -2305 DE19 3A EA E5 NXENT1: LD A,(FILEPOS) ;get file position within directory. -2306 DE1C E6 03 AND 03H ;only look within this sector (only 4 entries fit). -2307 DE1E 06 05 LD B,5 ;convert to relative position (32 bytes each). -2308 DE20 87 NXENT2: ADD A,A ;note that this is not efficient code. -2309 DE21 05 DEC B ;5 'ADD A's would be better. -2310 DE22 C2 20 DE JP NZ,NXENT2 -2311 DE25 32 E9 E5 LD (FCBPOS),A ;save it as position of fcb. -2312 DE28 B7 OR A -2313 DE29 C0 RET NZ ;return if we are within buffer. -2314 DE2A C5 PUSH BC -2315 DE2B CD C3 DB CALL TRKSEC ;we need the next directory sector. -2316 DE2E CD D4 DD CALL DIRREAD -2317 DE31 C1 POP BC -2318 DE32 C3 9E DD JP CHECKDIR -2319 DE35 ; -2320 DE35 ; Routine to to get a bit from the disk space allocation -2321 DE35 ; map. It is returned in (A), bit position 0. On entry to here, -2322 DE35 ; set (BC) to the block number on the disk to check. -2323 DE35 ; On return, (D) will contain the original bit position for -2324 DE35 ; this block number and (HL) will point to the address for it. -2325 DE35 ; -2326 DE35 79 CKBITMAP: LD A,C ;determine bit number of interest. -2327 DE36 E6 07 AND 07H ;compute (D)=(E)=(C and 7)+1. -2328 DE38 3C INC A -2329 DE39 5F LD E,A ;save particular bit number. -2330 DE3A 57 LD D,A -2331 DE3B ; -2332 DE3B ; compute (BC)=(BC)/8. -2333 DE3B ; -2334 DE3B 79 LD A,C -2335 DE3C 0F RRCA ;now shift right 3 bits. -2336 DE3D 0F RRCA -2337 DE3E 0F RRCA -2338 DE3F E6 1F AND 1FH ;and clear bits 7,6,5. -2339 DE41 4F LD C,A -2340 DE42 78 LD A,B -2341 DE43 87 ADD A,A ;now shift (B) into bits 7,6,5. -2342 DE44 87 ADD A,A -2343 DE45 87 ADD A,A -2344 DE46 87 ADD A,A -2345 DE47 87 ADD A,A -2346 DE48 B1 OR C ;and add in (C). -2347 DE49 4F LD C,A ;ok, (C) ha been completed. -2348 DE4A 78 LD A,B ;is there a better way of doing this? -2349 DE4B 0F RRCA -2350 DE4C 0F RRCA -2351 DE4D 0F RRCA -2352 DE4E E6 1F AND 1FH -2353 DE50 47 LD B,A ;and now (B) is completed. -2354 DE51 ; -2355 DE51 ; use this as an offset into the disk space allocation -2356 DE51 ; table. -2357 DE51 ; -2358 DE51 2A BF E5 LD HL,(ALOCVECT) -2359 DE54 09 ADD HL,BC -2360 DE55 7E LD A,(HL) ;now get correct byte. -2361 DE56 07 CKBMAP1:RLCA ;get correct bit into position 0. -2362 DE57 1D DEC E -2363 DE58 C2 56 DE JP NZ,CKBMAP1 -2364 DE5B C9 RET -2365 DE5C ; -2366 DE5C ; Set or clear the bit map such that block number (BC) will be marked -2367 DE5C ; as used. On entry, if (E)=0 then this bit will be cleared, if it equals -2368 DE5C ; 1 then it will be set (don't use anyother values). -2369 DE5C ; -2370 DE5C D5 STBITMAP: PUSH DE -2371 DE5D CD 35 DE CALL CKBITMAP ;get the byte of interest. -2372 DE60 E6 FE AND 0FEH ;clear the affected bit. -2373 DE62 C1 POP BC -2374 DE63 B1 OR C ;and now set it acording to (C). -2375 DE64 ; -2376 DE64 ; entry to restore the original bit position and then store -2377 DE64 ; in table. (A) contains the value, (D) contains the bit -2378 DE64 ; position (1-8), and (HL) points to the address within the -2379 DE64 ; space allocation table for this byte. -2380 DE64 ; -2381 DE64 0F STBMAP1:RRCA ;restore original bit position. -2382 DE65 15 DEC D -2383 DE66 C2 64 DE JP NZ,STBMAP1 -2384 DE69 77 LD (HL),A ;and stor byte in table. -2385 DE6A C9 RET -2386 DE6B ; -2387 DE6B ; Set/clear space used bits in allocation map for this file. -2388 DE6B ; On entry, (C)=1 to set the map and (C)=0 to clear it. -2389 DE6B ; -2390 DE6B CD 5E DD SETFILE:CALL FCB2HL ;get address of fcb -2391 DE6E 11 10 00 LD DE,16 -2392 DE71 19 ADD HL,DE ;get to block number bytes. -2393 DE72 C5 PUSH BC -2394 DE73 0E 11 LD C,17 ;check all 17 bytes (max) of table. -2395 DE75 D1 SETFL1: POP DE -2396 DE76 0D DEC C ;done all bytes yet? -2397 DE77 C8 RET Z -2398 DE78 D5 PUSH DE -2399 DE79 3A DD E5 LD A,(BIGDISK) ;check disk size for 16 bit block numbers. -2400 DE7C B7 OR A -2401 DE7D CA 88 DE JP Z,SETFL2 -2402 DE80 C5 PUSH BC ;only 8 bit numbers. set (BC) to this one. -2403 DE81 E5 PUSH HL -2404 DE82 4E LD C,(HL) ;get low byte from table, always -2405 DE83 06 00 LD B,0 ;set high byte to zero. -2406 DE85 C3 8E DE JP SETFL3 -2407 DE88 0D SETFL2: DEC C ;for 16 bit block numbers, adjust counter. -2408 DE89 C5 PUSH BC -2409 DE8A 4E LD C,(HL) ;now get both the low and high bytes. -2410 DE8B 23 INC HL -2411 DE8C 46 LD B,(HL) -2412 DE8D E5 PUSH HL -2413 DE8E 79 SETFL3: LD A,C ;block used? -2414 DE8F B0 OR B -2415 DE90 CA 9D DE JP Z,SETFL4 -2416 DE93 2A C6 E5 LD HL,(DSKSIZE) ;is this block number within the -2417 DE96 7D LD A,L ;space on the disk? -2418 DE97 91 SUB C -2419 DE98 7C LD A,H -2420 DE99 98 SBC A,B -2421 DE9A D4 5C DE CALL NC,STBITMAP ;yes, set the proper bit. -2422 DE9D E1 SETFL4: POP HL ;point to next block number in fcb. -2423 DE9E 23 INC HL -2424 DE9F C1 POP BC -2425 DEA0 C3 75 DE JP SETFL1 -2426 DEA3 ; -2427 DEA3 ; Construct the space used allocation bit map for the active -2428 DEA3 ; drive. If a file name starts with '$' and it is under the -2429 DEA3 ; current user number, then (STATUS) is set to minus 1. Otherwise -2430 DEA3 ; it is not set at all. -2431 DEA3 ; -2432 DEA3 2A C6 E5 BITMAP: LD HL,(DSKSIZE) ;compute size of allocation table. -2433 DEA6 0E 03 LD C,3 -2434 DEA8 CD EA DC CALL SHIFTR ;(HL)=(HL)/8. -2435 DEAB 23 INC HL ;at lease 1 byte. -2436 DEAC 44 LD B,H -2437 DEAD 4D LD C,L ;set (BC) to the allocation table length. -2438 DEAE ; -2439 DEAE ; Initialize the bitmap for this drive. Right now, the first -2440 DEAE ; two bytes are specified by the disk parameter block. However -2441 DEAE ; a patch could be entered here if it were necessary to setup -2442 DEAE ; this table in a special mannor. For example, the bios could -2443 DEAE ; determine locations of 'bad blocks' and set them as already -2444 DEAE ; 'used' in the map. -2445 DEAE ; -2446 DEAE 2A BF E5 LD HL,(ALOCVECT) ;now zero out the table now. -2447 DEB1 36 00 BITMAP1:LD (HL),0 -2448 DEB3 23 INC HL -2449 DEB4 0B DEC BC -2450 DEB5 78 LD A,B -2451 DEB6 B1 OR C -2452 DEB7 C2 B1 DE JP NZ,BITMAP1 -2453 DEBA 2A CA E5 LD HL,(ALLOC0) ;get initial space used by directory. -2454 DEBD EB EX DE,HL -2455 DEBE 2A BF E5 LD HL,(ALOCVECT) ;and put this into map. -2456 DEC1 73 LD (HL),E -2457 DEC2 23 INC HL -2458 DEC3 72 LD (HL),D -2459 DEC4 ; -2460 DEC4 ; End of initialization portion. -2461 DEC4 ; -2462 DEC4 CD A1 DB CALL HOMEDRV ;now home the drive. -2463 DEC7 2A B3 E5 LD HL,(SCRATCH1) -2464 DECA 36 03 LD (HL),3 ;force next directory request to read -2465 DECC 23 INC HL ;in a sector. -2466 DECD 36 00 LD (HL),0 -2467 DECF CD FE DD CALL STFILPOS ;clear initial file position also. -2468 DED2 0E FF BITMAP2:LD C,0FFH ;read next file name in directory -2469 DED4 CD 05 DE CALL NXENTRY ;and set checksum byte. -2470 DED7 CD F5 DD CALL CKFILPOS ;is there another file? -2471 DEDA C8 RET Z -2472 DEDB CD 5E DD CALL FCB2HL ;yes, get its address. -2473 DEDE 3E E5 LD A,0E5H -2474 DEE0 BE CP (HL) ;empty file entry? -2475 DEE1 CA D2 DE JP Z,BITMAP2 -2476 DEE4 3A 41 DB LD A,(USERNO) ;no, correct user number? -2477 DEE7 BE CP (HL) -2478 DEE8 C2 F6 DE JP NZ,BITMAP3 -2479 DEEB 23 INC HL -2480 DEEC 7E LD A,(HL) ;yes, does name start with a '$'? -2481 DEED D6 24 SUB '$' -2482 DEEF C2 F6 DE JP NZ,BITMAP3 -2483 DEF2 3D DEC A ;yes, set atatus to minus one. -2484 DEF3 32 45 DB LD (STATUS),A -2485 DEF6 0E 01 BITMAP3:LD C,1 ;now set this file's space as used in bit map. -2486 DEF8 CD 6B DE CALL SETFILE -2487 DEFB CD 8C DD CALL CHKNMBR ;keep (SCRATCH1) in bounds. -2488 DEFE C3 D2 DE JP BITMAP2 -2489 DF01 ; -2490 DF01 ; Set the status (STATUS) and return. -2491 DF01 ; -2492 DF01 3A D4 E5 STSTATUS: LD A,(FNDSTAT) -2493 DF04 C3 01 DB JP SETSTAT -2494 DF07 ; -2495 DF07 ; Check extents in (A) and (C). Set the zero flag if they -2496 DF07 ; are the same. The number of 16k chunks of disk space that -2497 DF07 ; the directory extent covers is expressad is (EXTMASK+1). -2498 DF07 ; No registers are modified. -2499 DF07 ; -2500 DF07 C5 SAMEXT: PUSH BC -2501 DF08 F5 PUSH AF -2502 DF09 3A C5 E5 LD A,(EXTMASK) ;get extent mask and use it to -2503 DF0C 2F CPL ;to compare both extent numbers. -2504 DF0D 47 LD B,A ;save resulting mask here. -2505 DF0E 79 LD A,C ;mask first extent and save in (C). -2506 DF0F A0 AND B -2507 DF10 4F LD C,A -2508 DF11 F1 POP AF ;now mask second extent and compare -2509 DF12 A0 AND B ;with the first one. -2510 DF13 91 SUB C -2511 DF14 E6 1F AND 1FH ;(* only check buts 0-4 *) -2512 DF16 C1 POP BC ;the zero flag is set if they are the same. -2513 DF17 C9 RET ;restore (BC) and return. -2514 DF18 ; -2515 DF18 ; Search for the first occurence of a file name. On entry, -2516 DF18 ; register (C) should contain the number of bytes of the fcb -2517 DF18 ; that must match. -2518 DF18 ; -2519 DF18 3E FF FINDFST:LD A,0FFH -2520 DF1A 32 D4 E5 LD (FNDSTAT),A -2521 DF1D 21 D8 E5 LD HL,COUNTER ;save character count. -2522 DF20 71 LD (HL),C -2523 DF21 2A 43 DB LD HL,(PARAMS) ;get filename to match. -2524 DF24 22 D9 E5 LD (SAVEFCB),HL ;and save. -2525 DF27 CD FE DD CALL STFILPOS ;clear initial file position (set to 0ffffh). -2526 DF2A CD A1 DB CALL HOMEDRV ;home the drive. -2527 DF2D ; -2528 DF2D ; Entry to locate the next occurence of a filename within the -2529 DF2D ; directory. The disk is not expected to have been changed. If -2530 DF2D ; it was, then it will be write protected. -2531 DF2D ; -2532 DF2D 0E 00 FINDNXT:LD C,0 ;write protect the disk if changed. -2533 DF2F CD 05 DE CALL NXENTRY ;get next filename entry in directory. -2534 DF32 CD F5 DD CALL CKFILPOS ;is file position = 0ffffh? -2535 DF35 CA 94 DF JP Z,FNDNXT6 ;yes, exit now then. -2536 DF38 2A D9 E5 LD HL,(SAVEFCB) ;set (DE) pointing to filename to match. -2537 DF3B EB EX DE,HL -2538 DF3C 1A LD A,(DE) -2539 DF3D FE E5 CP 0E5H ;empty directory entry? -2540 DF3F CA 4A DF JP Z,FNDNXT1 ;(* are we trying to reserect erased entries? *) -2541 DF42 D5 PUSH DE -2542 DF43 CD 7F DD CALL MOREFLS ;more files in directory? -2543 DF46 D1 POP DE -2544 DF47 D2 94 DF JP NC,FNDNXT6 ;no more. Exit now. -2545 DF4A CD 5E DD FNDNXT1:CALL FCB2HL ;get address of this fcb in directory. -2546 DF4D 3A D8 E5 LD A,(COUNTER) ;get number of bytes (characters) to check. -2547 DF50 4F LD C,A -2548 DF51 06 00 LD B,0 ;initialize byte position counter. -2549 DF53 79 FNDNXT2:LD A,C ;are we done with the compare? -2550 DF54 B7 OR A -2551 DF55 CA 83 DF JP Z,FNDNXT5 -2552 DF58 1A LD A,(DE) ;no, check next byte. -2553 DF59 FE 3F CP '?' ;don't care about this character? -2554 DF5B CA 7C DF JP Z,FNDNXT4 -2555 DF5E 78 LD A,B ;get bytes position in fcb. -2556 DF5F FE 0D CP 13 ;don't care about the thirteenth byte either. -2557 DF61 CA 7C DF JP Z,FNDNXT4 -2558 DF64 FE 0C CP 12 ;extent byte? -2559 DF66 1A LD A,(DE) -2560 DF67 CA 73 DF JP Z,FNDNXT3 -2561 DF6A 96 SUB (HL) ;otherwise compare characters. -2562 DF6B E6 7F AND 7FH -2563 DF6D C2 2D DF JP NZ,FINDNXT ;not the same, check next entry. -2564 DF70 C3 7C DF JP FNDNXT4 ;so far so good, keep checking. -2565 DF73 C5 FNDNXT3:PUSH BC ;check the extent byte here. -2566 DF74 4E LD C,(HL) -2567 DF75 CD 07 DF CALL SAMEXT -2568 DF78 C1 POP BC -2569 DF79 C2 2D DF JP NZ,FINDNXT ;not the same, look some more. -2570 DF7C ; -2571 DF7C ; So far the names compare. Bump pointers to the next byte -2572 DF7C ; and continue until all (C) characters have been checked. -2573 DF7C ; -2574 DF7C 13 FNDNXT4:INC DE ;bump pointers. -2575 DF7D 23 INC HL -2576 DF7E 04 INC B -2577 DF7F 0D DEC C ;adjust character counter. -2578 DF80 C3 53 DF JP FNDNXT2 -2579 DF83 3A EA E5 FNDNXT5:LD A,(FILEPOS) ;return the position of this entry. -2580 DF86 E6 03 AND 03H -2581 DF88 32 45 DB LD (STATUS),A -2582 DF8B 21 D4 E5 LD HL,FNDSTAT -2583 DF8E 7E LD A,(HL) -2584 DF8F 17 RLA -2585 DF90 D0 RET NC -2586 DF91 AF XOR A -2587 DF92 77 LD (HL),A -2588 DF93 C9 RET -2589 DF94 ; -2590 DF94 ; Filename was not found. Set appropriate status. -2591 DF94 ; -2592 DF94 CD FE DD FNDNXT6:CALL STFILPOS ;set (FILEPOS) to 0ffffh. -2593 DF97 3E FF LD A,0FFH ;say not located. -2594 DF99 C3 01 DB JP SETSTAT -2595 DF9C ; -2596 DF9C ; Erase files from the directory. Only the first byte of the -2597 DF9C ; fcb will be affected. It is set to (E5). -2598 DF9C ; -2599 DF9C CD 54 DD ERAFILE:CALL CHKWPRT ;is disk write protected? -2600 DF9F 0E 0C LD C,12 ;only compare file names. -2601 DFA1 CD 18 DF CALL FINDFST ;get first file name. -2602 DFA4 CD F5 DD ERAFIL1:CALL CKFILPOS ;any found? -2603 DFA7 C8 RET Z ;nope, we must be done. -2604 DFA8 CD 44 DD CALL CHKROFL ;is file read only? -2605 DFAB CD 5E DD CALL FCB2HL ;nope, get address of fcb and -2606 DFAE 36 E5 LD (HL),0E5H ;set first byte to 'empty'. -2607 DFB0 0E 00 LD C,0 ;clear the space from the bit map. -2608 DFB2 CD 6B DE CALL SETFILE -2609 DFB5 CD C6 DD CALL DIRWRITE ;now write the directory sector back out. -2610 DFB8 CD 2D DF CALL FINDNXT ;find the next file name. -2611 DFBB C3 A4 DF JP ERAFIL1 ;and repeat process. -2612 DFBE ; -2613 DFBE ; Look through the space allocation map (bit map) for the -2614 DFBE ; next available block. Start searching at block number (BC-1). -2615 DFBE ; The search procedure is to look for an empty block that is -2616 DFBE ; before the starting block. If not empty, look at a later -2617 DFBE ; block number. In this way, we return the closest empty block -2618 DFBE ; on either side of the 'target' block number. This will speed -2619 DFBE ; access on random devices. For serial devices, this should be -2620 DFBE ; changed to look in the forward direction first and then start -2621 DFBE ; at the front and search some more. -2622 DFBE ; -2623 DFBE ; On return, (DE)= block number that is empty and (HL) =0 -2624 DFBE ; if no empry block was found. -2625 DFBE ; -2626 DFBE 50 FNDSPACE: LD D,B ;set (DE) as the block that is checked. -2627 DFBF 59 LD E,C -2628 DFC0 ; -2629 DFC0 ; Look before target block. Registers (BC) are used as the lower -2630 DFC0 ; pointer and (DE) as the upper pointer. -2631 DFC0 ; -2632 DFC0 79 FNDSPA1:LD A,C ;is block 0 specified? -2633 DFC1 B0 OR B -2634 DFC2 CA D1 DF JP Z,FNDSPA2 -2635 DFC5 0B DEC BC ;nope, check previous block. -2636 DFC6 D5 PUSH DE -2637 DFC7 C5 PUSH BC -2638 DFC8 CD 35 DE CALL CKBITMAP -2639 DFCB 1F RRA ;is this block empty? -2640 DFCC D2 EC DF JP NC,FNDSPA3 ;yes. use this. -2641 DFCF ; -2642 DFCF ; Note that the above logic gets the first block that it finds -2643 DFCF ; that is empty. Thus a file could be written 'backward' making -2644 DFCF ; it very slow to access. This could be changed to look for the -2645 DFCF ; first empty block and then continue until the start of this -2646 DFCF ; empty space is located and then used that starting block. -2647 DFCF ; This should help speed up access to some files especially on -2648 DFCF ; a well used disk with lots of fairly small 'holes'. -2649 DFCF ; -2650 DFCF C1 POP BC ;nope, check some more. -2651 DFD0 D1 POP DE -2652 DFD1 ; -2653 DFD1 ; Now look after target block. -2654 DFD1 ; -2655 DFD1 2A C6 E5 FNDSPA2:LD HL,(DSKSIZE) ;is block (DE) within disk limits? -2656 DFD4 7B LD A,E -2657 DFD5 95 SUB L -2658 DFD6 7A LD A,D -2659 DFD7 9C SBC A,H -2660 DFD8 D2 F4 DF JP NC,FNDSPA4 -2661 DFDB 13 INC DE ;yes, move on to next one. -2662 DFDC C5 PUSH BC -2663 DFDD D5 PUSH DE -2664 DFDE 42 LD B,D -2665 DFDF 4B LD C,E -2666 DFE0 CD 35 DE CALL CKBITMAP ;check it. -2667 DFE3 1F RRA ;empty? -2668 DFE4 D2 EC DF JP NC,FNDSPA3 -2669 DFE7 D1 POP DE ;nope, continue searching. -2670 DFE8 C1 POP BC -2671 DFE9 C3 C0 DF JP FNDSPA1 -2672 DFEC ; -2673 DFEC ; Empty block found. Set it as used and return with (HL) -2674 DFEC ; pointing to it (true?). -2675 DFEC ; -2676 DFEC 17 FNDSPA3:RLA ;reset byte. -2677 DFED 3C INC A ;and set bit 0. -2678 DFEE CD 64 DE CALL STBMAP1 ;update bit map. -2679 DFF1 E1 POP HL ;set return registers. -2680 DFF2 D1 POP DE -2681 DFF3 C9 RET -2682 DFF4 ; -2683 DFF4 ; Free block was not found. If (BC) is not zero, then we have -2684 DFF4 ; not checked all of the disk space. -2685 DFF4 ; -2686 DFF4 79 FNDSPA4:LD A,C -2687 DFF5 B0 OR B -2688 DFF6 C2 C0 DF JP NZ,FNDSPA1 -2689 DFF9 21 00 00 LD HL,0 ;set 'not found' status. -2690 DFFC C9 RET -2691 DFFD ; -2692 DFFD ; Move a complete fcb entry into the directory and write it. -2693 DFFD ; -2694 DFFD 0E 00 FCBSET: LD C,0 -2695 DFFF 1E 20 LD E,32 ;length of each entry. -2696 E001 ; -2697 E001 ; Move (E) bytes from the fcb pointed to by (PARAMS) into -2698 E001 ; fcb in directory starting at relative byte (C). This updated -2699 E001 ; directory buffer is then written to the disk. -2700 E001 ; -2701 E001 D5 UPDATE: PUSH DE -2702 E002 06 00 LD B,0 ;set (BC) to relative byte position. -2703 E004 2A 43 DB LD HL,(PARAMS) ;get address of fcb. -2704 E007 09 ADD HL,BC ;compute starting byte. -2705 E008 EB EX DE,HL -2706 E009 CD 5E DD CALL FCB2HL ;get address of fcb to update in directory. -2707 E00C C1 POP BC ;set (C) to number of bytes to change. -2708 E00D CD 4F DB CALL DE2HL -2709 E010 CD C3 DB UPDATE1:CALL TRKSEC ;determine the track and sector affected. -2710 E013 C3 C6 DD JP DIRWRITE ;then write this sector out. -2711 E016 ; -2712 E016 ; Routine to change the name of all files on the disk with a -2713 E016 ; specified name. The fcb contains the current name as the -2714 E016 ; first 12 characters and the new name 16 bytes into the fcb. -2715 E016 ; -2716 E016 CD 54 DD CHGNAMES: CALL CHKWPRT ;check for a write protected disk. -2717 E019 0E 0C LD C,12 ;match first 12 bytes of fcb only. -2718 E01B CD 18 DF CALL FINDFST ;get first name. -2719 E01E 2A 43 DB LD HL,(PARAMS) ;get address of fcb. -2720 E021 7E LD A,(HL) ;get user number. -2721 E022 11 10 00 LD DE,16 ;move over to desired name. -2722 E025 19 ADD HL,DE -2723 E026 77 LD (HL),A ;keep same user number. -2724 E027 CD F5 DD CHGNAM1:CALL CKFILPOS ;any matching file found? -2725 E02A C8 RET Z ;no, we must be done. -2726 E02B CD 44 DD CALL CHKROFL ;check for read only file. -2727 E02E 0E 10 LD C,16 ;start 16 bytes into fcb. -2728 E030 1E 0C LD E,12 ;and update the first 12 bytes of directory. -2729 E032 CD 01 E0 CALL UPDATE -2730 E035 CD 2D DF CALL FINDNXT ;get te next file name. -2731 E038 C3 27 E0 JP CHGNAM1 ;and continue. -2732 E03B ; -2733 E03B ; Update a files attributes. The procedure is to search for -2734 E03B ; every file with the same name as shown in fcb (ignoring bit 7) -2735 E03B ; and then to update it (which includes bit 7). No other changes -2736 E03B ; are made. -2737 E03B ; -2738 E03B 0E 0C SAVEATTR: LD C,12 ;match first 12 bytes. -2739 E03D CD 18 DF CALL FINDFST ;look for first filename. -2740 E040 CD F5 DD SAVATR1:CALL CKFILPOS ;was one found? -2741 E043 C8 RET Z ;nope, we must be done. -2742 E044 0E 00 LD C,0 ;yes, update the first 12 bytes now. -2743 E046 1E 0C LD E,12 -2744 E048 CD 01 E0 CALL UPDATE ;update filename and write directory. -2745 E04B CD 2D DF CALL FINDNXT ;and get the next file. -2746 E04E C3 40 E0 JP SAVATR1 ;then continue until done. -2747 E051 ; -2748 E051 ; Open a file (name specified in fcb). -2749 E051 ; -2750 E051 0E 0F OPENIT: LD C,15 ;compare the first 15 bytes. -2751 E053 CD 18 DF CALL FINDFST ;get the first one in directory. -2752 E056 CD F5 DD CALL CKFILPOS ;any at all? -2753 E059 C8 RET Z -2754 E05A CD A6 DC OPENIT1:CALL SETEXT ;point to extent byte within users fcb. -2755 E05D 7E LD A,(HL) ;and get it. -2756 E05E F5 PUSH AF ;save it and address. -2757 E05F E5 PUSH HL -2758 E060 CD 5E DD CALL FCB2HL ;point to fcb in directory. -2759 E063 EB EX DE,HL -2760 E064 2A 43 DB LD HL,(PARAMS) ;this is the users copy. -2761 E067 0E 20 LD C,32 ;move it into users space. -2762 E069 D5 PUSH DE -2763 E06A CD 4F DB CALL DE2HL -2764 E06D CD 78 DD CALL SETS2B7 ;set bit 7 in 's2' byte (unmodified). -2765 E070 D1 POP DE ;now get the extent byte from this fcb. -2766 E071 21 0C 00 LD HL,12 -2767 E074 19 ADD HL,DE -2768 E075 4E LD C,(HL) ;into (C). -2769 E076 21 0F 00 LD HL,15 ;now get the record count byte into (B). -2770 E079 19 ADD HL,DE -2771 E07A 46 LD B,(HL) -2772 E07B E1 POP HL ;keep the same extent as the user had originally. -2773 E07C F1 POP AF -2774 E07D 77 LD (HL),A -2775 E07E 79 LD A,C ;is it the same as in the directory fcb? -2776 E07F BE CP (HL) -2777 E080 78 LD A,B ;if yes, then use the same record count. -2778 E081 CA 8B E0 JP Z,OPENIT2 -2779 E084 3E 00 LD A,0 ;if the user specified an extent greater than -2780 E086 DA 8B E0 JP C,OPENIT2 ;the one in the directory, then set record count to 0. -2781 E089 3E 80 LD A,128 ;otherwise set to maximum. -2782 E08B 2A 43 DB OPENIT2:LD HL,(PARAMS) ;set record count in users fcb to (A). -2783 E08E 11 0F 00 LD DE,15 -2784 E091 19 ADD HL,DE ;compute relative position. -2785 E092 77 LD (HL),A ;and set the record count. -2786 E093 C9 RET -2787 E094 ; -2788 E094 ; Move two bytes from (DE) to (HL) if (and only if) (HL) -2789 E094 ; point to a zero value (16 bit). -2790 E094 ; Return with zero flag set it (DE) was moved. Registers (DE) -2791 E094 ; and (HL) are not changed. However (A) is. -2792 E094 ; -2793 E094 7E MOVEWORD: LD A,(HL) ;check for a zero word. -2794 E095 23 INC HL -2795 E096 B6 OR (HL) ;both bytes zero? -2796 E097 2B DEC HL -2797 E098 C0 RET NZ ;nope, just return. -2798 E099 1A LD A,(DE) ;yes, move two bytes from (DE) into -2799 E09A 77 LD (HL),A ;this zero space. -2800 E09B 13 INC DE -2801 E09C 23 INC HL -2802 E09D 1A LD A,(DE) -2803 E09E 77 LD (HL),A -2804 E09F 1B DEC DE ;don't disturb these registers. -2805 E0A0 2B DEC HL -2806 E0A1 C9 RET -2807 E0A2 ; -2808 E0A2 ; Get here to close a file specified by (fcb). -2809 E0A2 ; -2810 E0A2 AF CLOSEIT:XOR A ;clear status and file position bytes. -2811 E0A3 32 45 DB LD (STATUS),A -2812 E0A6 32 EA E5 LD (FILEPOS),A -2813 E0A9 32 EB E5 LD (FILEPOS+1),A -2814 E0AC CD 1E DD CALL GETWPRT ;get write protect bit for this drive. -2815 E0AF C0 RET NZ ;just return if it is set. -2816 E0B0 CD 69 DD CALL GETS2 ;else get the 's2' byte. -2817 E0B3 E6 80 AND 80H ;and look at bit 7 (file unmodified?). -2818 E0B5 C0 RET NZ ;just return if set. -2819 E0B6 0E 0F LD C,15 ;else look up this file in directory. -2820 E0B8 CD 18 DF CALL FINDFST -2821 E0BB CD F5 DD CALL CKFILPOS ;was it found? -2822 E0BE C8 RET Z ;just return if not. -2823 E0BF 01 10 00 LD BC,16 ;set (HL) pointing to records used section. -2824 E0C2 CD 5E DD CALL FCB2HL -2825 E0C5 09 ADD HL,BC -2826 E0C6 EB EX DE,HL -2827 E0C7 2A 43 DB LD HL,(PARAMS) ;do the same for users specified fcb. -2828 E0CA 09 ADD HL,BC -2829 E0CB 0E 10 LD C,16 ;this many bytes are present in this extent. -2830 E0CD 3A DD E5 CLOSEIT1: LD A,(BIGDISK) ;8 or 16 bit record numbers? -2831 E0D0 B7 OR A -2832 E0D1 CA E8 E0 JP Z,CLOSEIT4 -2833 E0D4 7E LD A,(HL) ;just 8 bit. Get one from users fcb. -2834 E0D5 B7 OR A -2835 E0D6 1A LD A,(DE) ;now get one from directory fcb. -2836 E0D7 C2 DB E0 JP NZ,CLOSEIT2 -2837 E0DA 77 LD (HL),A ;users byte was zero. Update from directory. -2838 E0DB B7 CLOSEIT2: OR A -2839 E0DC C2 E1 E0 JP NZ,CLOSEIT3 -2840 E0DF 7E LD A,(HL) ;directories byte was zero, update from users fcb. -2841 E0E0 12 LD (DE),A -2842 E0E1 BE CLOSEIT3: CP (HL) ;if neither one of these bytes were zero, -2843 E0E2 C2 1F E1 JP NZ,CLOSEIT7 ;then close error if they are not the same. -2844 E0E5 C3 FD E0 JP CLOSEIT5 ;ok so far, get to next byte in fcbs. -2845 E0E8 CD 94 E0 CLOSEIT4: CALL MOVEWORD ;update users fcb if it is zero. -2846 E0EB EB EX DE,HL -2847 E0EC CD 94 E0 CALL MOVEWORD ;update directories fcb if it is zero. -2848 E0EF EB EX DE,HL -2849 E0F0 1A LD A,(DE) ;if these two values are no different, -2850 E0F1 BE CP (HL) ;then a close error occured. -2851 E0F2 C2 1F E1 JP NZ,CLOSEIT7 -2852 E0F5 13 INC DE ;check second byte. -2853 E0F6 23 INC HL -2854 E0F7 1A LD A,(DE) -2855 E0F8 BE CP (HL) -2856 E0F9 C2 1F E1 JP NZ,CLOSEIT7 -2857 E0FC 0D DEC C ;remember 16 bit values. -2858 E0FD 13 CLOSEIT5: INC DE ;bump to next item in table. -2859 E0FE 23 INC HL -2860 E0FF 0D DEC C ;there are 16 entries only. -2861 E100 C2 CD E0 JP NZ,CLOSEIT1 ;continue if more to do. -2862 E103 01 EC FF LD BC,0FFECH ;backup 20 places (extent byte). -2863 E106 09 ADD HL,BC -2864 E107 EB EX DE,HL -2865 E108 09 ADD HL,BC -2866 E109 1A LD A,(DE) -2867 E10A BE CP (HL) ;directory's extent already greater than the -2868 E10B DA 17 E1 JP C,CLOSEIT6 ;users extent? -2869 E10E 77 LD (HL),A ;no, update directory extent. -2870 E10F 01 03 00 LD BC,3 ;and update the record count byte in -2871 E112 09 ADD HL,BC ;directories fcb. -2872 E113 EB EX DE,HL -2873 E114 09 ADD HL,BC -2874 E115 7E LD A,(HL) ;get from user. -2875 E116 12 LD (DE),A ;and put in directory. -2876 E117 3E FF CLOSEIT6: LD A,0FFH ;set 'was open and is now closed' byte. -2877 E119 32 D2 E5 LD (CLOSEFLG),A -2878 E11C C3 10 E0 JP UPDATE1 ;update the directory now. -2879 E11F 21 45 DB CLOSEIT7: LD HL,STATUS ;set return status and then return. -2880 E122 35 DEC (HL) -2881 E123 C9 RET -2882 E124 ; -2883 E124 ; Routine to get the next empty space in the directory. It -2884 E124 ; will then be cleared for use. -2885 E124 ; -2886 E124 CD 54 DD GETEMPTY: CALL CHKWPRT ;make sure disk is not write protected. -2887 E127 2A 43 DB LD HL,(PARAMS) ;save current parameters (fcb). -2888 E12A E5 PUSH HL -2889 E12B 21 AC E5 LD HL,EMPTYFCB ;use special one for empty space. -2890 E12E 22 43 DB LD (PARAMS),HL -2891 E131 0E 01 LD C,1 ;search for first empty spot in directory. -2892 E133 CD 18 DF CALL FINDFST ;(* only check first byte *) -2893 E136 CD F5 DD CALL CKFILPOS ;none? -2894 E139 E1 POP HL -2895 E13A 22 43 DB LD (PARAMS),HL ;restore original fcb address. -2896 E13D C8 RET Z ;return if no more space. -2897 E13E EB EX DE,HL -2898 E13F 21 0F 00 LD HL,15 ;point to number of records for this file. -2899 E142 19 ADD HL,DE -2900 E143 0E 11 LD C,17 ;and clear all of this space. -2901 E145 AF XOR A -2902 E146 77 GETMT1: LD (HL),A -2903 E147 23 INC HL -2904 E148 0D DEC C -2905 E149 C2 46 E1 JP NZ,GETMT1 -2906 E14C 21 0D 00 LD HL,13 ;clear the 's1' byte also. -2907 E14F 19 ADD HL,DE -2908 E150 77 LD (HL),A -2909 E151 CD 8C DD CALL CHKNMBR ;keep (SCRATCH1) within bounds. -2910 E154 CD FD DF CALL FCBSET ;write out this fcb entry to directory. -2911 E157 C3 78 DD JP SETS2B7 ;set 's2' byte bit 7 (unmodified at present). -2912 E15A ; -2913 E15A ; Routine to close the current extent and open the next one -2914 E15A ; for reading. -2915 E15A ; -2916 E15A AF GETNEXT:XOR A -2917 E15B 32 D2 E5 LD (CLOSEFLG),A ;clear close flag. -2918 E15E CD A2 E0 CALL CLOSEIT ;close this extent. -2919 E161 CD F5 DD CALL CKFILPOS -2920 E164 C8 RET Z ;not there??? -2921 E165 2A 43 DB LD HL,(PARAMS) ;get extent byte. -2922 E168 01 0C 00 LD BC,12 -2923 E16B 09 ADD HL,BC -2924 E16C 7E LD A,(HL) ;and increment it. -2925 E16D 3C INC A -2926 E16E E6 1F AND 1FH ;keep within range 0-31. -2927 E170 77 LD (HL),A -2928 E171 CA 83 E1 JP Z,GTNEXT1 ;overflow? -2929 E174 47 LD B,A ;mask extent byte. -2930 E175 3A C5 E5 LD A,(EXTMASK) -2931 E178 A0 AND B -2932 E179 21 D2 E5 LD HL,CLOSEFLG ;check close flag (0ffh is ok). -2933 E17C A6 AND (HL) -2934 E17D CA 8E E1 JP Z,GTNEXT2 ;if zero, we must read in next extent. -2935 E180 C3 AC E1 JP GTNEXT3 ;else, it is already in memory. -2936 E183 01 02 00 GTNEXT1:LD BC,2 ;Point to the 's2' byte. -2937 E186 09 ADD HL,BC -2938 E187 34 INC (HL) ;and bump it. -2939 E188 7E LD A,(HL) ;too many extents? -2940 E189 E6 0F AND 0FH -2941 E18B CA B6 E1 JP Z,GTNEXT5 ;yes, set error code. -2942 E18E ; -2943 E18E ; Get here to open the next extent. -2944 E18E ; -2945 E18E 0E 0F GTNEXT2:LD C,15 ;set to check first 15 bytes of fcb. -2946 E190 CD 18 DF CALL FINDFST ;find the first one. -2947 E193 CD F5 DD CALL CKFILPOS ;none available? -2948 E196 C2 AC E1 JP NZ,GTNEXT3 -2949 E199 3A D3 E5 LD A,(RDWRTFLG) ;no extent present. Can we open an empty one? -2950 E19C 3C INC A ;0ffh means reading (so not possible). -2951 E19D CA B6 E1 JP Z,GTNEXT5 ;or an error. -2952 E1A0 CD 24 E1 CALL GETEMPTY ;we are writing, get an empty entry. -2953 E1A3 CD F5 DD CALL CKFILPOS ;none? -2954 E1A6 CA B6 E1 JP Z,GTNEXT5 ;error if true. -2955 E1A9 C3 AF E1 JP GTNEXT4 ;else we are almost done. -2956 E1AC CD 5A E0 GTNEXT3:CALL OPENIT1 ;open this extent. -2957 E1AF CD BB DC GTNEXT4:CALL STRDATA ;move in updated data (rec #, extent #, etc.) -2958 E1B2 AF XOR A ;clear status and return. -2959 E1B3 C3 01 DB JP SETSTAT -2960 E1B6 ; -2961 E1B6 ; Error in extending the file. Too many extents were needed -2962 E1B6 ; or not enough space on the disk. -2963 E1B6 ; -2964 E1B6 CD 05 DB GTNEXT5:CALL IOERR1 ;set error code, clear bit 7 of 's2' -2965 E1B9 C3 78 DD JP SETS2B7 ;so this is not written on a close. -2966 E1BC ; -2967 E1BC ; Read a sequential file. -2968 E1BC ; -2969 E1BC 3E 01 RDSEQ: LD A,1 ;set sequential access mode. -2970 E1BE 32 D5 E5 LD (MODE),A -2971 E1C1 3E FF RDSEQ1: LD A,0FFH ;don't allow reading unwritten space. -2972 E1C3 32 D3 E5 LD (RDWRTFLG),A -2973 E1C6 CD BB DC CALL STRDATA ;put rec# and ext# into fcb. -2974 E1C9 3A E3 E5 LD A,(SAVNREC) ;get next record to read. -2975 E1CC 21 E1 E5 LD HL,SAVNXT ;get number of records in extent. -2976 E1CF BE CP (HL) ;within this extent? -2977 E1D0 DA E6 E1 JP C,RDSEQ2 -2978 E1D3 FE 80 CP 128 ;no. Is this extent fully used? -2979 E1D5 C2 FB E1 JP NZ,RDSEQ3 ;no. End-of-file. -2980 E1D8 CD 5A E1 CALL GETNEXT ;yes, open the next one. -2981 E1DB AF XOR A ;reset next record to read. -2982 E1DC 32 E3 E5 LD (SAVNREC),A -2983 E1DF 3A 45 DB LD A,(STATUS) ;check on open, successful? -2984 E1E2 B7 OR A -2985 E1E3 C2 FB E1 JP NZ,RDSEQ3 ;no, error. -2986 E1E6 CD 77 DC RDSEQ2: CALL COMBLK ;ok. compute block number to read. -2987 E1E9 CD 84 DC CALL CHKBLK ;check it. Within bounds? -2988 E1EC CA FB E1 JP Z,RDSEQ3 ;no, error. -2989 E1EF CD 8A DC CALL LOGICAL ;convert (BLKNMBR) to logical sector (128 byte). -2990 E1F2 CD D1 DB CALL TRKSEC1 ;set the track and sector for this block #. -2991 E1F5 CD B2 DB CALL DOREAD ;and read it. -2992 E1F8 C3 D2 DC JP SETNREC ;and set the next record to be accessed. -2993 E1FB ; -2994 E1FB ; Read error occured. Set status and return. -2995 E1FB ; -2996 E1FB C3 05 DB RDSEQ3: JP IOERR1 -2997 E1FE ; -2998 E1FE ; Write the next sequential record. -2999 E1FE ; -3000 E1FE 3E 01 WTSEQ: LD A,1 ;set sequential access mode. -3001 E200 32 D5 E5 LD (MODE),A -3002 E203 3E 00 WTSEQ1: LD A,0 ;allow an addition empty extent to be opened. -3003 E205 32 D3 E5 LD (RDWRTFLG),A -3004 E208 CD 54 DD CALL CHKWPRT ;check write protect status. -3005 E20B 2A 43 DB LD HL,(PARAMS) -3006 E20E CD 47 DD CALL CKROF1 ;check for read only file, (HL) already set to fcb. -3007 E211 CD BB DC CALL STRDATA ;put updated data into fcb. -3008 E214 3A E3 E5 LD A,(SAVNREC) ;get record number to write. -3009 E217 FE 80 CP 128 ;within range? -3010 E219 D2 05 DB JP NC,IOERR1 ;no, error(?). -3011 E21C CD 77 DC CALL COMBLK ;compute block number. -3012 E21F CD 84 DC CALL CHKBLK ;check number. -3013 E222 0E 00 LD C,0 ;is there one to write to? -3014 E224 C2 6E E2 JP NZ,WTSEQ6 ;yes, go do it. -3015 E227 CD 3E DC CALL GETBLOCK ;get next block number within fcb to use. -3016 E22A 32 D7 E5 LD (RELBLOCK),A ;and save. -3017 E22D 01 00 00 LD BC,0 ;start looking for space from the start -3018 E230 B7 OR A ;if none allocated as yet. -3019 E231 CA 3B E2 JP Z,WTSEQ2 -3020 E234 4F LD C,A ;extract previous block number from fcb -3021 E235 0B DEC BC ;so we can be closest to it. -3022 E236 CD 5E DC CALL EXTBLK -3023 E239 44 LD B,H -3024 E23A 4D LD C,L -3025 E23B CD BE DF WTSEQ2: CALL FNDSPACE ;find the next empty block nearest number (BC). -3026 E23E 7D LD A,L ;check for a zero number. -3027 E23F B4 OR H -3028 E240 C2 48 E2 JP NZ,WTSEQ3 -3029 E243 3E 02 LD A,2 ;no more space? -3030 E245 C3 01 DB JP SETSTAT -3031 E248 22 E5 E5 WTSEQ3: LD (BLKNMBR),HL ;save block number to access. -3032 E24B EB EX DE,HL ;put block number into (DE). -3033 E24C 2A 43 DB LD HL,(PARAMS) ;now we must update the fcb for this -3034 E24F 01 10 00 LD BC,16 ;newly allocated block. -3035 E252 09 ADD HL,BC -3036 E253 3A DD E5 LD A,(BIGDISK) ;8 or 16 bit block numbers? -3037 E256 B7 OR A -3038 E257 3A D7 E5 LD A,(RELBLOCK) ;(* update this entry *) -3039 E25A CA 64 E2 JP Z,WTSEQ4 ;zero means 16 bit ones. -3040 E25D CD 64 DD CALL ADDA2HL ;(HL)=(HL)+(A) -3041 E260 73 LD (HL),E ;store new block number. -3042 E261 C3 6C E2 JP WTSEQ5 -3043 E264 4F WTSEQ4: LD C,A ;compute spot in this 16 bit table. -3044 E265 06 00 LD B,0 -3045 E267 09 ADD HL,BC -3046 E268 09 ADD HL,BC -3047 E269 73 LD (HL),E ;stuff block number (DE) there. -3048 E26A 23 INC HL -3049 E26B 72 LD (HL),D -3050 E26C 0E 02 WTSEQ5: LD C,2 ;set (C) to indicate writing to un-used disk space. -3051 E26E 3A 45 DB WTSEQ6: LD A,(STATUS) ;are we ok so far? -3052 E271 B7 OR A -3053 E272 C0 RET NZ -3054 E273 C5 PUSH BC ;yes, save write flag for bios (register C). -3055 E274 CD 8A DC CALL LOGICAL ;convert (BLKNMBR) over to loical sectors. -3056 E277 3A D5 E5 LD A,(MODE) ;get access mode flag (1=sequential, -3057 E27A 3D DEC A ;0=random, 2=special?). -3058 E27B 3D DEC A -3059 E27C C2 BB E2 JP NZ,WTSEQ9 -3060 E27F ; -3061 E27F ; Special random i/o from function #40. Maybe for M/PM, but the -3062 E27F ; current block, if it has not been written to, will be zeroed -3063 E27F ; out and then written (reason?). -3064 E27F ; -3065 E27F C1 POP BC -3066 E280 C5 PUSH BC -3067 E281 79 LD A,C ;get write status flag (2=writing unused space). -3068 E282 3D DEC A -3069 E283 3D DEC A -3070 E284 C2 BB E2 JP NZ,WTSEQ9 -3071 E287 E5 PUSH HL -3072 E288 2A B9 E5 LD HL,(DIRBUF) ;zero out the directory buffer. -3073 E28B 57 LD D,A ;note that (A) is zero here. -3074 E28C 77 WTSEQ7: LD (HL),A -3075 E28D 23 INC HL -3076 E28E 14 INC D ;do 128 bytes. -3077 E28F F2 8C E2 JP P,WTSEQ7 -3078 E292 CD E0 DD CALL DIRDMA ;tell the bios the dma address for directory access. -3079 E295 2A E7 E5 LD HL,(LOGSECT) ;get sector that starts current block. -3080 E298 0E 02 LD C,2 ;set 'writing to unused space' flag. -3081 E29A 22 E5 E5 WTSEQ8: LD (BLKNMBR),HL ;save sector to write. -3082 E29D C5 PUSH BC -3083 E29E CD D1 DB CALL TRKSEC1 ;determine its track and sector numbers. -3084 E2A1 C1 POP BC -3085 E2A2 CD B8 DB CALL DOWRITE ;now write out 128 bytes of zeros. -3086 E2A5 2A E5 E5 LD HL,(BLKNMBR) ;get sector number. -3087 E2A8 0E 00 LD C,0 ;set normal write flag. -3088 E2AA 3A C4 E5 LD A,(BLKMASK) ;determine if we have written the entire -3089 E2AD 47 LD B,A ;physical block. -3090 E2AE A5 AND L -3091 E2AF B8 CP B -3092 E2B0 23 INC HL ;prepare for the next one. -3093 E2B1 C2 9A E2 JP NZ,WTSEQ8 ;continue until (BLKMASK+1) sectors written. -3094 E2B4 E1 POP HL ;reset next sector number. -3095 E2B5 22 E5 E5 LD (BLKNMBR),HL -3096 E2B8 CD DA DD CALL DEFDMA ;and reset dma address. -3097 E2BB ; -3098 E2BB ; Normal disk write. Set the desired track and sector then -3099 E2BB ; do the actual write. -3100 E2BB ; -3101 E2BB CD D1 DB WTSEQ9: CALL TRKSEC1 ;determine track and sector for this write. -3102 E2BE C1 POP BC ;get write status flag. -3103 E2BF C5 PUSH BC -3104 E2C0 CD B8 DB CALL DOWRITE ;and write this out. -3105 E2C3 C1 POP BC -3106 E2C4 3A E3 E5 LD A,(SAVNREC) ;get number of records in file. -3107 E2C7 21 E1 E5 LD HL,SAVNXT ;get last record written. -3108 E2CA BE CP (HL) -3109 E2CB DA D2 E2 JP C,WTSEQ10 -3110 E2CE 77 LD (HL),A ;we have to update record count. -3111 E2CF 34 INC (HL) -3112 E2D0 0E 02 LD C,2 -3113 E2D2 ; -3114 E2D2 ;* This area has been patched to correct disk update problem -3115 E2D2 ;* when using blocking and de-blocking in the BIOS. -3116 E2D2 ; -3117 E2D2 00 WTSEQ10:NOP ;was 'dcr c' -3118 E2D3 00 NOP ;was 'dcr c' -3119 E2D4 21 00 00 LD HL,0 ;was 'jnz wtseq99' -3120 E2D7 ; -3121 E2D7 ; * End of patch. -3122 E2D7 ; -3123 E2D7 F5 PUSH AF -3124 E2D8 CD 69 DD CALL GETS2 ;set 'extent written to' flag. -3125 E2DB E6 7F AND 7FH ;(* clear bit 7 *) -3126 E2DD 77 LD (HL),A -3127 E2DE F1 POP AF ;get record count for this extent. -3128 E2DF FE 7F WTSEQ99:CP 127 ;is it full? -3129 E2E1 C2 00 E3 JP NZ,WTSEQ12 -3130 E2E4 3A D5 E5 LD A,(MODE) ;yes, are we in sequential mode? -3131 E2E7 FE 01 CP 1 -3132 E2E9 C2 00 E3 JP NZ,WTSEQ12 -3133 E2EC CD D2 DC CALL SETNREC ;yes, set next record number. -3134 E2EF CD 5A E1 CALL GETNEXT ;and get next empty space in directory. -3135 E2F2 21 45 DB LD HL,STATUS ;ok? -3136 E2F5 7E LD A,(HL) -3137 E2F6 B7 OR A -3138 E2F7 C2 FE E2 JP NZ,WTSEQ11 -3139 E2FA 3D DEC A ;yes, set record count to -1. -3140 E2FB 32 E3 E5 LD (SAVNREC),A -3141 E2FE 36 00 WTSEQ11:LD (HL),0 ;clear status. -3142 E300 C3 D2 DC WTSEQ12:JP SETNREC ;set next record to access. -3143 E303 ; -3144 E303 ; For random i/o, set the fcb for the desired record number -3145 E303 ; based on the 'r0,r1,r2' bytes. These bytes in the fcb are -3146 E303 ; used as follows: -3147 E303 ; -3148 E303 ; fcb+35 fcb+34 fcb+33 -3149 E303 ; | 'r-2' | 'r-1' | 'r-0' | -3150 E303 ; |7 0 | 7 0 | 7 0| -3151 E303 ; |0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0| -3152 E303 ; | overflow | | extra | extent | record # | -3153 E303 ; | ______________| |_extent|__number___|_____________| -3154 E303 ; also 's2' -3155 E303 ; -3156 E303 ; On entry, register (C) contains 0ffh if this is a read -3157 E303 ; and thus we can not access unwritten disk space. Otherwise, -3158 E303 ; another extent will be opened (for writing) if required. -3159 E303 ; -3160 E303 AF POSITION: XOR A ;set random i/o flag. -3161 E304 32 D5 E5 LD (MODE),A -3162 E307 ; -3163 E307 ; Special entry (function #40). M/PM ? -3164 E307 ; -3165 E307 C5 POSITN1:PUSH BC ;save read/write flag. -3166 E308 2A 43 DB LD HL,(PARAMS) ;get address of fcb. -3167 E30B EB EX DE,HL -3168 E30C 21 21 00 LD HL,33 ;now get byte 'r0'. -3169 E30F 19 ADD HL,DE -3170 E310 7E LD A,(HL) -3171 E311 E6 7F AND 7FH ;keep bits 0-6 for the record number to access. -3172 E313 F5 PUSH AF -3173 E314 7E LD A,(HL) ;now get bit 7 of 'r0' and bits 0-3 of 'r1'. -3174 E315 17 RLA -3175 E316 23 INC HL -3176 E317 7E LD A,(HL) -3177 E318 17 RLA -3178 E319 E6 1F AND 1FH ;and save this in bits 0-4 of (C). -3179 E31B 4F LD C,A ;this is the extent byte. -3180 E31C 7E LD A,(HL) ;now get the extra extent byte. -3181 E31D 1F RRA -3182 E31E 1F RRA -3183 E31F 1F RRA -3184 E320 1F RRA -3185 E321 E6 0F AND 0FH -3186 E323 47 LD B,A ;and save it in (B). -3187 E324 F1 POP AF ;get record number back to (A). -3188 E325 23 INC HL ;check overflow byte 'r2'. -3189 E326 6E LD L,(HL) -3190 E327 2C INC L -3191 E328 2D DEC L -3192 E329 2E 06 LD L,6 ;prepare for error. -3193 E32B C2 8B E3 JP NZ,POSITN5 ;out of disk space error. -3194 E32E 21 20 00 LD HL,32 ;store record number into fcb. -3195 E331 19 ADD HL,DE -3196 E332 77 LD (HL),A -3197 E333 21 0C 00 LD HL,12 ;and now check the extent byte. -3198 E336 19 ADD HL,DE -3199 E337 79 LD A,C -3200 E338 96 SUB (HL) ;same extent as before? -3201 E339 C2 47 E3 JP NZ,POSITN2 -3202 E33C 21 0E 00 LD HL,14 ;yes, check extra extent byte 's2' also. -3203 E33F 19 ADD HL,DE -3204 E340 78 LD A,B -3205 E341 96 SUB (HL) -3206 E342 E6 7F AND 7FH -3207 E344 CA 7F E3 JP Z,POSITN3 ;same, we are almost done then. -3208 E347 ; -3209 E347 ; Get here when another extent is required. -3210 E347 ; -3211 E347 C5 POSITN2:PUSH BC -3212 E348 D5 PUSH DE -3213 E349 CD A2 E0 CALL CLOSEIT ;close current extent. -3214 E34C D1 POP DE -3215 E34D C1 POP BC -3216 E34E 2E 03 LD L,3 ;prepare for error. -3217 E350 3A 45 DB LD A,(STATUS) -3218 E353 3C INC A -3219 E354 CA 84 E3 JP Z,POSITN4 ;close error. -3220 E357 21 0C 00 LD HL,12 ;put desired extent into fcb now. -3221 E35A 19 ADD HL,DE -3222 E35B 71 LD (HL),C -3223 E35C 21 0E 00 LD HL,14 ;and store extra extent byte 's2'. -3224 E35F 19 ADD HL,DE -3225 E360 70 LD (HL),B -3226 E361 CD 51 E0 CALL OPENIT ;try and get this extent. -3227 E364 3A 45 DB LD A,(STATUS) ;was it there? -3228 E367 3C INC A -3229 E368 C2 7F E3 JP NZ,POSITN3 -3230 E36B C1 POP BC ;no. can we create a new one (writing?). -3231 E36C C5 PUSH BC -3232 E36D 2E 04 LD L,4 ;prepare for error. -3233 E36F 0C INC C -3234 E370 CA 84 E3 JP Z,POSITN4 ;nope, reading unwritten space error. -3235 E373 CD 24 E1 CALL GETEMPTY ;yes we can, try to find space. -3236 E376 2E 05 LD L,5 ;prepare for error. -3237 E378 3A 45 DB LD A,(STATUS) -3238 E37B 3C INC A -3239 E37C CA 84 E3 JP Z,POSITN4 ;out of space? -3240 E37F ; -3241 E37F ; Normal return location. Clear error code and return. -3242 E37F ; -3243 E37F C1 POSITN3:POP BC ;restore stack. -3244 E380 AF XOR A ;and clear error code byte. -3245 E381 C3 01 DB JP SETSTAT -3246 E384 ; -3247 E384 ; Error. Set the 's2' byte to indicate this (why?). -3248 E384 ; -3249 E384 E5 POSITN4:PUSH HL -3250 E385 CD 69 DD CALL GETS2 -3251 E388 36 C0 LD (HL),0C0H -3252 E38A E1 POP HL -3253 E38B ; -3254 E38B ; Return with error code (presently in L). -3255 E38B ; -3256 E38B C1 POSITN5:POP BC -3257 E38C 7D LD A,L ;get error code. -3258 E38D 32 45 DB LD (STATUS),A -3259 E390 C3 78 DD JP SETS2B7 -3260 E393 ; -3261 E393 ; Read a random record. -3262 E393 ; -3263 E393 0E FF READRAN:LD C,0FFH ;set 'read' status. -3264 E395 CD 03 E3 CALL POSITION ;position the file to proper record. -3265 E398 CC C1 E1 CALL Z,RDSEQ1 ;and read it as usual (if no errors). -3266 E39B C9 RET -3267 E39C ; -3268 E39C ; Write to a random record. -3269 E39C ; -3270 E39C 0E 00 WRITERAN: LD C,0 ;set 'writing' flag. -3271 E39E CD 03 E3 CALL POSITION ;position the file to proper record. -3272 E3A1 CC 03 E2 CALL Z,WTSEQ1 ;and write as usual (if no errors). -3273 E3A4 C9 RET -3274 E3A5 ; -3275 E3A5 ; Compute the random record number. Enter with (HL) pointing -3276 E3A5 ; to a fcb an (DE) contains a relative location of a record -3277 E3A5 ; number. On exit, (C) contains the 'r0' byte, (B) the 'r1' -3278 E3A5 ; byte, and (A) the 'r2' byte. -3279 E3A5 ; -3280 E3A5 ; On return, the zero flag is set if the record is within -3281 E3A5 ; bounds. Otherwise, an overflow occured. -3282 E3A5 ; -3283 E3A5 EB COMPRAND: EX DE,HL ;save fcb pointer in (DE). -3284 E3A6 19 ADD HL,DE ;compute relative position of record #. -3285 E3A7 4E LD C,(HL) ;get record number into (BC). -3286 E3A8 06 00 LD B,0 -3287 E3AA 21 0C 00 LD HL,12 ;now get extent. -3288 E3AD 19 ADD HL,DE -3289 E3AE 7E LD A,(HL) ;compute (BC)=(record #)+(extent)*128. -3290 E3AF 0F RRCA ;move lower bit into bit 7. -3291 E3B0 E6 80 AND 80H ;and ignore all other bits. -3292 E3B2 81 ADD A,C ;add to our record number. -3293 E3B3 4F LD C,A -3294 E3B4 3E 00 LD A,0 ;take care of any carry. -3295 E3B6 88 ADC A,B -3296 E3B7 47 LD B,A -3297 E3B8 7E LD A,(HL) ;now get the upper bits of extent into -3298 E3B9 0F RRCA ;bit positions 0-3. -3299 E3BA E6 0F AND 0FH ;and ignore all others. -3300 E3BC 80 ADD A,B ;add this in to 'r1' byte. -3301 E3BD 47 LD B,A -3302 E3BE 21 0E 00 LD HL,14 ;get the 's2' byte (extra extent). -3303 E3C1 19 ADD HL,DE -3304 E3C2 7E LD A,(HL) -3305 E3C3 87 ADD A,A ;and shift it left 4 bits (bits 4-7). -3306 E3C4 87 ADD A,A -3307 E3C5 87 ADD A,A -3308 E3C6 87 ADD A,A -3309 E3C7 F5 PUSH AF ;save carry flag (bit 0 of flag byte). -3310 E3C8 80 ADD A,B ;now add extra extent into 'r1'. -3311 E3C9 47 LD B,A -3312 E3CA F5 PUSH AF ;and save carry (overflow byte 'r2'). -3313 E3CB E1 POP HL ;bit 0 of (L) is the overflow indicator. -3314 E3CC 7D LD A,L -3315 E3CD E1 POP HL ;and same for first carry flag. -3316 E3CE B5 OR L ;either one of these set? -3317 E3CF E6 01 AND 01H ;only check the carry flags. -3318 E3D1 C9 RET -3319 E3D2 ; -3320 E3D2 ; Routine to setup the fcb (bytes 'r0', 'r1', 'r2') to -3321 E3D2 ; reflect the last record used for a random (or other) file. -3322 E3D2 ; This reads the directory and looks at all extents computing -3323 E3D2 ; the largerst record number for each and keeping the maximum -3324 E3D2 ; value only. Then 'r0', 'r1', and 'r2' will reflect this -3325 E3D2 ; maximum record number. This is used to compute the space used -3326 E3D2 ; by a random file. -3327 E3D2 ; -3328 E3D2 0E 0C RANSIZE:LD C,12 ;look thru directory for first entry with -3329 E3D4 CD 18 DF CALL FINDFST ;this name. -3330 E3D7 2A 43 DB LD HL,(PARAMS) ;zero out the 'r0, r1, r2' bytes. -3331 E3DA 11 21 00 LD DE,33 -3332 E3DD 19 ADD HL,DE -3333 E3DE E5 PUSH HL -3334 E3DF 72 LD (HL),D ;note that (D)=0. -3335 E3E0 23 INC HL -3336 E3E1 72 LD (HL),D -3337 E3E2 23 INC HL -3338 E3E3 72 LD (HL),D -3339 E3E4 CD F5 DD RANSIZ1:CALL CKFILPOS ;is there an extent to process? -3340 E3E7 CA 0C E4 JP Z,RANSIZ3 ;no, we are done. -3341 E3EA CD 5E DD CALL FCB2HL ;set (HL) pointing to proper fcb in dir. -3342 E3ED 11 0F 00 LD DE,15 ;point to last record in extent. -3343 E3F0 CD A5 E3 CALL COMPRAND ;and compute random parameters. -3344 E3F3 E1 POP HL -3345 E3F4 E5 PUSH HL ;now check these values against those -3346 E3F5 5F LD E,A ;already in fcb. -3347 E3F6 79 LD A,C ;the carry flag will be set if those -3348 E3F7 96 SUB (HL) ;in the fcb represent a larger size than -3349 E3F8 23 INC HL ;this extent does. -3350 E3F9 78 LD A,B -3351 E3FA 9E SBC A,(HL) -3352 E3FB 23 INC HL -3353 E3FC 7B LD A,E -3354 E3FD 9E SBC A,(HL) -3355 E3FE DA 06 E4 JP C,RANSIZ2 -3356 E401 73 LD (HL),E ;we found a larger (in size) extent. -3357 E402 2B DEC HL ;stuff these values into fcb. -3358 E403 70 LD (HL),B -3359 E404 2B DEC HL -3360 E405 71 LD (HL),C -3361 E406 CD 2D DF RANSIZ2:CALL FINDNXT ;now get the next extent. -3362 E409 C3 E4 E3 JP RANSIZ1 ;continue til all done. -3363 E40C E1 RANSIZ3:POP HL ;we are done, restore the stack and -3364 E40D C9 RET ;return. -3365 E40E ; -3366 E40E ; Function to return the random record position of a given -3367 E40E ; file which has been read in sequential mode up to now. -3368 E40E ; -3369 E40E 2A 43 DB SETRAN: LD HL,(PARAMS) ;point to fcb. -3370 E411 11 20 00 LD DE,32 ;and to last used record. -3371 E414 CD A5 E3 CALL COMPRAND ;compute random position. -3372 E417 21 21 00 LD HL,33 ;now stuff these values into fcb. -3373 E41A 19 ADD HL,DE -3374 E41B 71 LD (HL),C ;move 'r0'. -3375 E41C 23 INC HL -3376 E41D 70 LD (HL),B ;and 'r1'. -3377 E41E 23 INC HL -3378 E41F 77 LD (HL),A ;and lastly 'r2'. -3379 E420 C9 RET -3380 E421 ; -3381 E421 ; This routine select the drive specified in (ACTIVE) and -3382 E421 ; update the login vector and bitmap table if this drive was -3383 E421 ; not already active. -3384 E421 ; -3385 E421 2A AF E5 LOGINDRV: LD HL,(LOGIN) ;get the login vector. -3386 E424 3A 42 DB LD A,(ACTIVE) ;get the default drive. -3387 E427 4F LD C,A -3388 E428 CD EA DC CALL SHIFTR ;position active bit for this drive -3389 E42B E5 PUSH HL ;into bit 0. -3390 E42C EB EX DE,HL -3391 E42D CD 59 DB CALL SELECT ;select this drive. -3392 E430 E1 POP HL -3393 E431 CC 47 DB CALL Z,SLCTERR ;valid drive? -3394 E434 7D LD A,L ;is this a newly activated drive? -3395 E435 1F RRA -3396 E436 D8 RET C -3397 E437 2A AF E5 LD HL,(LOGIN) ;yes, update the login vector. -3398 E43A 4D LD C,L -3399 E43B 44 LD B,H -3400 E43C CD 0B DD CALL SETBIT -3401 E43F 22 AF E5 LD (LOGIN),HL ;and save. -3402 E442 C3 A3 DE JP BITMAP ;now update the bitmap. -3403 E445 ; -3404 E445 ; Function to set the active disk number. -3405 E445 ; -3406 E445 3A D6 E5 SETDSK: LD A,(EPARAM) ;get parameter passed and see if this -3407 E448 21 42 DB LD HL,ACTIVE ;represents a change in drives. -3408 E44B BE CP (HL) -3409 E44C C8 RET Z -3410 E44D 77 LD (HL),A ;yes it does, log it in. -3411 E44E C3 21 E4 JP LOGINDRV -3412 E451 ; -3413 E451 ; This is the 'auto disk select' routine. The firsst byte -3414 E451 ; of the fcb is examined for a drive specification. If non -3415 E451 ; zero then the drive will be selected and loged in. -3416 E451 ; -3417 E451 3E FF AUTOSEL:LD A,0FFH ;say 'auto-select activated'. -3418 E453 32 DE E5 LD (AUTO),A -3419 E456 2A 43 DB LD HL,(PARAMS) ;get drive specified. -3420 E459 7E LD A,(HL) -3421 E45A E6 1F AND 1FH ;look at lower 5 bits. -3422 E45C 3D DEC A ;adjust for (1=A, 2=B) etc. -3423 E45D 32 D6 E5 LD (EPARAM),A ;and save for the select routine. -3424 E460 FE 1E CP 1EH ;check for 'no change' condition. -3425 E462 D2 75 E4 JP NC,AUTOSL1 ;yes, don't change. -3426 E465 3A 42 DB LD A,(ACTIVE) ;we must change, save currently active -3427 E468 32 DF E5 LD (OLDDRV),A ;drive. -3428 E46B 7E LD A,(HL) ;and save first byte of fcb also. -3429 E46C 32 E0 E5 LD (AUTOFLAG),A ;this must be non-zero. -3430 E46F E6 E0 AND 0E0H ;whats this for (bits 6,7 are used for -3431 E471 77 LD (HL),A ;something)? -3432 E472 CD 45 E4 CALL SETDSK ;select and log in this drive. -3433 E475 3A 41 DB AUTOSL1:LD A,(USERNO) ;move user number into fcb. -3434 E478 2A 43 DB LD HL,(PARAMS) ;(* upper half of first byte *) -3435 E47B B6 OR (HL) -3436 E47C 77 LD (HL),A -3437 E47D C9 RET ;and return (all done). -3438 E47E ; -3439 E47E ; Function to return the current cp/m version number. -3440 E47E ; -3441 E47E 3E 22 GETVER: LD A,022H ;version 2.2 -3442 E480 C3 01 DB JP SETSTAT -3443 E483 ; -3444 E483 ; Function to reset the disk system. -3445 E483 ; -3446 E483 21 00 00 RSTDSK: LD HL,0 ;clear write protect status and log -3447 E486 22 AD E5 LD (WRTPRT),HL ;in vector. -3448 E489 22 AF E5 LD (LOGIN),HL -3449 E48C AF XOR A ;select drive 'A'. -3450 E48D 32 42 DB LD (ACTIVE),A -3451 E490 21 80 00 LD HL,TBUFF ;setup default dma address. -3452 E493 22 B1 E5 LD (USERDMA),HL -3453 E496 CD DA DD CALL DEFDMA -3454 E499 C3 21 E4 JP LOGINDRV ;now log in drive 'A'. -3455 E49C ; -3456 E49C ; Function to open a specified file. -3457 E49C ; -3458 E49C CD 72 DD OPENFIL:CALL CLEARS2 ;clear 's2' byte. -3459 E49F CD 51 E4 CALL AUTOSEL ;select proper disk. -3460 E4A2 C3 51 E0 JP OPENIT ;and open the file. -3461 E4A5 ; -3462 E4A5 ; Function to close a specified file. -3463 E4A5 ; -3464 E4A5 CD 51 E4 CLOSEFIL: CALL AUTOSEL ;select proper disk. -3465 E4A8 C3 A2 E0 JP CLOSEIT ;and close the file. -3466 E4AB ; -3467 E4AB ; Function to return the first occurence of a specified file -3468 E4AB ; name. If the first byte of the fcb is '?' then the name will -3469 E4AB ; not be checked (get the first entry no matter what). -3470 E4AB ; -3471 E4AB 0E 00 GETFST: LD C,0 ;prepare for special search. -3472 E4AD EB EX DE,HL -3473 E4AE 7E LD A,(HL) ;is first byte a '?'? -3474 E4AF FE 3F CP '?' -3475 E4B1 CA C2 E4 JP Z,GETFST1 ;yes, just get very first entry (zero length match). -3476 E4B4 CD A6 DC CALL SETEXT ;get the extension byte from fcb. -3477 E4B7 7E LD A,(HL) ;is it '?'? if yes, then we want -3478 E4B8 FE 3F CP '?' ;an entry with a specific 's2' byte. -3479 E4BA C4 72 DD CALL NZ,CLEARS2 ;otherwise, look for a zero 's2' byte. -3480 E4BD CD 51 E4 CALL AUTOSEL ;select proper drive. -3481 E4C0 0E 0F LD C,15 ;compare bytes 0-14 in fcb (12&13 excluded). -3482 E4C2 CD 18 DF GETFST1:CALL FINDFST ;find an entry and then move it into -3483 E4C5 C3 E9 DD JP MOVEDIR ;the users dma space. -3484 E4C8 ; -3485 E4C8 ; Function to return the next occurence of a file name. -3486 E4C8 ; -3487 E4C8 2A D9 E5 GETNXT: LD HL,(SAVEFCB) ;restore pointers. note that no -3488 E4CB 22 43 DB LD (PARAMS),HL ;other dbos calls are allowed. -3489 E4CE CD 51 E4 CALL AUTOSEL ;no error will be returned, but the -3490 E4D1 CD 2D DF CALL FINDNXT ;results will be wrong. -3491 E4D4 C3 E9 DD JP MOVEDIR -3492 E4D7 ; -3493 E4D7 ; Function to delete a file by name. -3494 E4D7 ; -3495 E4D7 CD 51 E4 DELFILE:CALL AUTOSEL ;select proper drive. -3496 E4DA CD 9C DF CALL ERAFILE ;erase the file. -3497 E4DD C3 01 DF JP STSTATUS ;set status and return. -3498 E4E0 ; -3499 E4E0 ; Function to execute a sequential read of the specified -3500 E4E0 ; record number. -3501 E4E0 ; -3502 E4E0 CD 51 E4 READSEQ:CALL AUTOSEL ;select proper drive then read. -3503 E4E3 C3 BC E1 JP RDSEQ -3504 E4E6 ; -3505 E4E6 ; Function to write the net sequential record. -3506 E4E6 ; -3507 E4E6 CD 51 E4 WRTSEQ: CALL AUTOSEL ;select proper drive then write. -3508 E4E9 C3 FE E1 JP WTSEQ -3509 E4EC ; -3510 E4EC ; Create a file function. -3511 E4EC ; -3512 E4EC CD 72 DD FCREATE:CALL CLEARS2 ;clear the 's2' byte on all creates. -3513 E4EF CD 51 E4 CALL AUTOSEL ;select proper drive and get the next -3514 E4F2 C3 24 E1 JP GETEMPTY ;empty directory space. -3515 E4F5 ; -3516 E4F5 ; Function to rename a file. -3517 E4F5 ; -3518 E4F5 CD 51 E4 RENFILE:CALL AUTOSEL ;select proper drive and then switch -3519 E4F8 CD 16 E0 CALL CHGNAMES ;file names. -3520 E4FB C3 01 DF JP STSTATUS -3521 E4FE ; -3522 E4FE ; Function to return the login vector. -3523 E4FE ; -3524 E4FE 2A AF E5 GETLOG: LD HL,(LOGIN) -3525 E501 C3 29 E5 JP GETPRM1 -3526 E504 ; -3527 E504 ; Function to return the current disk assignment. -3528 E504 ; -3529 E504 3A 42 DB GETCRNT:LD A,(ACTIVE) -3530 E507 C3 01 DB JP SETSTAT -3531 E50A ; -3532 E50A ; Function to set the dma address. -3533 E50A ; -3534 E50A EB PUTDMA: EX DE,HL -3535 E50B 22 B1 E5 LD (USERDMA),HL ;save in our space and then get to -3536 E50E C3 DA DD JP DEFDMA ;the bios with this also. -3537 E511 ; -3538 E511 ; Function to return the allocation vector. -3539 E511 ; -3540 E511 2A BF E5 GETALOC:LD HL,(ALOCVECT) -3541 E514 C3 29 E5 JP GETPRM1 -3542 E517 ; -3543 E517 ; Function to return the read-only status vector. -3544 E517 ; -3545 E517 2A AD E5 GETROV: LD HL,(WRTPRT) -3546 E51A C3 29 E5 JP GETPRM1 -3547 E51D ; -3548 E51D ; Function to set the file attributes (read-only, system). -3549 E51D ; -3550 E51D CD 51 E4 SETATTR:CALL AUTOSEL ;select proper drive then save attributes. -3551 E520 CD 3B E0 CALL SAVEATTR -3552 E523 C3 01 DF JP STSTATUS -3553 E526 ; -3554 E526 ; Function to return the address of the disk parameter block -3555 E526 ; for the current drive. -3556 E526 ; -3557 E526 2A BB E5 GETPARM:LD HL,(DISKPB) -3558 E529 22 45 DB GETPRM1:LD (STATUS),HL -3559 E52C C9 RET -3560 E52D ; -3561 E52D ; Function to get or set the user number. If (E) was (FF) -3562 E52D ; then this is a request to return the current user number. -3563 E52D ; Else set the user number from (E). -3564 E52D ; -3565 E52D 3A D6 E5 GETUSER:LD A,(EPARAM) ;get parameter. -3566 E530 FE FF CP 0FFH ;get user number? -3567 E532 C2 3B E5 JP NZ,SETUSER -3568 E535 3A 41 DB LD A,(USERNO) ;yes, just do it. -3569 E538 C3 01 DB JP SETSTAT -3570 E53B E6 1F SETUSER:AND 1FH ;no, we should set it instead. keep low -3571 E53D 32 41 DB LD (USERNO),A ;bits (0-4) only. -3572 E540 C9 RET -3573 E541 ; -3574 E541 ; Function to read a random record from a file. -3575 E541 ; -3576 E541 CD 51 E4 RDRANDOM: CALL AUTOSEL ;select proper drive and read. -3577 E544 C3 93 E3 JP READRAN -3578 E547 ; -3579 E547 ; Function to compute the file size for random files. -3580 E547 ; -3581 E547 CD 51 E4 WTRANDOM: CALL AUTOSEL ;select proper drive and write. -3582 E54A C3 9C E3 JP WRITERAN -3583 E54D ; -3584 E54D ; Function to compute the size of a random file. -3585 E54D ; -3586 E54D CD 51 E4 FILESIZE: CALL AUTOSEL ;select proper drive and check file length -3587 E550 C3 D2 E3 JP RANSIZE -3588 E553 ; -3589 E553 ; Function #37. This allows a program to log off any drives. -3590 E553 ; On entry, set (DE) to contain a word with bits set for those -3591 E553 ; drives that are to be logged off. The log-in vector and the -3592 E553 ; write protect vector will be updated. This must be a M/PM -3593 E553 ; special function. -3594 E553 ; -3595 E553 2A 43 DB LOGOFF: LD HL,(PARAMS) ;get drives to log off. -3596 E556 7D LD A,L ;for each bit that is set, we want -3597 E557 2F CPL ;to clear that bit in (LOGIN) -3598 E558 5F LD E,A ;and (WRTPRT). -3599 E559 7C LD A,H -3600 E55A 2F CPL -3601 E55B 2A AF E5 LD HL,(LOGIN) ;reset the login vector. -3602 E55E A4 AND H -3603 E55F 57 LD D,A -3604 E560 7D LD A,L -3605 E561 A3 AND E -3606 E562 5F LD E,A -3607 E563 2A AD E5 LD HL,(WRTPRT) -3608 E566 EB EX DE,HL -3609 E567 22 AF E5 LD (LOGIN),HL ;and save. -3610 E56A 7D LD A,L ;now do the write protect vector. -3611 E56B A3 AND E -3612 E56C 6F LD L,A -3613 E56D 7C LD A,H -3614 E56E A2 AND D -3615 E56F 67 LD H,A -3616 E570 22 AD E5 LD (WRTPRT),HL ;and save. all done. -3617 E573 C9 RET -3618 E574 ; -3619 E574 ; Get here to return to the user. -3620 E574 ; -3621 E574 3A DE E5 GOBACK: LD A,(AUTO) ;was auto select activated? -3622 E577 B7 OR A -3623 E578 CA 91 E5 JP Z,GOBACK1 -3624 E57B 2A 43 DB LD HL,(PARAMS) ;yes, but was a change made? -3625 E57E 36 00 LD (HL),0 ;(* reset first byte of fcb *) -3626 E580 3A E0 E5 LD A,(AUTOFLAG) -3627 E583 B7 OR A -3628 E584 CA 91 E5 JP Z,GOBACK1 -3629 E587 77 LD (HL),A ;yes, reset first byte properly. -3630 E588 3A DF E5 LD A,(OLDDRV) ;and get the old drive and select it. -3631 E58B 32 D6 E5 LD (EPARAM),A -3632 E58E CD 45 E4 CALL SETDSK -3633 E591 2A 0F DB GOBACK1:LD HL,(USRSTACK) ;reset the users stack pointer. -3634 E594 F9 LD SP,HL -3635 E595 2A 45 DB LD HL,(STATUS) ;get return status. -3636 E598 7D LD A,L ;force version 1.4 compatability. -3637 E599 44 LD B,H -3638 E59A C9 RET ;and go back to user. -3639 E59B ; -3640 E59B ; Function #40. This is a special entry to do random i/o. -3641 E59B ; For the case where we are writing to unused disk space, this -3642 E59B ; space will be zeroed out first. This must be a M/PM special -3643 E59B ; purpose function, because why would any normal program even -3644 E59B ; care about the previous contents of a sector about to be -3645 E59B ; written over. -3646 E59B ; -3647 E59B CD 51 E4 WTSPECL:CALL AUTOSEL ;select proper drive. -3648 E59E 3E 02 LD A,2 ;use special write mode. -3649 E5A0 32 D5 E5 LD (MODE),A -3650 E5A3 0E 00 LD C,0 ;set write indicator. -3651 E5A5 CD 07 E3 CALL POSITN1 ;position the file. -3652 E5A8 CC 03 E2 CALL Z,WTSEQ1 ;and write (if no errors). -3653 E5AB C9 RET -3654 E5AC ; -3655 E5AC ;************************************************************** -3656 E5AC ;* -3657 E5AC ;* BDOS data storage pool. -3658 E5AC ;* -3659 E5AC ;************************************************************** -3660 E5AC ; -3661 E5AC E5 EMPTYFCB: .DB 0E5H ;empty directory segment indicator. -3662 E5AD 00 00 WRTPRT: .DW 0 ;write protect status for all 16 drives. -3663 E5AF 00 00 LOGIN: .DW 0 ;drive active word (1 bit per drive). -3664 E5B1 80 00 USERDMA:.DW 080H ;user's dma address (defaults to 80h). -3665 E5B3 ; -3666 E5B3 ; Scratch areas from parameter block. -3667 E5B3 ; -3668 E5B3 00 00 SCRATCH1: .DW 0 ;relative position within dir segment for file (0-3). -3669 E5B5 00 00 SCRATCH2: .DW 0 ;last selected track number. -3670 E5B7 00 00 SCRATCH3: .DW 0 ;last selected sector number. -3671 E5B9 ; -3672 E5B9 ; Disk storage areas from parameter block. -3673 E5B9 ; -3674 E5B9 00 00 DIRBUF: .DW 0 ;address of directory buffer to use. -3675 E5BB 00 00 DISKPB: .DW 0 ;contains address of disk parameter block. -3676 E5BD 00 00 CHKVECT:.DW 0 ;address of check vector. -3677 E5BF 00 00 ALOCVECT: .DW 0 ;address of allocation vector (bit map). -3678 E5C1 ; -3679 E5C1 ; Parameter block returned from the bios. -3680 E5C1 ; -3681 E5C1 00 00 SECTORS:.DW 0 ;sectors per track from bios. -3682 E5C3 00 BLKSHFT:.DB 0 ;block shift. -3683 E5C4 00 BLKMASK:.DB 0 ;block mask. -3684 E5C5 00 EXTMASK:.DB 0 ;extent mask. -3685 E5C6 00 00 DSKSIZE:.DW 0 ;disk size from bios (number of blocks-1). -3686 E5C8 00 00 DIRSIZE:.DW 0 ;directory size. -3687 E5CA 00 00 ALLOC0: .DW 0 ;storage for first bytes of bit map (dir space used). -3688 E5CC 00 00 ALLOC1: .DW 0 -3689 E5CE 00 00 OFFSET: .DW 0 ;first usable track number. -3690 E5D0 00 00 XLATE: .DW 0 ;sector translation table address. -3691 E5D2 ; -3692 E5D2 ; -3693 E5D2 00 CLOSEFLG: .DB 0 ;close flag (=0ffh is extent written ok). -3694 E5D3 00 RDWRTFLG: .DB 0 ;read/write flag (0ffh=read, 0=write). -3695 E5D4 00 FNDSTAT:.DB 0 ;filename found status (0=found first entry). -3696 E5D5 00 MODE: .DB 0 ;I/o mode select (0=random, 1=sequential, 2=special random). -3697 E5D6 00 EPARAM: .DB 0 ;storage for register (E) on entry to bdos. -3698 E5D7 00 RELBLOCK: .DB 0 ;relative position within fcb of block number written. -3699 E5D8 00 COUNTER:.DB 0 ;byte counter for directory name searches. -3700 E5D9 00 00 00 00 SAVEFCB:.DW 0,0 ;save space for address of fcb (for directory searches). -3701 E5DD 00 BIGDISK:.DB 0 ;if =0 then disk is > 256 blocks long. -3702 E5DE 00 AUTO: .DB 0 ;if non-zero, then auto select activated. -3703 E5DF 00 OLDDRV: .DB 0 ;on auto select, storage for previous drive. -3704 E5E0 00 AUTOFLAG: .DB 0 ;if non-zero, then auto select changed drives. -3705 E5E1 00 SAVNXT: .DB 0 ;storage for next record number to access. -3706 E5E2 00 SAVEXT: .DB 0 ;storage for extent number of file. -3707 E5E3 00 00 SAVNREC:.DW 0 ;storage for number of records in file. -3708 E5E5 00 00 BLKNMBR:.DW 0 ;block number (physical sector) used within a file or logical sect -3709 E5E7 00 00 LOGSECT:.DW 0 ;starting logical (128 byte) sector of block (physical sector). -3710 E5E9 00 FCBPOS: .DB 0 ;relative position within buffer for fcb of file of interest. -3711 E5EA 00 00 FILEPOS:.DW 0 ;files position within directory (0 to max entries -1). -3712 E5EC ; -3713 E5EC ; Disk directory buffer checksum bytes. One for each of the -3714 E5EC ; 16 possible drives. -3715 E5EC ; -3716 E5EC 000000000000CKSUMTBL: .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -3716 E5F2 00000000000000000000 -3717 E5FC ; -3718 E5FC ; Extra space ? -3719 E5FC ; -3720 E5FC 00 00 00 00 .DB 0,0,0,0 -3721 E600 ; -3722 E600 ;************************************************************** -3723 E600 ;* -3724 E600 ;* B I O S J U M P T A B L E -3725 E600 ;* -3726 E600 ;************************************************************** -3727 E600 ; -3728 E600 C3 00 00 BOOT: JP 0 ;NOTE WE USE FAKE DESTINATIONS -3729 E603 C3 00 00 WBOOT: JP 0 -3730 E606 C3 00 00 CONST: JP 0 -3731 E609 C3 00 00 CONIN: JP 0 -3732 E60C C3 00 00 CONOUT: JP 0 -3733 E60F C3 00 00 LIST: JP 0 -3734 E612 C3 00 00 PUNCH: JP 0 -3735 E615 C3 00 00 READER: JP 0 -3736 E618 C3 00 00 HOME: JP 0 -3737 E61B C3 00 00 SELDSK: JP 0 -3738 E61E C3 00 00 SETTRK: JP 0 -3739 E621 C3 00 00 SETSEC: JP 0 -3740 E624 C3 00 00 SETDMA: JP 0 -3741 E627 C3 00 00 READ: JP 0 -3742 E62A C3 00 00 WRITE: JP 0 -3743 E62D C3 00 00 PRSTAT: JP 0 -3744 E630 C3 00 00 SECTRN: JP 0 -3745 E633 ; -3746 E633 ;* -3747 E633 ;****************** E N D O F C P / M ***************** -3748 E633 ;* -3749 E633 -3750 E633 .END -tasm: Number of errors = 0 +0001 0000 ;************************************************************** +0002 0000 ;* +0003 0000 ;* C P / M version 2 . 2 +0004 0000 ;* +0005 0000 ;* Reconstructed from memory image on February 27, 1981 +0006 0000 ;* +0007 0000 ;* by Clark A. Calkins +0008 0000 ;* +0009 0000 ;************************************************************** +0010 0000 ; +0011 0000 ; Set memory limit here. This is the amount of contigeous +0012 0000 ; ram starting from 0000. CP/M will reside at the end of this space. +0013 0000 ; +0014 0000 +0015 0000 IOBYTE .EQU 3 ;i/o definition byte. +0016 0000 TDRIVE .EQU 4 ;current drive name and user number. +0017 0000 ENTRY .EQU 5 ;entry point for the cp/m bdos. +0018 0000 TFCB .EQU 5CH ;default file control block. +0019 0000 TBUFF .EQU 80H ;i/o buffer and command line storage. +0020 0000 TBASE .EQU 100H ;transiant program storage area. +0021 0000 ; +0022 0000 ; Set control character equates. +0023 0000 ; +0024 0000 CNTRLC .EQU 3 ;control-c +0025 0000 CNTRLE .EQU 05H ;control-e +0026 0000 BS .EQU 08H ;backspace +0027 0000 TAB .EQU 09H ;tab +0028 0000 LF .EQU 0AH ;line feed +0029 0000 FF .EQU 0CH ;form feed +0030 0000 CR .EQU 0DH ;carriage return +0031 0000 CNTRLP .EQU 10H ;control-p +0032 0000 CNTRLR .EQU 12H ;control-r +0033 0000 CNTRLS .EQU 13H ;control-s +0034 0000 CNTRLU .EQU 15H ;control-u +0035 0000 CNTRLX .EQU 18H ;control-x +0036 0000 CNTRLZ .EQU 1AH ;control-z (end-of-file mark) +0037 0000 DEL .EQU 7FH ;rubout +0038 0000 ; +0039 0000 ; Set origin for CP/M +0040 0000 ; +0041 D000 .ORG 0D000H +0042 D000 ; +0043 D000 C3 5C D3 CBASE: JP COMMAND ;execute command processor (ccp). +0044 D003 C3 58 D3 JP CLEARBUF ;entry to empty input buffer before starting ccp. +0045 D006 +0046 D006 ; +0047 D006 ; Standard cp/m ccp input buffer. Format is (max length), +0048 D006 ; (actual length), (char #1), (char #2), (char #3), etc. +0049 D006 ; +0050 D006 7F INBUFF: .DB 127 ;length of input buffer. +0051 D007 00 .DB 0 ;current length of contents. +0052 D008 43 6F 70 79 .TEXT "Copyright" +0052 D00C 72 69 67 68 +0052 D010 74 +0053 D011 20 31 39 37 .TEXT " 1979 (c) by Digital Research " +0053 D015 39 20 28 63 +0053 D019 29 20 62 79 +0053 D01D 20 44 69 67 +0053 D021 69 74 61 6C +0053 D025 20 52 65 73 +0053 D029 65 61 72 63 +0053 D02D 68 20 20 20 +0053 D031 20 20 20 +0054 D034 00 00 00 00 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0054 D038 00 00 00 00 +0054 D03C 00 00 00 00 +0054 D040 00 00 00 00 +0054 D044 00 00 00 00 +0054 D048 00 00 00 +0055 D04B 00 00 00 00 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0055 D04F 00 00 00 00 +0055 D053 00 00 00 00 +0055 D057 00 00 00 00 +0055 D05B 00 00 00 00 +0055 D05F 00 00 00 +0056 D062 00 00 00 00 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0056 D066 00 00 00 00 +0056 D06A 00 00 00 00 +0056 D06E 00 00 00 00 +0056 D072 00 00 00 00 +0056 D076 00 00 00 +0057 D079 00 00 00 00 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +0057 D07D 00 00 00 00 +0057 D081 00 00 00 00 +0057 D085 00 00 00 +0058 D088 08 D0 INPOINT:.DW INBUFF+2 ;input line pointer +0059 D08A 00 00 NAMEPNT:.DW 0 ;input line pointer used for error message. Points to +0060 D08C ; ;start of name in error. +0061 D08C ; +0062 D08C ; Routine to print (A) on the console. All registers used. +0063 D08C ; +0064 D08C 5F PRINT: LD E,A ;setup bdos call. +0065 D08D 0E 02 LD C,2 +0066 D08F C3 05 00 JP ENTRY +0067 D092 ; +0068 D092 ; Routine to print (A) on the console and to save (BC). +0069 D092 ; +0070 D092 C5 PRINTB: PUSH BC +0071 D093 CD 8C D0 CALL PRINT +0072 D096 C1 POP BC +0073 D097 C9 RET +0074 D098 ; +0075 D098 ; Routine to send a carriage return, line feed combination +0076 D098 ; to the console. +0077 D098 ; +0078 D098 3E 0D CRLF: LD A,CR +0079 D09A CD 92 D0 CALL PRINTB +0080 D09D 3E 0A LD A,LF +0081 D09F C3 92 D0 JP PRINTB +0082 D0A2 ; +0083 D0A2 ; Routine to send one space to the console and save (BC). +0084 D0A2 ; +0085 D0A2 3E 20 SPACE: LD A,' ' +0086 D0A4 C3 92 D0 JP PRINTB +0087 D0A7 ; +0088 D0A7 ; Routine to print character string pointed to be (BC) on the +0089 D0A7 ; console. It must terminate with a null byte. +0090 D0A7 ; +0091 D0A7 C5 PLINE: PUSH BC +0092 D0A8 CD 98 D0 CALL CRLF +0093 D0AB E1 POP HL +0094 D0AC 7E PLINE2: LD A,(HL) +0095 D0AD B7 OR A +0096 D0AE C8 RET Z +0097 D0AF 23 INC HL +0098 D0B0 E5 PUSH HL +0099 D0B1 CD 8C D0 CALL PRINT +0100 D0B4 E1 POP HL +0101 D0B5 C3 AC D0 JP PLINE2 +0102 D0B8 ; +0103 D0B8 ; Routine to reset the disk system. +0104 D0B8 ; +0105 D0B8 0E 0D RESDSK: LD C,13 +0106 D0BA C3 05 00 JP ENTRY +0107 D0BD ; +0108 D0BD ; Routine to select disk (A). +0109 D0BD ; +0110 D0BD 5F DSKSEL: LD E,A +0111 D0BE 0E 0E LD C,14 +0112 D0C0 C3 05 00 JP ENTRY +0113 D0C3 ; +0114 D0C3 ; Routine to call bdos and save the return code. The zero +0115 D0C3 ; flag is set on a return of 0ffh. +0116 D0C3 ; +0117 D0C3 CD 05 00 ENTRY1: CALL ENTRY +0118 D0C6 32 EE D7 LD (RTNCODE),A ;save return code. +0119 D0C9 3C INC A ;set zero if 0ffh returned. +0120 D0CA C9 RET +0121 D0CB ; +0122 D0CB ; Routine to open a file. (DE) must point to the FCB. +0123 D0CB ; +0124 D0CB 0E 0F OPEN: LD C,15 +0125 D0CD C3 C3 D0 JP ENTRY1 +0126 D0D0 ; +0127 D0D0 ; Routine to open file at (FCB). +0128 D0D0 ; +0129 D0D0 AF OPENFCB:XOR A ;clear the record number byte at fcb+32 +0130 D0D1 32 ED D7 LD (FCB+32),A +0131 D0D4 11 CD D7 LD DE,FCB +0132 D0D7 C3 CB D0 JP OPEN +0133 D0DA ; +0134 D0DA ; Routine to close a file. (DE) points to FCB. +0135 D0DA ; +0136 D0DA 0E 10 CLOSE: LD C,16 +0137 D0DC C3 C3 D0 JP ENTRY1 +0138 D0DF ; +0139 D0DF ; Routine to search for the first file with ambigueous name +0140 D0DF ; (DE). +0141 D0DF ; +0142 D0DF 0E 11 SRCHFST:LD C,17 +0143 D0E1 C3 C3 D0 JP ENTRY1 +0144 D0E4 ; +0145 D0E4 ; Search for the next ambigeous file name. +0146 D0E4 ; +0147 D0E4 0E 12 SRCHNXT:LD C,18 +0148 D0E6 C3 C3 D0 JP ENTRY1 +0149 D0E9 ; +0150 D0E9 ; Search for file at (FCB). +0151 D0E9 ; +0152 D0E9 11 CD D7 SRCHFCB:LD DE,FCB +0153 D0EC C3 DF D0 JP SRCHFST +0154 D0EF ; +0155 D0EF ; Routine to delete a file pointed to by (DE). +0156 D0EF ; +0157 D0EF 0E 13 DELETE: LD C,19 +0158 D0F1 C3 05 00 JP ENTRY +0159 D0F4 ; +0160 D0F4 ; Routine to call the bdos and set the zero flag if a zero +0161 D0F4 ; status is returned. +0162 D0F4 ; +0163 D0F4 CD 05 00 ENTRY2: CALL ENTRY +0164 D0F7 B7 OR A ;set zero flag if appropriate. +0165 D0F8 C9 RET +0166 D0F9 ; +0167 D0F9 ; Routine to read the next record from a sequential file. +0168 D0F9 ; (DE) points to the FCB. +0169 D0F9 ; +0170 D0F9 0E 14 RDREC: LD C,20 +0171 D0FB C3 F4 D0 JP ENTRY2 +0172 D0FE ; +0173 D0FE ; Routine to read file at (FCB). +0174 D0FE ; +0175 D0FE 11 CD D7 READFCB:LD DE,FCB +0176 D101 C3 F9 D0 JP RDREC +0177 D104 ; +0178 D104 ; Routine to write the next record of a sequential file. +0179 D104 ; (DE) points to the FCB. +0180 D104 ; +0181 D104 0E 15 WRTREC: LD C,21 +0182 D106 C3 F4 D0 JP ENTRY2 +0183 D109 ; +0184 D109 ; Routine to create the file pointed to by (DE). +0185 D109 ; +0186 D109 0E 16 CREATE: LD C,22 +0187 D10B C3 C3 D0 JP ENTRY1 +0188 D10E ; +0189 D10E ; Routine to rename the file pointed to by (DE). Note that +0190 D10E ; the new name starts at (DE+16). +0191 D10E ; +0192 D10E 0E 17 RENAM: LD C,23 +0193 D110 C3 05 00 JP ENTRY +0194 D113 ; +0195 D113 ; Get the current user code. +0196 D113 ; +0197 D113 1E FF GETUSR: LD E,0FFH +0198 D115 ; +0199 D115 ; Routne to get or set the current user code. +0200 D115 ; If (E) is FF then this is a GET, else it is a SET. +0201 D115 ; +0202 D115 0E 20 GETSETUC: LD C,32 +0203 D117 C3 05 00 JP ENTRY +0204 D11A ; +0205 D11A ; Routine to set the current drive byte at (TDRIVE). +0206 D11A ; +0207 D11A CD 13 D1 SETCDRV:CALL GETUSR ;get user number +0208 D11D 87 ADD A,A ;and shift into the upper 4 bits. +0209 D11E 87 ADD A,A +0210 D11F 87 ADD A,A +0211 D120 87 ADD A,A +0212 D121 21 EF D7 LD HL,CDRIVE ;now add in the current drive number. +0213 D124 B6 OR (HL) +0214 D125 32 04 00 LD (TDRIVE),A ;and save. +0215 D128 C9 RET +0216 D129 ; +0217 D129 ; Move currently active drive down to (TDRIVE). +0218 D129 ; +0219 D129 3A EF D7 MOVECD: LD A,(CDRIVE) +0220 D12C 32 04 00 LD (TDRIVE),A +0221 D12F C9 RET +0222 D130 ; +0223 D130 ; Routine to convert (A) into upper case ascii. Only letters +0224 D130 ; are affected. +0225 D130 ; +0226 D130 FE 61 UPPER: CP 'a' ;check for letters in the range of 'a' to 'z'. +0227 D132 D8 RET C +0228 D133 FE 7B CP '{' +0229 D135 D0 RET NC +0230 D136 E6 5F AND 5FH ;convert it if found. +0231 D138 C9 RET +0232 D139 ; +0233 D139 ; Routine to get a line of input. We must check to see if the +0234 D139 ; user is in (BATCH) mode. If so, then read the input from file +0235 D139 ; ($$$.SUB). At the end, reset to console input. +0236 D139 ; +0237 D139 3A AB D7 GETINP: LD A,(BATCH) ;if =0, then use console input. +0238 D13C B7 OR A +0239 D13D CA 96 D1 JP Z,GETINP1 +0240 D140 ; +0241 D140 ; Use the submit file ($$$.sub) which is prepared by a +0242 D140 ; SUBMIT run. It must be on drive (A) and it will be deleted +0243 D140 ; if and error occures (like eof). +0244 D140 ; +0245 D140 3A EF D7 LD A,(CDRIVE) ;select drive 0 if need be. +0246 D143 B7 OR A +0247 D144 3E 00 LD A,0 ;always use drive A for submit. +0248 D146 C4 BD D0 CALL NZ,DSKSEL ;select it if required. +0249 D149 11 AC D7 LD DE,BATCHFCB +0250 D14C CD CB D0 CALL OPEN ;look for it. +0251 D14F CA 96 D1 JP Z,GETINP1 ;if not there, use normal input. +0252 D152 3A BB D7 LD A,(BATCHFCB+15) ;get last record number+1. +0253 D155 3D DEC A +0254 D156 32 CC D7 LD (BATCHFCB+32),A +0255 D159 11 AC D7 LD DE,BATCHFCB +0256 D15C CD F9 D0 CALL RDREC ;read last record. +0257 D15F C2 96 D1 JP NZ,GETINP1 ;quit on end of file. +0258 D162 ; +0259 D162 ; Move this record into input buffer. +0260 D162 ; +0261 D162 11 07 D0 LD DE,INBUFF+1 +0262 D165 21 80 00 LD HL,TBUFF ;data was read into buffer here. +0263 D168 06 80 LD B,128 ;all 128 characters may be used. +0264 D16A CD 42 D4 CALL HL2DE ;(HL) to (DE), (B) bytes. +0265 D16D 21 BA D7 LD HL,BATCHFCB+14 +0266 D170 36 00 LD (HL),0 ;zero out the 's2' byte. +0267 D172 23 INC HL ;and decrement the record count. +0268 D173 35 DEC (HL) +0269 D174 11 AC D7 LD DE,BATCHFCB ;close the batch file now. +0270 D177 CD DA D0 CALL CLOSE +0271 D17A CA 96 D1 JP Z,GETINP1 ;quit on an error. +0272 D17D 3A EF D7 LD A,(CDRIVE) ;re-select previous drive if need be. +0273 D180 B7 OR A +0274 D181 C4 BD D0 CALL NZ,DSKSEL ;don't do needless selects. +0275 D184 ; +0276 D184 ; Print line just read on console. +0277 D184 ; +0278 D184 21 08 D0 LD HL,INBUFF+2 +0279 D187 CD AC D0 CALL PLINE2 +0280 D18A CD C2 D1 CALL CHKCON ;check console, quit on a key. +0281 D18D CA A7 D1 JP Z,GETINP2 ;jump if no key is pressed. +0282 D190 ; +0283 D190 ; Terminate the submit job on any keyboard input. Delete this +0284 D190 ; file such that it is not re-started and jump to normal keyboard +0285 D190 ; input section. +0286 D190 ; +0287 D190 CD DD D1 CALL DELBATCH ;delete the batch file. +0288 D193 C3 82 D3 JP CMMND1 ;and restart command input. +0289 D196 ; +0290 D196 ; Get here for normal keyboard input. Delete the submit file +0291 D196 ; incase there was one. +0292 D196 ; +0293 D196 CD DD D1 GETINP1:CALL DELBATCH ;delete file ($$$.sub). +0294 D199 CD 1A D1 CALL SETCDRV ;reset active disk. +0295 D19C 0E 0A LD C,10 ;get line from console device. +0296 D19E 11 06 D0 LD DE,INBUFF +0297 D1A1 CD 05 00 CALL ENTRY +0298 D1A4 CD 29 D1 CALL MOVECD ;reset current drive (again). +0299 D1A7 ; +0300 D1A7 ; Convert input line to upper case. +0301 D1A7 ; +0302 D1A7 21 07 D0 GETINP2:LD HL,INBUFF+1 +0303 D1AA 46 LD B,(HL) ;(B)=character counter. +0304 D1AB 23 GETINP3:INC HL +0305 D1AC 78 LD A,B ;end of the line? +0306 D1AD B7 OR A +0307 D1AE CA BA D1 JP Z,GETINP4 +0308 D1B1 7E LD A,(HL) ;convert to upper case. +0309 D1B2 CD 30 D1 CALL UPPER +0310 D1B5 77 LD (HL),A +0311 D1B6 05 DEC B ;adjust character count. +0312 D1B7 C3 AB D1 JP GETINP3 +0313 D1BA 77 GETINP4:LD (HL),A ;add trailing null. +0314 D1BB 21 08 D0 LD HL,INBUFF+2 +0315 D1BE 22 88 D0 LD (INPOINT),HL ;reset input line pointer. +0316 D1C1 C9 RET +0317 D1C2 ; +0318 D1C2 ; Routine to check the console for a key pressed. The zero +0319 D1C2 ; flag is set is none, else the character is returned in (A). +0320 D1C2 ; +0321 D1C2 0E 0B CHKCON: LD C,11 ;check console. +0322 D1C4 CD 05 00 CALL ENTRY +0323 D1C7 B7 OR A +0324 D1C8 C8 RET Z ;return if nothing. +0325 D1C9 0E 01 LD C,1 ;else get character. +0326 D1CB CD 05 00 CALL ENTRY +0327 D1CE B7 OR A ;clear zero flag and return. +0328 D1CF C9 RET +0329 D1D0 ; +0330 D1D0 ; Routine to get the currently active drive number. +0331 D1D0 ; +0332 D1D0 0E 19 GETDSK: LD C,25 +0333 D1D2 C3 05 00 JP ENTRY +0334 D1D5 ; +0335 D1D5 ; Set the stabdard dma address. +0336 D1D5 ; +0337 D1D5 11 80 00 STDDMA: LD DE,TBUFF +0338 D1D8 ; +0339 D1D8 ; Routine to set the dma address to (DE). +0340 D1D8 ; +0341 D1D8 0E 1A DMASET: LD C,26 +0342 D1DA C3 05 00 JP ENTRY +0343 D1DD ; +0344 D1DD ; Delete the batch file created by SUBMIT. +0345 D1DD ; +0346 D1DD 21 AB D7 DELBATCH: LD HL,BATCH ;is batch active? +0347 D1E0 7E LD A,(HL) +0348 D1E1 B7 OR A +0349 D1E2 C8 RET Z +0350 D1E3 36 00 LD (HL),0 ;yes, de-activate it. +0351 D1E5 AF XOR A +0352 D1E6 CD BD D0 CALL DSKSEL ;select drive 0 for sure. +0353 D1E9 11 AC D7 LD DE,BATCHFCB ;and delete this file. +0354 D1EC CD EF D0 CALL DELETE +0355 D1EF 3A EF D7 LD A,(CDRIVE) ;reset current drive. +0356 D1F2 C3 BD D0 JP DSKSEL +0357 D1F5 ; +0358 D1F5 ; Check to two strings at (PATTRN1) and (PATTRN2). They must be +0359 D1F5 ; the same or we halt.... +0360 D1F5 ; +0361 D1F5 11 28 D3 VERIFY: LD DE,PATTRN1 ;these are the serial number bytes. +0362 D1F8 21 00 D8 LD HL,PATTRN2 ;ditto, but how could they be different? +0363 D1FB 06 06 LD B,6 ;6 bytes each. +0364 D1FD 1A VERIFY1:LD A,(DE) +0365 D1FE BE CP (HL) +0366 D1FF C2 CF D3 JP NZ,HALT ;jump to halt routine. +0367 D202 13 INC DE +0368 D203 23 INC HL +0369 D204 05 DEC B +0370 D205 C2 FD D1 JP NZ,VERIFY1 +0371 D208 C9 RET +0372 D209 ; +0373 D209 ; Print back file name with a '?' to indicate a syntax error. +0374 D209 ; +0375 D209 CD 98 D0 SYNERR: CALL CRLF ;end current line. +0376 D20C 2A 8A D0 LD HL,(NAMEPNT) ;this points to name in error. +0377 D20F 7E SYNERR1:LD A,(HL) ;print it until a space or null is found. +0378 D210 FE 20 CP ' ' +0379 D212 CA 22 D2 JP Z,SYNERR2 +0380 D215 B7 OR A +0381 D216 CA 22 D2 JP Z,SYNERR2 +0382 D219 E5 PUSH HL +0383 D21A CD 8C D0 CALL PRINT +0384 D21D E1 POP HL +0385 D21E 23 INC HL +0386 D21F C3 0F D2 JP SYNERR1 +0387 D222 3E 3F SYNERR2:LD A,'?' ;add trailing '?'. +0388 D224 CD 8C D0 CALL PRINT +0389 D227 CD 98 D0 CALL CRLF +0390 D22A CD DD D1 CALL DELBATCH ;delete any batch file. +0391 D22D C3 82 D3 JP CMMND1 ;and restart from console input. +0392 D230 ; +0393 D230 ; Check character at (DE) for legal command input. Note that the +0394 D230 ; zero flag is set if the character is a delimiter. +0395 D230 ; +0396 D230 1A CHECK: LD A,(DE) +0397 D231 B7 OR A +0398 D232 C8 RET Z +0399 D233 FE 20 CP ' ' ;control characters are not legal here. +0400 D235 DA 09 D2 JP C,SYNERR +0401 D238 C8 RET Z ;check for valid delimiter. +0402 D239 FE 3D CP '=' +0403 D23B C8 RET Z +0404 D23C FE 5F CP '_' +0405 D23E C8 RET Z +0406 D23F FE 2E CP '.' +0407 D241 C8 RET Z +0408 D242 FE 3A CP ':' +0409 D244 C8 RET Z +0410 D245 FE 3B CP 03BH ; ';' +0411 D247 C8 RET Z +0412 D248 FE 3C CP '<' +0413 D24A C8 RET Z +0414 D24B FE 3E CP '>' +0415 D24D C8 RET Z +0416 D24E C9 RET +0417 D24F ; +0418 D24F ; Get the next non-blank character from (DE). +0419 D24F ; +0420 D24F 1A NONBLANK: LD A,(DE) +0421 D250 B7 OR A ;string ends with a null. +0422 D251 C8 RET Z +0423 D252 FE 20 CP ' ' +0424 D254 C0 RET NZ +0425 D255 13 INC DE +0426 D256 C3 4F D2 JP NONBLANK +0427 D259 ; +0428 D259 ; Add (HL)=(HL)+(A) +0429 D259 ; +0430 D259 85 ADDHL: ADD A,L +0431 D25A 6F LD L,A +0432 D25B D0 RET NC ;take care of any carry. +0433 D25C 24 INC H +0434 D25D C9 RET +0435 D25E ; +0436 D25E ; Convert the first name in (FCB). +0437 D25E ; +0438 D25E 3E 00 CONVFST:LD A,0 +0439 D260 ; +0440 D260 ; Format a file name (convert * to '?', etc.). On return, +0441 D260 ; (A)=0 is an unambigeous name was specified. Enter with (A) equal to +0442 D260 ; the position within the fcb for the name (either 0 or 16). +0443 D260 ; +0444 D260 21 CD D7 CONVERT:LD HL,FCB +0445 D263 CD 59 D2 CALL ADDHL +0446 D266 E5 PUSH HL +0447 D267 E5 PUSH HL +0448 D268 AF XOR A +0449 D269 32 F0 D7 LD (CHGDRV),A ;initialize drive change flag. +0450 D26C 2A 88 D0 LD HL,(INPOINT) ;set (HL) as pointer into input line. +0451 D26F EB EX DE,HL +0452 D270 CD 4F D2 CALL NONBLANK ;get next non-blank character. +0453 D273 EB EX DE,HL +0454 D274 22 8A D0 LD (NAMEPNT),HL ;save pointer here for any error message. +0455 D277 EB EX DE,HL +0456 D278 E1 POP HL +0457 D279 1A LD A,(DE) ;get first character. +0458 D27A B7 OR A +0459 D27B CA 89 D2 JP Z,CONVRT1 +0460 D27E DE 40 SBC A,'A'-1 ;might be a drive name, convert to binary. +0461 D280 47 LD B,A ;and save. +0462 D281 13 INC DE ;check next character for a ':'. +0463 D282 1A LD A,(DE) +0464 D283 FE 3A CP ':' +0465 D285 CA 90 D2 JP Z,CONVRT2 +0466 D288 1B DEC DE ;nope, move pointer back to the start of the line. +0467 D289 3A EF D7 CONVRT1:LD A,(CDRIVE) +0468 D28C 77 LD (HL),A +0469 D28D C3 96 D2 JP CONVRT3 +0470 D290 78 CONVRT2:LD A,B +0471 D291 32 F0 D7 LD (CHGDRV),A ;set change in drives flag. +0472 D294 70 LD (HL),B +0473 D295 13 INC DE +0474 D296 ; +0475 D296 ; Convert the basic file name. +0476 D296 ; +0477 D296 06 08 CONVRT3:LD B,08H +0478 D298 CD 30 D2 CONVRT4:CALL CHECK +0479 D29B CA B9 D2 JP Z,CONVRT8 +0480 D29E 23 INC HL +0481 D29F FE 2A CP '*' ;note that an '*' will fill the remaining +0482 D2A1 C2 A9 D2 JP NZ,CONVRT5 ;field with '?'. +0483 D2A4 36 3F LD (HL),'?' +0484 D2A6 C3 AB D2 JP CONVRT6 +0485 D2A9 77 CONVRT5:LD (HL),A +0486 D2AA 13 INC DE +0487 D2AB 05 CONVRT6:DEC B +0488 D2AC C2 98 D2 JP NZ,CONVRT4 +0489 D2AF CD 30 D2 CONVRT7:CALL CHECK ;get next delimiter. +0490 D2B2 CA C0 D2 JP Z,GETEXT +0491 D2B5 13 INC DE +0492 D2B6 C3 AF D2 JP CONVRT7 +0493 D2B9 23 CONVRT8:INC HL ;blank fill the file name. +0494 D2BA 36 20 LD (HL),' ' +0495 D2BC 05 DEC B +0496 D2BD C2 B9 D2 JP NZ,CONVRT8 +0497 D2C0 ; +0498 D2C0 ; Get the extension and convert it. +0499 D2C0 ; +0500 D2C0 06 03 GETEXT: LD B,03H +0501 D2C2 FE 2E CP '.' +0502 D2C4 C2 E9 D2 JP NZ,GETEXT5 +0503 D2C7 13 INC DE +0504 D2C8 CD 30 D2 GETEXT1:CALL CHECK +0505 D2CB CA E9 D2 JP Z,GETEXT5 +0506 D2CE 23 INC HL +0507 D2CF FE 2A CP '*' +0508 D2D1 C2 D9 D2 JP NZ,GETEXT2 +0509 D2D4 36 3F LD (HL),'?' +0510 D2D6 C3 DB D2 JP GETEXT3 +0511 D2D9 77 GETEXT2:LD (HL),A +0512 D2DA 13 INC DE +0513 D2DB 05 GETEXT3:DEC B +0514 D2DC C2 C8 D2 JP NZ,GETEXT1 +0515 D2DF CD 30 D2 GETEXT4:CALL CHECK +0516 D2E2 CA F0 D2 JP Z,GETEXT6 +0517 D2E5 13 INC DE +0518 D2E6 C3 DF D2 JP GETEXT4 +0519 D2E9 23 GETEXT5:INC HL +0520 D2EA 36 20 LD (HL),' ' +0521 D2EC 05 DEC B +0522 D2ED C2 E9 D2 JP NZ,GETEXT5 +0523 D2F0 06 03 GETEXT6:LD B,3 +0524 D2F2 23 GETEXT7:INC HL +0525 D2F3 36 00 LD (HL),0 +0526 D2F5 05 DEC B +0527 D2F6 C2 F2 D2 JP NZ,GETEXT7 +0528 D2F9 EB EX DE,HL +0529 D2FA 22 88 D0 LD (INPOINT),HL ;save input line pointer. +0530 D2FD E1 POP HL +0531 D2FE ; +0532 D2FE ; Check to see if this is an ambigeous file name specification. +0533 D2FE ; Set the (A) register to non zero if it is. +0534 D2FE ; +0535 D2FE 01 0B 00 LD BC,11 ;set name length. +0536 D301 23 GETEXT8:INC HL +0537 D302 7E LD A,(HL) +0538 D303 FE 3F CP '?' ;any question marks? +0539 D305 C2 09 D3 JP NZ,GETEXT9 +0540 D308 04 INC B ;count them. +0541 D309 0D GETEXT9:DEC C +0542 D30A C2 01 D3 JP NZ,GETEXT8 +0543 D30D 78 LD A,B +0544 D30E B7 OR A +0545 D30F C9 RET +0546 D310 ; +0547 D310 ; CP/M command table. Note commands can be either 3 or 4 characters long. +0548 D310 ; +0549 D310 NUMCMDS .EQU 6 ;number of commands +0550 D310 44 49 52 20 CMDTBL: .TEXT "DIR " +0551 D314 45 52 41 20 .TEXT "ERA " +0552 D318 54 59 50 45 .TEXT "TYPE" +0553 D31C 53 41 56 45 .TEXT "SAVE" +0554 D320 52 45 4E 20 .TEXT "REN " +0555 D324 55 53 45 52 .TEXT "USER" +0556 D328 ; +0557 D328 ; The following six bytes must agree with those at (PATTRN2) +0558 D328 ; or cp/m will HALT. Why? +0559 D328 ; +0560 D328 00 16 00 00 PATTRN1:.DB 0,22,0,0,0,0 ;(* serial number bytes *). +0560 D32C 00 00 +0561 D32E ; +0562 D32E ; Search the command table for a match with what has just +0563 D32E ; been entered. If a match is found, then we jump to the +0564 D32E ; proper section. Else jump to (UNKNOWN). +0565 D32E ; On return, the (C) register is set to the command number +0566 D32E ; that matched (or NUMCMDS+1 if no match). +0567 D32E ; +0568 D32E 21 10 D3 SEARCH: LD HL,CMDTBL +0569 D331 0E 00 LD C,0 +0570 D333 79 SEARCH1:LD A,C +0571 D334 FE 06 CP NUMCMDS ;this commands exists. +0572 D336 D0 RET NC +0573 D337 11 CE D7 LD DE,FCB+1 ;check this one. +0574 D33A 06 04 LD B,4 ;max command length. +0575 D33C 1A SEARCH2:LD A,(DE) +0576 D33D BE CP (HL) +0577 D33E C2 4F D3 JP NZ,SEARCH3 ;not a match. +0578 D341 13 INC DE +0579 D342 23 INC HL +0580 D343 05 DEC B +0581 D344 C2 3C D3 JP NZ,SEARCH2 +0582 D347 1A LD A,(DE) ;allow a 3 character command to match. +0583 D348 FE 20 CP ' ' +0584 D34A C2 54 D3 JP NZ,SEARCH4 +0585 D34D 79 LD A,C ;set return register for this command. +0586 D34E C9 RET +0587 D34F 23 SEARCH3:INC HL +0588 D350 05 DEC B +0589 D351 C2 4F D3 JP NZ,SEARCH3 +0590 D354 0C SEARCH4:INC C +0591 D355 C3 33 D3 JP SEARCH1 +0592 D358 ; +0593 D358 ; Set the input buffer to empty and then start the command +0594 D358 ; processor (ccp). +0595 D358 ; +0596 D358 AF CLEARBUF: XOR A +0597 D359 32 07 D0 LD (INBUFF+1),A ;second byte is actual length. +0598 D35C ; +0599 D35C ;************************************************************** +0600 D35C ;* +0601 D35C ;* +0602 D35C ;* C C P - C o n s o l e C o m m a n d P r o c e s s o r +0603 D35C ;* +0604 D35C ;************************************************************** +0605 D35C ;* +0606 D35C 31 AB D7 COMMAND:LD SP,CCPSTACK ;setup stack area. +0607 D35F C5 PUSH BC ;note that (C) should be equal to: +0608 D360 79 LD A,C ;(uuuudddd) where 'uuuu' is the user number +0609 D361 1F RRA ;and 'dddd' is the drive number. +0610 D362 1F RRA +0611 D363 1F RRA +0612 D364 1F RRA +0613 D365 E6 0F AND 0FH ;isolate the user number. +0614 D367 5F LD E,A +0615 D368 CD 15 D1 CALL GETSETUC ;and set it. +0616 D36B CD B8 D0 CALL RESDSK ;reset the disk system. +0617 D36E 32 AB D7 LD (BATCH),A ;clear batch mode flag. +0618 D371 C1 POP BC +0619 D372 79 LD A,C +0620 D373 E6 0F AND 0FH ;isolate the drive number. +0621 D375 32 EF D7 LD (CDRIVE),A ;and save. +0622 D378 CD BD D0 CALL DSKSEL ;...and select. +0623 D37B 3A 07 D0 LD A,(INBUFF+1) +0624 D37E B7 OR A ;anything in input buffer already? +0625 D37F C2 98 D3 JP NZ,CMMND2 ;yes, we just process it. +0626 D382 ; +0627 D382 ; Entry point to get a command line from the console. +0628 D382 ; +0629 D382 31 AB D7 CMMND1: LD SP,CCPSTACK ;set stack straight. +0630 D385 CD 98 D0 CALL CRLF ;start a new line on the screen. +0631 D388 CD D0 D1 CALL GETDSK ;get current drive. +0632 D38B C6 41 ADD A,'A' +0633 D38D CD 8C D0 CALL PRINT ;print current drive. +0634 D390 3E 3E LD A,'>' +0635 D392 CD 8C D0 CALL PRINT ;and add prompt. +0636 D395 CD 39 D1 CALL GETINP ;get line from user. +0637 D398 ; +0638 D398 ; Process command line here. +0639 D398 ; +0640 D398 11 80 00 CMMND2: LD DE,TBUFF +0641 D39B CD D8 D1 CALL DMASET ;set standard dma address. +0642 D39E CD D0 D1 CALL GETDSK +0643 D3A1 32 EF D7 LD (CDRIVE),A ;set current drive. +0644 D3A4 CD 5E D2 CALL CONVFST ;convert name typed in. +0645 D3A7 C4 09 D2 CALL NZ,SYNERR ;wild cards are not allowed. +0646 D3AA 3A F0 D7 LD A,(CHGDRV) ;if a change in drives was indicated, +0647 D3AD B7 OR A ;then treat this as an unknown command +0648 D3AE C2 A5 D6 JP NZ,UNKNOWN ;which gets executed. +0649 D3B1 CD 2E D3 CALL SEARCH ;else search command table for a match. +0650 D3B4 ; +0651 D3B4 ; Note that an unknown command returns +0652 D3B4 ; with (A) pointing to the last address +0653 D3B4 ; in our table which is (UNKNOWN). +0654 D3B4 ; +0655 D3B4 21 C1 D3 LD HL,CMDADR ;now, look thru our address table for command (A). +0656 D3B7 5F LD E,A ;set (DE) to command number. +0657 D3B8 16 00 LD D,0 +0658 D3BA 19 ADD HL,DE +0659 D3BB 19 ADD HL,DE ;(HL)=(CMDADR)+2*(command number). +0660 D3BC 7E LD A,(HL) ;now pick out this address. +0661 D3BD 23 INC HL +0662 D3BE 66 LD H,(HL) +0663 D3BF 6F LD L,A +0664 D3C0 E9 JP (HL) ;now execute it. +0665 D3C1 ; +0666 D3C1 ; CP/M command address table. +0667 D3C1 ; +0668 D3C1 77 D4 1F D5 CMDADR: .DW DIRECT,ERASE,TYPE,SAVE +0668 D3C5 5D D5 AD D5 +0669 D3C9 10 D6 8E D6 .DW RENAME,USER,UNKNOWN +0669 D3CD A5 D6 +0670 D3CF ; +0671 D3CF ; Halt the system. Reason for this is unknown at present. +0672 D3CF ; +0673 D3CF 21 F3 76 HALT: LD HL,76F3H ;'DI HLT' instructions. +0674 D3D2 22 00 D0 LD (CBASE),HL +0675 D3D5 21 00 D0 LD HL,CBASE +0676 D3D8 E9 JP (HL) +0677 D3D9 ; +0678 D3D9 ; Read error while TYPEing a file. +0679 D3D9 ; +0680 D3D9 01 DF D3 RDERROR:LD BC,RDERR +0681 D3DC C3 A7 D0 JP PLINE +0682 D3DF 52 65 61 64 RDERR: .TEXT "Read error" +0682 D3E3 20 65 72 72 +0682 D3E7 6F 72 +0683 D3E9 00 .DB 0 +0684 D3EA ; +0685 D3EA ; Required file was not located. +0686 D3EA ; +0687 D3EA 01 F0 D3 NONE: LD BC,NOFILE +0688 D3ED C3 A7 D0 JP PLINE +0689 D3F0 4E 6F 20 66 NOFILE: .TEXT "No file" +0689 D3F4 69 6C 65 +0690 D3F7 00 .DB 0 +0691 D3F8 ; +0692 D3F8 ; Decode a command of the form 'A>filename number{ filename}. +0693 D3F8 ; Note that a drive specifier is not allowed on the first file +0694 D3F8 ; name. On return, the number is in register (A). Any error +0695 D3F8 ; causes 'filename?' to be printed and the command is aborted. +0696 D3F8 ; +0697 D3F8 CD 5E D2 DECODE: CALL CONVFST ;convert filename. +0698 D3FB 3A F0 D7 LD A,(CHGDRV) ;do not allow a drive to be specified. +0699 D3FE B7 OR A +0700 D3FF C2 09 D2 JP NZ,SYNERR +0701 D402 21 CE D7 LD HL,FCB+1 ;convert number now. +0702 D405 01 0B 00 LD BC,11 ;(B)=sum register, (C)=max digit count. +0703 D408 7E DECODE1:LD A,(HL) +0704 D409 FE 20 CP ' ' ;a space terminates the numeral. +0705 D40B CA 33 D4 JP Z,DECODE3 +0706 D40E 23 INC HL +0707 D40F D6 30 SUB '0' ;make binary from ascii. +0708 D411 FE 0A CP 10 ;legal digit? +0709 D413 D2 09 D2 JP NC,SYNERR +0710 D416 57 LD D,A ;yes, save it in (D). +0711 D417 78 LD A,B ;compute (B)=(B)*10 and check for overflow. +0712 D418 E6 E0 AND 0E0H +0713 D41A C2 09 D2 JP NZ,SYNERR +0714 D41D 78 LD A,B +0715 D41E 07 RLCA +0716 D41F 07 RLCA +0717 D420 07 RLCA ;(A)=(B)*8 +0718 D421 80 ADD A,B ;.......*9 +0719 D422 DA 09 D2 JP C,SYNERR +0720 D425 80 ADD A,B ;.......*10 +0721 D426 DA 09 D2 JP C,SYNERR +0722 D429 82 ADD A,D ;add in new digit now. +0723 D42A DA 09 D2 DECODE2:JP C,SYNERR +0724 D42D 47 LD B,A ;and save result. +0725 D42E 0D DEC C ;only look at 11 digits. +0726 D42F C2 08 D4 JP NZ,DECODE1 +0727 D432 C9 RET +0728 D433 7E DECODE3:LD A,(HL) ;spaces must follow (why?). +0729 D434 FE 20 CP ' ' +0730 D436 C2 09 D2 JP NZ,SYNERR +0731 D439 23 INC HL +0732 D43A 0D DECODE4:DEC C +0733 D43B C2 33 D4 JP NZ,DECODE3 +0734 D43E 78 LD A,B ;set (A)=the numeric value entered. +0735 D43F C9 RET +0736 D440 ; +0737 D440 ; Move 3 bytes from (HL) to (DE). Note that there is only +0738 D440 ; one reference to this at (A2D5h). +0739 D440 ; +0740 D440 06 03 MOVE3: LD B,3 +0741 D442 ; +0742 D442 ; Move (B) bytes from (HL) to (DE). +0743 D442 ; +0744 D442 7E HL2DE: LD A,(HL) +0745 D443 12 LD (DE),A +0746 D444 23 INC HL +0747 D445 13 INC DE +0748 D446 05 DEC B +0749 D447 C2 42 D4 JP NZ,HL2DE +0750 D44A C9 RET +0751 D44B ; +0752 D44B ; Compute (HL)=(TBUFF)+(A)+(C) and get the byte that's here. +0753 D44B ; +0754 D44B 21 80 00 EXTRACT:LD HL,TBUFF +0755 D44E 81 ADD A,C +0756 D44F CD 59 D2 CALL ADDHL +0757 D452 7E LD A,(HL) +0758 D453 C9 RET +0759 D454 ; +0760 D454 ; Check drive specified. If it means a change, then the new +0761 D454 ; drive will be selected. In any case, the drive byte of the +0762 D454 ; fcb will be set to null (means use current drive). +0763 D454 ; +0764 D454 AF DSELECT:XOR A ;null out first byte of fcb. +0765 D455 32 CD D7 LD (FCB),A +0766 D458 3A F0 D7 LD A,(CHGDRV) ;a drive change indicated? +0767 D45B B7 OR A +0768 D45C C8 RET Z +0769 D45D 3D DEC A ;yes, is it the same as the current drive? +0770 D45E 21 EF D7 LD HL,CDRIVE +0771 D461 BE CP (HL) +0772 D462 C8 RET Z +0773 D463 C3 BD D0 JP DSKSEL ;no. Select it then. +0774 D466 ; +0775 D466 ; Check the drive selection and reset it to the previous +0776 D466 ; drive if it was changed for the preceeding command. +0777 D466 ; +0778 D466 3A F0 D7 RESETDR:LD A,(CHGDRV) ;drive change indicated? +0779 D469 B7 OR A +0780 D46A C8 RET Z +0781 D46B 3D DEC A ;yes, was it a different drive? +0782 D46C 21 EF D7 LD HL,CDRIVE +0783 D46F BE CP (HL) +0784 D470 C8 RET Z +0785 D471 3A EF D7 LD A,(CDRIVE) ;yes, re-select our old drive. +0786 D474 C3 BD D0 JP DSKSEL +0787 D477 ; +0788 D477 ;************************************************************** +0789 D477 ;* +0790 D477 ;* D I R E C T O R Y C O M M A N D +0791 D477 ;* +0792 D477 ;************************************************************** +0793 D477 ; +0794 D477 CD 5E D2 DIRECT: CALL CONVFST ;convert file name. +0795 D47A CD 54 D4 CALL DSELECT ;select indicated drive. +0796 D47D 21 CE D7 LD HL,FCB+1 ;was any file indicated? +0797 D480 7E LD A,(HL) +0798 D481 FE 20 CP ' ' +0799 D483 C2 8F D4 JP NZ,DIRECT2 +0800 D486 06 0B LD B,11 ;no. Fill field with '?' - same as *.*. +0801 D488 36 3F DIRECT1:LD (HL),'?' +0802 D48A 23 INC HL +0803 D48B 05 DEC B +0804 D48C C2 88 D4 JP NZ,DIRECT1 +0805 D48F 1E 00 DIRECT2:LD E,0 ;set initial cursor position. +0806 D491 D5 PUSH DE +0807 D492 CD E9 D0 CALL SRCHFCB ;get first file name. +0808 D495 CC EA D3 CALL Z,NONE ;none found at all? +0809 D498 CA 1B D5 DIRECT3:JP Z,DIRECT9 ;terminate if no more names. +0810 D49B 3A EE D7 LD A,(RTNCODE) ;get file's position in segment (0-3). +0811 D49E 0F RRCA +0812 D49F 0F RRCA +0813 D4A0 0F RRCA +0814 D4A1 E6 60 AND 60H ;(A)=position*32 +0815 D4A3 4F LD C,A +0816 D4A4 3E 0A LD A,10 +0817 D4A6 CD 4B D4 CALL EXTRACT ;extract the tenth entry in fcb. +0818 D4A9 17 RLA ;check system file status bit. +0819 D4AA DA 0F D5 JP C,DIRECT8 ;we don't list them. +0820 D4AD D1 POP DE +0821 D4AE 7B LD A,E ;bump name count. +0822 D4AF 1C INC E +0823 D4B0 D5 PUSH DE +0824 D4B1 E6 03 AND 03H ;at end of line? +0825 D4B3 F5 PUSH AF +0826 D4B4 C2 CC D4 JP NZ,DIRECT4 +0827 D4B7 CD 98 D0 CALL CRLF ;yes, end this line and start another. +0828 D4BA C5 PUSH BC +0829 D4BB CD D0 D1 CALL GETDSK ;start line with ('A:'). +0830 D4BE C1 POP BC +0831 D4BF C6 41 ADD A,'A' +0832 D4C1 CD 92 D0 CALL PRINTB +0833 D4C4 3E 3A LD A,':' +0834 D4C6 CD 92 D0 CALL PRINTB +0835 D4C9 C3 D4 D4 JP DIRECT5 +0836 D4CC CD A2 D0 DIRECT4:CALL SPACE ;add seperator between file names. +0837 D4CF 3E 3A LD A,':' +0838 D4D1 CD 92 D0 CALL PRINTB +0839 D4D4 CD A2 D0 DIRECT5:CALL SPACE +0840 D4D7 06 01 LD B,1 ;'extract' each file name character at a time. +0841 D4D9 78 DIRECT6:LD A,B +0842 D4DA CD 4B D4 CALL EXTRACT +0843 D4DD E6 7F AND 7FH ;strip bit 7 (status bit). +0844 D4DF FE 20 CP ' ' ;are we at the end of the name? +0845 D4E1 C2 F9 D4 JP NZ,DRECT65 +0846 D4E4 F1 POP AF ;yes, don't print spaces at the end of a line. +0847 D4E5 F5 PUSH AF +0848 D4E6 FE 03 CP 3 +0849 D4E8 C2 F7 D4 JP NZ,DRECT63 +0850 D4EB 3E 09 LD A,9 ;first check for no extension. +0851 D4ED CD 4B D4 CALL EXTRACT +0852 D4F0 E6 7F AND 7FH +0853 D4F2 FE 20 CP ' ' +0854 D4F4 CA 0E D5 JP Z,DIRECT7 ;don't print spaces. +0855 D4F7 3E 20 DRECT63:LD A,' ' ;else print them. +0856 D4F9 CD 92 D0 DRECT65:CALL PRINTB +0857 D4FC 04 INC B ;bump to next character psoition. +0858 D4FD 78 LD A,B +0859 D4FE FE 0C CP 12 ;end of the name? +0860 D500 D2 0E D5 JP NC,DIRECT7 +0861 D503 FE 09 CP 9 ;nope, starting extension? +0862 D505 C2 D9 D4 JP NZ,DIRECT6 +0863 D508 CD A2 D0 CALL SPACE ;yes, add seperating space. +0864 D50B C3 D9 D4 JP DIRECT6 +0865 D50E F1 DIRECT7:POP AF ;get the next file name. +0866 D50F CD C2 D1 DIRECT8:CALL CHKCON ;first check console, quit on anything. +0867 D512 C2 1B D5 JP NZ,DIRECT9 +0868 D515 CD E4 D0 CALL SRCHNXT ;get next name. +0869 D518 C3 98 D4 JP DIRECT3 ;and continue with our list. +0870 D51B D1 DIRECT9:POP DE ;restore the stack and return to command level. +0871 D51C C3 86 D7 JP GETBACK +0872 D51F ; +0873 D51F ;************************************************************** +0874 D51F ;* +0875 D51F ;* E R A S E C O M M A N D +0876 D51F ;* +0877 D51F ;************************************************************** +0878 D51F ; +0879 D51F CD 5E D2 ERASE: CALL CONVFST ;convert file name. +0880 D522 FE 0B CP 11 ;was '*.*' entered? +0881 D524 C2 42 D5 JP NZ,ERASE1 +0882 D527 01 52 D5 LD BC,YESNO ;yes, ask for confirmation. +0883 D52A CD A7 D0 CALL PLINE +0884 D52D CD 39 D1 CALL GETINP +0885 D530 21 07 D0 LD HL,INBUFF+1 +0886 D533 35 DEC (HL) ;must be exactly 'y'. +0887 D534 C2 82 D3 JP NZ,CMMND1 +0888 D537 23 INC HL +0889 D538 7E LD A,(HL) +0890 D539 FE 59 CP 'Y' +0891 D53B C2 82 D3 JP NZ,CMMND1 +0892 D53E 23 INC HL +0893 D53F 22 88 D0 LD (INPOINT),HL ;save input line pointer. +0894 D542 CD 54 D4 ERASE1: CALL DSELECT ;select desired disk. +0895 D545 11 CD D7 LD DE,FCB +0896 D548 CD EF D0 CALL DELETE ;delete the file. +0897 D54B 3C INC A +0898 D54C CC EA D3 CALL Z,NONE ;not there? +0899 D54F C3 86 D7 JP GETBACK ;return to command level now. +0900 D552 41 6C 6C 20 YESNO: .TEXT "All (y/n)?" +0900 D556 28 79 2F 6E +0900 D55A 29 3F +0901 D55C 00 .DB 0 +0902 D55D ; +0903 D55D ;************************************************************** +0904 D55D ;* +0905 D55D ;* T Y P E C O M M A N D +0906 D55D ;* +0907 D55D ;************************************************************** +0908 D55D ; +0909 D55D CD 5E D2 TYPE: CALL CONVFST ;convert file name. +0910 D560 C2 09 D2 JP NZ,SYNERR ;wild cards not allowed. +0911 D563 CD 54 D4 CALL DSELECT ;select indicated drive. +0912 D566 CD D0 D0 CALL OPENFCB ;open the file. +0913 D569 CA A7 D5 JP Z,TYPE5 ;not there? +0914 D56C CD 98 D0 CALL CRLF ;ok, start a new line on the screen. +0915 D56F 21 F1 D7 LD HL,NBYTES ;initialize byte counter. +0916 D572 36 FF LD (HL),0FFH ;set to read first sector. +0917 D574 21 F1 D7 TYPE1: LD HL,NBYTES +0918 D577 7E TYPE2: LD A,(HL) ;have we written the entire sector? +0919 D578 FE 80 CP 128 +0920 D57A DA 87 D5 JP C,TYPE3 +0921 D57D E5 PUSH HL ;yes, read in the next one. +0922 D57E CD FE D0 CALL READFCB +0923 D581 E1 POP HL +0924 D582 C2 A0 D5 JP NZ,TYPE4 ;end or error? +0925 D585 AF XOR A ;ok, clear byte counter. +0926 D586 77 LD (HL),A +0927 D587 34 TYPE3: INC (HL) ;count this byte. +0928 D588 21 80 00 LD HL,TBUFF ;and get the (A)th one from the buffer (TBUFF). +0929 D58B CD 59 D2 CALL ADDHL +0930 D58E 7E LD A,(HL) +0931 D58F FE 1A CP CNTRLZ ;end of file mark? +0932 D591 CA 86 D7 JP Z,GETBACK +0933 D594 CD 8C D0 CALL PRINT ;no, print it. +0934 D597 CD C2 D1 CALL CHKCON ;check console, quit if anything ready. +0935 D59A C2 86 D7 JP NZ,GETBACK +0936 D59D C3 74 D5 JP TYPE1 +0937 D5A0 ; +0938 D5A0 ; Get here on an end of file or read error. +0939 D5A0 ; +0940 D5A0 3D TYPE4: DEC A ;read error? +0941 D5A1 CA 86 D7 JP Z,GETBACK +0942 D5A4 CD D9 D3 CALL RDERROR ;yes, print message. +0943 D5A7 CD 66 D4 TYPE5: CALL RESETDR ;and reset proper drive +0944 D5AA C3 09 D2 JP SYNERR ;now print file name with problem. +0945 D5AD ; +0946 D5AD ;************************************************************** +0947 D5AD ;* +0948 D5AD ;* S A V E C O M M A N D +0949 D5AD ;* +0950 D5AD ;************************************************************** +0951 D5AD ; +0952 D5AD CD F8 D3 SAVE: CALL DECODE ;get numeric number that follows SAVE. +0953 D5B0 F5 PUSH AF ;save number of pages to write. +0954 D5B1 CD 5E D2 CALL CONVFST ;convert file name. +0955 D5B4 C2 09 D2 JP NZ,SYNERR ;wild cards not allowed. +0956 D5B7 CD 54 D4 CALL DSELECT ;select specified drive. +0957 D5BA 11 CD D7 LD DE,FCB ;now delete this file. +0958 D5BD D5 PUSH DE +0959 D5BE CD EF D0 CALL DELETE +0960 D5C1 D1 POP DE +0961 D5C2 CD 09 D1 CALL CREATE ;and create it again. +0962 D5C5 CA FB D5 JP Z,SAVE3 ;can't create? +0963 D5C8 AF XOR A ;clear record number byte. +0964 D5C9 32 ED D7 LD (FCB+32),A +0965 D5CC F1 POP AF ;convert pages to sectors. +0966 D5CD 6F LD L,A +0967 D5CE 26 00 LD H,0 +0968 D5D0 29 ADD HL,HL ;(HL)=number of sectors to write. +0969 D5D1 11 00 01 LD DE,TBASE ;and we start from here. +0970 D5D4 7C SAVE1: LD A,H ;done yet? +0971 D5D5 B5 OR L +0972 D5D6 CA F1 D5 JP Z,SAVE2 +0973 D5D9 2B DEC HL ;nope, count this and compute the start +0974 D5DA E5 PUSH HL ;of the next 128 byte sector. +0975 D5DB 21 80 00 LD HL,128 +0976 D5DE 19 ADD HL,DE +0977 D5DF E5 PUSH HL ;save it and set the transfer address. +0978 D5E0 CD D8 D1 CALL DMASET +0979 D5E3 11 CD D7 LD DE,FCB ;write out this sector now. +0980 D5E6 CD 04 D1 CALL WRTREC +0981 D5E9 D1 POP DE ;reset (DE) to the start of the last sector. +0982 D5EA E1 POP HL ;restore sector count. +0983 D5EB C2 FB D5 JP NZ,SAVE3 ;write error? +0984 D5EE C3 D4 D5 JP SAVE1 +0985 D5F1 ; +0986 D5F1 ; Get here after writing all of the file. +0987 D5F1 ; +0988 D5F1 11 CD D7 SAVE2: LD DE,FCB ;now close the file. +0989 D5F4 CD DA D0 CALL CLOSE +0990 D5F7 3C INC A ;did it close ok? +0991 D5F8 C2 01 D6 JP NZ,SAVE4 +0992 D5FB ; +0993 D5FB ; Print out error message (no space). +0994 D5FB ; +0995 D5FB 01 07 D6 SAVE3: LD BC,NOSPACE +0996 D5FE CD A7 D0 CALL PLINE +0997 D601 CD D5 D1 SAVE4: CALL STDDMA ;reset the standard dma address. +0998 D604 C3 86 D7 JP GETBACK +0999 D607 4E 6F 20 73 NOSPACE:.TEXT "No space" +0999 D60B 70 61 63 65 +1000 D60F 00 .DB 0 +1001 D610 ; +1002 D610 ;************************************************************** +1003 D610 ;* +1004 D610 ;* R E N A M E C O M M A N D +1005 D610 ;* +1006 D610 ;************************************************************** +1007 D610 ; +1008 D610 CD 5E D2 RENAME: CALL CONVFST ;convert first file name. +1009 D613 C2 09 D2 JP NZ,SYNERR ;wild cards not allowed. +1010 D616 3A F0 D7 LD A,(CHGDRV) ;remember any change in drives specified. +1011 D619 F5 PUSH AF +1012 D61A CD 54 D4 CALL DSELECT ;and select this drive. +1013 D61D CD E9 D0 CALL SRCHFCB ;is this file present? +1014 D620 C2 79 D6 JP NZ,RENAME6 ;yes, print error message. +1015 D623 21 CD D7 LD HL,FCB ;yes, move this name into second slot. +1016 D626 11 DD D7 LD DE,FCB+16 +1017 D629 06 10 LD B,16 +1018 D62B CD 42 D4 CALL HL2DE +1019 D62E 2A 88 D0 LD HL,(INPOINT) ;get input pointer. +1020 D631 EB EX DE,HL +1021 D632 CD 4F D2 CALL NONBLANK ;get next non blank character. +1022 D635 FE 3D CP '=' ;only allow an '=' or '_' seperator. +1023 D637 CA 3F D6 JP Z,RENAME1 +1024 D63A FE 5F CP '_' +1025 D63C C2 73 D6 JP NZ,RENAME5 +1026 D63F EB RENAME1:EX DE,HL +1027 D640 23 INC HL ;ok, skip seperator. +1028 D641 22 88 D0 LD (INPOINT),HL ;save input line pointer. +1029 D644 CD 5E D2 CALL CONVFST ;convert this second file name now. +1030 D647 C2 73 D6 JP NZ,RENAME5 ;again, no wild cards. +1031 D64A F1 POP AF ;if a drive was specified, then it +1032 D64B 47 LD B,A ;must be the same as before. +1033 D64C 21 F0 D7 LD HL,CHGDRV +1034 D64F 7E LD A,(HL) +1035 D650 B7 OR A +1036 D651 CA 59 D6 JP Z,RENAME2 +1037 D654 B8 CP B +1038 D655 70 LD (HL),B +1039 D656 C2 73 D6 JP NZ,RENAME5 ;they were different, error. +1040 D659 70 RENAME2:LD (HL),B ; reset as per the first file specification. +1041 D65A AF XOR A +1042 D65B 32 CD D7 LD (FCB),A ;clear the drive byte of the fcb. +1043 D65E CD E9 D0 RENAME3:CALL SRCHFCB ;and go look for second file. +1044 D661 CA 6D D6 JP Z,RENAME4 ;doesn't exist? +1045 D664 11 CD D7 LD DE,FCB +1046 D667 CD 0E D1 CALL RENAM ;ok, rename the file. +1047 D66A C3 86 D7 JP GETBACK +1048 D66D ; +1049 D66D ; Process rename errors here. +1050 D66D ; +1051 D66D CD EA D3 RENAME4:CALL NONE ;file not there. +1052 D670 C3 86 D7 JP GETBACK +1053 D673 CD 66 D4 RENAME5:CALL RESETDR ;bad command format. +1054 D676 C3 09 D2 JP SYNERR +1055 D679 01 82 D6 RENAME6:LD BC,EXISTS ;destination file already exists. +1056 D67C CD A7 D0 CALL PLINE +1057 D67F C3 86 D7 JP GETBACK +1058 D682 46 69 6C 65 EXISTS: .TEXT "File exists" +1058 D686 20 65 78 69 +1058 D68A 73 74 73 +1059 D68D 00 .DB 0 +1060 D68E ; +1061 D68E ;************************************************************** +1062 D68E ;* +1063 D68E ;* U S E R C O M M A N D +1064 D68E ;* +1065 D68E ;************************************************************** +1066 D68E ; +1067 D68E CD F8 D3 USER: CALL DECODE ;get numeric value following command. +1068 D691 FE 10 CP 16 ;legal user number? +1069 D693 D2 09 D2 JP NC,SYNERR +1070 D696 5F LD E,A ;yes but is there anything else? +1071 D697 3A CE D7 LD A,(FCB+1) +1072 D69A FE 20 CP ' ' +1073 D69C CA 09 D2 JP Z,SYNERR ;yes, that is not allowed. +1074 D69F CD 15 D1 CALL GETSETUC ;ok, set user code. +1075 D6A2 C3 89 D7 JP GETBACK1 +1076 D6A5 ; +1077 D6A5 ;************************************************************** +1078 D6A5 ;* +1079 D6A5 ;* T R A N S I A N T P R O G R A M C O M M A N D +1080 D6A5 ;* +1081 D6A5 ;************************************************************** +1082 D6A5 ; +1083 D6A5 CD F5 D1 UNKNOWN:CALL VERIFY ;check for valid system (why?). +1084 D6A8 3A CE D7 LD A,(FCB+1) ;anything to execute? +1085 D6AB FE 20 CP ' ' +1086 D6AD C2 C4 D6 JP NZ,UNKWN1 +1087 D6B0 3A F0 D7 LD A,(CHGDRV) ;nope, only a drive change? +1088 D6B3 B7 OR A +1089 D6B4 CA 89 D7 JP Z,GETBACK1 ;neither??? +1090 D6B7 3D DEC A +1091 D6B8 32 EF D7 LD (CDRIVE),A ;ok, store new drive. +1092 D6BB CD 29 D1 CALL MOVECD ;set (TDRIVE) also. +1093 D6BE CD BD D0 CALL DSKSEL ;and select this drive. +1094 D6C1 C3 89 D7 JP GETBACK1 ;then return. +1095 D6C4 ; +1096 D6C4 ; Here a file name was typed. Prepare to execute it. +1097 D6C4 ; +1098 D6C4 11 D6 D7 UNKWN1: LD DE,FCB+9 ;an extension specified? +1099 D6C7 1A LD A,(DE) +1100 D6C8 FE 20 CP ' ' +1101 D6CA C2 09 D2 JP NZ,SYNERR ;yes, not allowed. +1102 D6CD D5 UNKWN2: PUSH DE +1103 D6CE CD 54 D4 CALL DSELECT ;select specified drive. +1104 D6D1 D1 POP DE +1105 D6D2 21 83 D7 LD HL,COMFILE ;set the extension to 'COM'. +1106 D6D5 CD 40 D4 CALL MOVE3 +1107 D6D8 CD D0 D0 CALL OPENFCB ;and open this file. +1108 D6DB CA 6B D7 JP Z,UNKWN9 ;not present? +1109 D6DE ; +1110 D6DE ; Load in the program. +1111 D6DE ; +1112 D6DE 21 00 01 LD HL,TBASE ;store the program starting here. +1113 D6E1 E5 UNKWN3: PUSH HL +1114 D6E2 EB EX DE,HL +1115 D6E3 CD D8 D1 CALL DMASET ;set transfer address. +1116 D6E6 11 CD D7 LD DE,FCB ;and read the next record. +1117 D6E9 CD F9 D0 CALL RDREC +1118 D6EC C2 01 D7 JP NZ,UNKWN4 ;end of file or read error? +1119 D6EF E1 POP HL ;nope, bump pointer for next sector. +1120 D6F0 11 80 00 LD DE,128 +1121 D6F3 19 ADD HL,DE +1122 D6F4 11 00 D0 LD DE,CBASE ;enough room for the whole file? +1123 D6F7 7D LD A,L +1124 D6F8 93 SUB E +1125 D6F9 7C LD A,H +1126 D6FA 9A SBC A,D +1127 D6FB D2 71 D7 JP NC,UNKWN0 ;no, it can't fit. +1128 D6FE C3 E1 D6 JP UNKWN3 +1129 D701 ; +1130 D701 ; Get here after finished reading. +1131 D701 ; +1132 D701 E1 UNKWN4: POP HL +1133 D702 3D DEC A ;normal end of file? +1134 D703 C2 71 D7 JP NZ,UNKWN0 +1135 D706 CD 66 D4 CALL RESETDR ;yes, reset previous drive. +1136 D709 CD 5E D2 CALL CONVFST ;convert the first file name that follows +1137 D70C 21 F0 D7 LD HL,CHGDRV ;command name. +1138 D70F E5 PUSH HL +1139 D710 7E LD A,(HL) ;set drive code in default fcb. +1140 D711 32 CD D7 LD (FCB),A +1141 D714 3E 10 LD A,16 ;put second name 16 bytes later. +1142 D716 CD 60 D2 CALL CONVERT ;convert second file name. +1143 D719 E1 POP HL +1144 D71A 7E LD A,(HL) ;and set the drive for this second file. +1145 D71B 32 DD D7 LD (FCB+16),A +1146 D71E AF XOR A ;clear record byte in fcb. +1147 D71F 32 ED D7 LD (FCB+32),A +1148 D722 11 5C 00 LD DE,TFCB ;move it into place at(005Ch). +1149 D725 21 CD D7 LD HL,FCB +1150 D728 06 21 LD B,33 +1151 D72A CD 42 D4 CALL HL2DE +1152 D72D 21 08 D0 LD HL,INBUFF+2 ;now move the remainder of the input +1153 D730 7E UNKWN5: LD A,(HL) ;line down to (0080h). Look for a non blank. +1154 D731 B7 OR A ;or a null. +1155 D732 CA 3E D7 JP Z,UNKWN6 +1156 D735 FE 20 CP ' ' +1157 D737 CA 3E D7 JP Z,UNKWN6 +1158 D73A 23 INC HL +1159 D73B C3 30 D7 JP UNKWN5 +1160 D73E ; +1161 D73E ; Do the line move now. It ends in a null byte. +1162 D73E ; +1163 D73E 06 00 UNKWN6: LD B,0 ;keep a character count. +1164 D740 11 81 00 LD DE,TBUFF+1 ;data gets put here. +1165 D743 7E UNKWN7: LD A,(HL) ;move it now. +1166 D744 12 LD (DE),A +1167 D745 B7 OR A +1168 D746 CA 4F D7 JP Z,UNKWN8 +1169 D749 04 INC B +1170 D74A 23 INC HL +1171 D74B 13 INC DE +1172 D74C C3 43 D7 JP UNKWN7 +1173 D74F 78 UNKWN8: LD A,B ;now store the character count. +1174 D750 32 80 00 LD (TBUFF),A +1175 D753 CD 98 D0 CALL CRLF ;clean up the screen. +1176 D756 CD D5 D1 CALL STDDMA ;set standard transfer address. +1177 D759 CD 1A D1 CALL SETCDRV ;reset current drive. +1178 D75C CD 00 01 CALL TBASE ;and execute the program. +1179 D75F ; +1180 D75F ; Transiant programs return here (or reboot). +1181 D75F ; +1182 D75F 31 AB D7 LD SP,BATCH ;set stack first off. +1183 D762 CD 29 D1 CALL MOVECD ;move current drive into place (TDRIVE). +1184 D765 CD BD D0 CALL DSKSEL ;and reselect it. +1185 D768 C3 82 D3 JP CMMND1 ;back to comand mode. +1186 D76B ; +1187 D76B ; Get here if some error occured. +1188 D76B ; +1189 D76B CD 66 D4 UNKWN9: CALL RESETDR ;inproper format. +1190 D76E C3 09 D2 JP SYNERR +1191 D771 01 7A D7 UNKWN0: LD BC,BADLOAD ;read error or won't fit. +1192 D774 CD A7 D0 CALL PLINE +1193 D777 C3 86 D7 JP GETBACK +1194 D77A 42 61 64 20 BADLOAD:.TEXT "Bad load" +1194 D77E 6C 6F 61 64 +1195 D782 00 .DB 0 +1196 D783 43 4F 4D COMFILE:.TEXT "COM" ;command file extension. +1197 D786 ; +1198 D786 ; Get here to return to command level. We will reset the +1199 D786 ; previous active drive and then either return to command +1200 D786 ; level directly or print error message and then return. +1201 D786 ; +1202 D786 CD 66 D4 GETBACK:CALL RESETDR ;reset previous drive. +1203 D789 CD 5E D2 GETBACK1: CALL CONVFST ;convert first name in (FCB). +1204 D78C 3A CE D7 LD A,(FCB+1) ;if this was just a drive change request, +1205 D78F D6 20 SUB ' ' ;make sure it was valid. +1206 D791 21 F0 D7 LD HL,CHGDRV +1207 D794 B6 OR (HL) +1208 D795 C2 09 D2 JP NZ,SYNERR +1209 D798 C3 82 D3 JP CMMND1 ;ok, return to command level. +1210 D79B ; +1211 D79B ; ccp stack area. +1212 D79B ; +1213 D79B 00 00 00 00 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +1213 D79F 00 00 00 00 +1213 D7A3 00 00 00 00 +1213 D7A7 00 00 00 00 +1214 D7AB CCPSTACK .EQU $ ;end of ccp stack area. +1215 D7AB ; +1216 D7AB ; Batch (or SUBMIT) processing information storage. +1217 D7AB ; +1218 D7AB 00 BATCH: .DB 0 ;batch mode flag (0=not active). +1219 D7AC 00 BATCHFCB: .DB 0, +1220 D7AD 24 24 24 20 .TEXT "$$$ SUB" +1220 D7B1 20 20 20 20 +1220 D7B5 53 55 42 +1221 D7B8 00 00 00 00 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +1221 D7BC 00 00 00 00 +1221 D7C0 00 00 00 00 +1221 D7C4 00 00 00 00 +1221 D7C8 00 00 00 00 +1221 D7CC 00 +1222 D7CD ; +1223 D7CD ; File control block setup by the CCP. +1224 D7CD ; +1225 D7CD 00 FCB: .DB 0 +1226 D7CE 20 20 20 20 .TEXT " " +1226 D7D2 20 20 20 20 +1226 D7D6 20 20 20 +1227 D7D9 00 00 00 00 .DB 0,0,0,0,0 +1227 D7DD 00 +1228 D7DE 20 20 20 20 .TEXT " " +1228 D7E2 20 20 20 20 +1228 D7E6 20 20 20 +1229 D7E9 00 00 00 00 .DB 0,0,0,0,0 +1229 D7ED 00 +1230 D7EE 00 RTNCODE:.DB 0 ;status returned from bdos call. +1231 D7EF 00 CDRIVE: .DB 0 ;currently active drive. +1232 D7F0 00 CHGDRV: .DB 0 ;change in drives flag (0=no change). +1233 D7F1 00 00 NBYTES: .DW 0 ;byte counter used by TYPE. +1234 D7F3 ; +1235 D7F3 ; Room for expansion? +1236 D7F3 ; +1237 D7F3 00 00 00 00 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0 +1237 D7F7 00 00 00 00 +1237 D7FB 00 00 00 00 +1237 D7FF 00 +1238 D800 ; +1239 D800 ; Note that the following six bytes must match those at +1240 D800 ; (PATTRN1) or cp/m will HALT. Why? +1241 D800 ; +1242 D800 00 16 00 00 PATTRN2:.DB 0,22,0,0,0,0 ;(* serial number bytes *). +1242 D804 00 00 +1243 D806 ; +1244 D806 ;************************************************************** +1245 D806 ;* +1246 D806 ;* B D O S E N T R Y +1247 D806 ;* +1248 D806 ;************************************************************** +1249 D806 ; +1250 D806 C3 11 D8 FBASE: JP FBASE1 +1251 D809 ; +1252 D809 ; Bdos error table. +1253 D809 ; +1254 D809 99 D8 BADSCTR:.DW ERROR1 ;bad sector on read or write. +1255 D80B A5 D8 BADSLCT:.DW ERROR2 ;bad disk select. +1256 D80D AB D8 RODISK: .DW ERROR3 ;disk is read only. +1257 D80F B1 D8 ROFILE: .DW ERROR4 ;file is read only. +1258 D811 ; +1259 D811 ; Entry into bdos. (DE) or (E) are the parameters passed. The +1260 D811 ; function number desired is in register (C). +1261 D811 ; +1262 D811 EB FBASE1: EX DE,HL ;save the (DE) parameters. +1263 D812 22 43 DB LD (PARAMS),HL +1264 D815 EB EX DE,HL +1265 D816 7B LD A,E ;and save register (E) in particular. +1266 D817 32 D6 E5 LD (EPARAM),A +1267 D81A 21 00 00 LD HL,0 +1268 D81D 22 45 DB LD (STATUS),HL ;clear return status. +1269 D820 39 ADD HL,SP +1270 D821 22 0F DB LD (USRSTACK),HL ;save users stack pointer. +1271 D824 31 41 DB LD SP,STKAREA ;and set our own. +1272 D827 AF XOR A ;clear auto select storage space. +1273 D828 32 E0 E5 LD (AUTOFLAG),A +1274 D82B 32 DE E5 LD (AUTO),A +1275 D82E 21 74 E5 LD HL,GOBACK ;set return address. +1276 D831 E5 PUSH HL +1277 D832 79 LD A,C ;get function number. +1278 D833 FE 29 CP NFUNCTS ;valid function number? +1279 D835 D0 RET NC +1280 D836 4B LD C,E ;keep single register function here. +1281 D837 21 47 D8 LD HL,FUNCTNS ;now look thru the function table. +1282 D83A 5F LD E,A +1283 D83B 16 00 LD D,0 ;(DE)=function number. +1284 D83D 19 ADD HL,DE +1285 D83E 19 ADD HL,DE ;(HL)=(start of table)+2*(function number). +1286 D83F 5E LD E,(HL) +1287 D840 23 INC HL +1288 D841 56 LD D,(HL) ;now (DE)=address for this function. +1289 D842 2A 43 DB LD HL,(PARAMS) ;retrieve parameters. +1290 D845 EB EX DE,HL ;now (DE) has the original parameters. +1291 D846 E9 JP (HL) ;execute desired function. +1292 D847 ; +1293 D847 ; BDOS function jump table. +1294 D847 ; +1295 D847 NFUNCTS .EQU 41 ;number of functions in followin table. +1296 D847 ; +1297 D847 03 E6 C8 DA FUNCTNS:.DW WBOOT,GETCON,OUTCON,GETRDR,PUNCH,LIST,DIRCIO,GETIOB +1297 D84B 90 D9 CE DA +1297 D84F 12 E6 0F E6 +1297 D853 D4 DA ED DA +1298 D857 F3 DA F8 DA .DW SETIOB,PRTSTR,RDBUFF,GETCSTS,GETVER,RSTDSK,SETDSK,OPENFIL +1298 D85B E1 D9 FE DA +1298 D85F 7E E4 83 E4 +1298 D863 45 E4 9C E4 +1299 D867 A5 E4 AB E4 .DW CLOSEFIL,GETFST,GETNXT,DELFILE,READSEQ,WRTSEQ,FCREATE +1299 D86B C8 E4 D7 E4 +1299 D86F E0 E4 E6 E4 +1299 D873 EC E4 +1300 D875 F5 E4 FE E4 .DW RENFILE,GETLOG,GETCRNT,PUTDMA,GETALOC,WRTPRTD,GETROV,SETATTR +1300 D879 04 E5 0A E5 +1300 D87D 11 E5 2C DD +1300 D881 17 E5 1D E5 +1301 D885 26 E5 2D E5 .DW GETPARM,GETUSER,RDRANDOM,WTRANDOM,FILESIZE,SETRAN,LOGOFF,RTN +1301 D889 41 E5 47 E5 +1301 D88D 4D E5 0E E4 +1301 D891 53 E5 04 DB +1302 D895 04 DB 9B E5 .DW RTN,WTSPECL +1303 D899 ; +1304 D899 ; Bdos error message section. +1305 D899 ; +1306 D899 21 CA D8 ERROR1: LD HL,BADSEC ;bad sector message. +1307 D89C CD E5 D8 CALL PRTERR ;print it and get a 1 char responce. +1308 D89F FE 03 CP CNTRLC ;re-boot request (control-c)? +1309 D8A1 CA 00 00 JP Z,0 ;yes. +1310 D8A4 C9 RET ;no, return to retry i/o function. +1311 D8A5 ; +1312 D8A5 21 D5 D8 ERROR2: LD HL,BADSEL ;bad drive selected. +1313 D8A8 C3 B4 D8 JP ERROR5 +1314 D8AB ; +1315 D8AB 21 E1 D8 ERROR3: LD HL,DISKRO ;disk is read only. +1316 D8AE C3 B4 D8 JP ERROR5 +1317 D8B1 ; +1318 D8B1 21 DC D8 ERROR4: LD HL,FILERO ;file is read only. +1319 D8B4 ; +1320 D8B4 CD E5 D8 ERROR5: CALL PRTERR +1321 D8B7 C3 00 00 JP 0 ;always reboot on these errors. +1322 D8BA ; +1323 D8BA 42 64 6F 73 BDOSERR:.TEXT "Bdos Err On " +1323 D8BE 20 45 72 72 +1323 D8C2 20 4F 6E 20 +1324 D8C6 20 3A 20 24 BDOSDRV:.TEXT " : $" +1325 D8CA 42 61 64 20 BADSEC: .TEXT "Bad Sector$" +1325 D8CE 53 65 63 74 +1325 D8D2 6F 72 24 +1326 D8D5 53 65 6C 65 BADSEL: .TEXT "Select$" +1326 D8D9 63 74 24 +1327 D8DC 46 69 6C 65 FILERO: .TEXT "File " +1327 D8E0 20 +1328 D8E1 52 2F 4F 24 DISKRO: .TEXT "R/O$" +1329 D8E5 ; +1330 D8E5 ; Print bdos error message. +1331 D8E5 ; +1332 D8E5 E5 PRTERR: PUSH HL ;save second message pointer. +1333 D8E6 CD C9 D9 CALL OUTCRLF ;send (cr)(lf). +1334 D8E9 3A 42 DB LD A,(ACTIVE) ;get active drive. +1335 D8EC C6 41 ADD A,'A' ;make ascii. +1336 D8EE 32 C6 D8 LD (BDOSDRV),A ;and put in message. +1337 D8F1 01 BA D8 LD BC,BDOSERR ;and print it. +1338 D8F4 CD D3 D9 CALL PRTMESG +1339 D8F7 C1 POP BC ;print second message line now. +1340 D8F8 CD D3 D9 CALL PRTMESG +1341 D8FB ; +1342 D8FB ; Get an input character. We will check our 1 character +1343 D8FB ; buffer first. This may be set by the console status routine. +1344 D8FB ; +1345 D8FB 21 0E DB GETCHAR:LD HL,CHARBUF ;check character buffer. +1346 D8FE 7E LD A,(HL) ;anything present already? +1347 D8FF 36 00 LD (HL),0 ;...either case clear it. +1348 D901 B7 OR A +1349 D902 C0 RET NZ ;yes, use it. +1350 D903 C3 09 E6 JP CONIN ;nope, go get a character responce. +1351 D906 ; +1352 D906 ; Input and echo a character. +1353 D906 ; +1354 D906 CD FB D8 GETECHO:CALL GETCHAR ;input a character. +1355 D909 CD 14 D9 CALL CHKCHAR ;carriage control? +1356 D90C D8 RET C ;no, a regular control char so don't echo. +1357 D90D F5 PUSH AF ;ok, save character now. +1358 D90E 4F LD C,A +1359 D90F CD 90 D9 CALL OUTCON ;and echo it. +1360 D912 F1 POP AF ;get character and return. +1361 D913 C9 RET +1362 D914 ; +1363 D914 ; Check character in (A). Set the zero flag on a carriage +1364 D914 ; control character and the carry flag on any other control +1365 D914 ; character. +1366 D914 ; +1367 D914 FE 0D CHKCHAR:CP CR ;check for carriage return, line feed, backspace, +1368 D916 C8 RET Z ;or a tab. +1369 D917 FE 0A CP LF +1370 D919 C8 RET Z +1371 D91A FE 09 CP TAB +1372 D91C C8 RET Z +1373 D91D FE 08 CP BS +1374 D91F C8 RET Z +1375 D920 FE 20 CP ' ' ;other control char? Set carry flag. +1376 D922 C9 RET +1377 D923 ; +1378 D923 ; Check the console during output. Halt on a control-s, then +1379 D923 ; reboot on a control-c. If anything else is ready, clear the +1380 D923 ; zero flag and return (the calling routine may want to do +1381 D923 ; something). +1382 D923 ; +1383 D923 3A 0E DB CKCONSOL: LD A,(CHARBUF) ;check buffer. +1384 D926 B7 OR A ;if anything, just return without checking. +1385 D927 C2 45 D9 JP NZ,CKCON2 +1386 D92A CD 06 E6 CALL CONST ;nothing in buffer. Check console. +1387 D92D E6 01 AND 01H ;look at bit 0. +1388 D92F C8 RET Z ;return if nothing. +1389 D930 CD 09 E6 CALL CONIN ;ok, get it. +1390 D933 FE 13 CP CNTRLS ;if not control-s, return with zero cleared. +1391 D935 C2 42 D9 JP NZ,CKCON1 +1392 D938 CD 09 E6 CALL CONIN ;halt processing until another char +1393 D93B FE 03 CP CNTRLC ;is typed. Control-c? +1394 D93D CA 00 00 JP Z,0 ;yes, reboot now. +1395 D940 AF XOR A ;no, just pretend nothing was ever ready. +1396 D941 C9 RET +1397 D942 32 0E DB CKCON1: LD (CHARBUF),A ;save character in buffer for later processing. +1398 D945 3E 01 CKCON2: LD A,1 ;set (A) to non zero to mean something is ready. +1399 D947 C9 RET +1400 D948 ; +1401 D948 ; Output (C) to the screen. If the printer flip-flop flag +1402 D948 ; is set, we will send character to printer also. The console +1403 D948 ; will be checked in the process. +1404 D948 ; +1405 D948 3A 0A DB OUTCHAR:LD A,(OUTFLAG) ;check output flag. +1406 D94B B7 OR A ;anything and we won't generate output. +1407 D94C C2 62 D9 JP NZ,OUTCHR1 +1408 D94F C5 PUSH BC +1409 D950 CD 23 D9 CALL CKCONSOL ;check console (we don't care whats there). +1410 D953 C1 POP BC +1411 D954 C5 PUSH BC +1412 D955 CD 0C E6 CALL CONOUT ;output (C) to the screen. +1413 D958 C1 POP BC +1414 D959 C5 PUSH BC +1415 D95A 3A 0D DB LD A,(PRTFLAG) ;check printer flip-flop flag. +1416 D95D B7 OR A +1417 D95E C4 0F E6 CALL NZ,LIST ;print it also if non-zero. +1418 D961 C1 POP BC +1419 D962 79 OUTCHR1:LD A,C ;update cursors position. +1420 D963 21 0C DB LD HL,CURPOS +1421 D966 FE 7F CP DEL ;rubouts don't do anything here. +1422 D968 C8 RET Z +1423 D969 34 INC (HL) ;bump line pointer. +1424 D96A FE 20 CP ' ' ;and return if a normal character. +1425 D96C D0 RET NC +1426 D96D 35 DEC (HL) ;restore and check for the start of the line. +1427 D96E 7E LD A,(HL) +1428 D96F B7 OR A +1429 D970 C8 RET Z ;ingnore control characters at the start of the line. +1430 D971 79 LD A,C +1431 D972 FE 08 CP BS ;is it a backspace? +1432 D974 C2 79 D9 JP NZ,OUTCHR2 +1433 D977 35 DEC (HL) ;yes, backup pointer. +1434 D978 C9 RET +1435 D979 FE 0A OUTCHR2:CP LF ;is it a line feed? +1436 D97B C0 RET NZ ;ignore anything else. +1437 D97C 36 00 LD (HL),0 ;reset pointer to start of line. +1438 D97E C9 RET +1439 D97F ; +1440 D97F ; Output (A) to the screen. If it is a control character +1441 D97F ; (other than carriage control), use ^x format. +1442 D97F ; +1443 D97F 79 SHOWIT: LD A,C +1444 D980 CD 14 D9 CALL CHKCHAR ;check character. +1445 D983 D2 90 D9 JP NC,OUTCON ;not a control, use normal output. +1446 D986 F5 PUSH AF +1447 D987 0E 5E LD C,'^' ;for a control character, preceed it with '^'. +1448 D989 CD 48 D9 CALL OUTCHAR +1449 D98C F1 POP AF +1450 D98D F6 40 OR '@' ;and then use the letter equivelant. +1451 D98F 4F LD C,A +1452 D990 ; +1453 D990 ; Function to output (C) to the console device and expand tabs +1454 D990 ; if necessary. +1455 D990 ; +1456 D990 79 OUTCON: LD A,C +1457 D991 FE 09 CP TAB ;is it a tab? +1458 D993 C2 48 D9 JP NZ,OUTCHAR ;use regular output. +1459 D996 0E 20 OUTCON1:LD C,' ' ;yes it is, use spaces instead. +1460 D998 CD 48 D9 CALL OUTCHAR +1461 D99B 3A 0C DB LD A,(CURPOS) ;go until the cursor is at a multiple of 8 +1462 D99E +1463 D99E E6 07 AND 07H ;position. +1464 D9A0 C2 96 D9 JP NZ,OUTCON1 +1465 D9A3 C9 RET +1466 D9A4 ; +1467 D9A4 ; Echo a backspace character. Erase the prevoius character +1468 D9A4 ; on the screen. +1469 D9A4 ; +1470 D9A4 CD AC D9 BACKUP: CALL BACKUP1 ;backup the screen 1 place. +1471 D9A7 0E 20 LD C,' ' ;then blank that character. +1472 D9A9 CD 0C E6 CALL CONOUT +1473 D9AC 0E 08 BACKUP1:LD C,BS ;then back space once more. +1474 D9AE C3 0C E6 JP CONOUT +1475 D9B1 ; +1476 D9B1 ; Signal a deleted line. Print a '#' at the end and start +1477 D9B1 ; over. +1478 D9B1 ; +1479 D9B1 0E 23 NEWLINE:LD C,'#' +1480 D9B3 CD 48 D9 CALL OUTCHAR ;print this. +1481 D9B6 CD C9 D9 CALL OUTCRLF ;start new line. +1482 D9B9 3A 0C DB NEWLN1: LD A,(CURPOS) ;move the cursor to the starting position. +1483 D9BC 21 0B DB LD HL,STARTING +1484 D9BF BE CP (HL) +1485 D9C0 D0 RET NC ;there yet? +1486 D9C1 0E 20 LD C,' ' +1487 D9C3 CD 48 D9 CALL OUTCHAR ;nope, keep going. +1488 D9C6 C3 B9 D9 JP NEWLN1 +1489 D9C9 ; +1490 D9C9 ; Output a (cr) (lf) to the console device (screen). +1491 D9C9 ; +1492 D9C9 0E 0D OUTCRLF:LD C,CR +1493 D9CB CD 48 D9 CALL OUTCHAR +1494 D9CE 0E 0A LD C,LF +1495 D9D0 C3 48 D9 JP OUTCHAR +1496 D9D3 ; +1497 D9D3 ; Print message pointed to by (BC). It will end with a '$'. +1498 D9D3 ; +1499 D9D3 0A PRTMESG:LD A,(BC) ;check for terminating character. +1500 D9D4 FE 24 CP '$' +1501 D9D6 C8 RET Z +1502 D9D7 03 INC BC +1503 D9D8 C5 PUSH BC ;otherwise, bump pointer and print it. +1504 D9D9 4F LD C,A +1505 D9DA CD 90 D9 CALL OUTCON +1506 D9DD C1 POP BC +1507 D9DE C3 D3 D9 JP PRTMESG +1508 D9E1 ; +1509 D9E1 ; Function to execute a buffered read. +1510 D9E1 ; +1511 D9E1 3A 0C DB RDBUFF: LD A,(CURPOS) ;use present location as starting one. +1512 D9E4 32 0B DB LD (STARTING),A +1513 D9E7 2A 43 DB LD HL,(PARAMS) ;get the maximum buffer space. +1514 D9EA 4E LD C,(HL) +1515 D9EB 23 INC HL ;point to first available space. +1516 D9EC E5 PUSH HL ;and save. +1517 D9ED 06 00 LD B,0 ;keep a character count. +1518 D9EF C5 RDBUF1: PUSH BC +1519 D9F0 E5 PUSH HL +1520 D9F1 CD FB D8 RDBUF2: CALL GETCHAR ;get the next input character. +1521 D9F4 E6 7F AND 7FH ;strip bit 7. +1522 D9F6 E1 POP HL ;reset registers. +1523 D9F7 C1 POP BC +1524 D9F8 FE 0D CP CR ;en of the line? +1525 D9FA CA C1 DA JP Z,RDBUF17 +1526 D9FD FE 0A CP LF +1527 D9FF CA C1 DA JP Z,RDBUF17 +1528 DA02 FE 08 CP BS ;how about a backspace? +1529 DA04 C2 16 DA JP NZ,RDBUF3 +1530 DA07 78 LD A,B ;yes, but ignore at the beginning of the line. +1531 DA08 B7 OR A +1532 DA09 CA EF D9 JP Z,RDBUF1 +1533 DA0C 05 DEC B ;ok, update counter. +1534 DA0D 3A 0C DB LD A,(CURPOS) ;if we backspace to the start of the line, +1535 DA10 32 0A DB LD (OUTFLAG),A ;treat as a cancel (control-x). +1536 DA13 C3 70 DA JP RDBUF10 +1537 DA16 FE 7F RDBUF3: CP DEL ;user typed a rubout? +1538 DA18 C2 26 DA JP NZ,RDBUF4 +1539 DA1B 78 LD A,B ;ignore at the start of the line. +1540 DA1C B7 OR A +1541 DA1D CA EF D9 JP Z,RDBUF1 +1542 DA20 7E LD A,(HL) ;ok, echo the prevoius character. +1543 DA21 05 DEC B ;and reset pointers (counters). +1544 DA22 2B DEC HL +1545 DA23 C3 A9 DA JP RDBUF15 +1546 DA26 FE 05 RDBUF4: CP CNTRLE ;physical end of line? +1547 DA28 C2 37 DA JP NZ,RDBUF5 +1548 DA2B C5 PUSH BC ;yes, do it. +1549 DA2C E5 PUSH HL +1550 DA2D CD C9 D9 CALL OUTCRLF +1551 DA30 AF XOR A ;and update starting position. +1552 DA31 32 0B DB LD (STARTING),A +1553 DA34 C3 F1 D9 JP RDBUF2 +1554 DA37 FE 10 RDBUF5: CP CNTRLP ;control-p? +1555 DA39 C2 48 DA JP NZ,RDBUF6 +1556 DA3C E5 PUSH HL ;yes, flip the print flag filp-flop byte. +1557 DA3D 21 0D DB LD HL,PRTFLAG +1558 DA40 3E 01 LD A,1 ;PRTFLAG=1-PRTFLAG +1559 DA42 96 SUB (HL) +1560 DA43 77 LD (HL),A +1561 DA44 E1 POP HL +1562 DA45 C3 EF D9 JP RDBUF1 +1563 DA48 FE 18 RDBUF6: CP CNTRLX ;control-x (cancel)? +1564 DA4A C2 5F DA JP NZ,RDBUF8 +1565 DA4D E1 POP HL +1566 DA4E 3A 0B DB RDBUF7: LD A,(STARTING) ;yes, backup the cursor to here. +1567 DA51 21 0C DB LD HL,CURPOS +1568 DA54 BE CP (HL) +1569 DA55 D2 E1 D9 JP NC,RDBUFF ;done yet? +1570 DA58 35 DEC (HL) ;no, decrement pointer and output back up one space. +1571 DA59 CD A4 D9 CALL BACKUP +1572 DA5C C3 4E DA JP RDBUF7 +1573 DA5F FE 15 RDBUF8: CP CNTRLU ;cntrol-u (cancel line)? +1574 DA61 C2 6B DA JP NZ,RDBUF9 +1575 DA64 CD B1 D9 CALL NEWLINE ;start a new line. +1576 DA67 E1 POP HL +1577 DA68 C3 E1 D9 JP RDBUFF +1578 DA6B FE 12 RDBUF9: CP CNTRLR ;control-r? +1579 DA6D C2 A6 DA JP NZ,RDBUF14 +1580 DA70 C5 RDBUF10:PUSH BC ;yes, start a new line and retype the old one. +1581 DA71 CD B1 D9 CALL NEWLINE +1582 DA74 C1 POP BC +1583 DA75 E1 POP HL +1584 DA76 E5 PUSH HL +1585 DA77 C5 PUSH BC +1586 DA78 78 RDBUF11:LD A,B ;done whole line yet? +1587 DA79 B7 OR A +1588 DA7A CA 8A DA JP Z,RDBUF12 +1589 DA7D 23 INC HL ;nope, get next character. +1590 DA7E 4E LD C,(HL) +1591 DA7F 05 DEC B ;count it. +1592 DA80 C5 PUSH BC +1593 DA81 E5 PUSH HL +1594 DA82 CD 7F D9 CALL SHOWIT ;and display it. +1595 DA85 E1 POP HL +1596 DA86 C1 POP BC +1597 DA87 C3 78 DA JP RDBUF11 +1598 DA8A E5 RDBUF12:PUSH HL ;done with line. If we were displaying +1599 DA8B 3A 0A DB LD A,(OUTFLAG) ;then update cursor position. +1600 DA8E B7 OR A +1601 DA8F CA F1 D9 JP Z,RDBUF2 +1602 DA92 21 0C DB LD HL,CURPOS ;because this line is shorter, we must +1603 DA95 96 SUB (HL) ;back up the cursor (not the screen however) +1604 DA96 32 0A DB LD (OUTFLAG),A ;some number of positions. +1605 DA99 CD A4 D9 RDBUF13:CALL BACKUP ;note that as long as (OUTFLAG) is non +1606 DA9C 21 0A DB LD HL,OUTFLAG ;zero, the screen will not be changed. +1607 DA9F 35 DEC (HL) +1608 DAA0 C2 99 DA JP NZ,RDBUF13 +1609 DAA3 C3 F1 D9 JP RDBUF2 ;now just get the next character. +1610 DAA6 ; +1611 DAA6 ; Just a normal character, put this in our buffer and echo. +1612 DAA6 ; +1613 DAA6 23 RDBUF14:INC HL +1614 DAA7 77 LD (HL),A ;store character. +1615 DAA8 04 INC B ;and count it. +1616 DAA9 C5 RDBUF15:PUSH BC +1617 DAAA E5 PUSH HL +1618 DAAB 4F LD C,A ;echo it now. +1619 DAAC CD 7F D9 CALL SHOWIT +1620 DAAF E1 POP HL +1621 DAB0 C1 POP BC +1622 DAB1 7E LD A,(HL) ;was it an abort request? +1623 DAB2 FE 03 CP CNTRLC ;control-c abort? +1624 DAB4 78 LD A,B +1625 DAB5 C2 BD DA JP NZ,RDBUF16 +1626 DAB8 FE 01 CP 1 ;only if at start of line. +1627 DABA CA 00 00 JP Z,0 +1628 DABD B9 RDBUF16:CP C ;nope, have we filled the buffer? +1629 DABE DA EF D9 JP C,RDBUF1 +1630 DAC1 E1 RDBUF17:POP HL ;yes end the line and return. +1631 DAC2 70 LD (HL),B +1632 DAC3 0E 0D LD C,CR +1633 DAC5 C3 48 D9 JP OUTCHAR ;output (cr) and return. +1634 DAC8 ; +1635 DAC8 ; Function to get a character from the console device. +1636 DAC8 ; +1637 DAC8 CD 06 D9 GETCON: CALL GETECHO ;get and echo. +1638 DACB C3 01 DB JP SETSTAT ;save status and return. +1639 DACE ; +1640 DACE ; Function to get a character from the tape reader device. +1641 DACE ; +1642 DACE CD 15 E6 GETRDR: CALL READER ;get a character from reader, set status and return. +1643 DAD1 C3 01 DB JP SETSTAT +1644 DAD4 ; +1645 DAD4 ; Function to perform direct console i/o. If (C) contains (FF) +1646 DAD4 ; then this is an input request. If (C) contains (FE) then +1647 DAD4 ; this is a status request. Otherwise we are to output (C). +1648 DAD4 ; +1649 DAD4 79 DIRCIO: LD A,C ;test for (FF). +1650 DAD5 3C INC A +1651 DAD6 CA E0 DA JP Z,DIRC1 +1652 DAD9 3C INC A ;test for (FE). +1653 DADA CA 06 E6 JP Z,CONST +1654 DADD C3 0C E6 JP CONOUT ;just output (C). +1655 DAE0 CD 06 E6 DIRC1: CALL CONST ;this is an input request. +1656 DAE3 B7 OR A +1657 DAE4 CA 91 E5 JP Z,GOBACK1 ;not ready? Just return (directly). +1658 DAE7 CD 09 E6 CALL CONIN ;yes, get character. +1659 DAEA C3 01 DB JP SETSTAT ;set status and return. +1660 DAED ; +1661 DAED ; Function to return the i/o byte. +1662 DAED ; +1663 DAED 3A 03 00 GETIOB: LD A,(IOBYTE) +1664 DAF0 C3 01 DB JP SETSTAT +1665 DAF3 ; +1666 DAF3 ; Function to set the i/o byte. +1667 DAF3 ; +1668 DAF3 21 03 00 SETIOB: LD HL,IOBYTE +1669 DAF6 71 LD (HL),C +1670 DAF7 C9 RET +1671 DAF8 ; +1672 DAF8 ; Function to print the character string pointed to by (DE) +1673 DAF8 ; on the console device. The string ends with a '$'. +1674 DAF8 ; +1675 DAF8 EB PRTSTR: EX DE,HL +1676 DAF9 4D LD C,L +1677 DAFA 44 LD B,H ;now (BC) points to it. +1678 DAFB C3 D3 D9 JP PRTMESG +1679 DAFE ; +1680 DAFE ; Function to interigate the console device. +1681 DAFE ; +1682 DAFE CD 23 D9 GETCSTS:CALL CKCONSOL +1683 DB01 ; +1684 DB01 ; Get here to set the status and return to the cleanup +1685 DB01 ; section. Then back to the user. +1686 DB01 ; +1687 DB01 32 45 DB SETSTAT:LD (STATUS),A +1688 DB04 C9 RTN: RET +1689 DB05 ; +1690 DB05 ; Set the status to 1 (read or write error code). +1691 DB05 ; +1692 DB05 3E 01 IOERR1: LD A,1 +1693 DB07 C3 01 DB JP SETSTAT +1694 DB0A ; +1695 DB0A 00 OUTFLAG:.DB 0 ;output flag (non zero means no output). +1696 DB0B 02 STARTING: .DB 2 ;starting position for cursor. +1697 DB0C 00 CURPOS: .DB 0 ;cursor position (0=start of line). +1698 DB0D 00 PRTFLAG:.DB 0 ;printer flag (control-p toggle). List if non zero. +1699 DB0E 00 CHARBUF:.DB 0 ;single input character buffer. +1700 DB0F ; +1701 DB0F ; Stack area for BDOS calls. +1702 DB0F ; +1703 DB0F 00 00 USRSTACK: .DW 0 ;save users stack pointer here. +1704 DB11 ; +1705 DB11 00 00 00 00 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +1705 DB15 00 00 00 00 +1705 DB19 00 00 00 00 +1705 DB1D 00 00 00 00 +1705 DB21 00 00 00 00 +1705 DB25 00 00 00 00 +1706 DB29 00 00 00 00 .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +1706 DB2D 00 00 00 00 +1706 DB31 00 00 00 00 +1706 DB35 00 00 00 00 +1706 DB39 00 00 00 00 +1706 DB3D 00 00 00 00 +1707 DB41 STKAREA .EQU $ ;end of stack area. +1708 DB41 ; +1709 DB41 00 USERNO: .DB 0 ;current user number. +1710 DB42 00 ACTIVE: .DB 0 ;currently active drive. +1711 DB43 00 00 PARAMS: .DW 0 ;save (DE) parameters here on entry. +1712 DB45 00 00 STATUS: .DW 0 ;status returned from bdos function. +1713 DB47 ; +1714 DB47 ; Select error occured, jump to error routine. +1715 DB47 ; +1716 DB47 21 0B D8 SLCTERR:LD HL,BADSLCT +1717 DB4A ; +1718 DB4A ; Jump to (HL) indirectly. +1719 DB4A ; +1720 DB4A 5E JUMPHL: LD E,(HL) +1721 DB4B 23 INC HL +1722 DB4C 56 LD D,(HL) ;now (DE) contain the desired address. +1723 DB4D EB EX DE,HL +1724 DB4E E9 JP (HL) +1725 DB4F ; +1726 DB4F ; Block move. (DE) to (HL), (C) bytes total. +1727 DB4F ; +1728 DB4F 0C DE2HL: INC C ;is count down to zero? +1729 DB50 0D DE2HL1: DEC C +1730 DB51 C8 RET Z ;yes, we are done. +1731 DB52 1A LD A,(DE) ;no, move one more byte. +1732 DB53 77 LD (HL),A +1733 DB54 13 INC DE +1734 DB55 23 INC HL +1735 DB56 C3 50 DB JP DE2HL1 ;and repeat. +1736 DB59 ; +1737 DB59 ; Select the desired drive. +1738 DB59 ; +1739 DB59 3A 42 DB SELECT: LD A,(ACTIVE) ;get active disk. +1740 DB5C 4F LD C,A +1741 DB5D CD 1B E6 CALL SELDSK ;select it. +1742 DB60 7C LD A,H ;valid drive? +1743 DB61 B5 OR L ;valid drive? +1744 DB62 C8 RET Z ;return if not. +1745 DB63 ; +1746 DB63 ; Here, the BIOS returned the address of the parameter block +1747 DB63 ; in (HL). We will extract the necessary pointers and save them. +1748 DB63 ; +1749 DB63 5E LD E,(HL) ;yes, get address of translation table into (DE). +1750 DB64 23 INC HL +1751 DB65 56 LD D,(HL) +1752 DB66 23 INC HL +1753 DB67 22 B3 E5 LD (SCRATCH1),HL ;save pointers to scratch areas. +1754 DB6A 23 INC HL +1755 DB6B 23 INC HL +1756 DB6C 22 B5 E5 LD (SCRATCH2),HL ;ditto. +1757 DB6F 23 INC HL +1758 DB70 23 INC HL +1759 DB71 22 B7 E5 LD (SCRATCH3),HL ;ditto. +1760 DB74 23 INC HL +1761 DB75 23 INC HL +1762 DB76 EB EX DE,HL ;now save the translation table address. +1763 DB77 22 D0 E5 LD (XLATE),HL +1764 DB7A 21 B9 E5 LD HL,DIRBUF ;put the next 8 bytes here. +1765 DB7D 0E 08 LD C,8 ;they consist of the directory buffer +1766 DB7F CD 4F DB CALL DE2HL ;pointer, parameter block pointer, +1767 DB82 2A BB E5 LD HL,(DISKPB) ;check and allocation vectors. +1768 DB85 EB EX DE,HL +1769 DB86 21 C1 E5 LD HL,SECTORS ;move parameter block into our ram. +1770 DB89 0E 0F LD C,15 ;it is 15 bytes long. +1771 DB8B CD 4F DB CALL DE2HL +1772 DB8E 2A C6 E5 LD HL,(DSKSIZE) ;check disk size. +1773 DB91 7C LD A,H ;more than 256 blocks on this? +1774 DB92 21 DD E5 LD HL,BIGDISK +1775 DB95 36 FF LD (HL),0FFH ;set to samll. +1776 DB97 B7 OR A +1777 DB98 CA 9D DB JP Z,SELECT1 +1778 DB9B 36 00 LD (HL),0 ;wrong, set to large. +1779 DB9D 3E FF SELECT1:LD A,0FFH ;clear the zero flag. +1780 DB9F B7 OR A +1781 DBA0 C9 RET +1782 DBA1 ; +1783 DBA1 ; Routine to home the disk track head and clear pointers. +1784 DBA1 ; +1785 DBA1 CD 18 E6 HOMEDRV:CALL HOME ;home the head. +1786 DBA4 AF XOR A +1787 DBA5 2A B5 E5 LD HL,(SCRATCH2) ;set our track pointer also. +1788 DBA8 77 LD (HL),A +1789 DBA9 23 INC HL +1790 DBAA 77 LD (HL),A +1791 DBAB 2A B7 E5 LD HL,(SCRATCH3) ;and our sector pointer. +1792 DBAE 77 LD (HL),A +1793 DBAF 23 INC HL +1794 DBB0 77 LD (HL),A +1795 DBB1 C9 RET +1796 DBB2 ; +1797 DBB2 ; Do the actual disk read and check the error return status. +1798 DBB2 ; +1799 DBB2 CD 27 E6 DOREAD: CALL READ +1800 DBB5 C3 BB DB JP IORET +1801 DBB8 ; +1802 DBB8 ; Do the actual disk write and handle any bios error. +1803 DBB8 ; +1804 DBB8 CD 2A E6 DOWRITE:CALL WRITE +1805 DBBB B7 IORET: OR A +1806 DBBC C8 RET Z ;return unless an error occured. +1807 DBBD 21 09 D8 LD HL,BADSCTR ;bad read/write on this sector. +1808 DBC0 C3 4A DB JP JUMPHL +1809 DBC3 ; +1810 DBC3 ; Routine to select the track and sector that the desired +1811 DBC3 ; block number falls in. +1812 DBC3 ; +1813 DBC3 2A EA E5 TRKSEC: LD HL,(FILEPOS) ;get position of last accessed file +1814 DBC6 0E 02 LD C,2 ;in directory and compute sector #. +1815 DBC8 CD EA DC CALL SHIFTR ;sector #=file-position/4. +1816 DBCB 22 E5 E5 LD (BLKNMBR),HL ;save this as the block number of interest. +1817 DBCE 22 EC E5 LD (CKSUMTBL),HL ;what's it doing here too? +1818 DBD1 ; +1819 DBD1 ; if the sector number has already been set (BLKNMBR), enter +1820 DBD1 ; at this point. +1821 DBD1 ; +1822 DBD1 21 E5 E5 TRKSEC1:LD HL,BLKNMBR +1823 DBD4 4E LD C,(HL) ;move sector number into (BC). +1824 DBD5 23 INC HL +1825 DBD6 46 LD B,(HL) +1826 DBD7 2A B7 E5 LD HL,(SCRATCH3) ;get current sector number and +1827 DBDA 5E LD E,(HL) ;move this into (DE). +1828 DBDB 23 INC HL +1829 DBDC 56 LD D,(HL) +1830 DBDD 2A B5 E5 LD HL,(SCRATCH2) ;get current track number. +1831 DBE0 7E LD A,(HL) ;and this into (HL). +1832 DBE1 23 INC HL +1833 DBE2 66 LD H,(HL) +1834 DBE3 6F LD L,A +1835 DBE4 79 TRKSEC2:LD A,C ;is desired sector before current one? +1836 DBE5 93 SUB E +1837 DBE6 78 LD A,B +1838 DBE7 9A SBC A,D +1839 DBE8 D2 FA DB JP NC,TRKSEC3 +1840 DBEB E5 PUSH HL ;yes, decrement sectors by one track. +1841 DBEC 2A C1 E5 LD HL,(SECTORS) ;get sectors per track. +1842 DBEF 7B LD A,E +1843 DBF0 95 SUB L +1844 DBF1 5F LD E,A +1845 DBF2 7A LD A,D +1846 DBF3 9C SBC A,H +1847 DBF4 57 LD D,A ;now we have backed up one full track. +1848 DBF5 E1 POP HL +1849 DBF6 2B DEC HL ;adjust track counter. +1850 DBF7 C3 E4 DB JP TRKSEC2 +1851 DBFA E5 TRKSEC3:PUSH HL ;desired sector is after current one. +1852 DBFB 2A C1 E5 LD HL,(SECTORS) ;get sectors per track. +1853 DBFE 19 ADD HL,DE ;bump sector pointer to next track. +1854 DBFF DA 0F DC JP C,TRKSEC4 +1855 DC02 79 LD A,C ;is desired sector now before current one? +1856 DC03 95 SUB L +1857 DC04 78 LD A,B +1858 DC05 9C SBC A,H +1859 DC06 DA 0F DC JP C,TRKSEC4 +1860 DC09 EB EX DE,HL ;not yes, increment track counter +1861 DC0A E1 POP HL ;and continue until it is. +1862 DC0B 23 INC HL +1863 DC0C C3 FA DB JP TRKSEC3 +1864 DC0F ; +1865 DC0F ; here we have determined the track number that contains the +1866 DC0F ; desired sector. +1867 DC0F ; +1868 DC0F E1 TRKSEC4:POP HL ;get track number (HL). +1869 DC10 C5 PUSH BC +1870 DC11 D5 PUSH DE +1871 DC12 E5 PUSH HL +1872 DC13 EB EX DE,HL +1873 DC14 2A CE E5 LD HL,(OFFSET) ;adjust for first track offset. +1874 DC17 19 ADD HL,DE +1875 DC18 44 LD B,H +1876 DC19 4D LD C,L +1877 DC1A CD 1E E6 CALL SETTRK ;select this track. +1878 DC1D D1 POP DE ;reset current track pointer. +1879 DC1E 2A B5 E5 LD HL,(SCRATCH2) +1880 DC21 73 LD (HL),E +1881 DC22 23 INC HL +1882 DC23 72 LD (HL),D +1883 DC24 D1 POP DE +1884 DC25 2A B7 E5 LD HL,(SCRATCH3) ;reset the first sector on this track. +1885 DC28 73 LD (HL),E +1886 DC29 23 INC HL +1887 DC2A 72 LD (HL),D +1888 DC2B C1 POP BC +1889 DC2C 79 LD A,C ;now subtract the desired one. +1890 DC2D 93 SUB E ;to make it relative (1-# sectors/track). +1891 DC2E 4F LD C,A +1892 DC2F 78 LD A,B +1893 DC30 9A SBC A,D +1894 DC31 47 LD B,A +1895 DC32 2A D0 E5 LD HL,(XLATE) ;translate this sector according to this table. +1896 DC35 EB EX DE,HL +1897 DC36 CD 30 E6 CALL SECTRN ;let the bios translate it. +1898 DC39 4D LD C,L +1899 DC3A 44 LD B,H +1900 DC3B C3 21 E6 JP SETSEC ;and select it. +1901 DC3E ; +1902 DC3E ; Compute block number from record number (SAVNREC) and +1903 DC3E ; extent number (SAVEXT). +1904 DC3E ; +1905 DC3E 21 C3 E5 GETBLOCK: LD HL,BLKSHFT ;get logical to physical conversion. +1906 DC41 4E LD C,(HL) ;note that this is base 2 log of ratio. +1907 DC42 3A E3 E5 LD A,(SAVNREC) ;get record number. +1908 DC45 B7 GETBLK1:OR A ;compute (A)=(A)/2^BLKSHFT. +1909 DC46 1F RRA +1910 DC47 0D DEC C +1911 DC48 C2 45 DC JP NZ,GETBLK1 +1912 DC4B 47 LD B,A ;save result in (B). +1913 DC4C 3E 08 LD A,8 +1914 DC4E 96 SUB (HL) +1915 DC4F 4F LD C,A ;compute (C)=8-BLKSHFT. +1916 DC50 3A E2 E5 LD A,(SAVEXT) +1917 DC53 0D GETBLK2:DEC C ;compute (A)=SAVEXT*2^(8-BLKSHFT). +1918 DC54 CA 5C DC JP Z,GETBLK3 +1919 DC57 B7 OR A +1920 DC58 17 RLA +1921 DC59 C3 53 DC JP GETBLK2 +1922 DC5C 80 GETBLK3:ADD A,B +1923 DC5D C9 RET +1924 DC5E ; +1925 DC5E ; Routine to extract the (BC) block byte from the fcb pointed +1926 DC5E ; to by (PARAMS). If this is a big-disk, then these are 16 bit +1927 DC5E ; block numbers, else they are 8 bit numbers. +1928 DC5E ; Number is returned in (HL). +1929 DC5E ; +1930 DC5E 2A 43 DB EXTBLK: LD HL,(PARAMS) ;get fcb address. +1931 DC61 11 10 00 LD DE,16 ;block numbers start 16 bytes into fcb. +1932 DC64 19 ADD HL,DE +1933 DC65 09 ADD HL,BC +1934 DC66 3A DD E5 LD A,(BIGDISK) ;are we using a big-disk? +1935 DC69 B7 OR A +1936 DC6A CA 71 DC JP Z,EXTBLK1 +1937 DC6D 6E LD L,(HL) ;no, extract an 8 bit number from the fcb. +1938 DC6E 26 00 LD H,0 +1939 DC70 C9 RET +1940 DC71 09 EXTBLK1:ADD HL,BC ;yes, extract a 16 bit number. +1941 DC72 5E LD E,(HL) +1942 DC73 23 INC HL +1943 DC74 56 LD D,(HL) +1944 DC75 EB EX DE,HL ;return in (HL). +1945 DC76 C9 RET +1946 DC77 ; +1947 DC77 ; Compute block number. +1948 DC77 ; +1949 DC77 CD 3E DC COMBLK: CALL GETBLOCK +1950 DC7A 4F LD C,A +1951 DC7B 06 00 LD B,0 +1952 DC7D CD 5E DC CALL EXTBLK +1953 DC80 22 E5 E5 LD (BLKNMBR),HL +1954 DC83 C9 RET +1955 DC84 ; +1956 DC84 ; Check for a zero block number (unused). +1957 DC84 ; +1958 DC84 2A E5 E5 CHKBLK: LD HL,(BLKNMBR) +1959 DC87 7D LD A,L ;is it zero? +1960 DC88 B4 OR H +1961 DC89 C9 RET +1962 DC8A ; +1963 DC8A ; Adjust physical block (BLKNMBR) and convert to logical +1964 DC8A ; sector (LOGSECT). This is the starting sector of this block. +1965 DC8A ; The actual sector of interest is then added to this and the +1966 DC8A ; resulting sector number is stored back in (BLKNMBR). This +1967 DC8A ; will still have to be adjusted for the track number. +1968 DC8A ; +1969 DC8A 3A C3 E5 LOGICAL:LD A,(BLKSHFT) ;get log2(physical/logical sectors). +1970 DC8D 2A E5 E5 LD HL,(BLKNMBR) ;get physical sector desired. +1971 DC90 29 LOGICL1:ADD HL,HL ;compute logical sector number. +1972 DC91 3D DEC A ;note logical sectors are 128 bytes long. +1973 DC92 C2 90 DC JP NZ,LOGICL1 +1974 DC95 22 E7 E5 LD (LOGSECT),HL ;save logical sector. +1975 DC98 3A C4 E5 LD A,(BLKMASK) ;get block mask. +1976 DC9B 4F LD C,A +1977 DC9C 3A E3 E5 LD A,(SAVNREC) ;get next sector to access. +1978 DC9F A1 AND C ;extract the relative position within physical block. +1979 DCA0 B5 OR L ;and add it too logical sector. +1980 DCA1 6F LD L,A +1981 DCA2 22 E5 E5 LD (BLKNMBR),HL ;and store. +1982 DCA5 C9 RET +1983 DCA6 ; +1984 DCA6 ; Set (HL) to point to extent byte in fcb. +1985 DCA6 ; +1986 DCA6 2A 43 DB SETEXT: LD HL,(PARAMS) +1987 DCA9 11 0C 00 LD DE,12 ;it is the twelth byte. +1988 DCAC 19 ADD HL,DE +1989 DCAD C9 RET +1990 DCAE ; +1991 DCAE ; Set (HL) to point to record count byte in fcb and (DE) to +1992 DCAE ; next record number byte. +1993 DCAE ; +1994 DCAE 2A 43 DB SETHLDE:LD HL,(PARAMS) +1995 DCB1 11 0F 00 LD DE,15 ;record count byte (#15). +1996 DCB4 19 ADD HL,DE +1997 DCB5 EB EX DE,HL +1998 DCB6 21 11 00 LD HL,17 ;next record number (#32). +1999 DCB9 19 ADD HL,DE +2000 DCBA C9 RET +2001 DCBB ; +2002 DCBB ; Save current file data from fcb. +2003 DCBB ; +2004 DCBB CD AE DC STRDATA:CALL SETHLDE +2005 DCBE 7E LD A,(HL) ;get and store record count byte. +2006 DCBF 32 E3 E5 LD (SAVNREC),A +2007 DCC2 EB EX DE,HL +2008 DCC3 7E LD A,(HL) ;get and store next record number byte. +2009 DCC4 32 E1 E5 LD (SAVNXT),A +2010 DCC7 CD A6 DC CALL SETEXT ;point to extent byte. +2011 DCCA 3A C5 E5 LD A,(EXTMASK) ;get extent mask. +2012 DCCD A6 AND (HL) +2013 DCCE 32 E2 E5 LD (SAVEXT),A ;and save extent here. +2014 DCD1 C9 RET +2015 DCD2 ; +2016 DCD2 ; Set the next record to access. If (MODE) is set to 2, then +2017 DCD2 ; the last record byte (SAVNREC) has the correct number to access. +2018 DCD2 ; For sequential access, (MODE) will be equal to 1. +2019 DCD2 ; +2020 DCD2 CD AE DC SETNREC:CALL SETHLDE +2021 DCD5 3A D5 E5 LD A,(MODE) ;get sequential flag (=1). +2022 DCD8 FE 02 CP 2 ;a 2 indicates that no adder is needed. +2023 DCDA C2 DE DC JP NZ,STNREC1 +2024 DCDD AF XOR A ;clear adder (random access?). +2025 DCDE 4F STNREC1:LD C,A +2026 DCDF 3A E3 E5 LD A,(SAVNREC) ;get last record number. +2027 DCE2 81 ADD A,C ;increment record count. +2028 DCE3 77 LD (HL),A ;and set fcb's next record byte. +2029 DCE4 EB EX DE,HL +2030 DCE5 3A E1 E5 LD A,(SAVNXT) ;get next record byte from storage. +2031 DCE8 77 LD (HL),A ;and put this into fcb as number of records used. +2032 DCE9 C9 RET +2033 DCEA ; +2034 DCEA ; Shift (HL) right (C) bits. +2035 DCEA ; +2036 DCEA 0C SHIFTR: INC C +2037 DCEB 0D SHIFTR1:DEC C +2038 DCEC C8 RET Z +2039 DCED 7C LD A,H +2040 DCEE B7 OR A +2041 DCEF 1F RRA +2042 DCF0 67 LD H,A +2043 DCF1 7D LD A,L +2044 DCF2 1F RRA +2045 DCF3 6F LD L,A +2046 DCF4 C3 EB DC JP SHIFTR1 +2047 DCF7 ; +2048 DCF7 ; Compute the check-sum for the directory buffer. Return +2049 DCF7 ; integer sum in (A). +2050 DCF7 ; +2051 DCF7 0E 80 CHECKSUM: LD C,128 ;length of buffer. +2052 DCF9 2A B9 E5 LD HL,(DIRBUF) ;get its location. +2053 DCFC AF XOR A ;clear summation byte. +2054 DCFD 86 CHKSUM1:ADD A,(HL) ;and compute sum ignoring carries. +2055 DCFE 23 INC HL +2056 DCFF 0D DEC C +2057 DD00 C2 FD DC JP NZ,CHKSUM1 +2058 DD03 C9 RET +2059 DD04 ; +2060 DD04 ; Shift (HL) left (C) bits. +2061 DD04 ; +2062 DD04 0C SHIFTL: INC C +2063 DD05 0D SHIFTL1:DEC C +2064 DD06 C8 RET Z +2065 DD07 29 ADD HL,HL ;shift left 1 bit. +2066 DD08 C3 05 DD JP SHIFTL1 +2067 DD0B ; +2068 DD0B ; Routine to set a bit in a 16 bit value contained in (BC). +2069 DD0B ; The bit set depends on the current drive selection. +2070 DD0B ; +2071 DD0B C5 SETBIT: PUSH BC ;save 16 bit word. +2072 DD0C 3A 42 DB LD A,(ACTIVE) ;get active drive. +2073 DD0F 4F LD C,A +2074 DD10 21 01 00 LD HL,1 +2075 DD13 CD 04 DD CALL SHIFTL ;shift bit 0 into place. +2076 DD16 C1 POP BC ;now 'or' this with the original word. +2077 DD17 79 LD A,C +2078 DD18 B5 OR L +2079 DD19 6F LD L,A ;low byte done, do high byte. +2080 DD1A 78 LD A,B +2081 DD1B B4 OR H +2082 DD1C 67 LD H,A +2083 DD1D C9 RET +2084 DD1E ; +2085 DD1E ; Extract the write protect status bit for the current drive. +2086 DD1E ; The result is returned in (A), bit 0. +2087 DD1E ; +2088 DD1E 2A AD E5 GETWPRT:LD HL,(WRTPRT) ;get status bytes. +2089 DD21 3A 42 DB LD A,(ACTIVE) ;which drive is current? +2090 DD24 4F LD C,A +2091 DD25 CD EA DC CALL SHIFTR ;shift status such that bit 0 is the +2092 DD28 7D LD A,L ;one of interest for this drive. +2093 DD29 E6 01 AND 01H ;and isolate it. +2094 DD2B C9 RET +2095 DD2C ; +2096 DD2C ; Function to write protect the current disk. +2097 DD2C ; +2098 DD2C 21 AD E5 WRTPRTD:LD HL,WRTPRT ;point to status word. +2099 DD2F 4E LD C,(HL) ;set (BC) equal to the status. +2100 DD30 23 INC HL +2101 DD31 46 LD B,(HL) +2102 DD32 CD 0B DD CALL SETBIT ;and set this bit according to current drive. +2103 DD35 22 AD E5 LD (WRTPRT),HL ;then save. +2104 DD38 2A C8 E5 LD HL,(DIRSIZE) ;now save directory size limit. +2105 DD3B 23 INC HL ;remember the last one. +2106 DD3C EB EX DE,HL +2107 DD3D 2A B3 E5 LD HL,(SCRATCH1) ;and store it here. +2108 DD40 73 LD (HL),E ;put low byte. +2109 DD41 23 INC HL +2110 DD42 72 LD (HL),D ;then high byte. +2111 DD43 C9 RET +2112 DD44 ; +2113 DD44 ; Check for a read only file. +2114 DD44 ; +2115 DD44 CD 5E DD CHKROFL:CALL FCB2HL ;set (HL) to file entry in directory buffer. +2116 DD47 11 09 00 CKROF1: LD DE,9 ;look at bit 7 of the ninth byte. +2117 DD4A 19 ADD HL,DE +2118 DD4B 7E LD A,(HL) +2119 DD4C 17 RLA +2120 DD4D D0 RET NC ;return if ok. +2121 DD4E 21 0F D8 LD HL,ROFILE ;else, print error message and terminate. +2122 DD51 C3 4A DB JP JUMPHL +2123 DD54 ; +2124 DD54 ; Check the write protect status of the active disk. +2125 DD54 ; +2126 DD54 CD 1E DD CHKWPRT:CALL GETWPRT +2127 DD57 C8 RET Z ;return if ok. +2128 DD58 21 0D D8 LD HL,RODISK ;else print message and terminate. +2129 DD5B C3 4A DB JP JUMPHL +2130 DD5E ; +2131 DD5E ; Routine to set (HL) pointing to the proper entry in the +2132 DD5E ; directory buffer. +2133 DD5E ; +2134 DD5E 2A B9 E5 FCB2HL: LD HL,(DIRBUF) ;get address of buffer. +2135 DD61 3A E9 E5 LD A,(FCBPOS) ;relative position of file. +2136 DD64 ; +2137 DD64 ; Routine to add (A) to (HL). +2138 DD64 ; +2139 DD64 85 ADDA2HL:ADD A,L +2140 DD65 6F LD L,A +2141 DD66 D0 RET NC +2142 DD67 24 INC H ;take care of any carry. +2143 DD68 C9 RET +2144 DD69 ; +2145 DD69 ; Routine to get the 's2' byte from the fcb supplied in +2146 DD69 ; the initial parameter specification. +2147 DD69 ; +2148 DD69 2A 43 DB GETS2: LD HL,(PARAMS) ;get address of fcb. +2149 DD6C 11 0E 00 LD DE,14 ;relative position of 's2'. +2150 DD6F 19 ADD HL,DE +2151 DD70 7E LD A,(HL) ;extract this byte. +2152 DD71 C9 RET +2153 DD72 ; +2154 DD72 ; Clear the 's2' byte in the fcb. +2155 DD72 ; +2156 DD72 CD 69 DD CLEARS2:CALL GETS2 ;this sets (HL) pointing to it. +2157 DD75 36 00 LD (HL),0 ;now clear it. +2158 DD77 C9 RET +2159 DD78 ; +2160 DD78 ; Set bit 7 in the 's2' byte of the fcb. +2161 DD78 ; +2162 DD78 CD 69 DD SETS2B7:CALL GETS2 ;get the byte. +2163 DD7B F6 80 OR 80H ;and set bit 7. +2164 DD7D 77 LD (HL),A ;then store. +2165 DD7E C9 RET +2166 DD7F ; +2167 DD7F ; Compare (FILEPOS) with (SCRATCH1) and set flags based on +2168 DD7F ; the difference. This checks to see if there are more file +2169 DD7F ; names in the directory. We are at (FILEPOS) and there are +2170 DD7F ; (SCRATCH1) of them to check. +2171 DD7F ; +2172 DD7F 2A EA E5 MOREFLS:LD HL,(FILEPOS) ;we are here. +2173 DD82 EB EX DE,HL +2174 DD83 2A B3 E5 LD HL,(SCRATCH1) ;and don't go past here. +2175 DD86 7B LD A,E ;compute difference but don't keep. +2176 DD87 96 SUB (HL) +2177 DD88 23 INC HL +2178 DD89 7A LD A,D +2179 DD8A 9E SBC A,(HL) ;set carry if no more names. +2180 DD8B C9 RET +2181 DD8C ; +2182 DD8C ; Call this routine to prevent (SCRATCH1) from being greater +2183 DD8C ; than (FILEPOS). +2184 DD8C ; +2185 DD8C CD 7F DD CHKNMBR:CALL MOREFLS ;SCRATCH1 too big? +2186 DD8F D8 RET C +2187 DD90 13 INC DE ;yes, reset it to (FILEPOS). +2188 DD91 72 LD (HL),D +2189 DD92 2B DEC HL +2190 DD93 73 LD (HL),E +2191 DD94 C9 RET +2192 DD95 ; +2193 DD95 ; Compute (HL)=(DE)-(HL) +2194 DD95 ; +2195 DD95 7B SUBHL: LD A,E ;compute difference. +2196 DD96 95 SUB L +2197 DD97 6F LD L,A ;store low byte. +2198 DD98 7A LD A,D +2199 DD99 9C SBC A,H +2200 DD9A 67 LD H,A ;and then high byte. +2201 DD9B C9 RET +2202 DD9C ; +2203 DD9C ; Set the directory checksum byte. +2204 DD9C ; +2205 DD9C 0E FF SETDIR: LD C,0FFH +2206 DD9E ; +2207 DD9E ; Routine to set or compare the directory checksum byte. If +2208 DD9E ; (C)=0ffh, then this will set the checksum byte. Else the byte +2209 DD9E ; will be checked. If the check fails (the disk has been changed), +2210 DD9E ; then this disk will be write protected. +2211 DD9E ; +2212 DD9E 2A EC E5 CHECKDIR: LD HL,(CKSUMTBL) +2213 DDA1 EB EX DE,HL +2214 DDA2 2A CC E5 LD HL,(ALLOC1) +2215 DDA5 CD 95 DD CALL SUBHL +2216 DDA8 D0 RET NC ;ok if (CKSUMTBL) > (ALLOC1), so return. +2217 DDA9 C5 PUSH BC +2218 DDAA CD F7 DC CALL CHECKSUM ;else compute checksum. +2219 DDAD 2A BD E5 LD HL,(CHKVECT) ;get address of checksum table. +2220 DDB0 EB EX DE,HL +2221 DDB1 2A EC E5 LD HL,(CKSUMTBL) +2222 DDB4 19 ADD HL,DE ;set (HL) to point to byte for this drive. +2223 DDB5 C1 POP BC +2224 DDB6 0C INC C ;set or check ? +2225 DDB7 CA C4 DD JP Z,CHKDIR1 +2226 DDBA BE CP (HL) ;check them. +2227 DDBB C8 RET Z ;return if they are the same. +2228 DDBC CD 7F DD CALL MOREFLS ;not the same, do we care? +2229 DDBF D0 RET NC +2230 DDC0 CD 2C DD CALL WRTPRTD ;yes, mark this as write protected. +2231 DDC3 C9 RET +2232 DDC4 77 CHKDIR1:LD (HL),A ;just set the byte. +2233 DDC5 C9 RET +2234 DDC6 ; +2235 DDC6 ; Do a write to the directory of the current disk. +2236 DDC6 ; +2237 DDC6 CD 9C DD DIRWRITE: CALL SETDIR ;set checksum byte. +2238 DDC9 CD E0 DD CALL DIRDMA ;set directory dma address. +2239 DDCC 0E 01 LD C,1 ;tell the bios to actually write. +2240 DDCE CD B8 DB CALL DOWRITE ;then do the write. +2241 DDD1 C3 DA DD JP DEFDMA +2242 DDD4 ; +2243 DDD4 ; Read from the directory. +2244 DDD4 ; +2245 DDD4 CD E0 DD DIRREAD:CALL DIRDMA ;set the directory dma address. +2246 DDD7 CD B2 DB CALL DOREAD ;and read it. +2247 DDDA ; +2248 DDDA ; Routine to set the dma address to the users choice. +2249 DDDA ; +2250 DDDA 21 B1 E5 DEFDMA: LD HL,USERDMA ;reset the default dma address and return. +2251 DDDD C3 E3 DD JP DIRDMA1 +2252 DDE0 ; +2253 DDE0 ; Routine to set the dma address for directory work. +2254 DDE0 ; +2255 DDE0 21 B9 E5 DIRDMA: LD HL,DIRBUF +2256 DDE3 ; +2257 DDE3 ; Set the dma address. On entry, (HL) points to +2258 DDE3 ; word containing the desired dma address. +2259 DDE3 ; +2260 DDE3 4E DIRDMA1:LD C,(HL) +2261 DDE4 23 INC HL +2262 DDE5 46 LD B,(HL) ;setup (BC) and go to the bios to set it. +2263 DDE6 C3 24 E6 JP SETDMA +2264 DDE9 ; +2265 DDE9 ; Move the directory buffer into user's dma space. +2266 DDE9 ; +2267 DDE9 2A B9 E5 MOVEDIR:LD HL,(DIRBUF) ;buffer is located here, and +2268 DDEC EB EX DE,HL +2269 DDED 2A B1 E5 LD HL,(USERDMA) ; put it here. +2270 DDF0 0E 80 LD C,128 ;this is its length. +2271 DDF2 C3 4F DB JP DE2HL ;move it now and return. +2272 DDF5 ; +2273 DDF5 ; Check (FILEPOS) and set the zero flag if it equals 0ffffh. +2274 DDF5 ; +2275 DDF5 21 EA E5 CKFILPOS: LD HL,FILEPOS +2276 DDF8 7E LD A,(HL) +2277 DDF9 23 INC HL +2278 DDFA BE CP (HL) ;are both bytes the same? +2279 DDFB C0 RET NZ +2280 DDFC 3C INC A ;yes, but are they each 0ffh? +2281 DDFD C9 RET +2282 DDFE ; +2283 DDFE ; Set location (FILEPOS) to 0ffffh. +2284 DDFE ; +2285 DDFE 21 FF FF STFILPOS: LD HL,0FFFFH +2286 DE01 22 EA E5 LD (FILEPOS),HL +2287 DE04 C9 RET +2288 DE05 ; +2289 DE05 ; Move on to the next file position within the current +2290 DE05 ; directory buffer. If no more exist, set pointer to 0ffffh +2291 DE05 ; and the calling routine will check for this. Enter with (C) +2292 DE05 ; equal to 0ffh to cause the checksum byte to be set, else we +2293 DE05 ; will check this disk and set write protect if checksums are +2294 DE05 ; not the same (applies only if another directory sector must +2295 DE05 ; be read). +2296 DE05 ; +2297 DE05 2A C8 E5 NXENTRY:LD HL,(DIRSIZE) ;get directory entry size limit. +2298 DE08 EB EX DE,HL +2299 DE09 2A EA E5 LD HL,(FILEPOS) ;get current count. +2300 DE0C 23 INC HL ;go on to the next one. +2301 DE0D 22 EA E5 LD (FILEPOS),HL +2302 DE10 CD 95 DD CALL SUBHL ;(HL)=(DIRSIZE)-(FILEPOS) +2303 DE13 D2 19 DE JP NC,NXENT1 ;is there more room left? +2304 DE16 C3 FE DD JP STFILPOS ;no. Set this flag and return. +2305 DE19 3A EA E5 NXENT1: LD A,(FILEPOS) ;get file position within directory. +2306 DE1C E6 03 AND 03H ;only look within this sector (only 4 entries fit). +2307 DE1E 06 05 LD B,5 ;convert to relative position (32 bytes each). +2308 DE20 87 NXENT2: ADD A,A ;note that this is not efficient code. +2309 DE21 05 DEC B ;5 'ADD A's would be better. +2310 DE22 C2 20 DE JP NZ,NXENT2 +2311 DE25 32 E9 E5 LD (FCBPOS),A ;save it as position of fcb. +2312 DE28 B7 OR A +2313 DE29 C0 RET NZ ;return if we are within buffer. +2314 DE2A C5 PUSH BC +2315 DE2B CD C3 DB CALL TRKSEC ;we need the next directory sector. +2316 DE2E CD D4 DD CALL DIRREAD +2317 DE31 C1 POP BC +2318 DE32 C3 9E DD JP CHECKDIR +2319 DE35 ; +2320 DE35 ; Routine to to get a bit from the disk space allocation +2321 DE35 ; map. It is returned in (A), bit position 0. On entry to here, +2322 DE35 ; set (BC) to the block number on the disk to check. +2323 DE35 ; On return, (D) will contain the original bit position for +2324 DE35 ; this block number and (HL) will point to the address for it. +2325 DE35 ; +2326 DE35 79 CKBITMAP: LD A,C ;determine bit number of interest. +2327 DE36 E6 07 AND 07H ;compute (D)=(E)=(C and 7)+1. +2328 DE38 3C INC A +2329 DE39 5F LD E,A ;save particular bit number. +2330 DE3A 57 LD D,A +2331 DE3B ; +2332 DE3B ; compute (BC)=(BC)/8. +2333 DE3B ; +2334 DE3B 79 LD A,C +2335 DE3C 0F RRCA ;now shift right 3 bits. +2336 DE3D 0F RRCA +2337 DE3E 0F RRCA +2338 DE3F E6 1F AND 1FH ;and clear bits 7,6,5. +2339 DE41 4F LD C,A +2340 DE42 78 LD A,B +2341 DE43 87 ADD A,A ;now shift (B) into bits 7,6,5. +2342 DE44 87 ADD A,A +2343 DE45 87 ADD A,A +2344 DE46 87 ADD A,A +2345 DE47 87 ADD A,A +2346 DE48 B1 OR C ;and add in (C). +2347 DE49 4F LD C,A ;ok, (C) ha been completed. +2348 DE4A 78 LD A,B ;is there a better way of doing this? +2349 DE4B 0F RRCA +2350 DE4C 0F RRCA +2351 DE4D 0F RRCA +2352 DE4E E6 1F AND 1FH +2353 DE50 47 LD B,A ;and now (B) is completed. +2354 DE51 ; +2355 DE51 ; use this as an offset into the disk space allocation +2356 DE51 ; table. +2357 DE51 ; +2358 DE51 2A BF E5 LD HL,(ALOCVECT) +2359 DE54 09 ADD HL,BC +2360 DE55 7E LD A,(HL) ;now get correct byte. +2361 DE56 07 CKBMAP1:RLCA ;get correct bit into position 0. +2362 DE57 1D DEC E +2363 DE58 C2 56 DE JP NZ,CKBMAP1 +2364 DE5B C9 RET +2365 DE5C ; +2366 DE5C ; Set or clear the bit map such that block number (BC) will be marked +2367 DE5C ; as used. On entry, if (E)=0 then this bit will be cleared, if it equals +2368 DE5C ; 1 then it will be set (don't use anyother values). +2369 DE5C ; +2370 DE5C D5 STBITMAP: PUSH DE +2371 DE5D CD 35 DE CALL CKBITMAP ;get the byte of interest. +2372 DE60 E6 FE AND 0FEH ;clear the affected bit. +2373 DE62 C1 POP BC +2374 DE63 B1 OR C ;and now set it acording to (C). +2375 DE64 ; +2376 DE64 ; entry to restore the original bit position and then store +2377 DE64 ; in table. (A) contains the value, (D) contains the bit +2378 DE64 ; position (1-8), and (HL) points to the address within the +2379 DE64 ; space allocation table for this byte. +2380 DE64 ; +2381 DE64 0F STBMAP1:RRCA ;restore original bit position. +2382 DE65 15 DEC D +2383 DE66 C2 64 DE JP NZ,STBMAP1 +2384 DE69 77 LD (HL),A ;and stor byte in table. +2385 DE6A C9 RET +2386 DE6B ; +2387 DE6B ; Set/clear space used bits in allocation map for this file. +2388 DE6B ; On entry, (C)=1 to set the map and (C)=0 to clear it. +2389 DE6B ; +2390 DE6B CD 5E DD SETFILE:CALL FCB2HL ;get address of fcb +2391 DE6E 11 10 00 LD DE,16 +2392 DE71 19 ADD HL,DE ;get to block number bytes. +2393 DE72 C5 PUSH BC +2394 DE73 0E 11 LD C,17 ;check all 17 bytes (max) of table. +2395 DE75 D1 SETFL1: POP DE +2396 DE76 0D DEC C ;done all bytes yet? +2397 DE77 C8 RET Z +2398 DE78 D5 PUSH DE +2399 DE79 3A DD E5 LD A,(BIGDISK) ;check disk size for 16 bit block numbers. +2400 DE7C B7 OR A +2401 DE7D CA 88 DE JP Z,SETFL2 +2402 DE80 C5 PUSH BC ;only 8 bit numbers. set (BC) to this one. +2403 DE81 E5 PUSH HL +2404 DE82 4E LD C,(HL) ;get low byte from table, always +2405 DE83 06 00 LD B,0 ;set high byte to zero. +2406 DE85 C3 8E DE JP SETFL3 +2407 DE88 0D SETFL2: DEC C ;for 16 bit block numbers, adjust counter. +2408 DE89 C5 PUSH BC +2409 DE8A 4E LD C,(HL) ;now get both the low and high bytes. +2410 DE8B 23 INC HL +2411 DE8C 46 LD B,(HL) +2412 DE8D E5 PUSH HL +2413 DE8E 79 SETFL3: LD A,C ;block used? +2414 DE8F B0 OR B +2415 DE90 CA 9D DE JP Z,SETFL4 +2416 DE93 2A C6 E5 LD HL,(DSKSIZE) ;is this block number within the +2417 DE96 7D LD A,L ;space on the disk? +2418 DE97 91 SUB C +2419 DE98 7C LD A,H +2420 DE99 98 SBC A,B +2421 DE9A D4 5C DE CALL NC,STBITMAP ;yes, set the proper bit. +2422 DE9D E1 SETFL4: POP HL ;point to next block number in fcb. +2423 DE9E 23 INC HL +2424 DE9F C1 POP BC +2425 DEA0 C3 75 DE JP SETFL1 +2426 DEA3 ; +2427 DEA3 ; Construct the space used allocation bit map for the active +2428 DEA3 ; drive. If a file name starts with '$' and it is under the +2429 DEA3 ; current user number, then (STATUS) is set to minus 1. Otherwise +2430 DEA3 ; it is not set at all. +2431 DEA3 ; +2432 DEA3 2A C6 E5 BITMAP: LD HL,(DSKSIZE) ;compute size of allocation table. +2433 DEA6 0E 03 LD C,3 +2434 DEA8 CD EA DC CALL SHIFTR ;(HL)=(HL)/8. +2435 DEAB 23 INC HL ;at lease 1 byte. +2436 DEAC 44 LD B,H +2437 DEAD 4D LD C,L ;set (BC) to the allocation table length. +2438 DEAE ; +2439 DEAE ; Initialize the bitmap for this drive. Right now, the first +2440 DEAE ; two bytes are specified by the disk parameter block. However +2441 DEAE ; a patch could be entered here if it were necessary to setup +2442 DEAE ; this table in a special mannor. For example, the bios could +2443 DEAE ; determine locations of 'bad blocks' and set them as already +2444 DEAE ; 'used' in the map. +2445 DEAE ; +2446 DEAE 2A BF E5 LD HL,(ALOCVECT) ;now zero out the table now. +2447 DEB1 36 00 BITMAP1:LD (HL),0 +2448 DEB3 23 INC HL +2449 DEB4 0B DEC BC +2450 DEB5 78 LD A,B +2451 DEB6 B1 OR C +2452 DEB7 C2 B1 DE JP NZ,BITMAP1 +2453 DEBA 2A CA E5 LD HL,(ALLOC0) ;get initial space used by directory. +2454 DEBD EB EX DE,HL +2455 DEBE 2A BF E5 LD HL,(ALOCVECT) ;and put this into map. +2456 DEC1 73 LD (HL),E +2457 DEC2 23 INC HL +2458 DEC3 72 LD (HL),D +2459 DEC4 ; +2460 DEC4 ; End of initialization portion. +2461 DEC4 ; +2462 DEC4 CD A1 DB CALL HOMEDRV ;now home the drive. +2463 DEC7 2A B3 E5 LD HL,(SCRATCH1) +2464 DECA 36 03 LD (HL),3 ;force next directory request to read +2465 DECC 23 INC HL ;in a sector. +2466 DECD 36 00 LD (HL),0 +2467 DECF CD FE DD CALL STFILPOS ;clear initial file position also. +2468 DED2 0E FF BITMAP2:LD C,0FFH ;read next file name in directory +2469 DED4 CD 05 DE CALL NXENTRY ;and set checksum byte. +2470 DED7 CD F5 DD CALL CKFILPOS ;is there another file? +2471 DEDA C8 RET Z +2472 DEDB CD 5E DD CALL FCB2HL ;yes, get its address. +2473 DEDE 3E E5 LD A,0E5H +2474 DEE0 BE CP (HL) ;empty file entry? +2475 DEE1 CA D2 DE JP Z,BITMAP2 +2476 DEE4 3A 41 DB LD A,(USERNO) ;no, correct user number? +2477 DEE7 BE CP (HL) +2478 DEE8 C2 F6 DE JP NZ,BITMAP3 +2479 DEEB 23 INC HL +2480 DEEC 7E LD A,(HL) ;yes, does name start with a '$'? +2481 DEED D6 24 SUB '$' +2482 DEEF C2 F6 DE JP NZ,BITMAP3 +2483 DEF2 3D DEC A ;yes, set atatus to minus one. +2484 DEF3 32 45 DB LD (STATUS),A +2485 DEF6 0E 01 BITMAP3:LD C,1 ;now set this file's space as used in bit map. +2486 DEF8 CD 6B DE CALL SETFILE +2487 DEFB CD 8C DD CALL CHKNMBR ;keep (SCRATCH1) in bounds. +2488 DEFE C3 D2 DE JP BITMAP2 +2489 DF01 ; +2490 DF01 ; Set the status (STATUS) and return. +2491 DF01 ; +2492 DF01 3A D4 E5 STSTATUS: LD A,(FNDSTAT) +2493 DF04 C3 01 DB JP SETSTAT +2494 DF07 ; +2495 DF07 ; Check extents in (A) and (C). Set the zero flag if they +2496 DF07 ; are the same. The number of 16k chunks of disk space that +2497 DF07 ; the directory extent covers is expressad is (EXTMASK+1). +2498 DF07 ; No registers are modified. +2499 DF07 ; +2500 DF07 C5 SAMEXT: PUSH BC +2501 DF08 F5 PUSH AF +2502 DF09 3A C5 E5 LD A,(EXTMASK) ;get extent mask and use it to +2503 DF0C 2F CPL ;to compare both extent numbers. +2504 DF0D 47 LD B,A ;save resulting mask here. +2505 DF0E 79 LD A,C ;mask first extent and save in (C). +2506 DF0F A0 AND B +2507 DF10 4F LD C,A +2508 DF11 F1 POP AF ;now mask second extent and compare +2509 DF12 A0 AND B ;with the first one. +2510 DF13 91 SUB C +2511 DF14 E6 1F AND 1FH ;(* only check buts 0-4 *) +2512 DF16 C1 POP BC ;the zero flag is set if they are the same. +2513 DF17 C9 RET ;restore (BC) and return. +2514 DF18 ; +2515 DF18 ; Search for the first occurence of a file name. On entry, +2516 DF18 ; register (C) should contain the number of bytes of the fcb +2517 DF18 ; that must match. +2518 DF18 ; +2519 DF18 3E FF FINDFST:LD A,0FFH +2520 DF1A 32 D4 E5 LD (FNDSTAT),A +2521 DF1D 21 D8 E5 LD HL,COUNTER ;save character count. +2522 DF20 71 LD (HL),C +2523 DF21 2A 43 DB LD HL,(PARAMS) ;get filename to match. +2524 DF24 22 D9 E5 LD (SAVEFCB),HL ;and save. +2525 DF27 CD FE DD CALL STFILPOS ;clear initial file position (set to 0ffffh). +2526 DF2A CD A1 DB CALL HOMEDRV ;home the drive. +2527 DF2D ; +2528 DF2D ; Entry to locate the next occurence of a filename within the +2529 DF2D ; directory. The disk is not expected to have been changed. If +2530 DF2D ; it was, then it will be write protected. +2531 DF2D ; +2532 DF2D 0E 00 FINDNXT:LD C,0 ;write protect the disk if changed. +2533 DF2F CD 05 DE CALL NXENTRY ;get next filename entry in directory. +2534 DF32 CD F5 DD CALL CKFILPOS ;is file position = 0ffffh? +2535 DF35 CA 94 DF JP Z,FNDNXT6 ;yes, exit now then. +2536 DF38 2A D9 E5 LD HL,(SAVEFCB) ;set (DE) pointing to filename to match. +2537 DF3B EB EX DE,HL +2538 DF3C 1A LD A,(DE) +2539 DF3D FE E5 CP 0E5H ;empty directory entry? +2540 DF3F CA 4A DF JP Z,FNDNXT1 ;(* are we trying to reserect erased entries? *) +2541 DF42 D5 PUSH DE +2542 DF43 CD 7F DD CALL MOREFLS ;more files in directory? +2543 DF46 D1 POP DE +2544 DF47 D2 94 DF JP NC,FNDNXT6 ;no more. Exit now. +2545 DF4A CD 5E DD FNDNXT1:CALL FCB2HL ;get address of this fcb in directory. +2546 DF4D 3A D8 E5 LD A,(COUNTER) ;get number of bytes (characters) to check. +2547 DF50 4F LD C,A +2548 DF51 06 00 LD B,0 ;initialize byte position counter. +2549 DF53 79 FNDNXT2:LD A,C ;are we done with the compare? +2550 DF54 B7 OR A +2551 DF55 CA 83 DF JP Z,FNDNXT5 +2552 DF58 1A LD A,(DE) ;no, check next byte. +2553 DF59 FE 3F CP '?' ;don't care about this character? +2554 DF5B CA 7C DF JP Z,FNDNXT4 +2555 DF5E 78 LD A,B ;get bytes position in fcb. +2556 DF5F FE 0D CP 13 ;don't care about the thirteenth byte either. +2557 DF61 CA 7C DF JP Z,FNDNXT4 +2558 DF64 FE 0C CP 12 ;extent byte? +2559 DF66 1A LD A,(DE) +2560 DF67 CA 73 DF JP Z,FNDNXT3 +2561 DF6A 96 SUB (HL) ;otherwise compare characters. +2562 DF6B E6 7F AND 7FH +2563 DF6D C2 2D DF JP NZ,FINDNXT ;not the same, check next entry. +2564 DF70 C3 7C DF JP FNDNXT4 ;so far so good, keep checking. +2565 DF73 C5 FNDNXT3:PUSH BC ;check the extent byte here. +2566 DF74 4E LD C,(HL) +2567 DF75 CD 07 DF CALL SAMEXT +2568 DF78 C1 POP BC +2569 DF79 C2 2D DF JP NZ,FINDNXT ;not the same, look some more. +2570 DF7C ; +2571 DF7C ; So far the names compare. Bump pointers to the next byte +2572 DF7C ; and continue until all (C) characters have been checked. +2573 DF7C ; +2574 DF7C 13 FNDNXT4:INC DE ;bump pointers. +2575 DF7D 23 INC HL +2576 DF7E 04 INC B +2577 DF7F 0D DEC C ;adjust character counter. +2578 DF80 C3 53 DF JP FNDNXT2 +2579 DF83 3A EA E5 FNDNXT5:LD A,(FILEPOS) ;return the position of this entry. +2580 DF86 E6 03 AND 03H +2581 DF88 32 45 DB LD (STATUS),A +2582 DF8B 21 D4 E5 LD HL,FNDSTAT +2583 DF8E 7E LD A,(HL) +2584 DF8F 17 RLA +2585 DF90 D0 RET NC +2586 DF91 AF XOR A +2587 DF92 77 LD (HL),A +2588 DF93 C9 RET +2589 DF94 ; +2590 DF94 ; Filename was not found. Set appropriate status. +2591 DF94 ; +2592 DF94 CD FE DD FNDNXT6:CALL STFILPOS ;set (FILEPOS) to 0ffffh. +2593 DF97 3E FF LD A,0FFH ;say not located. +2594 DF99 C3 01 DB JP SETSTAT +2595 DF9C ; +2596 DF9C ; Erase files from the directory. Only the first byte of the +2597 DF9C ; fcb will be affected. It is set to (E5). +2598 DF9C ; +2599 DF9C CD 54 DD ERAFILE:CALL CHKWPRT ;is disk write protected? +2600 DF9F 0E 0C LD C,12 ;only compare file names. +2601 DFA1 CD 18 DF CALL FINDFST ;get first file name. +2602 DFA4 CD F5 DD ERAFIL1:CALL CKFILPOS ;any found? +2603 DFA7 C8 RET Z ;nope, we must be done. +2604 DFA8 CD 44 DD CALL CHKROFL ;is file read only? +2605 DFAB CD 5E DD CALL FCB2HL ;nope, get address of fcb and +2606 DFAE 36 E5 LD (HL),0E5H ;set first byte to 'empty'. +2607 DFB0 0E 00 LD C,0 ;clear the space from the bit map. +2608 DFB2 CD 6B DE CALL SETFILE +2609 DFB5 CD C6 DD CALL DIRWRITE ;now write the directory sector back out. +2610 DFB8 CD 2D DF CALL FINDNXT ;find the next file name. +2611 DFBB C3 A4 DF JP ERAFIL1 ;and repeat process. +2612 DFBE ; +2613 DFBE ; Look through the space allocation map (bit map) for the +2614 DFBE ; next available block. Start searching at block number (BC-1). +2615 DFBE ; The search procedure is to look for an empty block that is +2616 DFBE ; before the starting block. If not empty, look at a later +2617 DFBE ; block number. In this way, we return the closest empty block +2618 DFBE ; on either side of the 'target' block number. This will speed +2619 DFBE ; access on random devices. For serial devices, this should be +2620 DFBE ; changed to look in the forward direction first and then start +2621 DFBE ; at the front and search some more. +2622 DFBE ; +2623 DFBE ; On return, (DE)= block number that is empty and (HL) =0 +2624 DFBE ; if no empry block was found. +2625 DFBE ; +2626 DFBE 50 FNDSPACE: LD D,B ;set (DE) as the block that is checked. +2627 DFBF 59 LD E,C +2628 DFC0 ; +2629 DFC0 ; Look before target block. Registers (BC) are used as the lower +2630 DFC0 ; pointer and (DE) as the upper pointer. +2631 DFC0 ; +2632 DFC0 79 FNDSPA1:LD A,C ;is block 0 specified? +2633 DFC1 B0 OR B +2634 DFC2 CA D1 DF JP Z,FNDSPA2 +2635 DFC5 0B DEC BC ;nope, check previous block. +2636 DFC6 D5 PUSH DE +2637 DFC7 C5 PUSH BC +2638 DFC8 CD 35 DE CALL CKBITMAP +2639 DFCB 1F RRA ;is this block empty? +2640 DFCC D2 EC DF JP NC,FNDSPA3 ;yes. use this. +2641 DFCF ; +2642 DFCF ; Note that the above logic gets the first block that it finds +2643 DFCF ; that is empty. Thus a file could be written 'backward' making +2644 DFCF ; it very slow to access. This could be changed to look for the +2645 DFCF ; first empty block and then continue until the start of this +2646 DFCF ; empty space is located and then used that starting block. +2647 DFCF ; This should help speed up access to some files especially on +2648 DFCF ; a well used disk with lots of fairly small 'holes'. +2649 DFCF ; +2650 DFCF C1 POP BC ;nope, check some more. +2651 DFD0 D1 POP DE +2652 DFD1 ; +2653 DFD1 ; Now look after target block. +2654 DFD1 ; +2655 DFD1 2A C6 E5 FNDSPA2:LD HL,(DSKSIZE) ;is block (DE) within disk limits? +2656 DFD4 7B LD A,E +2657 DFD5 95 SUB L +2658 DFD6 7A LD A,D +2659 DFD7 9C SBC A,H +2660 DFD8 D2 F4 DF JP NC,FNDSPA4 +2661 DFDB 13 INC DE ;yes, move on to next one. +2662 DFDC C5 PUSH BC +2663 DFDD D5 PUSH DE +2664 DFDE 42 LD B,D +2665 DFDF 4B LD C,E +2666 DFE0 CD 35 DE CALL CKBITMAP ;check it. +2667 DFE3 1F RRA ;empty? +2668 DFE4 D2 EC DF JP NC,FNDSPA3 +2669 DFE7 D1 POP DE ;nope, continue searching. +2670 DFE8 C1 POP BC +2671 DFE9 C3 C0 DF JP FNDSPA1 +2672 DFEC ; +2673 DFEC ; Empty block found. Set it as used and return with (HL) +2674 DFEC ; pointing to it (true?). +2675 DFEC ; +2676 DFEC 17 FNDSPA3:RLA ;reset byte. +2677 DFED 3C INC A ;and set bit 0. +2678 DFEE CD 64 DE CALL STBMAP1 ;update bit map. +2679 DFF1 E1 POP HL ;set return registers. +2680 DFF2 D1 POP DE +2681 DFF3 C9 RET +2682 DFF4 ; +2683 DFF4 ; Free block was not found. If (BC) is not zero, then we have +2684 DFF4 ; not checked all of the disk space. +2685 DFF4 ; +2686 DFF4 79 FNDSPA4:LD A,C +2687 DFF5 B0 OR B +2688 DFF6 C2 C0 DF JP NZ,FNDSPA1 +2689 DFF9 21 00 00 LD HL,0 ;set 'not found' status. +2690 DFFC C9 RET +2691 DFFD ; +2692 DFFD ; Move a complete fcb entry into the directory and write it. +2693 DFFD ; +2694 DFFD 0E 00 FCBSET: LD C,0 +2695 DFFF 1E 20 LD E,32 ;length of each entry. +2696 E001 ; +2697 E001 ; Move (E) bytes from the fcb pointed to by (PARAMS) into +2698 E001 ; fcb in directory starting at relative byte (C). This updated +2699 E001 ; directory buffer is then written to the disk. +2700 E001 ; +2701 E001 D5 UPDATE: PUSH DE +2702 E002 06 00 LD B,0 ;set (BC) to relative byte position. +2703 E004 2A 43 DB LD HL,(PARAMS) ;get address of fcb. +2704 E007 09 ADD HL,BC ;compute starting byte. +2705 E008 EB EX DE,HL +2706 E009 CD 5E DD CALL FCB2HL ;get address of fcb to update in directory. +2707 E00C C1 POP BC ;set (C) to number of bytes to change. +2708 E00D CD 4F DB CALL DE2HL +2709 E010 CD C3 DB UPDATE1:CALL TRKSEC ;determine the track and sector affected. +2710 E013 C3 C6 DD JP DIRWRITE ;then write this sector out. +2711 E016 ; +2712 E016 ; Routine to change the name of all files on the disk with a +2713 E016 ; specified name. The fcb contains the current name as the +2714 E016 ; first 12 characters and the new name 16 bytes into the fcb. +2715 E016 ; +2716 E016 CD 54 DD CHGNAMES: CALL CHKWPRT ;check for a write protected disk. +2717 E019 0E 0C LD C,12 ;match first 12 bytes of fcb only. +2718 E01B CD 18 DF CALL FINDFST ;get first name. +2719 E01E 2A 43 DB LD HL,(PARAMS) ;get address of fcb. +2720 E021 7E LD A,(HL) ;get user number. +2721 E022 11 10 00 LD DE,16 ;move over to desired name. +2722 E025 19 ADD HL,DE +2723 E026 77 LD (HL),A ;keep same user number. +2724 E027 CD F5 DD CHGNAM1:CALL CKFILPOS ;any matching file found? +2725 E02A C8 RET Z ;no, we must be done. +2726 E02B CD 44 DD CALL CHKROFL ;check for read only file. +2727 E02E 0E 10 LD C,16 ;start 16 bytes into fcb. +2728 E030 1E 0C LD E,12 ;and update the first 12 bytes of directory. +2729 E032 CD 01 E0 CALL UPDATE +2730 E035 CD 2D DF CALL FINDNXT ;get te next file name. +2731 E038 C3 27 E0 JP CHGNAM1 ;and continue. +2732 E03B ; +2733 E03B ; Update a files attributes. The procedure is to search for +2734 E03B ; every file with the same name as shown in fcb (ignoring bit 7) +2735 E03B ; and then to update it (which includes bit 7). No other changes +2736 E03B ; are made. +2737 E03B ; +2738 E03B 0E 0C SAVEATTR: LD C,12 ;match first 12 bytes. +2739 E03D CD 18 DF CALL FINDFST ;look for first filename. +2740 E040 CD F5 DD SAVATR1:CALL CKFILPOS ;was one found? +2741 E043 C8 RET Z ;nope, we must be done. +2742 E044 0E 00 LD C,0 ;yes, update the first 12 bytes now. +2743 E046 1E 0C LD E,12 +2744 E048 CD 01 E0 CALL UPDATE ;update filename and write directory. +2745 E04B CD 2D DF CALL FINDNXT ;and get the next file. +2746 E04E C3 40 E0 JP SAVATR1 ;then continue until done. +2747 E051 ; +2748 E051 ; Open a file (name specified in fcb). +2749 E051 ; +2750 E051 0E 0F OPENIT: LD C,15 ;compare the first 15 bytes. +2751 E053 CD 18 DF CALL FINDFST ;get the first one in directory. +2752 E056 CD F5 DD CALL CKFILPOS ;any at all? +2753 E059 C8 RET Z +2754 E05A CD A6 DC OPENIT1:CALL SETEXT ;point to extent byte within users fcb. +2755 E05D 7E LD A,(HL) ;and get it. +2756 E05E F5 PUSH AF ;save it and address. +2757 E05F E5 PUSH HL +2758 E060 CD 5E DD CALL FCB2HL ;point to fcb in directory. +2759 E063 EB EX DE,HL +2760 E064 2A 43 DB LD HL,(PARAMS) ;this is the users copy. +2761 E067 0E 20 LD C,32 ;move it into users space. +2762 E069 D5 PUSH DE +2763 E06A CD 4F DB CALL DE2HL +2764 E06D CD 78 DD CALL SETS2B7 ;set bit 7 in 's2' byte (unmodified). +2765 E070 D1 POP DE ;now get the extent byte from this fcb. +2766 E071 21 0C 00 LD HL,12 +2767 E074 19 ADD HL,DE +2768 E075 4E LD C,(HL) ;into (C). +2769 E076 21 0F 00 LD HL,15 ;now get the record count byte into (B). +2770 E079 19 ADD HL,DE +2771 E07A 46 LD B,(HL) +2772 E07B E1 POP HL ;keep the same extent as the user had originally. +2773 E07C F1 POP AF +2774 E07D 77 LD (HL),A +2775 E07E 79 LD A,C ;is it the same as in the directory fcb? +2776 E07F BE CP (HL) +2777 E080 78 LD A,B ;if yes, then use the same record count. +2778 E081 CA 8B E0 JP Z,OPENIT2 +2779 E084 3E 00 LD A,0 ;if the user specified an extent greater than +2780 E086 DA 8B E0 JP C,OPENIT2 ;the one in the directory, then set record count to 0. +2781 E089 3E 80 LD A,128 ;otherwise set to maximum. +2782 E08B 2A 43 DB OPENIT2:LD HL,(PARAMS) ;set record count in users fcb to (A). +2783 E08E 11 0F 00 LD DE,15 +2784 E091 19 ADD HL,DE ;compute relative position. +2785 E092 77 LD (HL),A ;and set the record count. +2786 E093 C9 RET +2787 E094 ; +2788 E094 ; Move two bytes from (DE) to (HL) if (and only if) (HL) +2789 E094 ; point to a zero value (16 bit). +2790 E094 ; Return with zero flag set it (DE) was moved. Registers (DE) +2791 E094 ; and (HL) are not changed. However (A) is. +2792 E094 ; +2793 E094 7E MOVEWORD: LD A,(HL) ;check for a zero word. +2794 E095 23 INC HL +2795 E096 B6 OR (HL) ;both bytes zero? +2796 E097 2B DEC HL +2797 E098 C0 RET NZ ;nope, just return. +2798 E099 1A LD A,(DE) ;yes, move two bytes from (DE) into +2799 E09A 77 LD (HL),A ;this zero space. +2800 E09B 13 INC DE +2801 E09C 23 INC HL +2802 E09D 1A LD A,(DE) +2803 E09E 77 LD (HL),A +2804 E09F 1B DEC DE ;don't disturb these registers. +2805 E0A0 2B DEC HL +2806 E0A1 C9 RET +2807 E0A2 ; +2808 E0A2 ; Get here to close a file specified by (fcb). +2809 E0A2 ; +2810 E0A2 AF CLOSEIT:XOR A ;clear status and file position bytes. +2811 E0A3 32 45 DB LD (STATUS),A +2812 E0A6 32 EA E5 LD (FILEPOS),A +2813 E0A9 32 EB E5 LD (FILEPOS+1),A +2814 E0AC CD 1E DD CALL GETWPRT ;get write protect bit for this drive. +2815 E0AF C0 RET NZ ;just return if it is set. +2816 E0B0 CD 69 DD CALL GETS2 ;else get the 's2' byte. +2817 E0B3 E6 80 AND 80H ;and look at bit 7 (file unmodified?). +2818 E0B5 C0 RET NZ ;just return if set. +2819 E0B6 0E 0F LD C,15 ;else look up this file in directory. +2820 E0B8 CD 18 DF CALL FINDFST +2821 E0BB CD F5 DD CALL CKFILPOS ;was it found? +2822 E0BE C8 RET Z ;just return if not. +2823 E0BF 01 10 00 LD BC,16 ;set (HL) pointing to records used section. +2824 E0C2 CD 5E DD CALL FCB2HL +2825 E0C5 09 ADD HL,BC +2826 E0C6 EB EX DE,HL +2827 E0C7 2A 43 DB LD HL,(PARAMS) ;do the same for users specified fcb. +2828 E0CA 09 ADD HL,BC +2829 E0CB 0E 10 LD C,16 ;this many bytes are present in this extent. +2830 E0CD 3A DD E5 CLOSEIT1: LD A,(BIGDISK) ;8 or 16 bit record numbers? +2831 E0D0 B7 OR A +2832 E0D1 CA E8 E0 JP Z,CLOSEIT4 +2833 E0D4 7E LD A,(HL) ;just 8 bit. Get one from users fcb. +2834 E0D5 B7 OR A +2835 E0D6 1A LD A,(DE) ;now get one from directory fcb. +2836 E0D7 C2 DB E0 JP NZ,CLOSEIT2 +2837 E0DA 77 LD (HL),A ;users byte was zero. Update from directory. +2838 E0DB B7 CLOSEIT2: OR A +2839 E0DC C2 E1 E0 JP NZ,CLOSEIT3 +2840 E0DF 7E LD A,(HL) ;directories byte was zero, update from users fcb. +2841 E0E0 12 LD (DE),A +2842 E0E1 BE CLOSEIT3: CP (HL) ;if neither one of these bytes were zero, +2843 E0E2 C2 1F E1 JP NZ,CLOSEIT7 ;then close error if they are not the same. +2844 E0E5 C3 FD E0 JP CLOSEIT5 ;ok so far, get to next byte in fcbs. +2845 E0E8 CD 94 E0 CLOSEIT4: CALL MOVEWORD ;update users fcb if it is zero. +2846 E0EB EB EX DE,HL +2847 E0EC CD 94 E0 CALL MOVEWORD ;update directories fcb if it is zero. +2848 E0EF EB EX DE,HL +2849 E0F0 1A LD A,(DE) ;if these two values are no different, +2850 E0F1 BE CP (HL) ;then a close error occured. +2851 E0F2 C2 1F E1 JP NZ,CLOSEIT7 +2852 E0F5 13 INC DE ;check second byte. +2853 E0F6 23 INC HL +2854 E0F7 1A LD A,(DE) +2855 E0F8 BE CP (HL) +2856 E0F9 C2 1F E1 JP NZ,CLOSEIT7 +2857 E0FC 0D DEC C ;remember 16 bit values. +2858 E0FD 13 CLOSEIT5: INC DE ;bump to next item in table. +2859 E0FE 23 INC HL +2860 E0FF 0D DEC C ;there are 16 entries only. +2861 E100 C2 CD E0 JP NZ,CLOSEIT1 ;continue if more to do. +2862 E103 01 EC FF LD BC,0FFECH ;backup 20 places (extent byte). +2863 E106 09 ADD HL,BC +2864 E107 EB EX DE,HL +2865 E108 09 ADD HL,BC +2866 E109 1A LD A,(DE) +2867 E10A BE CP (HL) ;directory's extent already greater than the +2868 E10B DA 17 E1 JP C,CLOSEIT6 ;users extent? +2869 E10E 77 LD (HL),A ;no, update directory extent. +2870 E10F 01 03 00 LD BC,3 ;and update the record count byte in +2871 E112 09 ADD HL,BC ;directories fcb. +2872 E113 EB EX DE,HL +2873 E114 09 ADD HL,BC +2874 E115 7E LD A,(HL) ;get from user. +2875 E116 12 LD (DE),A ;and put in directory. +2876 E117 3E FF CLOSEIT6: LD A,0FFH ;set 'was open and is now closed' byte. +2877 E119 32 D2 E5 LD (CLOSEFLG),A +2878 E11C C3 10 E0 JP UPDATE1 ;update the directory now. +2879 E11F 21 45 DB CLOSEIT7: LD HL,STATUS ;set return status and then return. +2880 E122 35 DEC (HL) +2881 E123 C9 RET +2882 E124 ; +2883 E124 ; Routine to get the next empty space in the directory. It +2884 E124 ; will then be cleared for use. +2885 E124 ; +2886 E124 CD 54 DD GETEMPTY: CALL CHKWPRT ;make sure disk is not write protected. +2887 E127 2A 43 DB LD HL,(PARAMS) ;save current parameters (fcb). +2888 E12A E5 PUSH HL +2889 E12B 21 AC E5 LD HL,EMPTYFCB ;use special one for empty space. +2890 E12E 22 43 DB LD (PARAMS),HL +2891 E131 0E 01 LD C,1 ;search for first empty spot in directory. +2892 E133 CD 18 DF CALL FINDFST ;(* only check first byte *) +2893 E136 CD F5 DD CALL CKFILPOS ;none? +2894 E139 E1 POP HL +2895 E13A 22 43 DB LD (PARAMS),HL ;restore original fcb address. +2896 E13D C8 RET Z ;return if no more space. +2897 E13E EB EX DE,HL +2898 E13F 21 0F 00 LD HL,15 ;point to number of records for this file. +2899 E142 19 ADD HL,DE +2900 E143 0E 11 LD C,17 ;and clear all of this space. +2901 E145 AF XOR A +2902 E146 77 GETMT1: LD (HL),A +2903 E147 23 INC HL +2904 E148 0D DEC C +2905 E149 C2 46 E1 JP NZ,GETMT1 +2906 E14C 21 0D 00 LD HL,13 ;clear the 's1' byte also. +2907 E14F 19 ADD HL,DE +2908 E150 77 LD (HL),A +2909 E151 CD 8C DD CALL CHKNMBR ;keep (SCRATCH1) within bounds. +2910 E154 CD FD DF CALL FCBSET ;write out this fcb entry to directory. +2911 E157 C3 78 DD JP SETS2B7 ;set 's2' byte bit 7 (unmodified at present). +2912 E15A ; +2913 E15A ; Routine to close the current extent and open the next one +2914 E15A ; for reading. +2915 E15A ; +2916 E15A AF GETNEXT:XOR A +2917 E15B 32 D2 E5 LD (CLOSEFLG),A ;clear close flag. +2918 E15E CD A2 E0 CALL CLOSEIT ;close this extent. +2919 E161 CD F5 DD CALL CKFILPOS +2920 E164 C8 RET Z ;not there??? +2921 E165 2A 43 DB LD HL,(PARAMS) ;get extent byte. +2922 E168 01 0C 00 LD BC,12 +2923 E16B 09 ADD HL,BC +2924 E16C 7E LD A,(HL) ;and increment it. +2925 E16D 3C INC A +2926 E16E E6 1F AND 1FH ;keep within range 0-31. +2927 E170 77 LD (HL),A +2928 E171 CA 83 E1 JP Z,GTNEXT1 ;overflow? +2929 E174 47 LD B,A ;mask extent byte. +2930 E175 3A C5 E5 LD A,(EXTMASK) +2931 E178 A0 AND B +2932 E179 21 D2 E5 LD HL,CLOSEFLG ;check close flag (0ffh is ok). +2933 E17C A6 AND (HL) +2934 E17D CA 8E E1 JP Z,GTNEXT2 ;if zero, we must read in next extent. +2935 E180 C3 AC E1 JP GTNEXT3 ;else, it is already in memory. +2936 E183 01 02 00 GTNEXT1:LD BC,2 ;Point to the 's2' byte. +2937 E186 09 ADD HL,BC +2938 E187 34 INC (HL) ;and bump it. +2939 E188 7E LD A,(HL) ;too many extents? +2940 E189 E6 0F AND 0FH +2941 E18B CA B6 E1 JP Z,GTNEXT5 ;yes, set error code. +2942 E18E ; +2943 E18E ; Get here to open the next extent. +2944 E18E ; +2945 E18E 0E 0F GTNEXT2:LD C,15 ;set to check first 15 bytes of fcb. +2946 E190 CD 18 DF CALL FINDFST ;find the first one. +2947 E193 CD F5 DD CALL CKFILPOS ;none available? +2948 E196 C2 AC E1 JP NZ,GTNEXT3 +2949 E199 3A D3 E5 LD A,(RDWRTFLG) ;no extent present. Can we open an empty one? +2950 E19C 3C INC A ;0ffh means reading (so not possible). +2951 E19D CA B6 E1 JP Z,GTNEXT5 ;or an error. +2952 E1A0 CD 24 E1 CALL GETEMPTY ;we are writing, get an empty entry. +2953 E1A3 CD F5 DD CALL CKFILPOS ;none? +2954 E1A6 CA B6 E1 JP Z,GTNEXT5 ;error if true. +2955 E1A9 C3 AF E1 JP GTNEXT4 ;else we are almost done. +2956 E1AC CD 5A E0 GTNEXT3:CALL OPENIT1 ;open this extent. +2957 E1AF CD BB DC GTNEXT4:CALL STRDATA ;move in updated data (rec #, extent #, etc.) +2958 E1B2 AF XOR A ;clear status and return. +2959 E1B3 C3 01 DB JP SETSTAT +2960 E1B6 ; +2961 E1B6 ; Error in extending the file. Too many extents were needed +2962 E1B6 ; or not enough space on the disk. +2963 E1B6 ; +2964 E1B6 CD 05 DB GTNEXT5:CALL IOERR1 ;set error code, clear bit 7 of 's2' +2965 E1B9 C3 78 DD JP SETS2B7 ;so this is not written on a close. +2966 E1BC ; +2967 E1BC ; Read a sequential file. +2968 E1BC ; +2969 E1BC 3E 01 RDSEQ: LD A,1 ;set sequential access mode. +2970 E1BE 32 D5 E5 LD (MODE),A +2971 E1C1 3E FF RDSEQ1: LD A,0FFH ;don't allow reading unwritten space. +2972 E1C3 32 D3 E5 LD (RDWRTFLG),A +2973 E1C6 CD BB DC CALL STRDATA ;put rec# and ext# into fcb. +2974 E1C9 3A E3 E5 LD A,(SAVNREC) ;get next record to read. +2975 E1CC 21 E1 E5 LD HL,SAVNXT ;get number of records in extent. +2976 E1CF BE CP (HL) ;within this extent? +2977 E1D0 DA E6 E1 JP C,RDSEQ2 +2978 E1D3 FE 80 CP 128 ;no. Is this extent fully used? +2979 E1D5 C2 FB E1 JP NZ,RDSEQ3 ;no. End-of-file. +2980 E1D8 CD 5A E1 CALL GETNEXT ;yes, open the next one. +2981 E1DB AF XOR A ;reset next record to read. +2982 E1DC 32 E3 E5 LD (SAVNREC),A +2983 E1DF 3A 45 DB LD A,(STATUS) ;check on open, successful? +2984 E1E2 B7 OR A +2985 E1E3 C2 FB E1 JP NZ,RDSEQ3 ;no, error. +2986 E1E6 CD 77 DC RDSEQ2: CALL COMBLK ;ok. compute block number to read. +2987 E1E9 CD 84 DC CALL CHKBLK ;check it. Within bounds? +2988 E1EC CA FB E1 JP Z,RDSEQ3 ;no, error. +2989 E1EF CD 8A DC CALL LOGICAL ;convert (BLKNMBR) to logical sector (128 byte). +2990 E1F2 CD D1 DB CALL TRKSEC1 ;set the track and sector for this block #. +2991 E1F5 CD B2 DB CALL DOREAD ;and read it. +2992 E1F8 C3 D2 DC JP SETNREC ;and set the next record to be accessed. +2993 E1FB ; +2994 E1FB ; Read error occured. Set status and return. +2995 E1FB ; +2996 E1FB C3 05 DB RDSEQ3: JP IOERR1 +2997 E1FE ; +2998 E1FE ; Write the next sequential record. +2999 E1FE ; +3000 E1FE 3E 01 WTSEQ: LD A,1 ;set sequential access mode. +3001 E200 32 D5 E5 LD (MODE),A +3002 E203 3E 00 WTSEQ1: LD A,0 ;allow an addition empty extent to be opened. +3003 E205 32 D3 E5 LD (RDWRTFLG),A +3004 E208 CD 54 DD CALL CHKWPRT ;check write protect status. +3005 E20B 2A 43 DB LD HL,(PARAMS) +3006 E20E CD 47 DD CALL CKROF1 ;check for read only file, (HL) already set to fcb. +3007 E211 CD BB DC CALL STRDATA ;put updated data into fcb. +3008 E214 3A E3 E5 LD A,(SAVNREC) ;get record number to write. +3009 E217 FE 80 CP 128 ;within range? +3010 E219 D2 05 DB JP NC,IOERR1 ;no, error(?). +3011 E21C CD 77 DC CALL COMBLK ;compute block number. +3012 E21F CD 84 DC CALL CHKBLK ;check number. +3013 E222 0E 00 LD C,0 ;is there one to write to? +3014 E224 C2 6E E2 JP NZ,WTSEQ6 ;yes, go do it. +3015 E227 CD 3E DC CALL GETBLOCK ;get next block number within fcb to use. +3016 E22A 32 D7 E5 LD (RELBLOCK),A ;and save. +3017 E22D 01 00 00 LD BC,0 ;start looking for space from the start +3018 E230 B7 OR A ;if none allocated as yet. +3019 E231 CA 3B E2 JP Z,WTSEQ2 +3020 E234 4F LD C,A ;extract previous block number from fcb +3021 E235 0B DEC BC ;so we can be closest to it. +3022 E236 CD 5E DC CALL EXTBLK +3023 E239 44 LD B,H +3024 E23A 4D LD C,L +3025 E23B CD BE DF WTSEQ2: CALL FNDSPACE ;find the next empty block nearest number (BC). +3026 E23E 7D LD A,L ;check for a zero number. +3027 E23F B4 OR H +3028 E240 C2 48 E2 JP NZ,WTSEQ3 +3029 E243 3E 02 LD A,2 ;no more space? +3030 E245 C3 01 DB JP SETSTAT +3031 E248 22 E5 E5 WTSEQ3: LD (BLKNMBR),HL ;save block number to access. +3032 E24B EB EX DE,HL ;put block number into (DE). +3033 E24C 2A 43 DB LD HL,(PARAMS) ;now we must update the fcb for this +3034 E24F 01 10 00 LD BC,16 ;newly allocated block. +3035 E252 09 ADD HL,BC +3036 E253 3A DD E5 LD A,(BIGDISK) ;8 or 16 bit block numbers? +3037 E256 B7 OR A +3038 E257 3A D7 E5 LD A,(RELBLOCK) ;(* update this entry *) +3039 E25A CA 64 E2 JP Z,WTSEQ4 ;zero means 16 bit ones. +3040 E25D CD 64 DD CALL ADDA2HL ;(HL)=(HL)+(A) +3041 E260 73 LD (HL),E ;store new block number. +3042 E261 C3 6C E2 JP WTSEQ5 +3043 E264 4F WTSEQ4: LD C,A ;compute spot in this 16 bit table. +3044 E265 06 00 LD B,0 +3045 E267 09 ADD HL,BC +3046 E268 09 ADD HL,BC +3047 E269 73 LD (HL),E ;stuff block number (DE) there. +3048 E26A 23 INC HL +3049 E26B 72 LD (HL),D +3050 E26C 0E 02 WTSEQ5: LD C,2 ;set (C) to indicate writing to un-used disk space. +3051 E26E 3A 45 DB WTSEQ6: LD A,(STATUS) ;are we ok so far? +3052 E271 B7 OR A +3053 E272 C0 RET NZ +3054 E273 C5 PUSH BC ;yes, save write flag for bios (register C). +3055 E274 CD 8A DC CALL LOGICAL ;convert (BLKNMBR) over to loical sectors. +3056 E277 3A D5 E5 LD A,(MODE) ;get access mode flag (1=sequential, +3057 E27A 3D DEC A ;0=random, 2=special?). +3058 E27B 3D DEC A +3059 E27C C2 BB E2 JP NZ,WTSEQ9 +3060 E27F ; +3061 E27F ; Special random i/o from function #40. Maybe for M/PM, but the +3062 E27F ; current block, if it has not been written to, will be zeroed +3063 E27F ; out and then written (reason?). +3064 E27F ; +3065 E27F C1 POP BC +3066 E280 C5 PUSH BC +3067 E281 79 LD A,C ;get write status flag (2=writing unused space). +3068 E282 3D DEC A +3069 E283 3D DEC A +3070 E284 C2 BB E2 JP NZ,WTSEQ9 +3071 E287 E5 PUSH HL +3072 E288 2A B9 E5 LD HL,(DIRBUF) ;zero out the directory buffer. +3073 E28B 57 LD D,A ;note that (A) is zero here. +3074 E28C 77 WTSEQ7: LD (HL),A +3075 E28D 23 INC HL +3076 E28E 14 INC D ;do 128 bytes. +3077 E28F F2 8C E2 JP P,WTSEQ7 +3078 E292 CD E0 DD CALL DIRDMA ;tell the bios the dma address for directory access. +3079 E295 2A E7 E5 LD HL,(LOGSECT) ;get sector that starts current block. +3080 E298 0E 02 LD C,2 ;set 'writing to unused space' flag. +3081 E29A 22 E5 E5 WTSEQ8: LD (BLKNMBR),HL ;save sector to write. +3082 E29D C5 PUSH BC +3083 E29E CD D1 DB CALL TRKSEC1 ;determine its track and sector numbers. +3084 E2A1 C1 POP BC +3085 E2A2 CD B8 DB CALL DOWRITE ;now write out 128 bytes of zeros. +3086 E2A5 2A E5 E5 LD HL,(BLKNMBR) ;get sector number. +3087 E2A8 0E 00 LD C,0 ;set normal write flag. +3088 E2AA 3A C4 E5 LD A,(BLKMASK) ;determine if we have written the entire +3089 E2AD 47 LD B,A ;physical block. +3090 E2AE A5 AND L +3091 E2AF B8 CP B +3092 E2B0 23 INC HL ;prepare for the next one. +3093 E2B1 C2 9A E2 JP NZ,WTSEQ8 ;continue until (BLKMASK+1) sectors written. +3094 E2B4 E1 POP HL ;reset next sector number. +3095 E2B5 22 E5 E5 LD (BLKNMBR),HL +3096 E2B8 CD DA DD CALL DEFDMA ;and reset dma address. +3097 E2BB ; +3098 E2BB ; Normal disk write. Set the desired track and sector then +3099 E2BB ; do the actual write. +3100 E2BB ; +3101 E2BB CD D1 DB WTSEQ9: CALL TRKSEC1 ;determine track and sector for this write. +3102 E2BE C1 POP BC ;get write status flag. +3103 E2BF C5 PUSH BC +3104 E2C0 CD B8 DB CALL DOWRITE ;and write this out. +3105 E2C3 C1 POP BC +3106 E2C4 3A E3 E5 LD A,(SAVNREC) ;get number of records in file. +3107 E2C7 21 E1 E5 LD HL,SAVNXT ;get last record written. +3108 E2CA BE CP (HL) +3109 E2CB DA D2 E2 JP C,WTSEQ10 +3110 E2CE 77 LD (HL),A ;we have to update record count. +3111 E2CF 34 INC (HL) +3112 E2D0 0E 02 LD C,2 +3113 E2D2 ; +3114 E2D2 ;* This area has been patched to correct disk update problem +3115 E2D2 ;* when using blocking and de-blocking in the BIOS. +3116 E2D2 ; +3117 E2D2 00 WTSEQ10:NOP ;was 'dcr c' +3118 E2D3 00 NOP ;was 'dcr c' +3119 E2D4 21 00 00 LD HL,0 ;was 'jnz wtseq99' +3120 E2D7 ; +3121 E2D7 ; * End of patch. +3122 E2D7 ; +3123 E2D7 F5 PUSH AF +3124 E2D8 CD 69 DD CALL GETS2 ;set 'extent written to' flag. +3125 E2DB E6 7F AND 7FH ;(* clear bit 7 *) +3126 E2DD 77 LD (HL),A +3127 E2DE F1 POP AF ;get record count for this extent. +3128 E2DF FE 7F WTSEQ99:CP 127 ;is it full? +3129 E2E1 C2 00 E3 JP NZ,WTSEQ12 +3130 E2E4 3A D5 E5 LD A,(MODE) ;yes, are we in sequential mode? +3131 E2E7 FE 01 CP 1 +3132 E2E9 C2 00 E3 JP NZ,WTSEQ12 +3133 E2EC CD D2 DC CALL SETNREC ;yes, set next record number. +3134 E2EF CD 5A E1 CALL GETNEXT ;and get next empty space in directory. +3135 E2F2 21 45 DB LD HL,STATUS ;ok? +3136 E2F5 7E LD A,(HL) +3137 E2F6 B7 OR A +3138 E2F7 C2 FE E2 JP NZ,WTSEQ11 +3139 E2FA 3D DEC A ;yes, set record count to -1. +3140 E2FB 32 E3 E5 LD (SAVNREC),A +3141 E2FE 36 00 WTSEQ11:LD (HL),0 ;clear status. +3142 E300 C3 D2 DC WTSEQ12:JP SETNREC ;set next record to access. +3143 E303 ; +3144 E303 ; For random i/o, set the fcb for the desired record number +3145 E303 ; based on the 'r0,r1,r2' bytes. These bytes in the fcb are +3146 E303 ; used as follows: +3147 E303 ; +3148 E303 ; fcb+35 fcb+34 fcb+33 +3149 E303 ; | 'r-2' | 'r-1' | 'r-0' | +3150 E303 ; |7 0 | 7 0 | 7 0| +3151 E303 ; |0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0 | 0 0 0 0 0 0 0 0| +3152 E303 ; | overflow | | extra | extent | record # | +3153 E303 ; | ______________| |_extent|__number___|_____________| +3154 E303 ; also 's2' +3155 E303 ; +3156 E303 ; On entry, register (C) contains 0ffh if this is a read +3157 E303 ; and thus we can not access unwritten disk space. Otherwise, +3158 E303 ; another extent will be opened (for writing) if required. +3159 E303 ; +3160 E303 AF POSITION: XOR A ;set random i/o flag. +3161 E304 32 D5 E5 LD (MODE),A +3162 E307 ; +3163 E307 ; Special entry (function #40). M/PM ? +3164 E307 ; +3165 E307 C5 POSITN1:PUSH BC ;save read/write flag. +3166 E308 2A 43 DB LD HL,(PARAMS) ;get address of fcb. +3167 E30B EB EX DE,HL +3168 E30C 21 21 00 LD HL,33 ;now get byte 'r0'. +3169 E30F 19 ADD HL,DE +3170 E310 7E LD A,(HL) +3171 E311 E6 7F AND 7FH ;keep bits 0-6 for the record number to access. +3172 E313 F5 PUSH AF +3173 E314 7E LD A,(HL) ;now get bit 7 of 'r0' and bits 0-3 of 'r1'. +3174 E315 17 RLA +3175 E316 23 INC HL +3176 E317 7E LD A,(HL) +3177 E318 17 RLA +3178 E319 E6 1F AND 1FH ;and save this in bits 0-4 of (C). +3179 E31B 4F LD C,A ;this is the extent byte. +3180 E31C 7E LD A,(HL) ;now get the extra extent byte. +3181 E31D 1F RRA +3182 E31E 1F RRA +3183 E31F 1F RRA +3184 E320 1F RRA +3185 E321 E6 0F AND 0FH +3186 E323 47 LD B,A ;and save it in (B). +3187 E324 F1 POP AF ;get record number back to (A). +3188 E325 23 INC HL ;check overflow byte 'r2'. +3189 E326 6E LD L,(HL) +3190 E327 2C INC L +3191 E328 2D DEC L +3192 E329 2E 06 LD L,6 ;prepare for error. +3193 E32B C2 8B E3 JP NZ,POSITN5 ;out of disk space error. +3194 E32E 21 20 00 LD HL,32 ;store record number into fcb. +3195 E331 19 ADD HL,DE +3196 E332 77 LD (HL),A +3197 E333 21 0C 00 LD HL,12 ;and now check the extent byte. +3198 E336 19 ADD HL,DE +3199 E337 79 LD A,C +3200 E338 96 SUB (HL) ;same extent as before? +3201 E339 C2 47 E3 JP NZ,POSITN2 +3202 E33C 21 0E 00 LD HL,14 ;yes, check extra extent byte 's2' also. +3203 E33F 19 ADD HL,DE +3204 E340 78 LD A,B +3205 E341 96 SUB (HL) +3206 E342 E6 7F AND 7FH +3207 E344 CA 7F E3 JP Z,POSITN3 ;same, we are almost done then. +3208 E347 ; +3209 E347 ; Get here when another extent is required. +3210 E347 ; +3211 E347 C5 POSITN2:PUSH BC +3212 E348 D5 PUSH DE +3213 E349 CD A2 E0 CALL CLOSEIT ;close current extent. +3214 E34C D1 POP DE +3215 E34D C1 POP BC +3216 E34E 2E 03 LD L,3 ;prepare for error. +3217 E350 3A 45 DB LD A,(STATUS) +3218 E353 3C INC A +3219 E354 CA 84 E3 JP Z,POSITN4 ;close error. +3220 E357 21 0C 00 LD HL,12 ;put desired extent into fcb now. +3221 E35A 19 ADD HL,DE +3222 E35B 71 LD (HL),C +3223 E35C 21 0E 00 LD HL,14 ;and store extra extent byte 's2'. +3224 E35F 19 ADD HL,DE +3225 E360 70 LD (HL),B +3226 E361 CD 51 E0 CALL OPENIT ;try and get this extent. +3227 E364 3A 45 DB LD A,(STATUS) ;was it there? +3228 E367 3C INC A +3229 E368 C2 7F E3 JP NZ,POSITN3 +3230 E36B C1 POP BC ;no. can we create a new one (writing?). +3231 E36C C5 PUSH BC +3232 E36D 2E 04 LD L,4 ;prepare for error. +3233 E36F 0C INC C +3234 E370 CA 84 E3 JP Z,POSITN4 ;nope, reading unwritten space error. +3235 E373 CD 24 E1 CALL GETEMPTY ;yes we can, try to find space. +3236 E376 2E 05 LD L,5 ;prepare for error. +3237 E378 3A 45 DB LD A,(STATUS) +3238 E37B 3C INC A +3239 E37C CA 84 E3 JP Z,POSITN4 ;out of space? +3240 E37F ; +3241 E37F ; Normal return location. Clear error code and return. +3242 E37F ; +3243 E37F C1 POSITN3:POP BC ;restore stack. +3244 E380 AF XOR A ;and clear error code byte. +3245 E381 C3 01 DB JP SETSTAT +3246 E384 ; +3247 E384 ; Error. Set the 's2' byte to indicate this (why?). +3248 E384 ; +3249 E384 E5 POSITN4:PUSH HL +3250 E385 CD 69 DD CALL GETS2 +3251 E388 36 C0 LD (HL),0C0H +3252 E38A E1 POP HL +3253 E38B ; +3254 E38B ; Return with error code (presently in L). +3255 E38B ; +3256 E38B C1 POSITN5:POP BC +3257 E38C 7D LD A,L ;get error code. +3258 E38D 32 45 DB LD (STATUS),A +3259 E390 C3 78 DD JP SETS2B7 +3260 E393 ; +3261 E393 ; Read a random record. +3262 E393 ; +3263 E393 0E FF READRAN:LD C,0FFH ;set 'read' status. +3264 E395 CD 03 E3 CALL POSITION ;position the file to proper record. +3265 E398 CC C1 E1 CALL Z,RDSEQ1 ;and read it as usual (if no errors). +3266 E39B C9 RET +3267 E39C ; +3268 E39C ; Write to a random record. +3269 E39C ; +3270 E39C 0E 00 WRITERAN: LD C,0 ;set 'writing' flag. +3271 E39E CD 03 E3 CALL POSITION ;position the file to proper record. +3272 E3A1 CC 03 E2 CALL Z,WTSEQ1 ;and write as usual (if no errors). +3273 E3A4 C9 RET +3274 E3A5 ; +3275 E3A5 ; Compute the random record number. Enter with (HL) pointing +3276 E3A5 ; to a fcb an (DE) contains a relative location of a record +3277 E3A5 ; number. On exit, (C) contains the 'r0' byte, (B) the 'r1' +3278 E3A5 ; byte, and (A) the 'r2' byte. +3279 E3A5 ; +3280 E3A5 ; On return, the zero flag is set if the record is within +3281 E3A5 ; bounds. Otherwise, an overflow occured. +3282 E3A5 ; +3283 E3A5 EB COMPRAND: EX DE,HL ;save fcb pointer in (DE). +3284 E3A6 19 ADD HL,DE ;compute relative position of record #. +3285 E3A7 4E LD C,(HL) ;get record number into (BC). +3286 E3A8 06 00 LD B,0 +3287 E3AA 21 0C 00 LD HL,12 ;now get extent. +3288 E3AD 19 ADD HL,DE +3289 E3AE 7E LD A,(HL) ;compute (BC)=(record #)+(extent)*128. +3290 E3AF 0F RRCA ;move lower bit into bit 7. +3291 E3B0 E6 80 AND 80H ;and ignore all other bits. +3292 E3B2 81 ADD A,C ;add to our record number. +3293 E3B3 4F LD C,A +3294 E3B4 3E 00 LD A,0 ;take care of any carry. +3295 E3B6 88 ADC A,B +3296 E3B7 47 LD B,A +3297 E3B8 7E LD A,(HL) ;now get the upper bits of extent into +3298 E3B9 0F RRCA ;bit positions 0-3. +3299 E3BA E6 0F AND 0FH ;and ignore all others. +3300 E3BC 80 ADD A,B ;add this in to 'r1' byte. +3301 E3BD 47 LD B,A +3302 E3BE 21 0E 00 LD HL,14 ;get the 's2' byte (extra extent). +3303 E3C1 19 ADD HL,DE +3304 E3C2 7E LD A,(HL) +3305 E3C3 87 ADD A,A ;and shift it left 4 bits (bits 4-7). +3306 E3C4 87 ADD A,A +3307 E3C5 87 ADD A,A +3308 E3C6 87 ADD A,A +3309 E3C7 F5 PUSH AF ;save carry flag (bit 0 of flag byte). +3310 E3C8 80 ADD A,B ;now add extra extent into 'r1'. +3311 E3C9 47 LD B,A +3312 E3CA F5 PUSH AF ;and save carry (overflow byte 'r2'). +3313 E3CB E1 POP HL ;bit 0 of (L) is the overflow indicator. +3314 E3CC 7D LD A,L +3315 E3CD E1 POP HL ;and same for first carry flag. +3316 E3CE B5 OR L ;either one of these set? +3317 E3CF E6 01 AND 01H ;only check the carry flags. +3318 E3D1 C9 RET +3319 E3D2 ; +3320 E3D2 ; Routine to setup the fcb (bytes 'r0', 'r1', 'r2') to +3321 E3D2 ; reflect the last record used for a random (or other) file. +3322 E3D2 ; This reads the directory and looks at all extents computing +3323 E3D2 ; the largerst record number for each and keeping the maximum +3324 E3D2 ; value only. Then 'r0', 'r1', and 'r2' will reflect this +3325 E3D2 ; maximum record number. This is used to compute the space used +3326 E3D2 ; by a random file. +3327 E3D2 ; +3328 E3D2 0E 0C RANSIZE:LD C,12 ;look thru directory for first entry with +3329 E3D4 CD 18 DF CALL FINDFST ;this name. +3330 E3D7 2A 43 DB LD HL,(PARAMS) ;zero out the 'r0, r1, r2' bytes. +3331 E3DA 11 21 00 LD DE,33 +3332 E3DD 19 ADD HL,DE +3333 E3DE E5 PUSH HL +3334 E3DF 72 LD (HL),D ;note that (D)=0. +3335 E3E0 23 INC HL +3336 E3E1 72 LD (HL),D +3337 E3E2 23 INC HL +3338 E3E3 72 LD (HL),D +3339 E3E4 CD F5 DD RANSIZ1:CALL CKFILPOS ;is there an extent to process? +3340 E3E7 CA 0C E4 JP Z,RANSIZ3 ;no, we are done. +3341 E3EA CD 5E DD CALL FCB2HL ;set (HL) pointing to proper fcb in dir. +3342 E3ED 11 0F 00 LD DE,15 ;point to last record in extent. +3343 E3F0 CD A5 E3 CALL COMPRAND ;and compute random parameters. +3344 E3F3 E1 POP HL +3345 E3F4 E5 PUSH HL ;now check these values against those +3346 E3F5 5F LD E,A ;already in fcb. +3347 E3F6 79 LD A,C ;the carry flag will be set if those +3348 E3F7 96 SUB (HL) ;in the fcb represent a larger size than +3349 E3F8 23 INC HL ;this extent does. +3350 E3F9 78 LD A,B +3351 E3FA 9E SBC A,(HL) +3352 E3FB 23 INC HL +3353 E3FC 7B LD A,E +3354 E3FD 9E SBC A,(HL) +3355 E3FE DA 06 E4 JP C,RANSIZ2 +3356 E401 73 LD (HL),E ;we found a larger (in size) extent. +3357 E402 2B DEC HL ;stuff these values into fcb. +3358 E403 70 LD (HL),B +3359 E404 2B DEC HL +3360 E405 71 LD (HL),C +3361 E406 CD 2D DF RANSIZ2:CALL FINDNXT ;now get the next extent. +3362 E409 C3 E4 E3 JP RANSIZ1 ;continue til all done. +3363 E40C E1 RANSIZ3:POP HL ;we are done, restore the stack and +3364 E40D C9 RET ;return. +3365 E40E ; +3366 E40E ; Function to return the random record position of a given +3367 E40E ; file which has been read in sequential mode up to now. +3368 E40E ; +3369 E40E 2A 43 DB SETRAN: LD HL,(PARAMS) ;point to fcb. +3370 E411 11 20 00 LD DE,32 ;and to last used record. +3371 E414 CD A5 E3 CALL COMPRAND ;compute random position. +3372 E417 21 21 00 LD HL,33 ;now stuff these values into fcb. +3373 E41A 19 ADD HL,DE +3374 E41B 71 LD (HL),C ;move 'r0'. +3375 E41C 23 INC HL +3376 E41D 70 LD (HL),B ;and 'r1'. +3377 E41E 23 INC HL +3378 E41F 77 LD (HL),A ;and lastly 'r2'. +3379 E420 C9 RET +3380 E421 ; +3381 E421 ; This routine select the drive specified in (ACTIVE) and +3382 E421 ; update the login vector and bitmap table if this drive was +3383 E421 ; not already active. +3384 E421 ; +3385 E421 2A AF E5 LOGINDRV: LD HL,(LOGIN) ;get the login vector. +3386 E424 3A 42 DB LD A,(ACTIVE) ;get the default drive. +3387 E427 4F LD C,A +3388 E428 CD EA DC CALL SHIFTR ;position active bit for this drive +3389 E42B E5 PUSH HL ;into bit 0. +3390 E42C EB EX DE,HL +3391 E42D CD 59 DB CALL SELECT ;select this drive. +3392 E430 E1 POP HL +3393 E431 CC 47 DB CALL Z,SLCTERR ;valid drive? +3394 E434 7D LD A,L ;is this a newly activated drive? +3395 E435 1F RRA +3396 E436 D8 RET C +3397 E437 2A AF E5 LD HL,(LOGIN) ;yes, update the login vector. +3398 E43A 4D LD C,L +3399 E43B 44 LD B,H +3400 E43C CD 0B DD CALL SETBIT +3401 E43F 22 AF E5 LD (LOGIN),HL ;and save. +3402 E442 C3 A3 DE JP BITMAP ;now update the bitmap. +3403 E445 ; +3404 E445 ; Function to set the active disk number. +3405 E445 ; +3406 E445 3A D6 E5 SETDSK: LD A,(EPARAM) ;get parameter passed and see if this +3407 E448 21 42 DB LD HL,ACTIVE ;represents a change in drives. +3408 E44B BE CP (HL) +3409 E44C C8 RET Z +3410 E44D 77 LD (HL),A ;yes it does, log it in. +3411 E44E C3 21 E4 JP LOGINDRV +3412 E451 ; +3413 E451 ; This is the 'auto disk select' routine. The firsst byte +3414 E451 ; of the fcb is examined for a drive specification. If non +3415 E451 ; zero then the drive will be selected and loged in. +3416 E451 ; +3417 E451 3E FF AUTOSEL:LD A,0FFH ;say 'auto-select activated'. +3418 E453 32 DE E5 LD (AUTO),A +3419 E456 2A 43 DB LD HL,(PARAMS) ;get drive specified. +3420 E459 7E LD A,(HL) +3421 E45A E6 1F AND 1FH ;look at lower 5 bits. +3422 E45C 3D DEC A ;adjust for (1=A, 2=B) etc. +3423 E45D 32 D6 E5 LD (EPARAM),A ;and save for the select routine. +3424 E460 FE 1E CP 1EH ;check for 'no change' condition. +3425 E462 D2 75 E4 JP NC,AUTOSL1 ;yes, don't change. +3426 E465 3A 42 DB LD A,(ACTIVE) ;we must change, save currently active +3427 E468 32 DF E5 LD (OLDDRV),A ;drive. +3428 E46B 7E LD A,(HL) ;and save first byte of fcb also. +3429 E46C 32 E0 E5 LD (AUTOFLAG),A ;this must be non-zero. +3430 E46F E6 E0 AND 0E0H ;whats this for (bits 6,7 are used for +3431 E471 77 LD (HL),A ;something)? +3432 E472 CD 45 E4 CALL SETDSK ;select and log in this drive. +3433 E475 3A 41 DB AUTOSL1:LD A,(USERNO) ;move user number into fcb. +3434 E478 2A 43 DB LD HL,(PARAMS) ;(* upper half of first byte *) +3435 E47B B6 OR (HL) +3436 E47C 77 LD (HL),A +3437 E47D C9 RET ;and return (all done). +3438 E47E ; +3439 E47E ; Function to return the current cp/m version number. +3440 E47E ; +3441 E47E 3E 22 GETVER: LD A,022H ;version 2.2 +3442 E480 C3 01 DB JP SETSTAT +3443 E483 ; +3444 E483 ; Function to reset the disk system. +3445 E483 ; +3446 E483 21 00 00 RSTDSK: LD HL,0 ;clear write protect status and log +3447 E486 22 AD E5 LD (WRTPRT),HL ;in vector. +3448 E489 22 AF E5 LD (LOGIN),HL +3449 E48C AF XOR A ;select drive 'A'. +3450 E48D 32 42 DB LD (ACTIVE),A +3451 E490 21 80 00 LD HL,TBUFF ;setup default dma address. +3452 E493 22 B1 E5 LD (USERDMA),HL +3453 E496 CD DA DD CALL DEFDMA +3454 E499 C3 21 E4 JP LOGINDRV ;now log in drive 'A'. +3455 E49C ; +3456 E49C ; Function to open a specified file. +3457 E49C ; +3458 E49C CD 72 DD OPENFIL:CALL CLEARS2 ;clear 's2' byte. +3459 E49F CD 51 E4 CALL AUTOSEL ;select proper disk. +3460 E4A2 C3 51 E0 JP OPENIT ;and open the file. +3461 E4A5 ; +3462 E4A5 ; Function to close a specified file. +3463 E4A5 ; +3464 E4A5 CD 51 E4 CLOSEFIL: CALL AUTOSEL ;select proper disk. +3465 E4A8 C3 A2 E0 JP CLOSEIT ;and close the file. +3466 E4AB ; +3467 E4AB ; Function to return the first occurence of a specified file +3468 E4AB ; name. If the first byte of the fcb is '?' then the name will +3469 E4AB ; not be checked (get the first entry no matter what). +3470 E4AB ; +3471 E4AB 0E 00 GETFST: LD C,0 ;prepare for special search. +3472 E4AD EB EX DE,HL +3473 E4AE 7E LD A,(HL) ;is first byte a '?'? +3474 E4AF FE 3F CP '?' +3475 E4B1 CA C2 E4 JP Z,GETFST1 ;yes, just get very first entry (zero length match). +3476 E4B4 CD A6 DC CALL SETEXT ;get the extension byte from fcb. +3477 E4B7 7E LD A,(HL) ;is it '?'? if yes, then we want +3478 E4B8 FE 3F CP '?' ;an entry with a specific 's2' byte. +3479 E4BA C4 72 DD CALL NZ,CLEARS2 ;otherwise, look for a zero 's2' byte. +3480 E4BD CD 51 E4 CALL AUTOSEL ;select proper drive. +3481 E4C0 0E 0F LD C,15 ;compare bytes 0-14 in fcb (12&13 excluded). +3482 E4C2 CD 18 DF GETFST1:CALL FINDFST ;find an entry and then move it into +3483 E4C5 C3 E9 DD JP MOVEDIR ;the users dma space. +3484 E4C8 ; +3485 E4C8 ; Function to return the next occurence of a file name. +3486 E4C8 ; +3487 E4C8 2A D9 E5 GETNXT: LD HL,(SAVEFCB) ;restore pointers. note that no +3488 E4CB 22 43 DB LD (PARAMS),HL ;other dbos calls are allowed. +3489 E4CE CD 51 E4 CALL AUTOSEL ;no error will be returned, but the +3490 E4D1 CD 2D DF CALL FINDNXT ;results will be wrong. +3491 E4D4 C3 E9 DD JP MOVEDIR +3492 E4D7 ; +3493 E4D7 ; Function to delete a file by name. +3494 E4D7 ; +3495 E4D7 CD 51 E4 DELFILE:CALL AUTOSEL ;select proper drive. +3496 E4DA CD 9C DF CALL ERAFILE ;erase the file. +3497 E4DD C3 01 DF JP STSTATUS ;set status and return. +3498 E4E0 ; +3499 E4E0 ; Function to execute a sequential read of the specified +3500 E4E0 ; record number. +3501 E4E0 ; +3502 E4E0 CD 51 E4 READSEQ:CALL AUTOSEL ;select proper drive then read. +3503 E4E3 C3 BC E1 JP RDSEQ +3504 E4E6 ; +3505 E4E6 ; Function to write the net sequential record. +3506 E4E6 ; +3507 E4E6 CD 51 E4 WRTSEQ: CALL AUTOSEL ;select proper drive then write. +3508 E4E9 C3 FE E1 JP WTSEQ +3509 E4EC ; +3510 E4EC ; Create a file function. +3511 E4EC ; +3512 E4EC CD 72 DD FCREATE:CALL CLEARS2 ;clear the 's2' byte on all creates. +3513 E4EF CD 51 E4 CALL AUTOSEL ;select proper drive and get the next +3514 E4F2 C3 24 E1 JP GETEMPTY ;empty directory space. +3515 E4F5 ; +3516 E4F5 ; Function to rename a file. +3517 E4F5 ; +3518 E4F5 CD 51 E4 RENFILE:CALL AUTOSEL ;select proper drive and then switch +3519 E4F8 CD 16 E0 CALL CHGNAMES ;file names. +3520 E4FB C3 01 DF JP STSTATUS +3521 E4FE ; +3522 E4FE ; Function to return the login vector. +3523 E4FE ; +3524 E4FE 2A AF E5 GETLOG: LD HL,(LOGIN) +3525 E501 C3 29 E5 JP GETPRM1 +3526 E504 ; +3527 E504 ; Function to return the current disk assignment. +3528 E504 ; +3529 E504 3A 42 DB GETCRNT:LD A,(ACTIVE) +3530 E507 C3 01 DB JP SETSTAT +3531 E50A ; +3532 E50A ; Function to set the dma address. +3533 E50A ; +3534 E50A EB PUTDMA: EX DE,HL +3535 E50B 22 B1 E5 LD (USERDMA),HL ;save in our space and then get to +3536 E50E C3 DA DD JP DEFDMA ;the bios with this also. +3537 E511 ; +3538 E511 ; Function to return the allocation vector. +3539 E511 ; +3540 E511 2A BF E5 GETALOC:LD HL,(ALOCVECT) +3541 E514 C3 29 E5 JP GETPRM1 +3542 E517 ; +3543 E517 ; Function to return the read-only status vector. +3544 E517 ; +3545 E517 2A AD E5 GETROV: LD HL,(WRTPRT) +3546 E51A C3 29 E5 JP GETPRM1 +3547 E51D ; +3548 E51D ; Function to set the file attributes (read-only, system). +3549 E51D ; +3550 E51D CD 51 E4 SETATTR:CALL AUTOSEL ;select proper drive then save attributes. +3551 E520 CD 3B E0 CALL SAVEATTR +3552 E523 C3 01 DF JP STSTATUS +3553 E526 ; +3554 E526 ; Function to return the address of the disk parameter block +3555 E526 ; for the current drive. +3556 E526 ; +3557 E526 2A BB E5 GETPARM:LD HL,(DISKPB) +3558 E529 22 45 DB GETPRM1:LD (STATUS),HL +3559 E52C C9 RET +3560 E52D ; +3561 E52D ; Function to get or set the user number. If (E) was (FF) +3562 E52D ; then this is a request to return the current user number. +3563 E52D ; Else set the user number from (E). +3564 E52D ; +3565 E52D 3A D6 E5 GETUSER:LD A,(EPARAM) ;get parameter. +3566 E530 FE FF CP 0FFH ;get user number? +3567 E532 C2 3B E5 JP NZ,SETUSER +3568 E535 3A 41 DB LD A,(USERNO) ;yes, just do it. +3569 E538 C3 01 DB JP SETSTAT +3570 E53B E6 1F SETUSER:AND 1FH ;no, we should set it instead. keep low +3571 E53D 32 41 DB LD (USERNO),A ;bits (0-4) only. +3572 E540 C9 RET +3573 E541 ; +3574 E541 ; Function to read a random record from a file. +3575 E541 ; +3576 E541 CD 51 E4 RDRANDOM: CALL AUTOSEL ;select proper drive and read. +3577 E544 C3 93 E3 JP READRAN +3578 E547 ; +3579 E547 ; Function to compute the file size for random files. +3580 E547 ; +3581 E547 CD 51 E4 WTRANDOM: CALL AUTOSEL ;select proper drive and write. +3582 E54A C3 9C E3 JP WRITERAN +3583 E54D ; +3584 E54D ; Function to compute the size of a random file. +3585 E54D ; +3586 E54D CD 51 E4 FILESIZE: CALL AUTOSEL ;select proper drive and check file length +3587 E550 C3 D2 E3 JP RANSIZE +3588 E553 ; +3589 E553 ; Function #37. This allows a program to log off any drives. +3590 E553 ; On entry, set (DE) to contain a word with bits set for those +3591 E553 ; drives that are to be logged off. The log-in vector and the +3592 E553 ; write protect vector will be updated. This must be a M/PM +3593 E553 ; special function. +3594 E553 ; +3595 E553 2A 43 DB LOGOFF: LD HL,(PARAMS) ;get drives to log off. +3596 E556 7D LD A,L ;for each bit that is set, we want +3597 E557 2F CPL ;to clear that bit in (LOGIN) +3598 E558 5F LD E,A ;and (WRTPRT). +3599 E559 7C LD A,H +3600 E55A 2F CPL +3601 E55B 2A AF E5 LD HL,(LOGIN) ;reset the login vector. +3602 E55E A4 AND H +3603 E55F 57 LD D,A +3604 E560 7D LD A,L +3605 E561 A3 AND E +3606 E562 5F LD E,A +3607 E563 2A AD E5 LD HL,(WRTPRT) +3608 E566 EB EX DE,HL +3609 E567 22 AF E5 LD (LOGIN),HL ;and save. +3610 E56A 7D LD A,L ;now do the write protect vector. +3611 E56B A3 AND E +3612 E56C 6F LD L,A +3613 E56D 7C LD A,H +3614 E56E A2 AND D +3615 E56F 67 LD H,A +3616 E570 22 AD E5 LD (WRTPRT),HL ;and save. all done. +3617 E573 C9 RET +3618 E574 ; +3619 E574 ; Get here to return to the user. +3620 E574 ; +3621 E574 3A DE E5 GOBACK: LD A,(AUTO) ;was auto select activated? +3622 E577 B7 OR A +3623 E578 CA 91 E5 JP Z,GOBACK1 +3624 E57B 2A 43 DB LD HL,(PARAMS) ;yes, but was a change made? +3625 E57E 36 00 LD (HL),0 ;(* reset first byte of fcb *) +3626 E580 3A E0 E5 LD A,(AUTOFLAG) +3627 E583 B7 OR A +3628 E584 CA 91 E5 JP Z,GOBACK1 +3629 E587 77 LD (HL),A ;yes, reset first byte properly. +3630 E588 3A DF E5 LD A,(OLDDRV) ;and get the old drive and select it. +3631 E58B 32 D6 E5 LD (EPARAM),A +3632 E58E CD 45 E4 CALL SETDSK +3633 E591 2A 0F DB GOBACK1:LD HL,(USRSTACK) ;reset the users stack pointer. +3634 E594 F9 LD SP,HL +3635 E595 2A 45 DB LD HL,(STATUS) ;get return status. +3636 E598 7D LD A,L ;force version 1.4 compatability. +3637 E599 44 LD B,H +3638 E59A C9 RET ;and go back to user. +3639 E59B ; +3640 E59B ; Function #40. This is a special entry to do random i/o. +3641 E59B ; For the case where we are writing to unused disk space, this +3642 E59B ; space will be zeroed out first. This must be a M/PM special +3643 E59B ; purpose function, because why would any normal program even +3644 E59B ; care about the previous contents of a sector about to be +3645 E59B ; written over. +3646 E59B ; +3647 E59B CD 51 E4 WTSPECL:CALL AUTOSEL ;select proper drive. +3648 E59E 3E 02 LD A,2 ;use special write mode. +3649 E5A0 32 D5 E5 LD (MODE),A +3650 E5A3 0E 00 LD C,0 ;set write indicator. +3651 E5A5 CD 07 E3 CALL POSITN1 ;position the file. +3652 E5A8 CC 03 E2 CALL Z,WTSEQ1 ;and write (if no errors). +3653 E5AB C9 RET +3654 E5AC ; +3655 E5AC ;************************************************************** +3656 E5AC ;* +3657 E5AC ;* BDOS data storage pool. +3658 E5AC ;* +3659 E5AC ;************************************************************** +3660 E5AC ; +3661 E5AC E5 EMPTYFCB: .DB 0E5H ;empty directory segment indicator. +3662 E5AD 00 00 WRTPRT: .DW 0 ;write protect status for all 16 drives. +3663 E5AF 00 00 LOGIN: .DW 0 ;drive active word (1 bit per drive). +3664 E5B1 80 00 USERDMA:.DW 080H ;user's dma address (defaults to 80h). +3665 E5B3 ; +3666 E5B3 ; Scratch areas from parameter block. +3667 E5B3 ; +3668 E5B3 00 00 SCRATCH1: .DW 0 ;relative position within dir segment for file (0-3). +3669 E5B5 00 00 SCRATCH2: .DW 0 ;last selected track number. +3670 E5B7 00 00 SCRATCH3: .DW 0 ;last selected sector number. +3671 E5B9 ; +3672 E5B9 ; Disk storage areas from parameter block. +3673 E5B9 ; +3674 E5B9 00 00 DIRBUF: .DW 0 ;address of directory buffer to use. +3675 E5BB 00 00 DISKPB: .DW 0 ;contains address of disk parameter block. +3676 E5BD 00 00 CHKVECT:.DW 0 ;address of check vector. +3677 E5BF 00 00 ALOCVECT: .DW 0 ;address of allocation vector (bit map). +3678 E5C1 ; +3679 E5C1 ; Parameter block returned from the bios. +3680 E5C1 ; +3681 E5C1 00 00 SECTORS:.DW 0 ;sectors per track from bios. +3682 E5C3 00 BLKSHFT:.DB 0 ;block shift. +3683 E5C4 00 BLKMASK:.DB 0 ;block mask. +3684 E5C5 00 EXTMASK:.DB 0 ;extent mask. +3685 E5C6 00 00 DSKSIZE:.DW 0 ;disk size from bios (number of blocks-1). +3686 E5C8 00 00 DIRSIZE:.DW 0 ;directory size. +3687 E5CA 00 00 ALLOC0: .DW 0 ;storage for first bytes of bit map (dir space used). +3688 E5CC 00 00 ALLOC1: .DW 0 +3689 E5CE 00 00 OFFSET: .DW 0 ;first usable track number. +3690 E5D0 00 00 XLATE: .DW 0 ;sector translation table address. +3691 E5D2 ; +3692 E5D2 ; +3693 E5D2 00 CLOSEFLG: .DB 0 ;close flag (=0ffh is extent written ok). +3694 E5D3 00 RDWRTFLG: .DB 0 ;read/write flag (0ffh=read, 0=write). +3695 E5D4 00 FNDSTAT:.DB 0 ;filename found status (0=found first entry). +3696 E5D5 00 MODE: .DB 0 ;I/o mode select (0=random, 1=sequential, 2=special random). +3697 E5D6 00 EPARAM: .DB 0 ;storage for register (E) on entry to bdos. +3698 E5D7 00 RELBLOCK: .DB 0 ;relative position within fcb of block number written. +3699 E5D8 00 COUNTER:.DB 0 ;byte counter for directory name searches. +3700 E5D9 00 00 00 00 SAVEFCB:.DW 0,0 ;save space for address of fcb (for directory searches). +3701 E5DD 00 BIGDISK:.DB 0 ;if =0 then disk is > 256 blocks long. +3702 E5DE 00 AUTO: .DB 0 ;if non-zero, then auto select activated. +3703 E5DF 00 OLDDRV: .DB 0 ;on auto select, storage for previous drive. +3704 E5E0 00 AUTOFLAG: .DB 0 ;if non-zero, then auto select changed drives. +3705 E5E1 00 SAVNXT: .DB 0 ;storage for next record number to access. +3706 E5E2 00 SAVEXT: .DB 0 ;storage for extent number of file. +3707 E5E3 00 00 SAVNREC:.DW 0 ;storage for number of records in file. +3708 E5E5 00 00 BLKNMBR:.DW 0 ;block number (physical sector) used within a file or logical sect +3709 E5E7 00 00 LOGSECT:.DW 0 ;starting logical (128 byte) sector of block (physical sector). +3710 E5E9 00 FCBPOS: .DB 0 ;relative position within buffer for fcb of file of interest. +3711 E5EA 00 00 FILEPOS:.DW 0 ;files position within directory (0 to max entries -1). +3712 E5EC ; +3713 E5EC ; Disk directory buffer checksum bytes. One for each of the +3714 E5EC ; 16 possible drives. +3715 E5EC ; +3716 E5EC 00 00 00 00 CKSUMTBL: .DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +3716 E5F0 00 00 00 00 +3716 E5F4 00 00 00 00 +3716 E5F8 00 00 00 00 +3717 E5FC ; +3718 E5FC ; Extra space ? +3719 E5FC ; +3720 E5FC 00 00 00 00 .DB 0,0,0,0 +3721 E600 ; +3722 E600 ;************************************************************** +3723 E600 ;* +3724 E600 ;* B I O S J U M P T A B L E +3725 E600 ;* +3726 E600 ;************************************************************** +3727 E600 ; +3728 E600 C3 00 00 BOOT: JP 0 ;NOTE WE USE FAKE DESTINATIONS +3729 E603 C3 00 00 WBOOT: JP 0 +3730 E606 C3 00 00 CONST: JP 0 +3731 E609 C3 00 00 CONIN: JP 0 +3732 E60C C3 00 00 CONOUT: JP 0 +3733 E60F C3 00 00 LIST: JP 0 +3734 E612 C3 00 00 PUNCH: JP 0 +3735 E615 C3 00 00 READER: JP 0 +3736 E618 C3 00 00 HOME: JP 0 +3737 E61B C3 00 00 SELDSK: JP 0 +3738 E61E C3 00 00 SETTRK: JP 0 +3739 E621 C3 00 00 SETSEC: JP 0 +3740 E624 C3 00 00 SETDMA: JP 0 +3741 E627 C3 00 00 READ: JP 0 +3742 E62A C3 00 00 WRITE: JP 0 +3743 E62D C3 00 00 PRSTAT: JP 0 +3744 E630 C3 00 00 SECTRN: JP 0 +3745 E633 ; +3746 E633 ;* +3747 E633 ;****************** E N D O F C P / M ***************** +3748 E633 ;* +3749 E633 +3750 E633 .END +tasm: Number of errors = 0 diff --git a/Z80 CPM and bootloader (basmon)/source/DOWNLOAD.LST b/Z80 CPM and bootloader (basmon)/source/DOWNLOAD.LST index 98fa498..55369a5 100644 --- a/Z80 CPM and bootloader (basmon)/source/DOWNLOAD.LST +++ b/Z80 CPM and bootloader (basmon)/source/DOWNLOAD.LST @@ -1,290 +1,301 @@ -0001 0000 ;================================================================================== -0002 0000 ; Contents of this file are copyright Grant Searle -0003 0000 ; HEX routine from Joel Owens. -0004 0000 ; -0005 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY -0006 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. -0007 0000 ; -0008 0000 ; http://searle.hostei.com/grant/index.html -0009 0000 ; -0010 0000 ; eMail: home.micros01@btinternet.com -0011 0000 ; -0012 0000 ; If the above don't work, please perform an Internet search to see if I have -0013 0000 ; updated the web page hosting service. -0014 0000 ; -0015 0000 ;================================================================================== -0016 0000 -0017 0000 TPA .EQU 100H -0018 0000 REBOOT .EQU 0H -0019 0000 BDOS .EQU 5H -0020 0000 CONIO .EQU 6 -0021 0000 CONINP .EQU 1 -0022 0000 CONOUT .EQU 2 -0023 0000 PSTRING .EQU 9 -0024 0000 MAKEF .EQU 22 -0025 0000 CLOSEF .EQU 16 -0026 0000 WRITES .EQU 21 -0027 0000 DELF .EQU 19 -0028 0000 SETUSR .EQU 32 -0029 0000 -0030 0000 CR .EQU 0DH -0031 0000 LF .EQU 0AH -0032 0000 -0033 0000 FCB .EQU 05CH -0034 0000 BUFF .EQU 080H -0035 0000 -0036 0100 .ORG TPA -0037 0100 -0038 0100 -0039 0100 3E 00 LD A,0 -0040 0102 32 6D 02 LD (buffPos),A -0041 0105 32 71 02 LD (checkSum),A -0042 0108 32 72 02 LD (byteCount),A -0043 010B 32 70 02 LD (printCount),A -0044 010E 21 80 00 LD HL,BUFF -0045 0111 22 6E 02 LD (buffPtr),HL -0046 0114 -0047 0114 -0048 0114 CD 39 02 WAITLT: CALL GETCHR -0049 0117 FE 55 CP 'U' -0050 0119 CA 2A 02 JP Z,SETUSER -0051 011C FE 3A CP ':' -0052 011E 20 F4 JR NZ,WAITLT -0053 0120 -0054 0120 -0055 0120 0E 13 LD C,DELF -0056 0122 11 5C 00 LD DE,FCB -0057 0125 CD 05 00 CALL BDOS -0058 0128 -0059 0128 0E 16 LD C,MAKEF -0060 012A 11 5C 00 LD DE,FCB -0061 012D CD 05 00 CALL BDOS -0062 0130 -0063 0130 GETHEX: -0064 0130 CD 39 02 CALL GETCHR -0065 0133 FE 3E CP '>' -0066 0135 28 61 JR Z,CLOSE -0067 0137 47 LD B,A -0068 0138 C5 PUSH BC -0069 0139 CD 39 02 CALL GETCHR -0070 013C C1 POP BC -0071 013D 4F LD C,A -0072 013E -0073 013E CD 4C 02 CALL BCTOA -0074 0141 -0075 0141 47 LD B,A -0076 0142 3A 71 02 LD A,(checkSum) -0077 0145 80 ADD A,B -0078 0146 32 71 02 LD (checkSum),A -0079 0149 3A 72 02 LD A,(byteCount) -0080 014C 3C INC A -0081 014D 32 72 02 LD (byteCount),A -0082 0150 -0083 0150 78 LD A,B -0084 0151 -0085 0151 2A 6E 02 LD HL,(buffPtr) -0086 0154 -0087 0154 77 LD (HL),A -0088 0155 23 INC HL -0089 0156 22 6E 02 LD (buffPtr),HL -0090 0159 -0091 0159 3A 6D 02 LD A,(buffPos) -0092 015C 3C INC A -0093 015D 32 6D 02 LD (buffPos),A -0094 0160 FE 80 CP 80H -0095 0162 -0096 0162 20 32 JR NZ,NOWRITE -0097 0164 -0098 0164 0E 15 LD C,WRITES -0099 0166 11 5C 00 LD DE,FCB -0100 0169 CD 05 00 CALL BDOS -0101 016C 3E 2E LD A,'.' -0102 016E CD 45 02 CALL PUTCHR -0103 0171 -0104 0171 ; New line every 8K (64 dots) -0105 0171 3A 70 02 LD A,(printCount) -0106 0174 3C INC A -0107 0175 FE 40 CP 64 -0108 0177 20 0F JR NZ,noCRLF -0109 0179 32 70 02 LD (printCount),A -0110 017C 3E 0D LD A,CR -0111 017E CD 45 02 CALL PUTCHR -0112 0181 3E 0A LD A,LF -0113 0183 CD 45 02 CALL PUTCHR -0114 0186 3E 00 LD A,0 -0115 0188 32 70 02 noCRLF: LD (printCount),A -0116 018B -0117 018B 21 80 00 LD HL,BUFF -0118 018E 22 6E 02 LD (buffPtr),HL -0119 0191 -0120 0191 3E 00 LD A,0 -0121 0193 32 6D 02 LD (buffPos),A -0122 0196 NOWRITE: -0123 0196 18 98 JR GETHEX -0124 0198 -0125 0198 -0126 0198 CLOSE: -0127 0198 -0128 0198 3A 6D 02 LD A,(buffPos) -0129 019B FE 00 CP 0 -0130 019D 28 0D JR Z,NOWRITE2 -0131 019F -0132 019F 0E 15 LD C,WRITES -0133 01A1 11 5C 00 LD DE,FCB -0134 01A4 CD 05 00 CALL BDOS -0135 01A7 3E 2E LD A,'.' -0136 01A9 CD 45 02 CALL PUTCHR -0137 01AC -0138 01AC NOWRITE2: -0139 01AC 0E 10 LD C,CLOSEF -0140 01AE 11 5C 00 LD DE,FCB -0141 01B1 CD 05 00 CALL BDOS -0142 01B4 -0143 01B4 ; Byte count (lower 8 bits) -0144 01B4 CD 39 02 CALL GETCHR -0145 01B7 47 LD B,A -0146 01B8 C5 PUSH BC -0147 01B9 CD 39 02 CALL GETCHR -0148 01BC C1 POP BC -0149 01BD 4F LD C,A -0150 01BE -0151 01BE CD 4C 02 CALL BCTOA -0152 01C1 47 LD B,A -0153 01C2 3A 72 02 LD A,(byteCount) -0154 01C5 90 SUB B -0155 01C6 FE 00 CP 0 -0156 01C8 28 1A JR Z,byteCountOK -0157 01CA -0158 01CA 3E 0D LD A,CR -0159 01CC CD 45 02 CALL PUTCHR -0160 01CF 3E 0A LD A,LF -0161 01D1 CD 45 02 CALL PUTCHR -0162 01D4 -0163 01D4 11 91 02 LD DE,countErrMess -0164 01D7 0E 09 LD C,PSTRING -0165 01D9 CD 05 00 CALL BDOS -0166 01DC -0167 01DC ; Sink remaining 2 bytes -0168 01DC CD 39 02 CALL GETCHR -0169 01DF CD 39 02 CALL GETCHR -0170 01E2 -0171 01E2 18 3C JR FINISH -0172 01E4 -0173 01E4 byteCountOK: -0174 01E4 -0175 01E4 ; Checksum -0176 01E4 CD 39 02 CALL GETCHR -0177 01E7 47 LD B,A -0178 01E8 C5 PUSH BC -0179 01E9 CD 39 02 CALL GETCHR -0180 01EC C1 POP BC -0181 01ED 4F LD C,A -0182 01EE -0183 01EE CD 4C 02 CALL BCTOA -0184 01F1 47 LD B,A -0185 01F2 3A 71 02 LD A,(checkSum) -0186 01F5 90 SUB B -0187 01F6 FE 00 CP 0 -0188 01F8 28 14 JR Z,checksumOK -0189 01FA -0190 01FA 3E 0D LD A,CR -0191 01FC CD 45 02 CALL PUTCHR -0192 01FF 3E 0A LD A,LF -0193 0201 CD 45 02 CALL PUTCHR -0194 0204 -0195 0204 11 76 02 LD DE,chkErrMess -0196 0207 0E 09 LD C,PSTRING -0197 0209 CD 05 00 CALL BDOS -0198 020C 18 12 JR FINISH -0199 020E -0200 020E checksumOK: -0201 020E 3E 0D LD A,CR -0202 0210 CD 45 02 CALL PUTCHR -0203 0213 3E 0A LD A,LF -0204 0215 CD 45 02 CALL PUTCHR -0205 0218 -0206 0218 11 73 02 LD DE,OKMess -0207 021B 0E 09 LD C,PSTRING -0208 021D CD 05 00 CALL BDOS -0209 0220 -0210 0220 -0211 0220 -0212 0220 FINISH: -0213 0220 0E 20 LD C,SETUSR -0214 0222 1E 00 LD E,0 -0215 0224 CD 05 00 CALL BDOS -0216 0227 -0217 0227 C3 00 00 JP REBOOT -0218 022A -0219 022A -0220 022A SETUSER: -0221 022A CD 39 02 CALL GETCHR -0222 022D CD 65 02 CALL HEX2VAL -0223 0230 5F LD E,A -0224 0231 0E 20 LD C,SETUSR -0225 0233 CD 05 00 CALL BDOS -0226 0236 C3 14 01 JP WAITLT -0227 0239 -0228 0239 -0229 0239 ; Get a char into A -0230 0239 ;GETCHR: LD C,CONINP -0231 0239 ; CALL BDOS -0232 0239 ; RET -0233 0239 -0234 0239 ; Wait for a char into A (no echo) -0235 0239 GETCHR: -0236 0239 1E FF LD E,$FF -0237 023B 0E 06 LD C,CONIO -0238 023D CD 05 00 CALL BDOS -0239 0240 FE 00 CP 0 -0240 0242 28 F5 JR Z,GETCHR -0241 0244 C9 RET -0242 0245 -0243 0245 ; Write A to output -0244 0245 0E 02 PUTCHR: LD C,CONOUT -0245 0247 5F LD E,A -0246 0248 CD 05 00 CALL BDOS -0247 024B C9 RET -0248 024C -0249 024C -0250 024C ;------------------------------------------------------------------------------ -0251 024C ; Convert ASCII characters in B C registers to a byte value in A -0252 024C ;------------------------------------------------------------------------------ -0253 024C 78 BCTOA LD A,B ; Move the hi order byte to A -0254 024D D6 30 SUB $30 ; Take it down from Ascii -0255 024F FE 0A CP $0A ; Are we in the 0-9 range here? -0256 0251 38 02 JR C,BCTOA1 ; If so, get the next nybble -0257 0253 D6 07 SUB $07 ; But if A-F, take it down some more -0258 0255 07 BCTOA1 RLCA ; Rotate the nybble from low to high -0259 0256 07 RLCA ; One bit at a time -0260 0257 07 RLCA ; Until we -0261 0258 07 RLCA ; Get there with it -0262 0259 47 LD B,A ; Save the converted high nybble -0263 025A 79 LD A,C ; Now get the low order byte -0264 025B D6 30 SUB $30 ; Convert it down from Ascii -0265 025D FE 0A CP $0A ; 0-9 at this point? -0266 025F 38 02 JR C,BCTOA2 ; Good enough then, but -0267 0261 D6 07 SUB $07 ; Take off 7 more if it's A-F -0268 0263 80 BCTOA2 ADD A,B ; Add in the high order nybble -0269 0264 C9 RET -0270 0265 -0271 0265 ; Change Hex in A to actual value in A -0272 0265 D6 30 HEX2VAL SUB $30 -0273 0267 FE 0A CP $0A -0274 0269 D8 RET C -0275 026A D6 07 SUB $07 -0276 026C C9 RET -0277 026D -0278 026D -0279 026D 00 buffPos .DB 0H -0280 026E 00 00 buffPtr .DW 0000H -0281 0270 00 printCount .DB 0H -0282 0271 00 checkSum .DB 0H -0283 0272 00 byteCount .DB 0H -0284 0273 4F 4B 24 OKMess .BYTE "OK$" -0285 0276 3D3D3D3D3D3DchkErrMess .BYTE "======Checksum Error======$" -0285 027C 436865636B73756D204572726F723D3D3D3D3D3D24 -0286 0291 3D3D3D3D3D3DcountErrMess .BYTE "======File Length Error======$" -0286 0297 46696C65204C656E677468204572726F723D3D3D3D3D3D24 -0287 02AF .END -tasm: Number of errors = 0 +0001 0000 ;================================================================================== +0002 0000 ; Contents of this file are copyright Grant Searle +0003 0000 ; HEX routine from Joel Owens. +0004 0000 ; +0005 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY +0006 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. +0007 0000 ; +0008 0000 ; http://searle.hostei.com/grant/index.html +0009 0000 ; +0010 0000 ; eMail: home.micros01@btinternet.com +0011 0000 ; +0012 0000 ; If the above don't work, please perform an Internet search to see if I have +0013 0000 ; updated the web page hosting service. +0014 0000 ; +0015 0000 ;================================================================================== +0016 0000 +0017 0000 TPA .EQU 100H +0018 0000 REBOOT .EQU 0H +0019 0000 BDOS .EQU 5H +0020 0000 CONIO .EQU 6 +0021 0000 CONINP .EQU 1 +0022 0000 CONOUT .EQU 2 +0023 0000 PSTRING .EQU 9 +0024 0000 MAKEF .EQU 22 +0025 0000 CLOSEF .EQU 16 +0026 0000 WRITES .EQU 21 +0027 0000 DELF .EQU 19 +0028 0000 SETUSR .EQU 32 +0029 0000 +0030 0000 CR .EQU 0DH +0031 0000 LF .EQU 0AH +0032 0000 +0033 0000 FCB .EQU 05CH +0034 0000 BUFF .EQU 080H +0035 0000 +0036 0100 .ORG TPA +0037 0100 +0038 0100 +0039 0100 3E 00 LD A,0 +0040 0102 32 6D 02 LD (buffPos),A +0041 0105 32 71 02 LD (checkSum),A +0042 0108 32 72 02 LD (byteCount),A +0043 010B 32 70 02 LD (printCount),A +0044 010E 21 80 00 LD HL,BUFF +0045 0111 22 6E 02 LD (buffPtr),HL +0046 0114 +0047 0114 +0048 0114 CD 39 02 WAITLT: CALL GETCHR +0049 0117 FE 55 CP 'U' +0050 0119 CA 2A 02 JP Z,SETUSER +0051 011C FE 3A CP ':' +0052 011E 20 F4 JR NZ,WAITLT +0053 0120 +0054 0120 +0055 0120 0E 13 LD C,DELF +0056 0122 11 5C 00 LD DE,FCB +0057 0125 CD 05 00 CALL BDOS +0058 0128 +0059 0128 0E 16 LD C,MAKEF +0060 012A 11 5C 00 LD DE,FCB +0061 012D CD 05 00 CALL BDOS +0062 0130 +0063 0130 GETHEX: +0064 0130 CD 39 02 CALL GETCHR +0065 0133 FE 3E CP '>' +0066 0135 28 61 JR Z,CLOSE +0067 0137 47 LD B,A +0068 0138 C5 PUSH BC +0069 0139 CD 39 02 CALL GETCHR +0070 013C C1 POP BC +0071 013D 4F LD C,A +0072 013E +0073 013E CD 4C 02 CALL BCTOA +0074 0141 +0075 0141 47 LD B,A +0076 0142 3A 71 02 LD A,(checkSum) +0077 0145 80 ADD A,B +0078 0146 32 71 02 LD (checkSum),A +0079 0149 3A 72 02 LD A,(byteCount) +0080 014C 3C INC A +0081 014D 32 72 02 LD (byteCount),A +0082 0150 +0083 0150 78 LD A,B +0084 0151 +0085 0151 2A 6E 02 LD HL,(buffPtr) +0086 0154 +0087 0154 77 LD (HL),A +0088 0155 23 INC HL +0089 0156 22 6E 02 LD (buffPtr),HL +0090 0159 +0091 0159 3A 6D 02 LD A,(buffPos) +0092 015C 3C INC A +0093 015D 32 6D 02 LD (buffPos),A +0094 0160 FE 80 CP 80H +0095 0162 +0096 0162 20 32 JR NZ,NOWRITE +0097 0164 +0098 0164 0E 15 LD C,WRITES +0099 0166 11 5C 00 LD DE,FCB +0100 0169 CD 05 00 CALL BDOS +0101 016C 3E 2E LD A,'.' +0102 016E CD 45 02 CALL PUTCHR +0103 0171 +0104 0171 ; New line every 8K (64 dots) +0105 0171 3A 70 02 LD A,(printCount) +0106 0174 3C INC A +0107 0175 FE 40 CP 64 +0108 0177 20 0F JR NZ,noCRLF +0109 0179 32 70 02 LD (printCount),A +0110 017C 3E 0D LD A,CR +0111 017E CD 45 02 CALL PUTCHR +0112 0181 3E 0A LD A,LF +0113 0183 CD 45 02 CALL PUTCHR +0114 0186 3E 00 LD A,0 +0115 0188 32 70 02 noCRLF: LD (printCount),A +0116 018B +0117 018B 21 80 00 LD HL,BUFF +0118 018E 22 6E 02 LD (buffPtr),HL +0119 0191 +0120 0191 3E 00 LD A,0 +0121 0193 32 6D 02 LD (buffPos),A +0122 0196 NOWRITE: +0123 0196 18 98 JR GETHEX +0124 0198 +0125 0198 +0126 0198 CLOSE: +0127 0198 +0128 0198 3A 6D 02 LD A,(buffPos) +0129 019B FE 00 CP 0 +0130 019D 28 0D JR Z,NOWRITE2 +0131 019F +0132 019F 0E 15 LD C,WRITES +0133 01A1 11 5C 00 LD DE,FCB +0134 01A4 CD 05 00 CALL BDOS +0135 01A7 3E 2E LD A,'.' +0136 01A9 CD 45 02 CALL PUTCHR +0137 01AC +0138 01AC NOWRITE2: +0139 01AC 0E 10 LD C,CLOSEF +0140 01AE 11 5C 00 LD DE,FCB +0141 01B1 CD 05 00 CALL BDOS +0142 01B4 +0143 01B4 ; Byte count (lower 8 bits) +0144 01B4 CD 39 02 CALL GETCHR +0145 01B7 47 LD B,A +0146 01B8 C5 PUSH BC +0147 01B9 CD 39 02 CALL GETCHR +0148 01BC C1 POP BC +0149 01BD 4F LD C,A +0150 01BE +0151 01BE CD 4C 02 CALL BCTOA +0152 01C1 47 LD B,A +0153 01C2 3A 72 02 LD A,(byteCount) +0154 01C5 90 SUB B +0155 01C6 FE 00 CP 0 +0156 01C8 28 1A JR Z,byteCountOK +0157 01CA +0158 01CA 3E 0D LD A,CR +0159 01CC CD 45 02 CALL PUTCHR +0160 01CF 3E 0A LD A,LF +0161 01D1 CD 45 02 CALL PUTCHR +0162 01D4 +0163 01D4 11 91 02 LD DE,countErrMess +0164 01D7 0E 09 LD C,PSTRING +0165 01D9 CD 05 00 CALL BDOS +0166 01DC +0167 01DC ; Sink remaining 2 bytes +0168 01DC CD 39 02 CALL GETCHR +0169 01DF CD 39 02 CALL GETCHR +0170 01E2 +0171 01E2 18 3C JR FINISH +0172 01E4 +0173 01E4 byteCountOK: +0174 01E4 +0175 01E4 ; Checksum +0176 01E4 CD 39 02 CALL GETCHR +0177 01E7 47 LD B,A +0178 01E8 C5 PUSH BC +0179 01E9 CD 39 02 CALL GETCHR +0180 01EC C1 POP BC +0181 01ED 4F LD C,A +0182 01EE +0183 01EE CD 4C 02 CALL BCTOA +0184 01F1 47 LD B,A +0185 01F2 3A 71 02 LD A,(checkSum) +0186 01F5 90 SUB B +0187 01F6 FE 00 CP 0 +0188 01F8 28 14 JR Z,checksumOK +0189 01FA +0190 01FA 3E 0D LD A,CR +0191 01FC CD 45 02 CALL PUTCHR +0192 01FF 3E 0A LD A,LF +0193 0201 CD 45 02 CALL PUTCHR +0194 0204 +0195 0204 11 76 02 LD DE,chkErrMess +0196 0207 0E 09 LD C,PSTRING +0197 0209 CD 05 00 CALL BDOS +0198 020C 18 12 JR FINISH +0199 020E +0200 020E checksumOK: +0201 020E 3E 0D LD A,CR +0202 0210 CD 45 02 CALL PUTCHR +0203 0213 3E 0A LD A,LF +0204 0215 CD 45 02 CALL PUTCHR +0205 0218 +0206 0218 11 73 02 LD DE,OKMess +0207 021B 0E 09 LD C,PSTRING +0208 021D CD 05 00 CALL BDOS +0209 0220 +0210 0220 +0211 0220 +0212 0220 FINISH: +0213 0220 0E 20 LD C,SETUSR +0214 0222 1E 00 LD E,0 +0215 0224 CD 05 00 CALL BDOS +0216 0227 +0217 0227 C3 00 00 JP REBOOT +0218 022A +0219 022A +0220 022A SETUSER: +0221 022A CD 39 02 CALL GETCHR +0222 022D CD 65 02 CALL HEX2VAL +0223 0230 5F LD E,A +0224 0231 0E 20 LD C,SETUSR +0225 0233 CD 05 00 CALL BDOS +0226 0236 C3 14 01 JP WAITLT +0227 0239 +0228 0239 +0229 0239 ; Get a char into A +0230 0239 ;GETCHR: LD C,CONINP +0231 0239 ; CALL BDOS +0232 0239 ; RET +0233 0239 +0234 0239 ; Wait for a char into A (no echo) +0235 0239 GETCHR: +0236 0239 1E FF LD E,$FF +0237 023B 0E 06 LD C,CONIO +0238 023D CD 05 00 CALL BDOS +0239 0240 FE 00 CP 0 +0240 0242 28 F5 JR Z,GETCHR +0241 0244 C9 RET +0242 0245 +0243 0245 ; Write A to output +0244 0245 0E 02 PUTCHR: LD C,CONOUT +0245 0247 5F LD E,A +0246 0248 CD 05 00 CALL BDOS +0247 024B C9 RET +0248 024C +0249 024C +0250 024C ;------------------------------------------------------------------------------ +0251 024C ; Convert ASCII characters in B C registers to a byte value in A +0252 024C ;------------------------------------------------------------------------------ +0253 024C 78 BCTOA LD A,B ; Move the hi order byte to A +0254 024D D6 30 SUB $30 ; Take it down from Ascii +0255 024F FE 0A CP $0A ; Are we in the 0-9 range here? +0256 0251 38 02 JR C,BCTOA1 ; If so, get the next nybble +0257 0253 D6 07 SUB $07 ; But if A-F, take it down some more +0258 0255 07 BCTOA1 RLCA ; Rotate the nybble from low to high +0259 0256 07 RLCA ; One bit at a time +0260 0257 07 RLCA ; Until we +0261 0258 07 RLCA ; Get there with it +0262 0259 47 LD B,A ; Save the converted high nybble +0263 025A 79 LD A,C ; Now get the low order byte +0264 025B D6 30 SUB $30 ; Convert it down from Ascii +0265 025D FE 0A CP $0A ; 0-9 at this point? +0266 025F 38 02 JR C,BCTOA2 ; Good enough then, but +0267 0261 D6 07 SUB $07 ; Take off 7 more if it's A-F +0268 0263 80 BCTOA2 ADD A,B ; Add in the high order nybble +0269 0264 C9 RET +0270 0265 +0271 0265 ; Change Hex in A to actual value in A +0272 0265 D6 30 HEX2VAL SUB $30 +0273 0267 FE 0A CP $0A +0274 0269 D8 RET C +0275 026A D6 07 SUB $07 +0276 026C C9 RET +0277 026D +0278 026D +0279 026D 00 buffPos .DB 0H +0280 026E 00 00 buffPtr .DW 0000H +0281 0270 00 printCount .DB 0H +0282 0271 00 checkSum .DB 0H +0283 0272 00 byteCount .DB 0H +0284 0273 4F 4B 24 OKMess .BYTE "OK$" +0285 0276 3D 3D 3D 3D chkErrMess .BYTE "======Checksum Error======$" +0285 027A 3D 3D 43 68 +0285 027E 65 63 6B 73 +0285 0282 75 6D 20 45 +0285 0286 72 72 6F 72 +0285 028A 3D 3D 3D 3D +0285 028E 3D 3D 24 +0286 0291 3D 3D 3D 3D countErrMess .BYTE "======File Length Error======$" +0286 0295 3D 3D 46 69 +0286 0299 6C 65 20 4C +0286 029D 65 6E 67 74 +0286 02A1 68 20 45 72 +0286 02A5 72 6F 72 3D +0286 02A9 3D 3D 3D 3D +0286 02AD 3D 24 +0287 02AF .END +tasm: Number of errors = 0 diff --git a/Z80 CPM and bootloader (basmon)/source/FORM128.LST b/Z80 CPM and bootloader (basmon)/source/FORM128.LST index 6e1d005..69d614e 100644 --- a/Z80 CPM and bootloader (basmon)/source/FORM128.LST +++ b/Z80 CPM and bootloader (basmon)/source/FORM128.LST @@ -1,230 +1,256 @@ -0001 0000 ;================================================================================== -0002 0000 ; Contents of this file are copyright Grant Searle -0003 0000 ; -0004 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY -0005 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. -0006 0000 ; -0007 0000 ; http://searle.hostei.com/grant/index.html -0008 0000 ; -0009 0000 ; eMail: home.micros01@btinternet.com -0010 0000 ; -0011 0000 ; If the above don't work, please perform an Internet search to see if I have -0012 0000 ; updated the web page hosting service. -0013 0000 ; -0014 0000 ;================================================================================== -0015 0000 -0016 0000 numDrives .EQU 15 ; Not including A: -0017 0000 -0018 0000 -0019 0000 SD_DATA .EQU 088H -0020 0000 SD_CONTROL .EQU 089H -0021 0000 SD_STATUS .EQU 089H -0022 0000 SD_LBA0 .EQU 08AH -0023 0000 SD_LBA1 .EQU 08BH -0024 0000 SD_LBA2 .EQU 08CH -0025 0000 -0026 0000 LF .EQU 0AH ;line feed -0027 0000 FF .EQU 0CH ;form feed -0028 0000 CR .EQU 0DH ;carriage RETurn -0029 0000 -0030 0000 ;==================================================================================== -0031 0000 -0032 5000 .ORG 5000H ; Format program origin. -0033 5000 -0034 5000 -0035 5000 CD D5 50 CALL printInline -0036 5003 43502F4D2046 .TEXT "CP/M Formatter 2.0 by G. Searle 2013" -0036 5009 6F726D617474657220322E3020627920472E20536561726C652032303133 -0037 5027 0D 0A 00 .DB CR,LF,0 -0038 502A -0039 502A 3E 41 LD A,'A' -0040 502C 32 E7 50 LD (drvName),A -0041 502F -0042 502F ; There are 512 directory entries per disk, 4 DIR entries per sector -0043 502F ; So 128 x 128 byte sectors are to be initialised -0044 502F ; The drive uses 512 byte sectors, so 32 x 512 byte sectors per disk -0045 502F ; require initialisation -0046 502F -0047 502F ;Drive 0 (A:) is slightly different due to reserved track, so DIR sector starts at 32 -0048 502F 3A E7 50 LD A,(drvName) -0049 5032 CF RST 08H ; Print drive letter -0050 5033 3C INC A -0051 5034 32 E7 50 LD (drvName),A -0052 5037 -0053 5037 3E 20 LD A,$20 -0054 5039 32 E6 50 LD (secNo),A -0055 503C -0056 503C processSectorA: -0057 503C -0058 503C 3A E6 50 LD A,(secNo) -0059 503F D3 8A OUT (SD_LBA0),A -0060 5041 3E 00 LD A,0 -0061 5043 D3 8B OUT (SD_LBA1),A -0062 5045 3E 00 LD A,0 -0063 5047 D3 8C OUT (SD_LBA2),A -0064 5049 3E E0 LD a,$E0 -0065 504B -0066 504B CD A7 50 call writehst -0067 504E -0068 504E 3A E6 50 LD A,(secNo) -0069 5051 3C INC A -0070 5052 32 E6 50 LD (secNo),A -0071 5055 FE 40 CP $40 -0072 5057 20 E3 JR NZ, processSectorA -0073 5059 -0074 5059 -0075 5059 -0076 5059 ;Drive 1 onwards (B: etc) don't have reserved tracks, so sector starts at 0 -0077 5059 -0078 5059 11 40 00 LD DE,$0040 ; HL increment -0079 505C 21 40 00 LD HL,$0040 ; H = LBA2, L=LBA1, initialise for drive 1 (B:) -0080 505F -0081 505F 06 0F LD B,numDrives -0082 5061 -0083 5061 processDirs: -0084 5061 -0085 5061 3A E7 50 LD A,(drvName) -0086 5064 CF RST 08H ; Print drive letter -0087 5065 3C INC A -0088 5066 32 E7 50 LD (drvName),A -0089 5069 -0090 5069 3E 00 LD A,0 -0091 506B 32 E6 50 LD (secNo),A -0092 506E -0093 506E processSector: -0094 506E 3A E6 50 LD A,(secNo) -0095 5071 D3 8A OUT (SD_LBA0),A -0096 5073 7D LD A,L -0097 5074 D3 8B OUT (SD_LBA1),A -0098 5076 7C LD A,H -0099 5077 D3 8C OUT (SD_LBA2),A -0100 5079 -0101 5079 CD A7 50 call writehst -0102 507C -0103 507C 3A E6 50 LD A,(secNo) -0104 507F 3C INC A -0105 5080 32 E6 50 LD (secNo),A -0106 5083 FE 20 CP $20 -0107 5085 20 E7 JR NZ, processSector -0108 5087 -0109 5087 19 ADD HL,DE -0110 5088 -0111 5088 05 DEC B -0112 5089 20 D6 JR NZ,processDirs -0113 508B -0114 508B CD D5 50 CALL printInline -0115 508E 0D 0A .DB CR,LF -0116 5090 466F726D6174 .TEXT "Formatting complete" -0116 5096 74696E6720636F6D706C657465 -0117 50A3 0D 0A 00 .DB CR,LF,0 -0118 50A6 -0119 50A6 C9 RET -0120 50A7 -0121 50A7 ;================================================================================================ -0122 50A7 ; Write physical sector to host -0123 50A7 ;================================================================================================ -0124 50A7 -0125 50A7 writehst: -0126 50A7 F5 PUSH AF -0127 50A8 C5 PUSH BC -0128 50A9 E5 PUSH HL -0129 50AA -0130 50AA DB 89 wrWait1: IN A,(SD_STATUS) -0131 50AC FE 80 CP 128 -0132 50AE 20 FA JR NZ,wrWait1 -0133 50B0 -0134 50B0 ;CALL setLBAaddr -0135 50B0 -0136 50B0 3E 01 LD A,$01 ; 01 = Write block -0137 50B2 D3 89 OUT (SD_CONTROL),A -0138 50B4 -0139 50B4 0E 04 LD c,4 -0140 50B6 wr4secs: -0141 50B6 21 E8 50 LD HL,dirData -0142 50B9 06 80 LD b,128 -0143 50BB wrByte: -0144 50BB DB 89 wrWait2: IN A,(SD_STATUS) -0145 50BD FE A0 CP 160 ; Write buffer empty -0146 50BF 20 FA JR NZ,wrWait2 -0147 50C1 -0148 50C1 ;LD A,'.' -0149 50C1 ;RST 08H -0150 50C1 -0151 50C1 ; UPDATE S0urceror, inserted wait cycle between IN and OUT -0152 50C1 ; to resolve unknown write issue in sd_controller.vhd in combination -0153 50C1 ; with MISTer virtual SD interface sys/sd_card.sv -0154 50C1 ; which results in hangs or write errors. -0155 50C1 C5 push bc -0156 50C2 06 32 ld b,50 -0157 50C4 _again: -0158 50C4 10 FE djnz _again -0159 50C6 C1 pop bc -0160 50C7 ; END UPDATE -0161 50C7 -0162 50C7 7E LD A,(HL) -0163 50C8 D3 88 OUT (SD_DATA),A -0164 50CA -0165 50CA 23 INC HL -0166 50CB 05 dec b -0167 50CC 20 ED JR NZ, wrByte -0168 50CE -0169 50CE 0D dec c -0170 50CF 20 E5 JR NZ,wr4secs -0171 50D1 -0172 50D1 E1 POP HL -0173 50D2 C1 POP BC -0174 50D3 F1 POP AF -0175 50D4 -0176 50D4 ;XOR a -0177 50D4 ;ld (erflag),a -0178 50D4 C9 RET -0179 50D5 -0180 50D5 ;================================================================================================ -0181 50D5 ; Utilities -0182 50D5 ;================================================================================================ -0183 50D5 -0184 50D5 printInline: -0185 50D5 E3 EX (SP),HL ; PUSH HL and put RET ADDress into HL -0186 50D6 F5 PUSH AF -0187 50D7 C5 PUSH BC -0188 50D8 7E nextILChar: LD A,(HL) -0189 50D9 FE 00 CP 0 -0190 50DB 28 04 JR Z,endOfPrint -0191 50DD CF RST 08H -0192 50DE 23 INC HL -0193 50DF 18 F7 JR nextILChar -0194 50E1 23 endOfPrint: INC HL ; Get past "null" terminator -0195 50E2 C1 POP BC -0196 50E3 F1 POP AF -0197 50E4 E3 EX (SP),HL ; PUSH new RET ADDress on stack and restore HL -0198 50E5 C9 RET -0199 50E6 -0200 50E6 -0201 50E6 00 secNo .db 0 -0202 50E7 00 drvName .db 0 -0203 50E8 -0204 50E8 -0205 50E8 ; Directory data for 1 x 128 byte sector -0206 50E8 dirData: -0207 50E8 E52020202020 .DB $E5,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,$00 -0207 50EE 20202020202000000000 -0208 50F8 000000000000 .DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -0208 50FE 00000000000000000000 -0209 5108 -0210 5108 E52020202020 .DB $E5,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,$00 -0210 510E 20202020202000000000 -0211 5118 000000000000 .DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -0211 511E 00000000000000000000 -0212 5128 -0213 5128 E52020202020 .DB $E5,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,$00 -0213 512E 20202020202000000000 -0214 5138 000000000000 .DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -0214 513E 00000000000000000000 -0215 5148 -0216 5148 E52020202020 .DB $E5,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,$00 -0216 514E 20202020202000000000 -0217 5158 000000000000 .DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 -0217 515E 00000000000000000000 -0218 5168 -0219 5168 .END -tasm: Number of errors = 0 +0001 0000 ;================================================================================== +0002 0000 ; Contents of this file are copyright Grant Searle +0003 0000 ; +0004 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY +0005 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. +0006 0000 ; +0007 0000 ; http://searle.hostei.com/grant/index.html +0008 0000 ; +0009 0000 ; eMail: home.micros01@btinternet.com +0010 0000 ; +0011 0000 ; If the above don't work, please perform an Internet search to see if I have +0012 0000 ; updated the web page hosting service. +0013 0000 ; +0014 0000 ;================================================================================== +0015 0000 +0016 0000 numDrives .EQU 15 ; Not including A: +0017 0000 +0018 0000 +0019 0000 SD_DATA .EQU 088H +0020 0000 SD_CONTROL .EQU 089H +0021 0000 SD_STATUS .EQU 089H +0022 0000 SD_LBA0 .EQU 08AH +0023 0000 SD_LBA1 .EQU 08BH +0024 0000 SD_LBA2 .EQU 08CH +0025 0000 +0026 0000 LF .EQU 0AH ;line feed +0027 0000 FF .EQU 0CH ;form feed +0028 0000 CR .EQU 0DH ;carriage RETurn +0029 0000 +0030 0000 ;==================================================================================== +0031 0000 +0032 5000 .ORG 5000H ; Format program origin. +0033 5000 +0034 5000 +0035 5000 CD D5 50 CALL printInline +0036 5003 43 50 2F 4D .TEXT "CP/M Formatter 2.0 by G. Searle 2013" +0036 5007 20 46 6F 72 +0036 500B 6D 61 74 74 +0036 500F 65 72 20 32 +0036 5013 2E 30 20 62 +0036 5017 79 20 47 2E +0036 501B 20 53 65 61 +0036 501F 72 6C 65 20 +0036 5023 32 30 31 33 +0037 5027 0D 0A 00 .DB CR,LF,0 +0038 502A +0039 502A 3E 41 LD A,'A' +0040 502C 32 E7 50 LD (drvName),A +0041 502F +0042 502F ; There are 512 directory entries per disk, 4 DIR entries per sector +0043 502F ; So 128 x 128 byte sectors are to be initialised +0044 502F ; The drive uses 512 byte sectors, so 32 x 512 byte sectors per disk +0045 502F ; require initialisation +0046 502F +0047 502F ;Drive 0 (A:) is slightly different due to reserved track, so DIR sector starts at 32 +0048 502F 3A E7 50 LD A,(drvName) +0049 5032 CF RST 08H ; Print drive letter +0050 5033 3C INC A +0051 5034 32 E7 50 LD (drvName),A +0052 5037 +0053 5037 3E 20 LD A,$20 +0054 5039 32 E6 50 LD (secNo),A +0055 503C +0056 503C processSectorA: +0057 503C +0058 503C 3A E6 50 LD A,(secNo) +0059 503F D3 8A OUT (SD_LBA0),A +0060 5041 3E 00 LD A,0 +0061 5043 D3 8B OUT (SD_LBA1),A +0062 5045 3E 00 LD A,0 +0063 5047 D3 8C OUT (SD_LBA2),A +0064 5049 3E E0 LD a,$E0 +0065 504B +0066 504B CD A7 50 call writehst +0067 504E +0068 504E 3A E6 50 LD A,(secNo) +0069 5051 3C INC A +0070 5052 32 E6 50 LD (secNo),A +0071 5055 FE 40 CP $40 +0072 5057 20 E3 JR NZ, processSectorA +0073 5059 +0074 5059 +0075 5059 +0076 5059 ;Drive 1 onwards (B: etc) don't have reserved tracks, so sector starts at 0 +0077 5059 +0078 5059 11 40 00 LD DE,$0040 ; HL increment +0079 505C 21 40 00 LD HL,$0040 ; H = LBA2, L=LBA1, initialise for drive 1 (B:) +0080 505F +0081 505F 06 0F LD B,numDrives +0082 5061 +0083 5061 processDirs: +0084 5061 +0085 5061 3A E7 50 LD A,(drvName) +0086 5064 CF RST 08H ; Print drive letter +0087 5065 3C INC A +0088 5066 32 E7 50 LD (drvName),A +0089 5069 +0090 5069 3E 00 LD A,0 +0091 506B 32 E6 50 LD (secNo),A +0092 506E +0093 506E processSector: +0094 506E 3A E6 50 LD A,(secNo) +0095 5071 D3 8A OUT (SD_LBA0),A +0096 5073 7D LD A,L +0097 5074 D3 8B OUT (SD_LBA1),A +0098 5076 7C LD A,H +0099 5077 D3 8C OUT (SD_LBA2),A +0100 5079 +0101 5079 CD A7 50 call writehst +0102 507C +0103 507C 3A E6 50 LD A,(secNo) +0104 507F 3C INC A +0105 5080 32 E6 50 LD (secNo),A +0106 5083 FE 20 CP $20 +0107 5085 20 E7 JR NZ, processSector +0108 5087 +0109 5087 19 ADD HL,DE +0110 5088 +0111 5088 05 DEC B +0112 5089 20 D6 JR NZ,processDirs +0113 508B +0114 508B CD D5 50 CALL printInline +0115 508E 0D 0A .DB CR,LF +0116 5090 46 6F 72 6D .TEXT "Formatting complete" +0116 5094 61 74 74 69 +0116 5098 6E 67 20 63 +0116 509C 6F 6D 70 6C +0116 50A0 65 74 65 +0117 50A3 0D 0A 00 .DB CR,LF,0 +0118 50A6 +0119 50A6 C9 RET +0120 50A7 +0121 50A7 ;================================================================================================ +0122 50A7 ; Write physical sector to host +0123 50A7 ;================================================================================================ +0124 50A7 +0125 50A7 writehst: +0126 50A7 F5 PUSH AF +0127 50A8 C5 PUSH BC +0128 50A9 E5 PUSH HL +0129 50AA +0130 50AA DB 89 wrWait1: IN A,(SD_STATUS) +0131 50AC FE 80 CP 128 +0132 50AE 20 FA JR NZ,wrWait1 +0133 50B0 +0134 50B0 ;CALL setLBAaddr +0135 50B0 +0136 50B0 3E 01 LD A,$01 ; 01 = Write block +0137 50B2 D3 89 OUT (SD_CONTROL),A +0138 50B4 +0139 50B4 0E 04 LD c,4 +0140 50B6 wr4secs: +0141 50B6 21 E8 50 LD HL,dirData +0142 50B9 06 80 LD b,128 +0143 50BB wrByte: +0144 50BB DB 89 wrWait2: IN A,(SD_STATUS) +0145 50BD FE A0 CP 160 ; Write buffer empty +0146 50BF 20 FA JR NZ,wrWait2 +0147 50C1 +0148 50C1 ;LD A,'.' +0149 50C1 ;RST 08H +0150 50C1 +0151 50C1 ; UPDATE S0urceror, inserted wait cycle between IN and OUT +0152 50C1 ; to resolve unknown write issue in sd_controller.vhd in combination +0153 50C1 ; with MISTer virtual SD interface sys/sd_card.sv +0154 50C1 ; which results in hangs or write errors. +0155 50C1 C5 push bc +0156 50C2 06 32 ld b,50 +0157 50C4 _again: +0158 50C4 10 FE djnz _again +0159 50C6 C1 pop bc +0160 50C7 ; END UPDATE +0161 50C7 +0162 50C7 7E LD A,(HL) +0163 50C8 D3 88 OUT (SD_DATA),A +0164 50CA +0165 50CA 23 INC HL +0166 50CB 05 dec b +0167 50CC 20 ED JR NZ, wrByte +0168 50CE +0169 50CE 0D dec c +0170 50CF 20 E5 JR NZ,wr4secs +0171 50D1 +0172 50D1 E1 POP HL +0173 50D2 C1 POP BC +0174 50D3 F1 POP AF +0175 50D4 +0176 50D4 ;XOR a +0177 50D4 ;ld (erflag),a +0178 50D4 C9 RET +0179 50D5 +0180 50D5 ;================================================================================================ +0181 50D5 ; Utilities +0182 50D5 ;================================================================================================ +0183 50D5 +0184 50D5 printInline: +0185 50D5 E3 EX (SP),HL ; PUSH HL and put RET ADDress into HL +0186 50D6 F5 PUSH AF +0187 50D7 C5 PUSH BC +0188 50D8 7E nextILChar: LD A,(HL) +0189 50D9 FE 00 CP 0 +0190 50DB 28 04 JR Z,endOfPrint +0191 50DD CF RST 08H +0192 50DE 23 INC HL +0193 50DF 18 F7 JR nextILChar +0194 50E1 23 endOfPrint: INC HL ; Get past "null" terminator +0195 50E2 C1 POP BC +0196 50E3 F1 POP AF +0197 50E4 E3 EX (SP),HL ; PUSH new RET ADDress on stack and restore HL +0198 50E5 C9 RET +0199 50E6 +0200 50E6 +0201 50E6 00 secNo .db 0 +0202 50E7 00 drvName .db 0 +0203 50E8 +0204 50E8 +0205 50E8 ; Directory data for 1 x 128 byte sector +0206 50E8 dirData: +0207 50E8 E5 20 20 20 .DB $E5,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,$00 +0207 50EC 20 20 20 20 +0207 50F0 20 20 20 20 +0207 50F4 00 00 00 00 +0208 50F8 00 00 00 00 .DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 +0208 50FC 00 00 00 00 +0208 5100 00 00 00 00 +0208 5104 00 00 00 00 +0209 5108 +0210 5108 E5 20 20 20 .DB $E5,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,$00 +0210 510C 20 20 20 20 +0210 5110 20 20 20 20 +0210 5114 00 00 00 00 +0211 5118 00 00 00 00 .DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 +0211 511C 00 00 00 00 +0211 5120 00 00 00 00 +0211 5124 00 00 00 00 +0212 5128 +0213 5128 E5 20 20 20 .DB $E5,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,$00 +0213 512C 20 20 20 20 +0213 5130 20 20 20 20 +0213 5134 00 00 00 00 +0214 5138 00 00 00 00 .DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 +0214 513C 00 00 00 00 +0214 5140 00 00 00 00 +0214 5144 00 00 00 00 +0215 5148 +0216 5148 E5 20 20 20 .DB $E5,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$00,$00,$00,$00 +0216 514C 20 20 20 20 +0216 5150 20 20 20 20 +0216 5154 00 00 00 00 +0217 5158 00 00 00 00 .DB $00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00 +0217 515C 00 00 00 00 +0217 5160 00 00 00 00 +0217 5164 00 00 00 00 +0218 5168 +0219 5168 .END +0220 5168 tasm: Number of errors = 0 diff --git a/Z80 CPM and bootloader (basmon)/source/PUTSYS.LST b/Z80 CPM and bootloader (basmon)/source/PUTSYS.LST index 8f755bc..3db955d 100644 --- a/Z80 CPM and bootloader (basmon)/source/PUTSYS.LST +++ b/Z80 CPM and bootloader (basmon)/source/PUTSYS.LST @@ -1,166 +1,179 @@ -0001 0000 ;================================================================================== -0002 0000 ; Contents of this file are copyright Grant Searle -0003 0000 ; -0004 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY -0005 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. -0006 0000 ; -0007 0000 ; http://searle.hostei.com/grant/index.html -0008 0000 ; -0009 0000 ; eMail: home.micros01@btinternet.com -0010 0000 ; -0011 0000 ; If the above don't work, please perform an Internet search to see if I have -0012 0000 ; updated the web page hosting service. -0013 0000 ; -0014 0000 ;================================================================================== -0015 0000 -0016 0000 loadAddr .EQU 0D000h -0017 0000 numSecs .EQU 24 ; Number of 512 sectors to be loaded -0018 0000 -0019 0000 SD_DATA .EQU 088H -0020 0000 SD_CONTROL .EQU 089H -0021 0000 SD_STATUS .EQU 089H -0022 0000 SD_LBA0 .EQU 08AH -0023 0000 SD_LBA1 .EQU 08BH -0024 0000 SD_LBA2 .EQU 08CH -0025 0000 -0026 0000 LF .EQU 0AH ;line feed -0027 0000 FF .EQU 0CH ;form feed -0028 0000 CR .EQU 0DH ;carriage RETurn -0029 0000 -0030 0000 ;================================================================================================ -0031 0000 -0032 5000 .ORG 5000H ; Loader origin. -0033 5000 -0034 5000 CD BA 50 CALL printInline -0035 5003 43502F4D2053 .TEXT "CP/M System Transfer by G. Searle 2012-13" -0035 5009 797374656D205472616E7366657220627920472E20536561726C6520323031322D3133 -0036 502C 0D 0A 00 .DB CR,LF,0 -0037 502F -0038 502F 06 18 LD B,numSecs -0039 5031 -0040 5031 3E 00 LD A,0 -0041 5033 32 CB 50 LD (lba0),A -0042 5036 32 CC 50 ld (lba1),A -0043 5039 32 CD 50 ld (lba2),A -0044 503C 32 CE 50 ld (lba3),A -0045 503F 21 00 D0 LD HL,loadAddr -0046 5042 22 CF 50 LD (dmaAddr),HL -0047 5045 processSectors: -0048 5045 -0049 5045 CD 8C 50 call writehst -0050 5048 -0051 5048 11 00 02 LD DE,0200H -0052 504B 2A CF 50 LD HL,(dmaAddr) -0053 504E 19 ADD HL,DE -0054 504F 22 CF 50 LD (dmaAddr),HL -0055 5052 3A CB 50 LD A,(lba0) -0056 5055 3C INC A -0057 5056 32 CB 50 LD (lba0),A -0058 5059 -0059 5059 10 EA djnz processSectors -0060 505B -0061 505B CD BA 50 CALL printInline -0062 505E 0D 0A .DB CR,LF -0063 5060 53797374656D .TEXT "System transfer complete" -0063 5066 207472616E7366657220636F6D706C657465 -0064 5078 0D 0A 00 .DB CR,LF,0 -0065 507B -0066 507B C9 RET -0067 507C -0068 507C ; ========================================================================= -0069 507C ; Disk routines as used in CBIOS -0070 507C ; ========================================================================= -0071 507C setLBAaddr: -0072 507C 3A CD 50 LD A,(lba2) -0073 507F D3 8C OUT (SD_LBA2),A -0074 5081 3A CC 50 LD A,(lba1) -0075 5084 D3 8B OUT (SD_LBA1),A -0076 5086 3A CB 50 LD A,(lba0) -0077 5089 D3 8A OUT (SD_LBA0),A -0078 508B C9 ret -0079 508C -0080 508C ;================================================================================================ -0081 508C ; Write physical sector to host -0082 508C ;================================================================================================ -0083 508C -0084 508C writehst: -0085 508C F5 PUSH AF -0086 508D C5 PUSH BC -0087 508E E5 PUSH HL -0088 508F -0089 508F DB 89 wrWait1: IN A,(SD_STATUS) -0090 5091 FE 80 CP 128 -0091 5093 20 FA JR NZ,wrWait1 -0092 5095 -0093 5095 CD 7C 50 CALL setLBAaddr -0094 5098 -0095 5098 3E 01 LD A,$01 ; 01 = Write block -0096 509A D3 89 OUT (SD_CONTROL),A -0097 509C -0098 509C 0E 04 LD c,4 -0099 509E ;LD HL,hstbuf -0100 509E wr4secs: -0101 509E 06 80 LD b,128 -0102 50A0 wrByte: -0103 50A0 -0104 50A0 DB 89 wrWait2: IN A,(SD_STATUS) -0105 50A2 FE A0 CP 160 ; Write buffer empty -0106 50A4 20 FA JR NZ,wrWait2 -0107 50A6 -0108 50A6 ; UPDATE S0urceror, inserted wait cycle between IN and OUT -0109 50A6 ; to resolve unknown write issue in sd_controller.vhd in combination -0110 50A6 ; with MISTer virtual SD interface sys/sd_card.sv -0111 50A6 ; which results in hangs or write errors. -0112 50A6 C5 push bc -0113 50A7 06 32 ld b,50 -0114 50A9 _again: -0115 50A9 10 FE djnz _again -0116 50AB C1 pop bc -0117 50AC ; END UPDATE -0118 50AC -0119 50AC 7E LD A,(HL) -0120 50AD D3 88 OUT (SD_DATA),A -0121 50AF 23 INC HL -0122 50B0 05 dec b -0123 50B1 20 ED JR NZ, wrByte -0124 50B3 -0125 50B3 0D dec c -0126 50B4 20 E8 JR NZ,wr4secs -0127 50B6 -0128 50B6 E1 POP HL -0129 50B7 C1 POP BC -0130 50B8 F1 POP AF -0131 50B9 -0132 50B9 ;XOR a -0133 50B9 ;ld (erflag),a -0134 50B9 C9 RET -0135 50BA -0136 50BA -0137 50BA ;================================================================================================ -0138 50BA ; Utilities -0139 50BA ;================================================================================================ -0140 50BA -0141 50BA printInline: -0142 50BA E3 EX (SP),HL ; PUSH HL and put RET ADDress into HL -0143 50BB F5 PUSH AF -0144 50BC C5 PUSH BC -0145 50BD 7E nextILChar: LD A,(HL) -0146 50BE FE 00 CP 0 -0147 50C0 28 04 JR Z,endOfPrint -0148 50C2 CF RST 08H -0149 50C3 23 INC HL -0150 50C4 18 F7 JR nextILChar -0151 50C6 23 endOfPrint: INC HL ; Get past "null" terminator -0152 50C7 C1 POP BC -0153 50C8 F1 POP AF -0154 50C9 E3 EX (SP),HL ; PUSH new RET ADDress on stack and restore HL -0155 50CA C9 RET -0156 50CB -0157 50CB 00 lba0 .DB 00h -0158 50CC 00 lba1 .DB 00h -0159 50CD 00 lba2 .DB 00h -0160 50CE 00 lba3 .DB 00h -0161 50CF 00 00 dmaAddr .dw 0 -0162 50D1 -0163 50D1 .END -tasm: Number of errors = 0 +0001 0000 ;================================================================================== +0002 0000 ; Contents of this file are copyright Grant Searle +0003 0000 ; +0004 0000 ; You have permission to use this for NON COMMERCIAL USE ONLY +0005 0000 ; If you wish to use it elsewhere, please include an acknowledgement to myself. +0006 0000 ; +0007 0000 ; http://searle.hostei.com/grant/index.html +0008 0000 ; +0009 0000 ; eMail: home.micros01@btinternet.com +0010 0000 ; +0011 0000 ; If the above don't work, please perform an Internet search to see if I have +0012 0000 ; updated the web page hosting service. +0013 0000 ; +0014 0000 ;================================================================================== +0015 0000 +0016 0000 loadAddr .EQU 0D000h +0017 0000 numSecs .EQU 24 ; Number of 512 sectors to be loaded +0018 0000 +0019 0000 SD_DATA .EQU 088H +0020 0000 SD_CONTROL .EQU 089H +0021 0000 SD_STATUS .EQU 089H +0022 0000 SD_LBA0 .EQU 08AH +0023 0000 SD_LBA1 .EQU 08BH +0024 0000 SD_LBA2 .EQU 08CH +0025 0000 +0026 0000 LF .EQU 0AH ;line feed +0027 0000 FF .EQU 0CH ;form feed +0028 0000 CR .EQU 0DH ;carriage RETurn +0029 0000 +0030 0000 ;================================================================================================ +0031 0000 +0032 5000 .ORG 5000H ; Loader origin. +0033 5000 +0034 5000 CD BA 50 CALL printInline +0035 5003 43 50 2F 4D .TEXT "CP/M System Transfer by G. Searle 2012-13" +0035 5007 20 53 79 73 +0035 500B 74 65 6D 20 +0035 500F 54 72 61 6E +0035 5013 73 66 65 72 +0035 5017 20 62 79 20 +0035 501B 47 2E 20 53 +0035 501F 65 61 72 6C +0035 5023 65 20 32 30 +0035 5027 31 32 2D 31 +0035 502B 33 +0036 502C 0D 0A 00 .DB CR,LF,0 +0037 502F +0038 502F 06 18 LD B,numSecs +0039 5031 +0040 5031 3E 00 LD A,0 +0041 5033 32 CB 50 LD (lba0),A +0042 5036 32 CC 50 ld (lba1),A +0043 5039 32 CD 50 ld (lba2),A +0044 503C 32 CE 50 ld (lba3),A +0045 503F 21 00 D0 LD HL,loadAddr +0046 5042 22 CF 50 LD (dmaAddr),HL +0047 5045 processSectors: +0048 5045 +0049 5045 CD 8C 50 call writehst +0050 5048 +0051 5048 11 00 02 LD DE,0200H +0052 504B 2A CF 50 LD HL,(dmaAddr) +0053 504E 19 ADD HL,DE +0054 504F 22 CF 50 LD (dmaAddr),HL +0055 5052 3A CB 50 LD A,(lba0) +0056 5055 3C INC A +0057 5056 32 CB 50 LD (lba0),A +0058 5059 +0059 5059 10 EA djnz processSectors +0060 505B +0061 505B CD BA 50 CALL printInline +0062 505E 0D 0A .DB CR,LF +0063 5060 53 79 73 74 .TEXT "System transfer complete" +0063 5064 65 6D 20 74 +0063 5068 72 61 6E 73 +0063 506C 66 65 72 20 +0063 5070 63 6F 6D 70 +0063 5074 6C 65 74 65 +0064 5078 0D 0A 00 .DB CR,LF,0 +0065 507B +0066 507B C9 RET +0067 507C +0068 507C ; ========================================================================= +0069 507C ; Disk routines as used in CBIOS +0070 507C ; ========================================================================= +0071 507C setLBAaddr: +0072 507C 3A CD 50 LD A,(lba2) +0073 507F D3 8C OUT (SD_LBA2),A +0074 5081 3A CC 50 LD A,(lba1) +0075 5084 D3 8B OUT (SD_LBA1),A +0076 5086 3A CB 50 LD A,(lba0) +0077 5089 D3 8A OUT (SD_LBA0),A +0078 508B C9 ret +0079 508C +0080 508C ;================================================================================================ +0081 508C ; Write physical sector to host +0082 508C ;================================================================================================ +0083 508C +0084 508C writehst: +0085 508C F5 PUSH AF +0086 508D C5 PUSH BC +0087 508E E5 PUSH HL +0088 508F +0089 508F DB 89 wrWait1: IN A,(SD_STATUS) +0090 5091 FE 80 CP 128 +0091 5093 20 FA JR NZ,wrWait1 +0092 5095 +0093 5095 CD 7C 50 CALL setLBAaddr +0094 5098 +0095 5098 3E 01 LD A,$01 ; 01 = Write block +0096 509A D3 89 OUT (SD_CONTROL),A +0097 509C +0098 509C 0E 04 LD c,4 +0099 509E ;LD HL,hstbuf +0100 509E wr4secs: +0101 509E 06 80 LD b,128 +0102 50A0 wrByte: +0103 50A0 +0104 50A0 DB 89 wrWait2: IN A,(SD_STATUS) +0105 50A2 FE A0 CP 160 ; Write buffer empty +0106 50A4 20 FA JR NZ,wrWait2 +0107 50A6 +0108 50A6 ; UPDATE S0urceror, inserted wait cycle between IN and OUT +0109 50A6 ; to resolve unknown write issue in sd_controller.vhd in combination +0110 50A6 ; with MISTer virtual SD interface sys/sd_card.sv +0111 50A6 ; which results in hangs or write errors. +0112 50A6 C5 push bc +0113 50A7 06 32 ld b,50 +0114 50A9 _again: +0115 50A9 10 FE djnz _again +0116 50AB C1 pop bc +0117 50AC ; END UPDATE +0118 50AC +0119 50AC 7E LD A,(HL) +0120 50AD D3 88 OUT (SD_DATA),A +0121 50AF 23 INC HL +0122 50B0 05 dec b +0123 50B1 20 ED JR NZ, wrByte +0124 50B3 +0125 50B3 0D dec c +0126 50B4 20 E8 JR NZ,wr4secs +0127 50B6 +0128 50B6 E1 POP HL +0129 50B7 C1 POP BC +0130 50B8 F1 POP AF +0131 50B9 +0132 50B9 ;XOR a +0133 50B9 ;ld (erflag),a +0134 50B9 C9 RET +0135 50BA +0136 50BA +0137 50BA ;================================================================================================ +0138 50BA ; Utilities +0139 50BA ;================================================================================================ +0140 50BA +0141 50BA printInline: +0142 50BA E3 EX (SP),HL ; PUSH HL and put RET ADDress into HL +0143 50BB F5 PUSH AF +0144 50BC C5 PUSH BC +0145 50BD 7E nextILChar: LD A,(HL) +0146 50BE FE 00 CP 0 +0147 50C0 28 04 JR Z,endOfPrint +0148 50C2 CF RST 08H +0149 50C3 23 INC HL +0150 50C4 18 F7 JR nextILChar +0151 50C6 23 endOfPrint: INC HL ; Get past "null" terminator +0152 50C7 C1 POP BC +0153 50C8 F1 POP AF +0154 50C9 E3 EX (SP),HL ; PUSH new RET ADDress on stack and restore HL +0155 50CA C9 RET +0156 50CB +0157 50CB 00 lba0 .DB 00h +0158 50CC 00 lba1 .DB 00h +0159 50CD 00 lba2 .DB 00h +0160 50CE 00 lba3 .DB 00h +0161 50CF 00 00 dmaAddr .dw 0 +0162 50D1 +0163 50D1 .END +tasm: Number of errors = 0 diff --git a/Z80 CPM and bootloader (basmon)/source/cbios128.asm b/Z80 CPM and bootloader (basmon)/source/cbios128.asm index 7110247..ce43c2e 100644 --- a/Z80 CPM and bootloader (basmon)/source/cbios128.asm +++ b/Z80 CPM and bootloader (basmon)/source/cbios128.asm @@ -710,45 +710,78 @@ setLBAaddr: ;================================================================================================ readhst: - PUSH AF - PUSH BC - PUSH HL + PUSH AF + PUSH BC + PUSH HL -rdWait1: IN A,(SD_STATUS) - CP 128 - JR NZ,rdWait1 - - CALL setLBAaddr - - LD A,$00 ; 00 = Read block - OUT (SD_CONTROL),A +rdWait1: IN A,(SD_STATUS) + CP 128 ; Check for ready status + JR NZ,rdWait1 - LD c,4 - LD HL,hstbuf + ; Add multiple status checks before starting read + LD B,3 ; Check status 3 times +rdCheck1: + IN A,(SD_STATUS) + CP 128 + JR NZ,rdCheck1 + DJNZ rdCheck1 + + CALL setLBAaddr + + LD A,$00 ; 00 = Read block + OUT (SD_CONTROL),A + + LD c,4 + LD HL,hstbuf rd4secs: - LD b,128 + LD b,128 rdByte: -rdWait2: IN A,(SD_STATUS) - CP 224 ; Read byte waiting - JR NZ,rdWait2 +rdWait2: IN A,(SD_STATUS) + CP 224 ; Read byte waiting + JR NZ,rdWait2 - IN A,(SD_DATA) + ; Add extra validation checks before each read + PUSH BC ; Save main counters + LD B,2 ; Check status twice +rdCheck2: + IN A,(SD_STATUS) + CP 224 + JR NZ,rdCheck2 + DJNZ rdCheck2 + POP BC ; Restore main counters - LD (HL),A - INC HL - dec b - JR NZ, rdByte - dec c - JR NZ,rd4secs + IN A,(SD_DATA) - POP HL - POP BC - POP AF + ; Add small delay after read before store + PUSH BC + LD B,10 +rdDelay: + DJNZ rdDelay + POP BC - XOR a - ld (erflag),a - RET + LD (HL),A + INC HL + dec b + JR NZ, rdByte + dec c + JR NZ,rd4secs + + ; Add final wait before returning + LD B,0 +rdWaitFinal: + IN A,(SD_STATUS) + CP 128 ; Wait for ready status + JR NZ,rdWaitFinal + DJNZ rdWaitFinal + + POP HL + POP BC + POP AF + + XOR a + ld (erflag),a + RET ;================================================================================================ @@ -756,56 +789,63 @@ rdWait2: IN A,(SD_STATUS) ;================================================================================================ writehst: - PUSH AF - PUSH BC - PUSH HL + PUSH AF + PUSH BC + PUSH HL -wrWait1: IN A,(SD_STATUS) - CP 128 - JR NZ,wrWait1 +wrWait1: IN A,(SD_STATUS) + CP 128 + JR NZ,wrWait1 - CALL setLBAaddr - - LD A,$01 ; 01 = Write block - OUT (SD_CONTROL),A - - LD c,4 - LD HL,hstbuf + CALL setLBAaddr + + LD A,$01 ; 01 = Write block + OUT (SD_CONTROL),A + + LD c,4 + LD HL,hstbuf wr4secs: - LD b,128 + LD b,128 wrByte: - -wrWait2: IN A,(SD_STATUS) - CP 160 ; Write buffer empty - JR NZ,wrWait2 + +wrWait2: IN A,(SD_STATUS) + CP 160 ; Write buffer empty + JR NZ,wrWait2 - ; UPDATE S0urceror, inserted wait cycle between IN and OUT - ; to resolve unknown write issue in sd_controller.vhd in combination - ; with MISTer virtual SD interface sys/sd_card.sv - ; which results in hangs or write errors. - push bc - ld b,50 -_again: - djnz _again - pop bc - ; END UPDATE + ; Add multiple status checks before proceeding with write + PUSH BC ; Save main counters + LD B,3 ; Check status 3 times +wrCheck: + IN A,(SD_STATUS) + CP 160 + JR NZ,wrCheck + DJNZ wrCheck + POP BC ; Restore main counters - LD A,(HL) - OUT (SD_DATA),A - INC HL - dec b - JR NZ, wrByte + LD A,(HL) + OUT (SD_DATA),A + INC HL + dec b + JR NZ,wrByte - dec c - JR NZ,wr4secs + dec c + JR NZ,wr4secs - POP HL - POP BC - POP AF - - XOR a - ld (erflag),a - RET + ; Add final wait before returning + LD B,0 +wrWaitFinal: + IN A,(SD_STATUS) + CP 128 ; Wait for ready status + JR NZ,wrWaitFinal + DJNZ wrWaitFinal + + POP HL + POP BC + POP AF + + XOR a + ld (erflag),a + RET ;================================================================================================ ; Utilities diff --git a/Z80 CPM and bootloader (basmon)/source/mon.asm b/Z80 CPM and bootloader (basmon)/source/mon.asm index 81f0c86..6fd30d9 100644 --- a/Z80 CPM and bootloader (basmon)/source/mon.asm +++ b/Z80 CPM and bootloader (basmon)/source/mon.asm @@ -589,45 +589,75 @@ setLBAaddr: ;================================================================================================ readhst: - PUSH AF - PUSH BC - PUSH HL + PUSH AF + PUSH BC + PUSH HL -rdWait1: IN A,(SD_STATUS) - CP 128 - JR NZ,rdWait1 - - CALL setLBAaddr - - LD A,$00 ; 00 = Read block - OUT (SD_CONTROL),A +rdWait1: IN A,(SD_STATUS) + CP 128 ; Check for ready status + JR NZ,rdWait1 - LD c,4 -; LD HL,hstbuf + ; Add multiple status checks before starting read + LD B,3 ; Check status 3 times +rdCheck1: + IN A,(SD_STATUS) + CP 128 + JR NZ,rdCheck1 + DJNZ rdCheck1 + + CALL setLBAaddr + + LD A,$00 ; 00 = Read block + OUT (SD_CONTROL),A + + LD c,4 rd4secs: - LD b,128 + LD b,128 rdByte: -rdWait2: IN A,(SD_STATUS) - CP 224 ; Read byte waiting - JR NZ,rdWait2 +rdWait2: IN A,(SD_STATUS) + CP 224 ; Read byte waiting + JR NZ,rdWait2 - IN A,(SD_DATA) + ; Add extra validation checks before each read + PUSH BC ; Save main counters + LD B,2 ; Check status twice +rdCheck2: + IN A,(SD_STATUS) + CP 224 + JR NZ,rdCheck2 + DJNZ rdCheck2 + POP BC ; Restore main counters - LD (HL),A - INC HL - dec b - JR NZ, rdByte - dec c - JR NZ,rd4secs + IN A,(SD_DATA) - POP HL - POP BC - POP AF + ; Add small delay after read before store + PUSH BC + LD B,10 +rdDelay: + DJNZ rdDelay + POP BC -; XOR a -; ld (erflag),a - RET + LD (HL),A + INC HL + dec b + JR NZ, rdByte + dec c + JR NZ,rd4secs + + ; Add final wait before returning + LD B,0 +rdWaitFinal: + IN A,(SD_STATUS) + CP 128 ; Wait for ready status + JR NZ,rdWaitFinal + DJNZ rdWaitFinal + + POP HL + POP BC + POP AF + + RET ;------------------------------------------------------------------------------ ; END OF ROUTINES AS USED IN BIOS diff --git a/Z80 CPM and bootloader (basmon)/source/mon.lst b/Z80 CPM and bootloader (basmon)/source/mon.lst index 69d66b0..addafc3 100644 --- a/Z80 CPM and bootloader (basmon)/source/mon.lst +++ b/Z80 CPM and bootloader (basmon)/source/mon.lst @@ -251,10 +251,10 @@ 0251 00AD ; Display the "Press space to start" message on both consoles 0252 00AD 3E 00 LD A,$00 0253 00AF 32 00 30 LD (primaryIO),A -0254 00B2 21 0E 03 LD HL,INITTXT +0254 00B2 21 34 03 LD HL,INITTXT 0255 00B5 CD 37 01 CALL M_PRINT 0256 00B8 ; On Display B we need to take care that it does not hang. -0257 00B8 21 0E 03 LD HL,INITTXT +0257 00B8 21 34 03 LD HL,INITTXT 0258 00BB 22 04 30 LD (InitTxtB),HL 0259 00BE 0260 00BE 2A 04 30 printInitB: LD HL,(InitTxtB) @@ -299,7 +299,7 @@ 0299 00FF 0300 00FF ; primaryIO is now set to the channel where SPACE was pressed 0301 00FF CD 3E 01 CALL TXCRLF ; TXCRLF -0302 0102 21 9C 02 LD HL,M_SIGNON ; Print SIGNON message +0302 0102 21 C2 02 LD HL,M_SIGNON ; Print SIGNON message 0303 0105 CD 37 01 CALL M_PRINT 0304 0108 0305 0108 ;------------------------------------------------------------------------------ @@ -490,11 +490,11 @@ 0490 01E6 A7 AND A ; Is it zero? 0491 01E7 C8 RET Z 0492 01E8 -0493 01E8 21 FD 02 LOADERR LD HL,CKSUMERR ; Get "Checksum Error" message +0493 01E8 21 23 03 LOADERR LD HL,CKSUMERR ; Get "Checksum Error" message 0494 01EB CD 37 01 CALL M_PRINT ; Print Message from (HL) and terminate the load 0495 01EE C9 RET 0496 01EF -0497 01EF 21 34 03 LOAD00 LD HL,LDETXT ; Print load complete message +0497 01EF 21 5A 03 LOAD00 LD HL,LDETXT ; Print load complete message 0498 01F2 CD 37 01 CALL M_PRINT 0499 01F5 C9 RET 0500 01F6 @@ -502,7 +502,7 @@ 0502 01F6 ; Start Interpreter 0503 01F6 ;------------------------------------------------------------------------------ 0504 01F6 INTERPRT -0505 01F6 C3 3F 03 JP STARTINT +0505 01F6 C3 65 03 JP STARTINT 0506 01F9 C9 RET 0507 01FA 0508 01FA ;------------------------------------------------------------------------------ @@ -593,4497 +593,4527 @@ 0589 0274 ;================================================================================================ 0590 0274 0591 0274 readhst: -0592 0274 F5 PUSH AF -0593 0275 C5 PUSH BC -0594 0276 E5 PUSH HL +0592 0274 F5 PUSH AF +0593 0275 C5 PUSH BC +0594 0276 E5 PUSH HL 0595 0277 -0596 0277 DB 89 rdWait1: IN A,(SD_STATUS) -0597 0279 FE 80 CP 128 -0598 027B 20 FA JR NZ,rdWait1 -0599 027D -0600 027D CD 64 02 CALL setLBAaddr -0601 0280 -0602 0280 3E 00 LD A,$00 ; 00 = Read block -0603 0282 D3 89 OUT (SD_CONTROL),A -0604 0284 -0605 0284 0E 04 LD c,4 -0606 0286 ; LD HL,hstbuf -0607 0286 rd4secs: -0608 0286 06 80 LD b,128 -0609 0288 rdByte: -0610 0288 -0611 0288 DB 89 rdWait2: IN A,(SD_STATUS) -0612 028A FE E0 CP 224 ; Read byte waiting -0613 028C 20 FA JR NZ,rdWait2 -0614 028E -0615 028E DB 88 IN A,(SD_DATA) -0616 0290 -0617 0290 77 LD (HL),A -0618 0291 23 INC HL -0619 0292 05 dec b -0620 0293 20 F3 JR NZ, rdByte -0621 0295 0D dec c -0622 0296 20 EE JR NZ,rd4secs -0623 0298 -0624 0298 E1 POP HL -0625 0299 C1 POP BC -0626 029A F1 POP AF -0627 029B -0628 029B ; XOR a -0629 029B ; ld (erflag),a -0630 029B C9 RET -0631 029C -0632 029C ;------------------------------------------------------------------------------ -0633 029C ; END OF ROUTINES AS USED IN BIOS -0634 029C ;------------------------------------------------------------------------------ -0635 029C -0636 029C -0637 029C 43 50 2F 4D M_SIGNON .BYTE "CP/M Boot ROM 2.0" -0637 02A0 20 42 6F 6F -0637 02A4 74 20 52 4F -0637 02A8 4D 20 32 2E -0637 02AC 30 -0638 02AD ; .BYTE " based on design by G. Searle" -0639 02AD ; .BYTE $0D,$0A -0640 02AD 0D 0A .BYTE $0D,$0A -0641 02AF 49 2D 53 74 .TEXT "I-Strt Intrp" -0641 02B3 72 74 20 49 -0641 02B7 6E 74 72 70 -0642 02BB 0D 0A .BYTE $0D,$0A -0643 02BD 58 2D 42 6F .TEXT "X-Boot CP/M" -0643 02C1 6F 74 20 43 -0643 02C5 50 2F 4D -0644 02C8 0D 0A .BYTE $0D,$0A -0645 02CA 3A 6E 6E 6E .TEXT ":nnnn-Load I rcrd" -0645 02CE 6E 2D 4C 6F -0645 02D2 61 64 20 49 -0645 02D6 20 72 63 72 -0645 02DA 64 -0646 02DB 0D 0A .BYTE $0D,$0A -0647 02DD 47 6E 6E 6E .TEXT "Gnnnn-R loc" -0647 02E1 6E 2D 52 20 -0647 02E5 6C 6F 63 -0648 02E8 0D 0A .BYTE $0D,$0A -0649 02EA 00 .BYTE $00 -0650 02EB -0651 02EB M_BASTXT -0652 02EB 0D 0A .BYTE $0D,$0A -0653 02ED 43 6F 6C 64 .TEXT "Cold or warm?" -0653 02F1 20 6F 72 20 -0653 02F5 77 61 72 6D -0653 02F9 3F -0654 02FA 0D 0A 00 .BYTE $0D,$0A,$00 -0655 02FD -0656 02FD 43 68 65 63 CKSUMERR .BYTE "Checksum error" -0656 0301 6B 73 75 6D -0656 0305 20 65 72 72 -0656 0309 6F 72 -0657 030B 0D 0A 00 .BYTE $0D,$0A,$00 -0658 030E -0659 030E INITTXT -0660 030E 0C .BYTE $0C -0661 030F 50 72 65 73 .TEXT "Press [space] to activate console." -0661 0313 73 20 5B 73 -0661 0317 70 61 63 65 -0661 031B 5D 20 74 6F -0661 031F 20 61 63 74 -0661 0323 69 76 61 74 -0661 0327 65 20 63 6F -0661 032B 6E 73 6F 6C -0661 032F 65 2E -0662 0331 0D 0A 00 .BYTE $0D,$0A, $00 -0663 0334 -0664 0334 LDETXT -0665 0334 43 6F 6D 70 .TEXT "Complete" -0665 0338 6C 65 74 65 -0666 033C 0D 0A 00 .BYTE $0D,$0A, $00 -0667 033F -0668 033F ; ========================================================================================================================== -0669 033F ; GENERAL EQUATES -0670 033F -0671 033F CTRLC .EQU 03H ; Control "C" -0672 033F CTRLG .EQU 07H ; Control "G" -0673 033F BKSP .EQU 08H ; Back space -0674 033F LF .EQU 0AH ; Line feed -0675 033F CS .EQU 0CH ; Clear screen -0676 033F CR .EQU 0DH ; Carriage return -0677 033F CTRLO .EQU 0FH ; Control "O" -0678 033F CTRLQ .EQU 11H ; Control "Q" -0679 033F CTRLR .EQU 12H ; Control "R" -0680 033F CTRLS .EQU 13H ; Control "S" -0681 033F CTRLU .EQU 15H ; Control "U" -0682 033F ESC .EQU 1BH ; Escape -0683 033F DEL .EQU 7FH ; Delete -0684 033F -0685 033F -0686 033F ;=========================================================================================================================== -0687 033F -0688 033F ; NASCOM ROM BASIC Ver 4.7, -0689 033F ; used to be here, removed to get rid of the '(C) 1978 Microsoft' -0690 033F -0691 033F STARTINT: -0692 033F #INCLUDE "SOURCE\\INTPRT.ASM" -0001+ 033F ;------------------------------------------------------------------------------ -0002+ 033F ; Start BASIC command -0003+ 033F ;------------------------------------------------------------------------------ -0004+ 033F BASIC -0005+ 033F 21 EB 02 LD HL,M_BASTXT -0006+ 0342 CD 37 01 CALL M_PRINT -0007+ 0345 CD 45 01 CALL M_GETCHR -0008+ 0348 C8 RET Z ; Cancel if CTRL-C -0009+ 0349 E6 5F AND $5F ; uppercase -0010+ 034B FE 43 CP 'C' -0011+ 034D CA 56 03 JP Z,COLD -0012+ 0350 FE 57 CP 'W' -0013+ 0352 CA 59 03 JP Z,WARM -0014+ 0355 C9 RET -0015+ 0356 -0016+ 0356 ; BASIC WORK SPACE LOCATIONS -0017+ 0356 -0018+ 0356 WRKSPC .EQU 30B0H ; BASIC Work space -0019+ 0356 USR .EQU WRKSPC+3H ; "USR (x)" jump -0020+ 0356 OUTSUB .EQU WRKSPC+6H ; "OUT p,n" -0021+ 0356 OTPORT .EQU WRKSPC+7H ; Port (p) -0022+ 0356 DIVSUP .EQU WRKSPC+9H ; Division support routine -0023+ 0356 DIV1 .EQU WRKSPC+0AH ; <- Values -0024+ 0356 DIV2 .EQU WRKSPC+0EH ; <- to -0025+ 0356 DIV3 .EQU WRKSPC+12H ; <- be -0026+ 0356 DIV4 .EQU WRKSPC+15H ; <-inserted -0027+ 0356 SEED .EQU WRKSPC+17H ; Random number seed -0028+ 0356 LSTRND .EQU WRKSPC+3AH ; Last random number -0029+ 0356 INPSUB .EQU WRKSPC+3EH ; #INP (x)" Routine -0030+ 0356 INPORT .EQU WRKSPC+3FH ; PORT (x) -0031+ 0356 NULLS .EQU WRKSPC+41H ; Number of nulls -0032+ 0356 LWIDTH .EQU WRKSPC+42H ; Terminal width -0033+ 0356 COMMAN .EQU WRKSPC+43H ; Width for commas -0034+ 0356 NULFLG .EQU WRKSPC+44H ; Null after input byte flag -0035+ 0356 CTLOFG .EQU WRKSPC+45H ; Control "O" flag -0036+ 0356 LINESC .EQU WRKSPC+46H ; Lines counter -0037+ 0356 LINESN .EQU WRKSPC+48H ; Lines number -0038+ 0356 CHKSUM .EQU WRKSPC+4AH ; Array load/save check sum -0039+ 0356 NMIFLG .EQU WRKSPC+4CH ; Flag for NMI break routine -0040+ 0356 BRKFLG .EQU WRKSPC+4DH ; Break flag -0041+ 0356 RINPUT .EQU WRKSPC+4EH ; Input reflection -0042+ 0356 POINT .EQU WRKSPC+51H ; "POINT" reflection (unused) -0043+ 0356 PSET .EQU WRKSPC+54H ; "SET" reflection -0044+ 0356 RESET .EQU WRKSPC+57H ; "RESET" reflection -0045+ 0356 STRSPC .EQU WRKSPC+5AH ; Bottom of string space -0046+ 0356 LINEAT .EQU WRKSPC+5CH ; Current line number -0047+ 0356 BASTXT .EQU WRKSPC+5EH ; Pointer to start of program -0048+ 0356 BUFFER .EQU WRKSPC+61H ; Input buffer -0049+ 0356 STACK .EQU WRKSPC+66H ; Initial stack -0050+ 0356 CURPOS .EQU WRKSPC+0ABH ; Character position on line -0051+ 0356 LCRFLG .EQU WRKSPC+0ACH ; Locate/Create flag -0052+ 0356 TYPE .EQU WRKSPC+0ADH ; Data type flag -0053+ 0356 DATFLG .EQU WRKSPC+0AEH ; Literal statement flag -0054+ 0356 LSTRAM .EQU WRKSPC+0AFH ; Last available RAM -0055+ 0356 TMSTPT .EQU WRKSPC+0B1H ; Temporary string pointer -0056+ 0356 TMSTPL .EQU WRKSPC+0B3H ; Temporary string pool -0057+ 0356 TMPSTR .EQU WRKSPC+0BFH ; Temporary string -0058+ 0356 STRBOT .EQU WRKSPC+0C3H ; Bottom of string space -0059+ 0356 CUROPR .EQU WRKSPC+0C5H ; Current operator in EVAL -0060+ 0356 LOOPST .EQU WRKSPC+0C7H ; First statement of loop -0061+ 0356 DATLIN .EQU WRKSPC+0C9H ; Line of current DATA item -0062+ 0356 FORFLG .EQU WRKSPC+0CBH ; "FOR" loop flag -0063+ 0356 LSTBIN .EQU WRKSPC+0CCH ; Last byte entered -0064+ 0356 READFG .EQU WRKSPC+0CDH ; Read/Input flag -0065+ 0356 BRKLIN .EQU WRKSPC+0CEH ; Line of break -0066+ 0356 NXTOPR .EQU WRKSPC+0D0H ; Next operator in EVAL -0067+ 0356 ERRLIN .EQU WRKSPC+0D2H ; Line of error -0068+ 0356 CONTAD .EQU WRKSPC+0D4H ; Where to CONTinue -0069+ 0356 PROGND .EQU WRKSPC+0D6H ; End of program -0070+ 0356 VAREND .EQU WRKSPC+0D8H ; End of variables -0071+ 0356 ARREND .EQU WRKSPC+0DAH ; End of arrays -0072+ 0356 NXTDAT .EQU WRKSPC+0DCH ; Next data item -0073+ 0356 FNRGNM .EQU WRKSPC+0DEH ; Name of FN argument -0074+ 0356 FNARG .EQU WRKSPC+0E0H ; FN argument value -0075+ 0356 FPREG .EQU WRKSPC+0E4H ; Floating point register -0076+ 0356 FPEXP .EQU FPREG+3 ; Floating point exponent -0077+ 0356 SGNRES .EQU WRKSPC+0E8H ; Sign of result -0078+ 0356 PBUFF .EQU WRKSPC+0E9H ; Number print buffer -0079+ 0356 MULVAL .EQU WRKSPC+0F6H ; Multiplier -0080+ 0356 PROGST .EQU WRKSPC+0F9H ; Start of program text area -0081+ 0356 STLOOK .EQU WRKSPC+15DH ; Start of memory test -0082+ 0356 -0083+ 0356 ; BASIC ERROR CODE VALUES -0084+ 0356 -0085+ 0356 NF .EQU 00H ; NEXT without FOR -0086+ 0356 SN .EQU 02H ; Syntax error -0087+ 0356 RG .EQU 04H ; RETURN without GOSUB -0088+ 0356 OD .EQU 06H ; Out of DATA -0089+ 0356 FC .EQU 08H ; Function call error -0090+ 0356 OV .EQU 0AH ; Overflow -0091+ 0356 OM .EQU 0CH ; Out of memory -0092+ 0356 UL .EQU 0EH ; Undefined line number -0093+ 0356 BS .EQU 10H ; Bad subscript -0094+ 0356 DD .EQU 12H ; Re-DIMensioned array -0095+ 0356 DZ .EQU 14H ; Division by zero (/0) -0096+ 0356 ID .EQU 16H ; Illegal direct -0097+ 0356 TM .EQU 18H ; Type miss-match -0098+ 0356 OS .EQU 1AH ; Out of string space -0099+ 0356 LS .EQU 1CH ; String too long -0100+ 0356 ST .EQU 1EH ; String formula too complex -0101+ 0356 CN .EQU 20H ; Can't CONTinue -0102+ 0356 UF .EQU 22H ; UnDEFined FN function -0103+ 0356 MO .EQU 24H ; Missing operand -0104+ 0356 HX .EQU 26H ; HEX error -0105+ 0356 BN .EQU 28H ; BIN error -0106+ 0356 -0107+ 0356 ; .ORG 00396H -0108+ 0356 -0109+ 0356 C3 5C 03 COLD: JP STARTB ; Jump for cold start -0110+ 0359 C3 FA 03 WARM: JP WARMST ; Jump for warm start -0111+ 035C STARTB: -0112+ 035C DD 21 00 00 LD IX,0 ; Flag cold start -0113+ 0360 C3 67 03 JP CSTART ; Jump to initialise -0114+ 0363 -0115+ 0363 0D 0C .WORD DEINT ; Get integer -32768 to 32767 -0116+ 0365 83 13 .WORD ABPASS ; Return integer in AB -0117+ 0367 -0118+ 0367 -0119+ 0367 21 B0 30 CSTART: LD HL,WRKSPC ; Start of workspace RAM -0120+ 036A F9 LD SP,HL ; Set up a temporary stack -0121+ 036B C3 A2 1F JP INITST ; Go to initialise -0122+ 036E -0123+ 036E 11 34 06 INIT: LD DE,INITAB ; Initialise workspace -0124+ 0371 06 63 LD B,INITBE-INITAB+3; Bytes to copy -0125+ 0373 21 B0 30 LD HL,WRKSPC ; Into workspace RAM -0126+ 0376 1A COPY: LD A,(DE) ; Get source -0127+ 0377 77 LD (HL),A ; To destination -0128+ 0378 23 INC HL ; Next destination -0129+ 0379 13 INC DE ; Next source -0130+ 037A 05 DEC B ; Count bytes -0131+ 037B C2 76 03 JP NZ,COPY ; More to move -0132+ 037E F9 LD SP,HL ; Temporary stack -0133+ 037F CD 35 08 CALL CLREG ; Clear registers and stack -0134+ 0382 CD 03 0E CALL PRNTCRLF ; Output CRLF -0135+ 0385 32 5A 31 LD (BUFFER+72+1),A ; Mark end of buffer -0136+ 0388 32 A9 31 LD (PROGST),A ; Initialise program area -0137+ 038B 21 49 04 MSIZE: LD HL,MEMMSG ; Point to message -0138+ 038E CD A1 14 CALL PRS ; Output "Memory size" -0139+ 0391 CD 52 08 CALL PROMPT ; Get input with '?' -0140+ 0394 CD 5B 0B CALL GETCHR ; Get next character -0141+ 0397 B7 OR A ; Set flags -0142+ 0398 C2 B0 03 JP NZ,TSTMEM ; If number - Test if RAM there -0143+ 039B 21 0D 32 LD HL,STLOOK ; Point to start of RAM -0144+ 039E 23 MLOOP: INC HL ; Next byte -0145+ 039F 7C LD A,H ; Above address FFFF ? -0146+ 03A0 B5 OR L -0147+ 03A1 CA C2 03 JP Z,SETTOP ; Yes - 64K RAM -0148+ 03A4 7E LD A,(HL) ; Get contents -0149+ 03A5 47 LD B,A ; Save it -0150+ 03A6 2F CPL ; Flip all bits -0151+ 03A7 77 LD (HL),A ; Put it back -0152+ 03A8 BE CP (HL) ; RAM there if same -0153+ 03A9 70 LD (HL),B ; Restore old contents -0154+ 03AA CA 9E 03 JP Z,MLOOP ; If RAM - test next byte -0155+ 03AD C3 C2 03 JP SETTOP ; Top of RAM found -0156+ 03B0 -0157+ 03B0 CD 27 0C TSTMEM: CALL ATOH ; Get high memory into DE -0158+ 03B3 B7 OR A ; Set flags on last byte -0159+ 03B4 C2 03 07 JP NZ,SNERR ; ?SN Error if bad character -0160+ 03B7 EB EX DE,HL ; Address into HL -0161+ 03B8 2B DEC HL ; Back one byte -0162+ 03B9 3E D9 LD A,11011001B ; Test byte -0163+ 03BB 46 LD B,(HL) ; Get old contents -0164+ 03BC 77 LD (HL),A ; Load test byte -0165+ 03BD BE CP (HL) ; RAM there if same -0166+ 03BE 70 LD (HL),B ; Restore old contents -0167+ 03BF C2 8B 03 JP NZ,MSIZE ; Ask again if no RAM -0168+ 03C2 -0169+ 03C2 2B SETTOP: DEC HL ; Back one byte -0170+ 03C3 11 0C 32 LD DE,STLOOK-1 ; See if enough RAM -0171+ 03C6 CD CB 09 CALL CPDEHL ; Compare DE with HL -0172+ 03C9 DA 8B 03 JP C,MSIZE ; Ask again if not enough RAM -0173+ 03CC 11 CE FF LD DE,0-50 ; 50 Bytes string space -0174+ 03CF 22 5F 31 LD (LSTRAM),HL ; Save last available RAM -0175+ 03D2 19 ADD HL,DE ; Allocate string space -0176+ 03D3 22 0A 31 LD (STRSPC),HL ; Save string space -0177+ 03D6 CD 10 08 CALL CLRPTR ; Clear program area -0178+ 03D9 2A 0A 31 LD HL,(STRSPC) ; Get end of memory -0179+ 03DC 11 EF FF LD DE,0-17 ; Offset for free bytes -0180+ 03DF 19 ADD HL,DE ; Adjust HL -0181+ 03E0 11 A9 31 LD DE,PROGST ; Start of program text -0182+ 03E3 7D LD A,L ; Get LSB -0183+ 03E4 93 SUB E ; Adjust it -0184+ 03E5 6F LD L,A ; Re-save -0185+ 03E6 7C LD A,H ; Get MSB -0186+ 03E7 9A SBC A,D ; Adjust it -0187+ 03E8 67 LD H,A ; Re-save -0188+ 03E9 E5 PUSH HL ; Save bytes free -0189+ 03EA 21 12 04 LD HL,SIGNON ; Sign-on message -0190+ 03ED CD A1 14 CALL PRS ; Output string -0191+ 03F0 E1 POP HL ; Get bytes free back -0192+ 03F1 CD 44 1B CALL PRNTHL ; Output amount of free memory -0193+ 03F4 21 03 04 LD HL,BFREE ; " Bytes free" message -0194+ 03F7 CD A1 14 CALL PRS ; Output string -0195+ 03FA -0196+ 03FA 31 16 31 WARMST: LD SP,STACK ; Temporary stack -0197+ 03FD CD 35 08 BRKRET: CALL CLREG ; Clear registers and stack -0198+ 0400 C3 4E 07 JP PRNTOK ; Go to get command line -0199+ 0403 -0200+ 0403 20 42 79 74 BFREE: .BYTE " Bytes free",CR,LF,0,0 -0200+ 0407 65 73 20 66 -0200+ 040B 72 65 65 0D -0200+ 040F 0A 00 00 -0201+ 0412 -0202+ 0412 5A 38 30 20 SIGNON: .BYTE "Z80 BASIC Ver 4.7b",CR,LF -0202+ 0416 42 41 53 49 -0202+ 041A 43 20 56 65 -0202+ 041E 72 20 34 2E -0202+ 0422 37 62 0D 0A -0203+ 0426 43 6F 70 79 .BYTE "Copyright ",40,"C",41 -0203+ 042A 72 69 67 68 -0203+ 042E 74 20 28 43 -0203+ 0432 29 -0204+ 0433 20 31 39 37 .BYTE " 1978 by Microsoft",CR,LF,0,0 -0204+ 0437 38 20 62 79 -0204+ 043B 20 4D 69 63 -0204+ 043F 72 6F 73 6F -0204+ 0443 66 74 0D 0A -0204+ 0447 00 00 -0205+ 0449 -0206+ 0449 4D 65 6D 6F MEMMSG: .BYTE "Memory top",0 -0206+ 044D 72 79 20 74 -0206+ 0451 6F 70 00 -0207+ 0454 -0208+ 0454 ; FUNCTION ADDRESS TABLE -0209+ 0454 -0210+ 0454 B9 19 FNCTAB: .WORD SGN -0211+ 0456 7D 1A .WORD INT -0212+ 0458 CF 19 .WORD ABS -0213+ 045A B3 30 .WORD USR -0214+ 045C 61 13 .WORD FRE -0215+ 045E E6 16 .WORD INP -0216+ 0460 8F 13 .WORD POS -0217+ 0462 43 1C .WORD SQR -0218+ 0464 22 1D .WORD RND -0219+ 0466 5E 18 .WORD LOG -0220+ 0468 91 1C .WORD EXP -0221+ 046A 97 1D .WORD COS -0222+ 046C 9D 1D .WORD SIN -0223+ 046E FE 1D .WORD TAN -0224+ 0470 13 1E .WORD ATN -0225+ 0472 3A 17 .WORD PEEK -0226+ 0474 7E 1E .WORD DEEK -0227+ 0476 01 31 .WORD POINT -0228+ 0478 13 16 .WORD LEN -0229+ 047A 2B 14 .WORD STR -0230+ 047C AD 16 .WORD VAL -0231+ 047E 22 16 .WORD ASC -0232+ 0480 33 16 .WORD CHR -0233+ 0482 A0 1E .WORD HEX -0234+ 0484 33 1F .WORD BIN -0235+ 0486 43 16 .WORD LEFT -0236+ 0488 73 16 .WORD RIGHT -0237+ 048A 7D 16 .WORD MID -0238+ 048C -0239+ 048C ; RESERVED WORD LIST -0240+ 048C -0241+ 048C C5 4E 44 WORDS: .BYTE 'E'+80H,"ND" -0242+ 048F C6 4F 52 .BYTE 'F'+80H,"OR" -0243+ 0492 CE 45 58 54 .BYTE 'N'+80H,"EXT" -0244+ 0496 C4 41 54 41 .BYTE 'D'+80H,"ATA" -0245+ 049A C9 4E 50 55 .BYTE 'I'+80H,"NPUT" -0245+ 049E 54 -0246+ 049F C4 49 4D .BYTE 'D'+80H,"IM" -0247+ 04A2 D2 45 41 44 .BYTE 'R'+80H,"EAD" -0248+ 04A6 CC 45 54 .BYTE 'L'+80H,"ET" -0249+ 04A9 C7 4F 54 4F .BYTE 'G'+80H,"OTO" -0250+ 04AD D2 55 4E .BYTE 'R'+80H,"UN" -0251+ 04B0 C9 46 .BYTE 'I'+80H,"F" -0252+ 04B2 D2 45 53 54 .BYTE 'R'+80H,"ESTORE" -0252+ 04B6 4F 52 45 -0253+ 04B9 C7 4F 53 55 .BYTE 'G'+80H,"OSUB" -0253+ 04BD 42 -0254+ 04BE D2 45 54 55 .BYTE 'R'+80H,"ETURN" -0254+ 04C2 52 4E -0255+ 04C4 D2 45 4D .BYTE 'R'+80H,"EM" -0256+ 04C7 D3 54 4F 50 .BYTE 'S'+80H,"TOP" -0257+ 04CB CF 55 54 .BYTE 'O'+80H,"UT" -0258+ 04CE CF 4E .BYTE 'O'+80H,"N" -0259+ 04D0 CE 55 4C 4C .BYTE 'N'+80H,"ULL" -0260+ 04D4 D7 41 49 54 .BYTE 'W'+80H,"AIT" -0261+ 04D8 C4 45 46 .BYTE 'D'+80H,"EF" -0262+ 04DB D0 4F 4B 45 .BYTE 'P'+80H,"OKE" -0263+ 04DF C4 4F 4B 45 .BYTE 'D'+80H,"OKE" -0264+ 04E3 D3 43 52 45 .BYTE 'S'+80H,"CREEN" -0264+ 04E7 45 4E -0265+ 04E9 CC 49 4E 45 .BYTE 'L'+80H,"INES" -0265+ 04ED 53 -0266+ 04EE C3 4C 53 .BYTE 'C'+80H,"LS" -0267+ 04F1 D7 49 44 54 .BYTE 'W'+80H,"IDTH" -0267+ 04F5 48 -0268+ 04F6 CD 4F 4E 49 .BYTE 'M'+80H,"ONITOR" -0268+ 04FA 54 4F 52 -0269+ 04FD D3 45 54 .BYTE 'S'+80H,"ET" -0270+ 0500 D2 45 53 45 .BYTE 'R'+80H,"ESET" -0270+ 0504 54 -0271+ 0505 D0 52 49 4E .BYTE 'P'+80H,"RINT" -0271+ 0509 54 -0272+ 050A C3 4F 4E 54 .BYTE 'C'+80H,"ONT" -0273+ 050E CC 49 53 54 .BYTE 'L'+80H,"IST" -0274+ 0512 C3 4C 45 41 .BYTE 'C'+80H,"LEAR" -0274+ 0516 52 -0275+ 0517 C3 4C 4F 41 .BYTE 'C'+80H,"LOAD" -0275+ 051B 44 -0276+ 051C C3 53 41 56 .BYTE 'C'+80H,"SAVE" -0276+ 0520 45 -0277+ 0521 CE 45 57 .BYTE 'N'+80H,"EW" -0278+ 0524 -0279+ 0524 D4 41 42 28 .BYTE 'T'+80H,"AB(" -0280+ 0528 D4 4F .BYTE 'T'+80H,"O" -0281+ 052A C6 4E .BYTE 'F'+80H,"N" -0282+ 052C D3 50 43 28 .BYTE 'S'+80H,"PC(" -0283+ 0530 D4 48 45 4E .BYTE 'T'+80H,"HEN" -0284+ 0534 CE 4F 54 .BYTE 'N'+80H,"OT" -0285+ 0537 D3 54 45 50 .BYTE 'S'+80H,"TEP" -0286+ 053B -0287+ 053B AB .BYTE '+'+80H -0288+ 053C AD .BYTE '-'+80H -0289+ 053D AA .BYTE '*'+80H -0290+ 053E AF .BYTE '/'+80H -0291+ 053F DE .BYTE '^'+80H -0292+ 0540 C1 4E 44 .BYTE 'A'+80H,"ND" -0293+ 0543 CF 52 .BYTE 'O'+80H,"R" -0294+ 0545 BE .BYTE '>'+80H -0295+ 0546 BD .BYTE '='+80H -0296+ 0547 BC .BYTE '<'+80H -0297+ 0548 -0298+ 0548 D3 47 4E .BYTE 'S'+80H,"GN" -0299+ 054B C9 4E 54 .BYTE 'I'+80H,"NT" -0300+ 054E C1 42 53 .BYTE 'A'+80H,"BS" -0301+ 0551 D5 53 52 .BYTE 'U'+80H,"SR" -0302+ 0554 C6 52 45 .BYTE 'F'+80H,"RE" -0303+ 0557 C9 4E 50 .BYTE 'I'+80H,"NP" -0304+ 055A D0 4F 53 .BYTE 'P'+80H,"OS" -0305+ 055D D3 51 52 .BYTE 'S'+80H,"QR" -0306+ 0560 D2 4E 44 .BYTE 'R'+80H,"ND" -0307+ 0563 CC 4F 47 .BYTE 'L'+80H,"OG" -0308+ 0566 C5 58 50 .BYTE 'E'+80H,"XP" -0309+ 0569 C3 4F 53 .BYTE 'C'+80H,"OS" -0310+ 056C D3 49 4E .BYTE 'S'+80H,"IN" -0311+ 056F D4 41 4E .BYTE 'T'+80H,"AN" -0312+ 0572 C1 54 4E .BYTE 'A'+80H,"TN" -0313+ 0575 D0 45 45 4B .BYTE 'P'+80H,"EEK" -0314+ 0579 C4 45 45 4B .BYTE 'D'+80H,"EEK" -0315+ 057D D0 4F 49 4E .BYTE 'P'+80H,"OINT" -0315+ 0581 54 -0316+ 0582 CC 45 4E .BYTE 'L'+80H,"EN" -0317+ 0585 D3 54 52 24 .BYTE 'S'+80H,"TR$" -0318+ 0589 D6 41 4C .BYTE 'V'+80H,"AL" -0319+ 058C C1 53 43 .BYTE 'A'+80H,"SC" -0320+ 058F C3 48 52 24 .BYTE 'C'+80H,"HR$" -0321+ 0593 C8 45 58 24 .BYTE 'H'+80H,"EX$" -0322+ 0597 C2 49 4E 24 .BYTE 'B'+80H,"IN$" -0323+ 059B CC 45 46 54 .BYTE 'L'+80H,"EFT$" -0323+ 059F 24 -0324+ 05A0 D2 49 47 48 .BYTE 'R'+80H,"IGHT$" -0324+ 05A4 54 24 -0325+ 05A6 CD 49 44 24 .BYTE 'M'+80H,"ID$" -0326+ 05AA 80 .BYTE 80H ; End of list marker -0327+ 05AB -0328+ 05AB ; KEYWORD ADDRESS TABLE -0329+ 05AB -0330+ 05AB A5 0B WORDTB: .WORD PEND -0331+ 05AD A2 0A .WORD FOR -0332+ 05AF 7D 0F .WORD NEXT -0333+ 05B1 F2 0C .WORD DATA -0334+ 05B3 84 0E .WORD INPUT -0335+ 05B5 B9 11 .WORD DIM -0336+ 05B7 B3 0E .WORD READ -0337+ 05B9 09 0D .WORD LET -0338+ 05BB AF 0C .WORD GOTO -0339+ 05BD 92 0C .WORD RUN -0340+ 05BF 81 0D .WORD IF -0341+ 05C1 6B 0B .WORD RESTOR -0342+ 05C3 9E 0C .WORD GOSUB -0343+ 05C5 CD 0C .WORD RETURN -0344+ 05C7 F4 0C .WORD REM -0345+ 05C9 A3 0B .WORD STOP -0346+ 05CB F2 16 .WORD POUT -0347+ 05CD 63 0D .WORD ON -0348+ 05CF E4 0B .WORD NULL -0349+ 05D1 F8 16 .WORD WAIT -0350+ 05D3 97 13 .WORD DEF -0351+ 05D5 41 17 .WORD POKE -0352+ 05D7 89 1E .WORD DOKE -0353+ 05D9 F4 0C .WORD REM -0354+ 05DB 6F 1E .WORD LINES -0355+ 05DD 62 1E .WORD CLS -0356+ 05DF 67 1E .WORD WIDTH -0357+ 05E1 9F 1F .WORD MONITR -0358+ 05E3 04 31 .WORD PSET -0359+ 05E5 07 31 .WORD RESET -0360+ 05E7 A5 0D .WORD PRINT -0361+ 05E9 D1 0B .WORD CONT -0362+ 05EB 17 0A .WORD LIST -0363+ 05ED 4C 0C .WORD CLEAR -0364+ 05EF F4 0C .WORD REM -0365+ 05F1 F4 0C .WORD REM -0366+ 05F3 0F 08 .WORD NEW -0367+ 05F5 -0368+ 05F5 ; RESERVED WORD TOKEN VALUES -0369+ 05F5 -0370+ 05F5 ZEND .EQU 080H ; END -0371+ 05F5 ZFOR .EQU 081H ; FOR -0372+ 05F5 ZDATA .EQU 083H ; DATA -0373+ 05F5 ZGOTO .EQU 088H ; GOTO -0374+ 05F5 ZGOSUB .EQU 08CH ; GOSUB -0375+ 05F5 ZREM .EQU 08EH ; REM -0376+ 05F5 ZPRINT .EQU 09EH ; PRINT -0377+ 05F5 ZNEW .EQU 0A4H ; NEW -0378+ 05F5 -0379+ 05F5 ZTAB .EQU 0A5H ; TAB -0380+ 05F5 ZTO .EQU 0A6H ; TO -0381+ 05F5 ZFN .EQU 0A7H ; FN -0382+ 05F5 ZSPC .EQU 0A8H ; SPC -0383+ 05F5 ZTHEN .EQU 0A9H ; THEN -0384+ 05F5 ZNOT .EQU 0AAH ; NOT -0385+ 05F5 ZSTEP .EQU 0ABH ; STEP -0386+ 05F5 -0387+ 05F5 ZPLUS .EQU 0ACH ; + -0388+ 05F5 ZMINUS .EQU 0ADH ; - -0389+ 05F5 ZTIMES .EQU 0AEH ; * -0390+ 05F5 ZDIV .EQU 0AFH ; / -0391+ 05F5 ZOR .EQU 0B2H ; OR -0392+ 05F5 ZGTR .EQU 0B3H ; > -0393+ 05F5 ZEQUAL .EQU 0B4H ; M -0394+ 05F5 ZLTH .EQU 0B5H ; < -0395+ 05F5 ZSGN .EQU 0B6H ; SGN -0396+ 05F5 ZPOINT .EQU 0C7H ; POINT -0397+ 05F5 ZLEFT .EQU 0CDH +2 ; LEFT$ -0398+ 05F5 -0399+ 05F5 ; ARITHMETIC PRECEDENCE TABLE -0400+ 05F5 -0401+ 05F5 79 PRITAB: .BYTE 79H ; Precedence value -0402+ 05F6 2B 1B .WORD PADD ; FPREG = + FPREG -0403+ 05F8 -0404+ 05F8 79 .BYTE 79H ; Precedence value -0405+ 05F9 5F 17 .WORD PSUB ; FPREG = - FPREG -0406+ 05FB -0407+ 05FB 7C .BYTE 7CH ; Precedence value -0408+ 05FC 9D 18 .WORD MULT ; PPREG = * FPREG -0409+ 05FE -0410+ 05FE 7C .BYTE 7CH ; Precedence value -0411+ 05FF FE 18 .WORD DIV ; FPREG = / FPREG -0412+ 0601 -0413+ 0601 7F .BYTE 7FH ; Precedence value -0414+ 0602 4C 1C .WORD POWER ; FPREG = ^ FPREG -0415+ 0604 -0416+ 0604 50 .BYTE 50H ; Precedence value -0417+ 0605 12 11 .WORD PAND ; FPREG = AND FPREG -0418+ 0607 -0419+ 0607 46 .BYTE 46H ; Precedence value -0420+ 0608 11 11 .WORD POR ; FPREG = OR FPREG -0421+ 060A -0422+ 060A ; BASIC ERROR CODE LIST -0423+ 060A -0424+ 060A 4E 46 ERRORS: .BYTE "NF" ; NEXT without FOR -0425+ 060C 53 4E .BYTE "SN" ; Syntax error -0426+ 060E 52 47 .BYTE "RG" ; RETURN without GOSUB -0427+ 0610 4F 44 .BYTE "OD" ; Out of DATA -0428+ 0612 46 43 .BYTE "FC" ; Illegal function call -0429+ 0614 4F 56 .BYTE "OV" ; Overflow error -0430+ 0616 4F 4D .BYTE "OM" ; Out of memory -0431+ 0618 55 4C .BYTE "UL" ; Undefined line -0432+ 061A 42 53 .BYTE "BS" ; Bad subscript -0433+ 061C 44 44 .BYTE "DD" ; Re-DIMensioned array -0434+ 061E 2F 30 .BYTE "/0" ; Division by zero -0435+ 0620 49 44 .BYTE "ID" ; Illegal direct -0436+ 0622 54 4D .BYTE "TM" ; Type mis-match -0437+ 0624 4F 53 .BYTE "OS" ; Out of string space -0438+ 0626 4C 53 .BYTE "LS" ; String too long -0439+ 0628 53 54 .BYTE "ST" ; String formula too complex -0440+ 062A 43 4E .BYTE "CN" ; Can't CONTinue -0441+ 062C 55 46 .BYTE "UF" ; Undefined FN function -0442+ 062E 4D 4F .BYTE "MO" ; Missing operand -0443+ 0630 48 58 .BYTE "HX" ; HEX error -0444+ 0632 42 4E .BYTE "BN" ; BIN error -0445+ 0634 -0446+ 0634 ; INITIALISATION TABLE ------------------------------------------------------- -0447+ 0634 -0448+ 0634 C3 FA 03 INITAB: JP WARMST ; Warm start jump -0449+ 0637 C3 22 0C JP FCERR ; "USR (X)" jump (Set to Error) -0450+ 063A D3 00 OUT (0),A ; "OUT p,n" skeleton -0451+ 063C C9 RET -0452+ 063D D6 00 SUB 0 ; Division support routine -0453+ 063F 6F LD L,A -0454+ 0640 7C LD A,H -0455+ 0641 DE 00 SBC A,0 -0456+ 0643 67 LD H,A -0457+ 0644 78 LD A,B -0458+ 0645 DE 00 SBC A,0 -0459+ 0647 47 LD B,A -0460+ 0648 3E 00 LD A,0 -0461+ 064A C9 RET -0462+ 064B 00 00 00 .BYTE 0,0,0 ; Random number seed table used by RND -0463+ 064E 35 4A CA 99 .BYTE 035H,04AH,0CAH,099H ;-2.65145E+07 -0464+ 0652 39 1C 76 98 .BYTE 039H,01CH,076H,098H ; 1.61291E+07 -0465+ 0656 22 95 B3 98 .BYTE 022H,095H,0B3H,098H ;-1.17691E+07 -0466+ 065A 0A DD 47 98 .BYTE 00AH,0DDH,047H,098H ; 1.30983E+07 -0467+ 065E 53 D1 99 99 .BYTE 053H,0D1H,099H,099H ;-2-01612E+07 -0468+ 0662 0A 1A 9F 98 .BYTE 00AH,01AH,09FH,098H ;-1.04269E+07 -0469+ 0666 65 BC CD 98 .BYTE 065H,0BCH,0CDH,098H ;-1.34831E+07 -0470+ 066A D6 77 3E 98 .BYTE 0D6H,077H,03EH,098H ; 1.24825E+07 -0471+ 066E 52 C7 4F 80 .BYTE 052H,0C7H,04FH,080H ; Last random number -0472+ 0672 DB 00 IN A,(0) ; INP (x) skeleton -0473+ 0674 C9 RET -0474+ 0675 01 .BYTE 1 ; POS (x) number (1) -0475+ 0676 FF .BYTE 255 ; Terminal width (255 = no auto CRLF) -0476+ 0677 1C .BYTE 28 ; Width for commas (3 columns) -0477+ 0678 00 .BYTE 0 ; No nulls after input bytes -0478+ 0679 00 .BYTE 0 ; Output enabled (^O off) -0479+ 067A 14 00 .WORD 20 ; Initial lines counter -0480+ 067C 14 00 .WORD 20 ; Initial lines number -0481+ 067E 00 00 .WORD 0 ; Array load/save check sum -0482+ 0680 00 .BYTE 0 ; Break not by NMI -0483+ 0681 00 .BYTE 0 ; Break flag -0484+ 0682 C3 48 09 JP TTYLIN ; Input reflection (set to TTY) -0485+ 0685 C3 00 00 JP $0000 ; POINT reflection unused -0486+ 0688 C3 00 00 JP $0000 ; SET reflection -0487+ 068B C3 00 00 JP $0000 ; RESET reflection -0488+ 068E 0D 32 .WORD STLOOK ; Temp string space -0489+ 0690 FE FF .WORD -2 ; Current line number (cold) -0490+ 0692 AA 31 .WORD PROGST+1 ; Start of program text -0491+ 0694 INITBE: -0492+ 0694 -0493+ 0694 ; END OF INITIALISATION TABLE --------------------------------------------------- -0494+ 0694 -0495+ 0694 20 45 72 72 ERRMSG: .BYTE " Error",0 -0495+ 0698 6F 72 00 -0496+ 069B 20 69 6E 20 INMSG: .BYTE " in ",0 -0496+ 069F 00 -0497+ 06A0 ZERBYT .EQU $-1 ; A zero byte -0498+ 06A0 4F 6B 0D 0A OKMSG: .BYTE "Ok",CR,LF,0,0 -0498+ 06A4 00 00 -0499+ 06A6 42 72 65 61 BRKMSG: .BYTE "Break",0 -0499+ 06AA 6B 00 -0500+ 06AC -0501+ 06AC 21 04 00 BAKSTK: LD HL,4 ; Look for "FOR" block with -0502+ 06AF 39 ADD HL,SP ; same index as specified -0503+ 06B0 7E LOKFOR: LD A,(HL) ; Get block ID -0504+ 06B1 23 INC HL ; Point to index address -0505+ 06B2 FE 81 CP ZFOR ; Is it a "FOR" token -0506+ 06B4 C0 RET NZ ; No - exit -0507+ 06B5 4E LD C,(HL) ; BC = Address of "FOR" index -0508+ 06B6 23 INC HL -0509+ 06B7 46 LD B,(HL) -0510+ 06B8 23 INC HL ; Point to sign of STEP -0511+ 06B9 E5 PUSH HL ; Save pointer to sign -0512+ 06BA 69 LD L,C ; HL = address of "FOR" index -0513+ 06BB 60 LD H,B -0514+ 06BC 7A LD A,D ; See if an index was specified -0515+ 06BD B3 OR E ; DE = 0 if no index specified -0516+ 06BE EB EX DE,HL ; Specified index into HL -0517+ 06BF CA C6 06 JP Z,INDFND ; Skip if no index given -0518+ 06C2 EB EX DE,HL ; Index back into DE -0519+ 06C3 CD CB 09 CALL CPDEHL ; Compare index with one given -0520+ 06C6 01 0D 00 INDFND: LD BC,16-3 ; Offset to next block -0521+ 06C9 E1 POP HL ; Restore pointer to sign -0522+ 06CA C8 RET Z ; Return if block found -0523+ 06CB 09 ADD HL,BC ; Point to next block -0524+ 06CC C3 B0 06 JP LOKFOR ; Keep on looking -0525+ 06CF -0526+ 06CF CD E9 06 MOVUP: CALL ENFMEM ; See if enough memory -0527+ 06D2 C5 MOVSTR: PUSH BC ; Save end of source -0528+ 06D3 E3 EX (SP),HL ; Swap source and dest" end -0529+ 06D4 C1 POP BC ; Get end of destination -0530+ 06D5 CD CB 09 MOVLP: CALL CPDEHL ; See if list moved -0531+ 06D8 7E LD A,(HL) ; Get byte -0532+ 06D9 02 LD (BC),A ; Move it -0533+ 06DA C8 RET Z ; Exit if all done -0534+ 06DB 0B DEC BC ; Next byte to move to -0535+ 06DC 2B DEC HL ; Next byte to move -0536+ 06DD C3 D5 06 JP MOVLP ; Loop until all bytes moved -0537+ 06E0 -0538+ 06E0 E5 CHKSTK: PUSH HL ; Save code string address -0539+ 06E1 2A 8A 31 LD HL,(ARREND) ; Lowest free memory -0540+ 06E4 06 00 LD B,0 ; BC = Number of levels to test -0541+ 06E6 09 ADD HL,BC ; 2 Bytes for each level -0542+ 06E7 09 ADD HL,BC -0543+ 06E8 3E .BYTE 3EH ; Skip "PUSH HL" -0544+ 06E9 E5 ENFMEM: PUSH HL ; Save code string address -0545+ 06EA 3E D0 LD A,0D0H ;LOW -48 ; 48 Bytes minimum RAM -0546+ 06EC 95 SUB L -0547+ 06ED 6F LD L,A -0548+ 06EE 3E FF LD A,0FFH; HIGH (-48) ; 48 Bytes minimum RAM -0549+ 06F0 9C SBC A,H -0550+ 06F1 DA F8 06 JP C,OMERR ; Not enough - ?OM Error -0551+ 06F4 67 LD H,A -0552+ 06F5 39 ADD HL,SP ; Test if stack is overflowed -0553+ 06F6 E1 POP HL ; Restore code string address -0554+ 06F7 D8 RET C ; Return if enough mmory -0555+ 06F8 1E 0C OMERR: LD E,OM ; ?OM Error -0556+ 06FA C3 17 07 JP ERROR -0557+ 06FD -0558+ 06FD 2A 79 31 DATSNR: LD HL,(DATLIN) ; Get line of current DATA item -0559+ 0700 22 0C 31 LD (LINEAT),HL ; Save as current line -0560+ 0703 1E 02 SNERR: LD E,SN ; ?SN Error -0561+ 0705 01 .BYTE 01H ; Skip "LD E,DZ" -0562+ 0706 1E 14 DZERR: LD E,DZ ; ?/0 Error -0563+ 0708 01 .BYTE 01H ; Skip "LD E,NF" -0564+ 0709 1E 00 NFERR: LD E,NF ; ?NF Error -0565+ 070B 01 .BYTE 01H ; Skip "LD E,DD" -0566+ 070C 1E 12 DDERR: LD E,DD ; ?DD Error -0567+ 070E 01 .BYTE 01H ; Skip "LD E,UF" -0568+ 070F 1E 22 UFERR: LD E,UF ; ?UF Error -0569+ 0711 01 .BYTE 01H ; Skip "LD E,OV -0570+ 0712 1E 0A OVERR: LD E,OV ; ?OV Error -0571+ 0714 01 .BYTE 01H ; Skip "LD E,TM" -0572+ 0715 1E 18 TMERR: LD E,TM ; ?TM Error -0573+ 0717 -0574+ 0717 CD 35 08 ERROR: CALL CLREG ; Clear registers and stack -0575+ 071A 32 F5 30 LD (CTLOFG),A ; Enable output (A is 0) -0576+ 071D CD F6 0D CALL STTLIN ; Start new line -0577+ 0720 21 0A 06 LD HL,ERRORS ; Point to error codes -0578+ 0723 57 LD D,A ; D = 0 (A is 0) -0579+ 0724 3E 3F LD A,'?' -0580+ 0726 CD DC 09 CALL OUTC ; Output '?' -0581+ 0729 19 ADD HL,DE ; Offset to correct error code -0582+ 072A 7E LD A,(HL) ; First character -0583+ 072B CD DC 09 CALL OUTC ; Output it -0584+ 072E CD 5B 0B CALL GETCHR ; Get next character -0585+ 0731 CD DC 09 CALL OUTC ; Output it -0586+ 0734 21 94 06 LD HL,ERRMSG ; "Error" message -0587+ 0737 CD A1 14 ERRIN: CALL PRS ; Output message -0588+ 073A 2A 0C 31 LD HL,(LINEAT) ; Get line of error -0589+ 073D 11 FE FF LD DE,-2 ; Cold start error if -2 -0590+ 0740 CD CB 09 CALL CPDEHL ; See if cold start error -0591+ 0743 CA 67 03 JP Z,CSTART ; Cold start error - Restart -0592+ 0746 7C LD A,H ; Was it a direct error? -0593+ 0747 A5 AND L ; Line = -1 if direct error -0594+ 0748 3C INC A -0595+ 0749 C4 3C 1B CALL NZ,LINEIN ; No - output line of error -0596+ 074C 3E .BYTE 3EH ; Skip "POP BC" -0597+ 074D C1 POPNOK: POP BC ; Drop address in input buffer -0598+ 074E -0599+ 074E AF PRNTOK: XOR A ; Output "Ok" and get command -0600+ 074F 32 F5 30 LD (CTLOFG),A ; Enable output -0601+ 0752 CD F6 0D CALL STTLIN ; Start new line -0602+ 0755 21 A0 06 LD HL,OKMSG ; "Ok" message -0603+ 0758 CD A1 14 CALL PRS ; Output "Ok" -0604+ 075B 21 FF FF GETCMD: LD HL,-1 ; Flag direct mode -0605+ 075E 22 0C 31 LD (LINEAT),HL ; Save as current line -0606+ 0761 CD 48 09 CALL GETLIN ; Get an input line -0607+ 0764 DA 5B 07 JP C,GETCMD ; Get line again if break -0608+ 0767 CD 5B 0B CALL GETCHR ; Get first character -0609+ 076A 3C INC A ; Test if end of line -0610+ 076B 3D DEC A ; Without affecting Carry -0611+ 076C CA 5B 07 JP Z,GETCMD ; Nothing entered - Get another -0612+ 076F F5 PUSH AF ; Save Carry status -0613+ 0770 CD 27 0C CALL ATOH ; Get line number into DE -0614+ 0773 D5 PUSH DE ; Save line number -0615+ 0774 CD 5F 08 CALL CRUNCH ; Tokenise rest of line -0616+ 0777 47 LD B,A ; Length of tokenised line -0617+ 0778 D1 POP DE ; Restore line number -0618+ 0779 F1 POP AF ; Restore Carry -0619+ 077A D2 3B 0B JP NC,EXCUTE ; No line number - Direct mode -0620+ 077D D5 PUSH DE ; Save line number -0621+ 077E C5 PUSH BC ; Save length of tokenised line -0622+ 077F AF XOR A -0623+ 0780 32 7C 31 LD (LSTBIN),A ; Clear last byte input -0624+ 0783 CD 5B 0B CALL GETCHR ; Get next character -0625+ 0786 B7 OR A ; Set flags -0626+ 0787 F5 PUSH AF ; And save them -0627+ 0788 CD EF 07 CALL SRCHLN ; Search for line number in DE -0628+ 078B DA 94 07 JP C,LINFND ; Jump if line found -0629+ 078E F1 POP AF ; Get status -0630+ 078F F5 PUSH AF ; And re-save -0631+ 0790 CA C8 0C JP Z,ULERR ; Nothing after number - Error -0632+ 0793 B7 OR A ; Clear Carry -0633+ 0794 C5 LINFND: PUSH BC ; Save address of line in prog -0634+ 0795 D2 AB 07 JP NC,INEWLN ; Line not found - Insert new -0635+ 0798 EB EX DE,HL ; Next line address in DE -0636+ 0799 2A 86 31 LD HL,(PROGND) ; End of program -0637+ 079C 1A SFTPRG: LD A,(DE) ; Shift rest of program down -0638+ 079D 02 LD (BC),A -0639+ 079E 03 INC BC ; Next destination -0640+ 079F 13 INC DE ; Next source -0641+ 07A0 CD CB 09 CALL CPDEHL ; All done? -0642+ 07A3 C2 9C 07 JP NZ,SFTPRG ; More to do -0643+ 07A6 60 LD H,B ; HL - New end of program -0644+ 07A7 69 LD L,C -0645+ 07A8 22 86 31 LD (PROGND),HL ; Update end of program -0646+ 07AB -0647+ 07AB D1 INEWLN: POP DE ; Get address of line, -0648+ 07AC F1 POP AF ; Get status -0649+ 07AD CA D2 07 JP Z,SETPTR ; No text - Set up pointers -0650+ 07B0 2A 86 31 LD HL,(PROGND) ; Get end of program -0651+ 07B3 E3 EX (SP),HL ; Get length of input line -0652+ 07B4 C1 POP BC ; End of program to BC -0653+ 07B5 09 ADD HL,BC ; Find new end -0654+ 07B6 E5 PUSH HL ; Save new end -0655+ 07B7 CD CF 06 CALL MOVUP ; Make space for line -0656+ 07BA E1 POP HL ; Restore new end -0657+ 07BB 22 86 31 LD (PROGND),HL ; Update end of program pointer -0658+ 07BE EB EX DE,HL ; Get line to move up in HL -0659+ 07BF 74 LD (HL),H ; Save MSB -0660+ 07C0 D1 POP DE ; Get new line number -0661+ 07C1 23 INC HL ; Skip pointer -0662+ 07C2 23 INC HL -0663+ 07C3 73 LD (HL),E ; Save LSB of line number -0664+ 07C4 23 INC HL -0665+ 07C5 72 LD (HL),D ; Save MSB of line number -0666+ 07C6 23 INC HL ; To first byte in line -0667+ 07C7 11 11 31 LD DE,BUFFER ; Copy buffer to program -0668+ 07CA 1A MOVBUF: LD A,(DE) ; Get source -0669+ 07CB 77 LD (HL),A ; Save destinations -0670+ 07CC 23 INC HL ; Next source -0671+ 07CD 13 INC DE ; Next destination -0672+ 07CE B7 OR A ; Done? -0673+ 07CF C2 CA 07 JP NZ,MOVBUF ; No - Repeat -0674+ 07D2 CD 1B 08 SETPTR: CALL RUNFST ; Set line pointers -0675+ 07D5 23 INC HL ; To LSB of pointer -0676+ 07D6 EB EX DE,HL ; Address to DE -0677+ 07D7 62 PTRLP: LD H,D ; Address to HL -0678+ 07D8 6B LD L,E -0679+ 07D9 7E LD A,(HL) ; Get LSB of pointer -0680+ 07DA 23 INC HL ; To MSB of pointer -0681+ 07DB B6 OR (HL) ; Compare with MSB pointer -0682+ 07DC CA 5B 07 JP Z,GETCMD ; Get command line if end -0683+ 07DF 23 INC HL ; To LSB of line number -0684+ 07E0 23 INC HL ; Skip line number -0685+ 07E1 23 INC HL ; Point to first byte in line -0686+ 07E2 AF XOR A ; Looking for 00 byte -0687+ 07E3 BE FNDEND: CP (HL) ; Found end of line? -0688+ 07E4 23 INC HL ; Move to next byte -0689+ 07E5 C2 E3 07 JP NZ,FNDEND ; No - Keep looking -0690+ 07E8 EB EX DE,HL ; Next line address to HL -0691+ 07E9 73 LD (HL),E ; Save LSB of pointer -0692+ 07EA 23 INC HL -0693+ 07EB 72 LD (HL),D ; Save MSB of pointer -0694+ 07EC C3 D7 07 JP PTRLP ; Do next line -0695+ 07EF -0696+ 07EF 2A 0E 31 SRCHLN: LD HL,(BASTXT) ; Start of program text -0697+ 07F2 44 SRCHLP: LD B,H ; BC = Address to look at -0698+ 07F3 4D LD C,L -0699+ 07F4 7E LD A,(HL) ; Get address of next line -0700+ 07F5 23 INC HL -0701+ 07F6 B6 OR (HL) ; End of program found? -0702+ 07F7 2B DEC HL -0703+ 07F8 C8 RET Z ; Yes - Line not found -0704+ 07F9 23 INC HL -0705+ 07FA 23 INC HL -0706+ 07FB 7E LD A,(HL) ; Get LSB of line number -0707+ 07FC 23 INC HL -0708+ 07FD 66 LD H,(HL) ; Get MSB of line number -0709+ 07FE 6F LD L,A -0710+ 07FF CD CB 09 CALL CPDEHL ; Compare with line in DE -0711+ 0802 60 LD H,B ; HL = Start of this line -0712+ 0803 69 LD L,C -0713+ 0804 7E LD A,(HL) ; Get LSB of next line address -0714+ 0805 23 INC HL -0715+ 0806 66 LD H,(HL) ; Get MSB of next line address -0716+ 0807 6F LD L,A ; Next line to HL -0717+ 0808 3F CCF -0718+ 0809 C8 RET Z ; Lines found - Exit -0719+ 080A 3F CCF -0720+ 080B D0 RET NC ; Line not found,at line after -0721+ 080C C3 F2 07 JP SRCHLP ; Keep looking -0722+ 080F -0723+ 080F C0 NEW: RET NZ ; Return if any more on line -0724+ 0810 2A 0E 31 CLRPTR: LD HL,(BASTXT) ; Point to start of program -0725+ 0813 AF XOR A ; Set program area to empty -0726+ 0814 77 LD (HL),A ; Save LSB = 00 -0727+ 0815 23 INC HL -0728+ 0816 77 LD (HL),A ; Save MSB = 00 -0729+ 0817 23 INC HL -0730+ 0818 22 86 31 LD (PROGND),HL ; Set program end -0731+ 081B -0732+ 081B 2A 0E 31 RUNFST: LD HL,(BASTXT) ; Clear all variables -0733+ 081E 2B DEC HL -0734+ 081F -0735+ 081F 22 7E 31 INTVAR: LD (BRKLIN),HL ; Initialise RUN variables -0736+ 0822 2A 5F 31 LD HL,(LSTRAM) ; Get end of RAM -0737+ 0825 22 73 31 LD (STRBOT),HL ; Clear string space -0738+ 0828 AF XOR A -0739+ 0829 CD 6B 0B CALL RESTOR ; Reset DATA pointers -0740+ 082C 2A 86 31 LD HL,(PROGND) ; Get end of program -0741+ 082F 22 88 31 LD (VAREND),HL ; Clear variables -0742+ 0832 22 8A 31 LD (ARREND),HL ; Clear arrays -0743+ 0835 -0744+ 0835 C1 CLREG: POP BC ; Save return address -0745+ 0836 2A 0A 31 LD HL,(STRSPC) ; Get end of working RAN -0746+ 0839 F9 LD SP,HL ; Set stack -0747+ 083A 21 63 31 LD HL,TMSTPL ; Temporary string pool -0748+ 083D 22 61 31 LD (TMSTPT),HL ; Reset temporary string ptr -0749+ 0840 AF XOR A ; A = 00 -0750+ 0841 6F LD L,A ; HL = 0000 -0751+ 0842 67 LD H,A -0752+ 0843 22 84 31 LD (CONTAD),HL ; No CONTinue -0753+ 0846 32 7B 31 LD (FORFLG),A ; Clear FOR flag -0754+ 0849 22 8E 31 LD (FNRGNM),HL ; Clear FN argument -0755+ 084C E5 PUSH HL ; HL = 0000 -0756+ 084D C5 PUSH BC ; Put back return -0757+ 084E 2A 7E 31 DOAGN: LD HL,(BRKLIN) ; Get address of code to RUN -0758+ 0851 C9 RET ; Return to execution driver -0759+ 0852 -0760+ 0852 3E 3F PROMPT: LD A,'?' ; '?' -0761+ 0854 CD DC 09 CALL OUTC ; Output character -0762+ 0857 3E 20 LD A,' ' ; Space -0763+ 0859 CD DC 09 CALL OUTC ; Output character -0764+ 085C C3 FE 30 JP RINPUT ; Get input line -0765+ 085F -0766+ 085F AF CRUNCH: XOR A ; Tokenise line @ HL to BUFFER -0767+ 0860 32 5E 31 LD (DATFLG),A ; Reset literal flag -0768+ 0863 0E 05 LD C,2+3 ; 2 byte number and 3 nulls -0769+ 0865 11 11 31 LD DE,BUFFER ; Start of input buffer -0770+ 0868 7E CRNCLP: LD A,(HL) ; Get byte -0771+ 0869 FE 20 CP ' ' ; Is it a space? -0772+ 086B CA E7 08 JP Z,MOVDIR ; Yes - Copy direct -0773+ 086E 47 LD B,A ; Save character -0774+ 086F FE 22 CP '"' ; Is it a quote? -0775+ 0871 CA 07 09 JP Z,CPYLIT ; Yes - Copy literal string -0776+ 0874 B7 OR A ; Is it end of buffer? -0777+ 0875 CA 0E 09 JP Z,ENDBUF ; Yes - End buffer -0778+ 0878 3A 5E 31 LD A,(DATFLG) ; Get data type -0779+ 087B B7 OR A ; Literal? -0780+ 087C 7E LD A,(HL) ; Get byte to copy -0781+ 087D C2 E7 08 JP NZ,MOVDIR ; Literal - Copy direct -0782+ 0880 FE 3F CP '?' ; Is it '?' short for PRINT -0783+ 0882 3E 9E LD A,ZPRINT ; "PRINT" token -0784+ 0884 CA E7 08 JP Z,MOVDIR ; Yes - replace it -0785+ 0887 7E LD A,(HL) ; Get byte again -0786+ 0888 FE 30 CP '0' ; Is it less than '0' -0787+ 088A DA 92 08 JP C,FNDWRD ; Yes - Look for reserved words -0788+ 088D FE 3C CP 60; ";"+1 ; Is it "0123456789:;" ? -0789+ 088F DA E7 08 JP C,MOVDIR ; Yes - copy it direct -0790+ 0892 D5 FNDWRD: PUSH DE ; Look for reserved words -0791+ 0893 11 8B 04 LD DE,WORDS-1 ; Point to table -0792+ 0896 C5 PUSH BC ; Save count -0793+ 0897 01 E3 08 LD BC,RETNAD ; Where to return to -0794+ 089A C5 PUSH BC ; Save return address -0795+ 089B 06 7F LD B,ZEND-1 ; First token value -1 -0796+ 089D 7E LD A,(HL) ; Get byte -0797+ 089E FE 61 CP 'a' ; Less than 'a' ? -0798+ 08A0 DA AB 08 JP C,SEARCH ; Yes - search for words -0799+ 08A3 FE 7B CP 'z'+1 ; Greater than 'z' ? -0800+ 08A5 D2 AB 08 JP NC,SEARCH ; Yes - search for words -0801+ 08A8 E6 5F AND 01011111B ; Force upper case -0802+ 08AA 77 LD (HL),A ; Replace byte -0803+ 08AB 4E SEARCH: LD C,(HL) ; Search for a word -0804+ 08AC EB EX DE,HL -0805+ 08AD 23 GETNXT: INC HL ; Get next reserved word -0806+ 08AE B6 OR (HL) ; Start of word? -0807+ 08AF F2 AD 08 JP P,GETNXT ; No - move on -0808+ 08B2 04 INC B ; Increment token value -0809+ 08B3 7E LD A, (HL) ; Get byte from table -0810+ 08B4 E6 7F AND 01111111B ; Strip bit 7 -0811+ 08B6 C8 RET Z ; Return if end of list -0812+ 08B7 B9 CP C ; Same character as in buffer? -0813+ 08B8 C2 AD 08 JP NZ,GETNXT ; No - get next word -0814+ 08BB EB EX DE,HL -0815+ 08BC E5 PUSH HL ; Save start of word -0816+ 08BD -0817+ 08BD 13 NXTBYT: INC DE ; Look through rest of word -0818+ 08BE 1A LD A,(DE) ; Get byte from table -0819+ 08BF B7 OR A ; End of word ? -0820+ 08C0 FA DF 08 JP M,MATCH ; Yes - Match found -0821+ 08C3 4F LD C,A ; Save it -0822+ 08C4 78 LD A,B ; Get token value -0823+ 08C5 FE 88 CP ZGOTO ; Is it "GOTO" token ? -0824+ 08C7 C2 CE 08 JP NZ,NOSPC ; No - Don't allow spaces -0825+ 08CA CD 5B 0B CALL GETCHR ; Get next character -0826+ 08CD 2B DEC HL ; Cancel increment from GETCHR -0827+ 08CE 23 NOSPC: INC HL ; Next byte -0828+ 08CF 7E LD A,(HL) ; Get byte -0829+ 08D0 FE 61 CP 'a' ; Less than 'a' ? -0830+ 08D2 DA D7 08 JP C,NOCHNG ; Yes - don't change -0831+ 08D5 E6 5F AND 01011111B ; Make upper case -0832+ 08D7 B9 NOCHNG: CP C ; Same as in buffer ? -0833+ 08D8 CA BD 08 JP Z,NXTBYT ; Yes - keep testing -0834+ 08DB E1 POP HL ; Get back start of word -0835+ 08DC C3 AB 08 JP SEARCH ; Look at next word -0836+ 08DF -0837+ 08DF 48 MATCH: LD C,B ; Word found - Save token value -0838+ 08E0 F1 POP AF ; Throw away return -0839+ 08E1 EB EX DE,HL -0840+ 08E2 C9 RET ; Return to "RETNAD" -0841+ 08E3 EB RETNAD: EX DE,HL ; Get address in string -0842+ 08E4 79 LD A,C ; Get token value -0843+ 08E5 C1 POP BC ; Restore buffer length -0844+ 08E6 D1 POP DE ; Get destination address -0845+ 08E7 23 MOVDIR: INC HL ; Next source in buffer -0846+ 08E8 12 LD (DE),A ; Put byte in buffer -0847+ 08E9 13 INC DE ; Move up buffer -0848+ 08EA 0C INC C ; Increment length of buffer -0849+ 08EB D6 3A SUB ':' ; End of statement? -0850+ 08ED CA F5 08 JP Z,SETLIT ; Jump if multi-statement line -0851+ 08F0 FE 49 CP ZDATA-3AH ; Is it DATA statement ? -0852+ 08F2 C2 F8 08 JP NZ,TSTREM ; No - see if REM -0853+ 08F5 32 5E 31 SETLIT: LD (DATFLG),A ; Set literal flag -0854+ 08F8 D6 54 TSTREM: SUB ZREM-3AH ; Is it REM? -0855+ 08FA C2 68 08 JP NZ,CRNCLP ; No - Leave flag -0856+ 08FD 47 LD B,A ; Copy rest of buffer -0857+ 08FE 7E NXTCHR: LD A,(HL) ; Get byte -0858+ 08FF B7 OR A ; End of line ? -0859+ 0900 CA 0E 09 JP Z,ENDBUF ; Yes - Terminate buffer -0860+ 0903 B8 CP B ; End of statement ? -0861+ 0904 CA E7 08 JP Z,MOVDIR ; Yes - Get next one -0862+ 0907 23 CPYLIT: INC HL ; Move up source string -0863+ 0908 12 LD (DE),A ; Save in destination -0864+ 0909 0C INC C ; Increment length -0865+ 090A 13 INC DE ; Move up destination -0866+ 090B C3 FE 08 JP NXTCHR ; Repeat -0867+ 090E -0868+ 090E 21 10 31 ENDBUF: LD HL,BUFFER-1 ; Point to start of buffer -0869+ 0911 12 LD (DE),A ; Mark end of buffer (A = 00) -0870+ 0912 13 INC DE -0871+ 0913 12 LD (DE),A ; A = 00 -0872+ 0914 13 INC DE -0873+ 0915 12 LD (DE),A ; A = 00 -0874+ 0916 C9 RET -0875+ 0917 -0876+ 0917 3A F4 30 DODEL: LD A,(NULFLG) ; Get null flag status -0877+ 091A B7 OR A ; Is it zero? -0878+ 091B 3E 00 LD A,0 ; Zero A - Leave flags -0879+ 091D 32 F4 30 LD (NULFLG),A ; Zero null flag -0880+ 0920 C2 2B 09 JP NZ,ECHDEL ; Set - Echo it -0881+ 0923 05 DEC B ; Decrement length -0882+ 0924 CA 48 09 JP Z,GETLIN ; Get line again if empty -0883+ 0927 CD DC 09 CALL OUTC ; Output null character -0884+ 092A 3E .BYTE 3EH ; Skip "DEC B" -0885+ 092B 05 ECHDEL: DEC B ; Count bytes in buffer -0886+ 092C 2B DEC HL ; Back space buffer -0887+ 092D CA 3F 09 JP Z,OTKLN ; No buffer - Try again -0888+ 0930 7E LD A,(HL) ; Get deleted byte -0889+ 0931 CD DC 09 CALL OUTC ; Echo it -0890+ 0934 C3 51 09 JP MORINP ; Get more input -0891+ 0937 -0892+ 0937 05 DELCHR: DEC B ; Count bytes in buffer -0893+ 0938 2B DEC HL ; Back space buffer -0894+ 0939 CD DC 09 CALL OUTC ; Output character in A -0895+ 093C C2 51 09 JP NZ,MORINP ; Not end - Get more -0896+ 093F CD DC 09 OTKLN: CALL OUTC ; Output character in A -0897+ 0942 CD 03 0E KILIN: CALL PRNTCRLF ; Output CRLF -0898+ 0945 C3 48 09 JP TTYLIN ; Get line again -0899+ 0948 -0900+ 0948 GETLIN: -0901+ 0948 21 11 31 TTYLIN: LD HL,BUFFER ; Get a line by character -0902+ 094B 06 01 LD B,1 ; Set buffer as empty -0903+ 094D AF XOR A -0904+ 094E 32 F4 30 LD (NULFLG),A ; Clear null flag -0905+ 0951 CD 06 0A MORINP: CALL CLOTST ; Get character and test ^O -0906+ 0954 4F LD C,A ; Save character in C -0907+ 0955 FE 7F CP DEL ; Delete character? -0908+ 0957 CA 17 09 JP Z,DODEL ; Yes - Process it -0909+ 095A 3A F4 30 LD A,(NULFLG) ; Get null flag -0910+ 095D B7 OR A ; Test null flag status -0911+ 095E CA 6A 09 JP Z,PROCES ; Reset - Process character -0912+ 0961 3E 00 LD A,0 ; Set a null -0913+ 0963 CD DC 09 CALL OUTC ; Output null -0914+ 0966 AF XOR A ; Clear A -0915+ 0967 32 F4 30 LD (NULFLG),A ; Reset null flag -0916+ 096A 79 PROCES: LD A,C ; Get character -0917+ 096B FE 07 CP CTRLG ; Bell? -0918+ 096D CA AE 09 JP Z,PUTCTL ; Yes - Save it -0919+ 0970 FE 03 CP CTRLC ; Is it control "C"? -0920+ 0972 CC 03 0E CALL Z,PRNTCRLF ; Yes - Output CRLF -0921+ 0975 37 SCF ; Flag break -0922+ 0976 C8 RET Z ; Return if control "C" -0923+ 0977 FE 0D CP CR ; Is it enter? -0924+ 0979 CA FE 0D JP Z,ENDINP ; Yes - Terminate input -0925+ 097C FE 15 CP CTRLU ; Is it control "U"? -0926+ 097E CA 42 09 JP Z,KILIN ; Yes - Get another line -0927+ 0981 FE 40 CP '@' ; Is it "kill line"? -0928+ 0983 CA 3F 09 JP Z,OTKLN ; Yes - Kill line -0929+ 0986 FE 5F CP '_' ; Is it delete? -0930+ 0988 CA 37 09 JP Z,DELCHR ; Yes - Delete character -0931+ 098B FE 08 CP BKSP ; Is it backspace? -0932+ 098D CA 37 09 JP Z,DELCHR ; Yes - Delete character -0933+ 0990 FE 12 CP CTRLR ; Is it control "R"? -0934+ 0992 C2 A9 09 JP NZ,PUTBUF ; No - Put in buffer -0935+ 0995 C5 PUSH BC ; Save buffer length -0936+ 0996 D5 PUSH DE ; Save DE -0937+ 0997 E5 PUSH HL ; Save buffer address -0938+ 0998 36 00 LD (HL),0 ; Mark end of buffer -0939+ 099A CD B3 1F CALL OUTNCR ; Output and do CRLF -0940+ 099D 21 11 31 LD HL,BUFFER ; Point to buffer start -0941+ 09A0 CD A1 14 CALL PRS ; Output buffer -0942+ 09A3 E1 POP HL ; Restore buffer address -0943+ 09A4 D1 POP DE ; Restore DE -0944+ 09A5 C1 POP BC ; Restore buffer length -0945+ 09A6 C3 51 09 JP MORINP ; Get another character -0946+ 09A9 -0947+ 09A9 FE 20 PUTBUF: CP ' ' ; Is it a control code? -0948+ 09AB DA 51 09 JP C,MORINP ; Yes - Ignore -0949+ 09AE 78 PUTCTL: LD A,B ; Get number of bytes in buffer -0950+ 09AF FE 49 CP 72+1 ; Test for line overflow -0951+ 09B1 3E 07 LD A,CTRLG ; Set a bell -0952+ 09B3 D2 C3 09 JP NC,OUTNBS ; Ring bell if buffer full -0953+ 09B6 79 LD A,C ; Get character -0954+ 09B7 71 LD (HL),C ; Save in buffer -0955+ 09B8 32 7C 31 LD (LSTBIN),A ; Save last input byte -0956+ 09BB 23 INC HL ; Move up buffer -0957+ 09BC 04 INC B ; Increment length -0958+ 09BD CD DC 09 OUTIT: CALL OUTC ; Output the character entered -0959+ 09C0 C3 51 09 JP MORINP ; Get another character -0960+ 09C3 -0961+ 09C3 CD DC 09 OUTNBS: CALL OUTC ; Output bell and back over it -0962+ 09C6 3E 08 LD A,BKSP ; Set back space -0963+ 09C8 C3 BD 09 JP OUTIT ; Output it and get more -0964+ 09CB -0965+ 09CB 7C CPDEHL: LD A,H ; Get H -0966+ 09CC 92 SUB D ; Compare with D -0967+ 09CD C0 RET NZ ; Different - Exit -0968+ 09CE 7D LD A,L ; Get L -0969+ 09CF 93 SUB E ; Compare with E -0970+ 09D0 C9 RET ; Return status -0971+ 09D1 -0972+ 09D1 7E CHKSYN: LD A,(HL) ; Check syntax of character -0973+ 09D2 E3 EX (SP),HL ; Address of test byte -0974+ 09D3 BE CP (HL) ; Same as in code string? -0975+ 09D4 23 INC HL ; Return address -0976+ 09D5 E3 EX (SP),HL ; Put it back -0977+ 09D6 CA 5B 0B JP Z,GETCHR ; Yes - Get next character -0978+ 09D9 C3 03 07 JP SNERR ; Different - ?SN Error -0979+ 09DC -0980+ 09DC F5 OUTC: PUSH AF ; Save character -0981+ 09DD 3A F5 30 LD A,(CTLOFG) ; Get control "O" flag -0982+ 09E0 B7 OR A ; Is it set? -0983+ 09E1 C2 D6 14 JP NZ,POPAF ; Yes - don't output -0984+ 09E4 F1 POP AF ; Restore character -0985+ 09E5 C5 PUSH BC ; Save buffer length -0986+ 09E6 F5 PUSH AF ; Save character -0987+ 09E7 FE 20 CP ' ' ; Is it a control code? -0988+ 09E9 DA 00 0A JP C,DINPOS ; Yes - Don't INC POS(X) -0989+ 09EC 3A F2 30 LD A,(LWIDTH) ; Get line width -0990+ 09EF 47 LD B,A ; To B -0991+ 09F0 3A 5B 31 LD A,(CURPOS) ; Get cursor position -0992+ 09F3 04 INC B ; Width 255? -0993+ 09F4 CA FC 09 JP Z,INCLEN ; Yes - No width limit -0994+ 09F7 05 DEC B ; Restore width -0995+ 09F8 B8 CP B ; At end of line? -0996+ 09F9 CC 03 0E CALL Z,PRNTCRLF ; Yes - output CRLF -0997+ 09FC 3C INCLEN: INC A ; Move on one character -0998+ 09FD 32 5B 31 LD (CURPOS),A ; Save new position -0999+ 0A00 F1 DINPOS: POP AF ; Restore character -1000+ 0A01 C1 POP BC ; Restore buffer length -1001+ 0A02 CD 9C 1F CALL MONOUT ; Send it -1002+ 0A05 C9 RET -1003+ 0A06 -1004+ 0A06 CD 60 1E CLOTST: CALL GETINP ; Get input character -1005+ 0A09 E6 7F AND 01111111B ; Strip bit 7 -1006+ 0A0B FE 0F CP CTRLO ; Is it control "O"? -1007+ 0A0D C0 RET NZ ; No don't flip flag -1008+ 0A0E 3A F5 30 LD A,(CTLOFG) ; Get flag -1009+ 0A11 2F CPL ; Flip it -1010+ 0A12 32 F5 30 LD (CTLOFG),A ; Put it back -1011+ 0A15 AF XOR A ; Null character -1012+ 0A16 C9 RET -1013+ 0A17 -1014+ 0A17 CD 27 0C LIST: CALL ATOH ; ASCII number to DE -1015+ 0A1A C0 RET NZ ; Return if anything extra -1016+ 0A1B C1 POP BC ; Rubbish - Not needed -1017+ 0A1C CD EF 07 CALL SRCHLN ; Search for line number in DE -1018+ 0A1F C5 PUSH BC ; Save address of line -1019+ 0A20 CD 6D 0A CALL SETLIN ; Set up lines counter -1020+ 0A23 E1 LISTLP: POP HL ; Restore address of line -1021+ 0A24 4E LD C,(HL) ; Get LSB of next line -1022+ 0A25 23 INC HL -1023+ 0A26 46 LD B,(HL) ; Get MSB of next line -1024+ 0A27 23 INC HL -1025+ 0A28 78 LD A,B ; BC = 0 (End of program)? -1026+ 0A29 B1 OR C -1027+ 0A2A CA 4E 07 JP Z,PRNTOK ; Yes - Go to command mode -1028+ 0A2D CD 76 0A CALL COUNT ; Count lines -1029+ 0A30 CD 86 0B CALL TSTBRK ; Test for break key -1030+ 0A33 C5 PUSH BC ; Save address of next line -1031+ 0A34 CD 03 0E CALL PRNTCRLF ; Output CRLF -1032+ 0A37 5E LD E,(HL) ; Get LSB of line number -1033+ 0A38 23 INC HL -1034+ 0A39 56 LD D,(HL) ; Get MSB of line number -1035+ 0A3A 23 INC HL -1036+ 0A3B E5 PUSH HL ; Save address of line start -1037+ 0A3C EB EX DE,HL ; Line number to HL -1038+ 0A3D CD 44 1B CALL PRNTHL ; Output line number in decimal -1039+ 0A40 3E 20 LD A,' ' ; Space after line number -1040+ 0A42 E1 POP HL ; Restore start of line address -1041+ 0A43 CD DC 09 LSTLP2: CALL OUTC ; Output character in A -1042+ 0A46 7E LSTLP3: LD A,(HL) ; Get next byte in line -1043+ 0A47 B7 OR A ; End of line? -1044+ 0A48 23 INC HL ; To next byte in line -1045+ 0A49 CA 23 0A JP Z,LISTLP ; Yes - get next line -1046+ 0A4C F2 43 0A JP P,LSTLP2 ; No token - output it -1047+ 0A4F D6 7F SUB ZEND-1 ; Find and output word -1048+ 0A51 4F LD C,A ; Token offset+1 to C -1049+ 0A52 11 8C 04 LD DE,WORDS ; Reserved word list -1050+ 0A55 1A FNDTOK: LD A,(DE) ; Get character in list -1051+ 0A56 13 INC DE ; Move on to next -1052+ 0A57 B7 OR A ; Is it start of word? -1053+ 0A58 F2 55 0A JP P,FNDTOK ; No - Keep looking for word -1054+ 0A5B 0D DEC C ; Count words -1055+ 0A5C C2 55 0A JP NZ,FNDTOK ; Not there - keep looking -1056+ 0A5F E6 7F OUTWRD: AND 01111111B ; Strip bit 7 -1057+ 0A61 CD DC 09 CALL OUTC ; Output first character -1058+ 0A64 1A LD A,(DE) ; Get next character -1059+ 0A65 13 INC DE ; Move on to next -1060+ 0A66 B7 OR A ; Is it end of word? -1061+ 0A67 F2 5F 0A JP P,OUTWRD ; No - output the rest -1062+ 0A6A C3 46 0A JP LSTLP3 ; Next byte in line -1063+ 0A6D -1064+ 0A6D E5 SETLIN: PUSH HL ; Set up LINES counter -1065+ 0A6E 2A F8 30 LD HL,(LINESN) ; Get LINES number -1066+ 0A71 22 F6 30 LD (LINESC),HL ; Save in LINES counter -1067+ 0A74 E1 POP HL -1068+ 0A75 C9 RET -1069+ 0A76 -1070+ 0A76 E5 COUNT: PUSH HL ; Save code string address -1071+ 0A77 D5 PUSH DE -1072+ 0A78 2A F6 30 LD HL,(LINESC) ; Get LINES counter -1073+ 0A7B 11 FF FF LD DE,-1 -1074+ 0A7E ED 5A ADC HL,DE ; Decrement -1075+ 0A80 22 F6 30 LD (LINESC),HL ; Put it back -1076+ 0A83 D1 POP DE -1077+ 0A84 E1 POP HL ; Restore code string address -1078+ 0A85 F0 RET P ; Return if more lines to go -1079+ 0A86 E5 PUSH HL ; Save code string address -1080+ 0A87 2A F8 30 LD HL,(LINESN) ; Get LINES number -1081+ 0A8A 22 F6 30 LD (LINESC),HL ; Reset LINES counter -1082+ 0A8D CD 60 1E CALL GETINP ; Get input character -1083+ 0A90 FE 03 CP CTRLC ; Is it control "C"? -1084+ 0A92 CA 99 0A JP Z,RSLNBK ; Yes - Reset LINES and break -1085+ 0A95 E1 POP HL ; Restore code string address -1086+ 0A96 C3 76 0A JP COUNT ; Keep on counting -1087+ 0A99 -1088+ 0A99 2A F8 30 RSLNBK: LD HL,(LINESN) ; Get LINES number -1089+ 0A9C 22 F6 30 LD (LINESC),HL ; Reset LINES counter -1090+ 0A9F C3 FD 03 JP BRKRET ; Go and output "Break" -1091+ 0AA2 -1092+ 0AA2 3E 64 FOR: LD A,64H ; Flag "FOR" assignment -1093+ 0AA4 32 7B 31 LD (FORFLG),A ; Save "FOR" flag -1094+ 0AA7 CD 09 0D CALL LET ; Set up initial index -1095+ 0AAA C1 POP BC ; Drop RETurn address -1096+ 0AAB E5 PUSH HL ; Save code string address -1097+ 0AAC CD F2 0C CALL DATA ; Get next statement address -1098+ 0AAF 22 77 31 LD (LOOPST),HL ; Save it for start of loop -1099+ 0AB2 21 02 00 LD HL,2 ; Offset for "FOR" block -1100+ 0AB5 39 ADD HL,SP ; Point to it -1101+ 0AB6 CD B0 06 FORSLP: CALL LOKFOR ; Look for existing "FOR" block -1102+ 0AB9 D1 POP DE ; Get code string address -1103+ 0ABA C2 D2 0A JP NZ,FORFND ; No nesting found -1104+ 0ABD 09 ADD HL,BC ; Move into "FOR" block -1105+ 0ABE D5 PUSH DE ; Save code string address -1106+ 0ABF 2B DEC HL -1107+ 0AC0 56 LD D,(HL) ; Get MSB of loop statement -1108+ 0AC1 2B DEC HL -1109+ 0AC2 5E LD E,(HL) ; Get LSB of loop statement -1110+ 0AC3 23 INC HL -1111+ 0AC4 23 INC HL -1112+ 0AC5 E5 PUSH HL ; Save block address -1113+ 0AC6 2A 77 31 LD HL,(LOOPST) ; Get address of loop statement -1114+ 0AC9 CD CB 09 CALL CPDEHL ; Compare the FOR loops -1115+ 0ACC E1 POP HL ; Restore block address -1116+ 0ACD C2 B6 0A JP NZ,FORSLP ; Different FORs - Find another -1117+ 0AD0 D1 POP DE ; Restore code string address -1118+ 0AD1 F9 LD SP,HL ; Remove all nested loops -1119+ 0AD2 -1120+ 0AD2 EB FORFND: EX DE,HL ; Code string address to HL -1121+ 0AD3 0E 08 LD C,8 -1122+ 0AD5 CD E0 06 CALL CHKSTK ; Check for 8 levels of stack -1123+ 0AD8 E5 PUSH HL ; Save code string address -1124+ 0AD9 2A 77 31 LD HL,(LOOPST) ; Get first statement of loop -1125+ 0ADC E3 EX (SP),HL ; Save and restore code string -1126+ 0ADD E5 PUSH HL ; Re-save code string address -1127+ 0ADE 2A 0C 31 LD HL,(LINEAT) ; Get current line number -1128+ 0AE1 E3 EX (SP),HL ; Save and restore code string -1129+ 0AE2 CD CB 0F CALL TSTNUM ; Make sure it's a number -1130+ 0AE5 CD D1 09 CALL CHKSYN ; Make sure "TO" is next -1131+ 0AE8 A6 .BYTE ZTO ; "TO" token -1132+ 0AE9 CD C8 0F CALL GETNUM ; Get "TO" expression value -1133+ 0AEC E5 PUSH HL ; Save code string address -1134+ 0AED CD F6 19 CALL BCDEFP ; Move "TO" value to BCDE -1135+ 0AF0 E1 POP HL ; Restore code string address -1136+ 0AF1 C5 PUSH BC ; Save "TO" value in block -1137+ 0AF2 D5 PUSH DE -1138+ 0AF3 01 00 81 LD BC,8100H ; BCDE - 1 (default STEP) -1139+ 0AF6 51 LD D,C ; C=0 -1140+ 0AF7 5A LD E,D ; D=0 -1141+ 0AF8 7E LD A,(HL) ; Get next byte in code string -1142+ 0AF9 FE AB CP ZSTEP ; See if "STEP" is stated -1143+ 0AFB 3E 01 LD A,1 ; Sign of step = 1 -1144+ 0AFD C2 0E 0B JP NZ,SAVSTP ; No STEP given - Default to 1 -1145+ 0B00 CD 5B 0B CALL GETCHR ; Jump over "STEP" token -1146+ 0B03 CD C8 0F CALL GETNUM ; Get step value -1147+ 0B06 E5 PUSH HL ; Save code string address -1148+ 0B07 CD F6 19 CALL BCDEFP ; Move STEP to BCDE -1149+ 0B0A CD AA 19 CALL TSTSGN ; Test sign of FPREG -1150+ 0B0D E1 POP HL ; Restore code string address -1151+ 0B0E C5 SAVSTP: PUSH BC ; Save the STEP value in block -1152+ 0B0F D5 PUSH DE -1153+ 0B10 F5 PUSH AF ; Save sign of STEP -1154+ 0B11 33 INC SP ; Don't save flags -1155+ 0B12 E5 PUSH HL ; Save code string address -1156+ 0B13 2A 7E 31 LD HL,(BRKLIN) ; Get address of index variable -1157+ 0B16 E3 EX (SP),HL ; Save and restore code string -1158+ 0B17 06 81 PUTFID: LD B,ZFOR ; "FOR" block marker -1159+ 0B19 C5 PUSH BC ; Save it -1160+ 0B1A 33 INC SP ; Don't save C -1161+ 0B1B -1162+ 0B1B CD 86 0B RUNCNT: CALL TSTBRK ; Execution driver - Test break -1163+ 0B1E 22 7E 31 LD (BRKLIN),HL ; Save code address for break -1164+ 0B21 7E LD A,(HL) ; Get next byte in code string -1165+ 0B22 FE 3A CP ':' ; Multi statement line? -1166+ 0B24 CA 3B 0B JP Z,EXCUTE ; Yes - Execute it -1167+ 0B27 B7 OR A ; End of line? -1168+ 0B28 C2 03 07 JP NZ,SNERR ; No - Syntax error -1169+ 0B2B 23 INC HL ; Point to address of next line -1170+ 0B2C 7E LD A,(HL) ; Get LSB of line pointer -1171+ 0B2D 23 INC HL -1172+ 0B2E B6 OR (HL) ; Is it zero (End of prog)? -1173+ 0B2F CA AD 0B JP Z,ENDPRG ; Yes - Terminate execution -1174+ 0B32 23 INC HL ; Point to line number -1175+ 0B33 5E LD E,(HL) ; Get LSB of line number -1176+ 0B34 23 INC HL -1177+ 0B35 56 LD D,(HL) ; Get MSB of line number -1178+ 0B36 EB EX DE,HL ; Line number to HL -1179+ 0B37 22 0C 31 LD (LINEAT),HL ; Save as current line number -1180+ 0B3A EB EX DE,HL ; Line number back to DE -1181+ 0B3B CD 5B 0B EXCUTE: CALL GETCHR ; Get key word -1182+ 0B3E 11 1B 0B LD DE,RUNCNT ; Where to RETurn to -1183+ 0B41 D5 PUSH DE ; Save for RETurn -1184+ 0B42 C8 IFJMP: RET Z ; Go to RUNCNT if end of STMT -1185+ 0B43 D6 80 ONJMP: SUB ZEND ; Is it a token? -1186+ 0B45 DA 09 0D JP C,LET ; No - try to assign it -1187+ 0B48 FE 25 CP ZNEW+1-ZEND ; END to NEW ? -1188+ 0B4A D2 03 07 JP NC,SNERR ; Not a key word - ?SN Error -1189+ 0B4D 07 RLCA ; Double it -1190+ 0B4E 4F LD C,A ; BC = Offset into table -1191+ 0B4F 06 00 LD B,0 -1192+ 0B51 EB EX DE,HL ; Save code string address -1193+ 0B52 21 AB 05 LD HL,WORDTB ; Keyword address table -1194+ 0B55 09 ADD HL,BC ; Point to routine address -1195+ 0B56 4E LD C,(HL) ; Get LSB of routine address -1196+ 0B57 23 INC HL -1197+ 0B58 46 LD B,(HL) ; Get MSB of routine address -1198+ 0B59 C5 PUSH BC ; Save routine address -1199+ 0B5A EB EX DE,HL ; Restore code string address -1200+ 0B5B -1201+ 0B5B 23 GETCHR: INC HL ; Point to next character -1202+ 0B5C 7E LD A,(HL) ; Get next code string byte -1203+ 0B5D FE 3A CP ':' ; Z if ':' -1204+ 0B5F D0 RET NC ; NC if > "9" -1205+ 0B60 FE 20 CP ' ' -1206+ 0B62 CA 5B 0B JP Z,GETCHR ; Skip over spaces -1207+ 0B65 FE 30 CP '0' -1208+ 0B67 3F CCF ; NC if < '0' -1209+ 0B68 3C INC A ; Test for zero - Leave carry -1210+ 0B69 3D DEC A ; Z if Null -1211+ 0B6A C9 RET -1212+ 0B6B -1213+ 0B6B EB RESTOR: EX DE,HL ; Save code string address -1214+ 0B6C 2A 0E 31 LD HL,(BASTXT) ; Point to start of program -1215+ 0B6F CA 80 0B JP Z,RESTNL ; Just RESTORE - reset pointer -1216+ 0B72 EB EX DE,HL ; Restore code string address -1217+ 0B73 CD 27 0C CALL ATOH ; Get line number to DE -1218+ 0B76 E5 PUSH HL ; Save code string address -1219+ 0B77 CD EF 07 CALL SRCHLN ; Search for line number in DE -1220+ 0B7A 60 LD H,B ; HL = Address of line -1221+ 0B7B 69 LD L,C -1222+ 0B7C D1 POP DE ; Restore code string address -1223+ 0B7D D2 C8 0C JP NC,ULERR ; ?UL Error if not found -1224+ 0B80 2B RESTNL: DEC HL ; Byte before DATA statement -1225+ 0B81 22 8C 31 UPDATA: LD (NXTDAT),HL ; Update DATA pointer -1226+ 0B84 EB EX DE,HL ; Restore code string address -1227+ 0B85 C9 RET -1228+ 0B86 -1229+ 0B86 -1230+ 0B86 DF TSTBRK: RST 18H ; Check input status -1231+ 0B87 C8 RET Z ; No key, go back -1232+ 0B88 D7 RST 10H ; Get the key into A -1233+ 0B89 FE 1B CP ESC ; Escape key? -1234+ 0B8B 28 11 JR Z,BRK ; Yes, break -1235+ 0B8D FE 03 CP CTRLC ; -1236+ 0B8F 28 0D JR Z,BRK ; Yes, break -1237+ 0B91 FE 13 CP CTRLS ; Stop scrolling? -1238+ 0B93 C0 RET NZ ; Other key, ignore -1239+ 0B94 -1240+ 0B94 -1241+ 0B94 D7 STALL: RST 10H ; Wait for key -1242+ 0B95 FE 11 CP CTRLQ ; Resume scrolling? -1243+ 0B97 C8 RET Z ; Release the chokehold -1244+ 0B98 FE 03 CP CTRLC ; Second break? -1245+ 0B9A 28 07 JR Z,STOP ; Break during hold exits prog -1246+ 0B9C 18 F6 JR STALL ; Loop until or -1247+ 0B9E -1248+ 0B9E 3E FF BRK LD A,$FF ; Set BRKFLG -1249+ 0BA0 32 FD 30 LD (BRKFLG),A ; Store it -1250+ 0BA3 -1251+ 0BA3 -1252+ 0BA3 C0 STOP: RET NZ ; Exit if anything else -1253+ 0BA4 F6 .BYTE 0F6H ; Flag "STOP" -1254+ 0BA5 C0 PEND: RET NZ ; Exit if anything else -1255+ 0BA6 22 7E 31 LD (BRKLIN),HL ; Save point of break -1256+ 0BA9 21 .BYTE 21H ; Skip "OR 11111111B" -1257+ 0BAA F6 FF INPBRK: OR 11111111B ; Flag "Break" wanted -1258+ 0BAC C1 POP BC ; Return not needed and more -1259+ 0BAD 2A 0C 31 ENDPRG: LD HL,(LINEAT) ; Get current line number -1260+ 0BB0 F5 PUSH AF ; Save STOP / END status -1261+ 0BB1 7D LD A,L ; Is it direct break? -1262+ 0BB2 A4 AND H -1263+ 0BB3 3C INC A ; Line is -1 if direct break -1264+ 0BB4 CA C0 0B JP Z,NOLIN ; Yes - No line number -1265+ 0BB7 22 82 31 LD (ERRLIN),HL ; Save line of break -1266+ 0BBA 2A 7E 31 LD HL,(BRKLIN) ; Get point of break -1267+ 0BBD 22 84 31 LD (CONTAD),HL ; Save point to CONTinue -1268+ 0BC0 AF NOLIN: XOR A -1269+ 0BC1 32 F5 30 LD (CTLOFG),A ; Enable output -1270+ 0BC4 CD F6 0D CALL STTLIN ; Start a new line -1271+ 0BC7 F1 POP AF ; Restore STOP / END status -1272+ 0BC8 21 A6 06 LD HL,BRKMSG ; "Break" message -1273+ 0BCB C2 37 07 JP NZ,ERRIN ; "in line" wanted? -1274+ 0BCE C3 4E 07 JP PRNTOK ; Go to command mode -1275+ 0BD1 -1276+ 0BD1 2A 84 31 CONT: LD HL,(CONTAD) ; Get CONTinue address -1277+ 0BD4 7C LD A,H ; Is it zero? -1278+ 0BD5 B5 OR L -1279+ 0BD6 1E 20 LD E,CN ; ?CN Error -1280+ 0BD8 CA 17 07 JP Z,ERROR ; Yes - output "?CN Error" -1281+ 0BDB EB EX DE,HL ; Save code string address -1282+ 0BDC 2A 82 31 LD HL,(ERRLIN) ; Get line of last break -1283+ 0BDF 22 0C 31 LD (LINEAT),HL ; Set up current line number -1284+ 0BE2 EB EX DE,HL ; Restore code string address -1285+ 0BE3 C9 RET ; CONTinue where left off -1286+ 0BE4 -1287+ 0BE4 CD 29 17 NULL: CALL GETINT ; Get integer 0-255 -1288+ 0BE7 C0 RET NZ ; Return if bad value -1289+ 0BE8 32 F1 30 LD (NULLS),A ; Set nulls number -1290+ 0BEB C9 RET -1291+ 0BEC -1292+ 0BEC -1293+ 0BEC E5 ACCSUM: PUSH HL ; Save address in array -1294+ 0BED 2A FA 30 LD HL,(CHKSUM) ; Get check sum -1295+ 0BF0 06 00 LD B,0 ; BC - Value of byte -1296+ 0BF2 4F LD C,A -1297+ 0BF3 09 ADD HL,BC ; Add byte to check sum -1298+ 0BF4 22 FA 30 LD (CHKSUM),HL ; Re-save check sum -1299+ 0BF7 E1 POP HL ; Restore address in array -1300+ 0BF8 C9 RET -1301+ 0BF9 -1302+ 0BF9 7E CHKLTR: LD A,(HL) ; Get byte -1303+ 0BFA FE 41 CP 'A' ; < 'a' ? -1304+ 0BFC D8 RET C ; Carry set if not letter -1305+ 0BFD FE 5B CP 'Z'+1 ; > 'z' ? -1306+ 0BFF 3F CCF -1307+ 0C00 C9 RET ; Carry set if not letter -1308+ 0C01 -1309+ 0C01 CD 5B 0B FPSINT: CALL GETCHR ; Get next character -1310+ 0C04 CD C8 0F POSINT: CALL GETNUM ; Get integer 0 to 32767 -1311+ 0C07 CD AA 19 DEPINT: CALL TSTSGN ; Test sign of FPREG -1312+ 0C0A FA 22 0C JP M,FCERR ; Negative - ?FC Error -1313+ 0C0D 3A 97 31 DEINT: LD A,(FPEXP) ; Get integer value to DE -1314+ 0C10 FE 90 CP 80H+16 ; Exponent in range (16 bits)? -1315+ 0C12 DA 52 1A JP C,FPINT ; Yes - convert it -1316+ 0C15 01 80 90 LD BC,9080H ; BCDE = -32768 -1317+ 0C18 11 00 00 LD DE,0000 -1318+ 0C1B E5 PUSH HL ; Save code string address -1319+ 0C1C CD 25 1A CALL CMPNUM ; Compare FPREG with BCDE -1320+ 0C1F E1 POP HL ; Restore code string address -1321+ 0C20 51 LD D,C ; MSB to D -1322+ 0C21 C8 RET Z ; Return if in range -1323+ 0C22 1E 08 FCERR: LD E,FC ; ?FC Error -1324+ 0C24 C3 17 07 JP ERROR ; Output error- -1325+ 0C27 -1326+ 0C27 2B ATOH: DEC HL ; ASCII number to DE binary -1327+ 0C28 11 00 00 GETLN: LD DE,0 ; Get number to DE -1328+ 0C2B CD 5B 0B GTLNLP: CALL GETCHR ; Get next character -1329+ 0C2E D0 RET NC ; Exit if not a digit -1330+ 0C2F E5 PUSH HL ; Save code string address -1331+ 0C30 F5 PUSH AF ; Save digit -1332+ 0C31 21 98 19 LD HL,65529/10 ; Largest number 65529 -1333+ 0C34 CD CB 09 CALL CPDEHL ; Number in range? -1334+ 0C37 DA 03 07 JP C,SNERR ; No - ?SN Error -1335+ 0C3A 62 LD H,D ; HL = Number -1336+ 0C3B 6B LD L,E -1337+ 0C3C 19 ADD HL,DE ; Times 2 -1338+ 0C3D 29 ADD HL,HL ; Times 4 -1339+ 0C3E 19 ADD HL,DE ; Times 5 -1340+ 0C3F 29 ADD HL,HL ; Times 10 -1341+ 0C40 F1 POP AF ; Restore digit -1342+ 0C41 D6 30 SUB '0' ; Make it 0 to 9 -1343+ 0C43 5F LD E,A ; DE = Value of digit -1344+ 0C44 16 00 LD D,0 -1345+ 0C46 19 ADD HL,DE ; Add to number -1346+ 0C47 EB EX DE,HL ; Number to DE -1347+ 0C48 E1 POP HL ; Restore code string address -1348+ 0C49 C3 2B 0C JP GTLNLP ; Go to next character -1349+ 0C4C -1350+ 0C4C CA 1F 08 CLEAR: JP Z,INTVAR ; Just "CLEAR" Keep parameters -1351+ 0C4F CD 04 0C CALL POSINT ; Get integer 0 to 32767 to DE -1352+ 0C52 2B DEC HL ; Cancel increment -1353+ 0C53 CD 5B 0B CALL GETCHR ; Get next character -1354+ 0C56 E5 PUSH HL ; Save code string address -1355+ 0C57 2A 5F 31 LD HL,(LSTRAM) ; Get end of RAM -1356+ 0C5A CA 6F 0C JP Z,STORED ; No value given - Use stored -1357+ 0C5D E1 POP HL ; Restore code string address -1358+ 0C5E CD D1 09 CALL CHKSYN ; Check for comma -1359+ 0C61 2C .BYTE ',' -1360+ 0C62 D5 PUSH DE ; Save number -1361+ 0C63 CD 04 0C CALL POSINT ; Get integer 0 to 32767 -1362+ 0C66 2B DEC HL ; Cancel increment -1363+ 0C67 CD 5B 0B CALL GETCHR ; Get next character -1364+ 0C6A C2 03 07 JP NZ,SNERR ; ?SN Error if more on line -1365+ 0C6D E3 EX (SP),HL ; Save code string address -1366+ 0C6E EB EX DE,HL ; Number to DE -1367+ 0C6F 7D STORED: LD A,L ; Get LSB of new RAM top -1368+ 0C70 93 SUB E ; Subtract LSB of string space -1369+ 0C71 5F LD E,A ; Save LSB -1370+ 0C72 7C LD A,H ; Get MSB of new RAM top -1371+ 0C73 9A SBC A,D ; Subtract MSB of string space -1372+ 0C74 57 LD D,A ; Save MSB -1373+ 0C75 DA F8 06 JP C,OMERR ; ?OM Error if not enough mem -1374+ 0C78 E5 PUSH HL ; Save RAM top -1375+ 0C79 2A 86 31 LD HL,(PROGND) ; Get program end -1376+ 0C7C 01 28 00 LD BC,40 ; 40 Bytes minimum working RAM -1377+ 0C7F 09 ADD HL,BC ; Get lowest address -1378+ 0C80 CD CB 09 CALL CPDEHL ; Enough memory? -1379+ 0C83 D2 F8 06 JP NC,OMERR ; No - ?OM Error -1380+ 0C86 EB EX DE,HL ; RAM top to HL -1381+ 0C87 22 0A 31 LD (STRSPC),HL ; Set new string space -1382+ 0C8A E1 POP HL ; End of memory to use -1383+ 0C8B 22 5F 31 LD (LSTRAM),HL ; Set new top of RAM -1384+ 0C8E E1 POP HL ; Restore code string address -1385+ 0C8F C3 1F 08 JP INTVAR ; Initialise variables -1386+ 0C92 -1387+ 0C92 CA 1B 08 RUN: JP Z,RUNFST ; RUN from start if just RUN -1388+ 0C95 CD 1F 08 CALL INTVAR ; Initialise variables -1389+ 0C98 01 1B 0B LD BC,RUNCNT ; Execution driver loop -1390+ 0C9B C3 AE 0C JP RUNLIN ; RUN from line number -1391+ 0C9E -1392+ 0C9E 0E 03 GOSUB: LD C,3 ; 3 Levels of stack needed -1393+ 0CA0 CD E0 06 CALL CHKSTK ; Check for 3 levels of stack -1394+ 0CA3 C1 POP BC ; Get return address -1395+ 0CA4 E5 PUSH HL ; Save code string for RETURN -1396+ 0CA5 E5 PUSH HL ; And for GOSUB routine -1397+ 0CA6 2A 0C 31 LD HL,(LINEAT) ; Get current line -1398+ 0CA9 E3 EX (SP),HL ; Into stack - Code string out -1399+ 0CAA 3E 8C LD A,ZGOSUB ; "GOSUB" token -1400+ 0CAC F5 PUSH AF ; Save token -1401+ 0CAD 33 INC SP ; Don't save flags -1402+ 0CAE -1403+ 0CAE C5 RUNLIN: PUSH BC ; Save return address -1404+ 0CAF CD 27 0C GOTO: CALL ATOH ; ASCII number to DE binary -1405+ 0CB2 CD F4 0C CALL REM ; Get end of line -1406+ 0CB5 E5 PUSH HL ; Save end of line -1407+ 0CB6 2A 0C 31 LD HL,(LINEAT) ; Get current line -1408+ 0CB9 CD CB 09 CALL CPDEHL ; Line after current? -1409+ 0CBC E1 POP HL ; Restore end of line -1410+ 0CBD 23 INC HL ; Start of next line -1411+ 0CBE DC F2 07 CALL C,SRCHLP ; Line is after current line -1412+ 0CC1 D4 EF 07 CALL NC,SRCHLN ; Line is before current line -1413+ 0CC4 60 LD H,B ; Set up code string address -1414+ 0CC5 69 LD L,C -1415+ 0CC6 2B DEC HL ; Incremented after -1416+ 0CC7 D8 RET C ; Line found -1417+ 0CC8 1E 0E ULERR: LD E,UL ; ?UL Error -1418+ 0CCA C3 17 07 JP ERROR ; Output error message -1419+ 0CCD -1420+ 0CCD C0 RETURN: RET NZ ; Return if not just RETURN -1421+ 0CCE 16 FF LD D,-1 ; Flag "GOSUB" search -1422+ 0CD0 CD AC 06 CALL BAKSTK ; Look "GOSUB" block -1423+ 0CD3 F9 LD SP,HL ; Kill all FORs in subroutine -1424+ 0CD4 FE 8C CP ZGOSUB ; Test for "GOSUB" token -1425+ 0CD6 1E 04 LD E,RG ; ?RG Error -1426+ 0CD8 C2 17 07 JP NZ,ERROR ; Error if no "GOSUB" found -1427+ 0CDB E1 POP HL ; Get RETURN line number -1428+ 0CDC 22 0C 31 LD (LINEAT),HL ; Save as current -1429+ 0CDF 23 INC HL ; Was it from direct statement? -1430+ 0CE0 7C LD A,H -1431+ 0CE1 B5 OR L ; Return to line -1432+ 0CE2 C2 EC 0C JP NZ,RETLIN ; No - Return to line -1433+ 0CE5 3A 7C 31 LD A,(LSTBIN) ; Any INPUT in subroutine? -1434+ 0CE8 B7 OR A ; If so buffer is corrupted -1435+ 0CE9 C2 4D 07 JP NZ,POPNOK ; Yes - Go to command mode -1436+ 0CEC 21 1B 0B RETLIN: LD HL,RUNCNT ; Execution driver loop -1437+ 0CEF E3 EX (SP),HL ; Into stack - Code string out -1438+ 0CF0 3E .BYTE 3EH ; Skip "POP HL" -1439+ 0CF1 E1 NXTDTA: POP HL ; Restore code string address -1440+ 0CF2 -1441+ 0CF2 01 3A DATA: .BYTE 01H,3AH ; ':' End of statement -1442+ 0CF4 0E 00 REM: LD C,0 ; 00 End of statement -1443+ 0CF6 06 00 LD B,0 -1444+ 0CF8 79 NXTSTL: LD A,C ; Statement and byte -1445+ 0CF9 48 LD C,B -1446+ 0CFA 47 LD B,A ; Statement end byte -1447+ 0CFB 7E NXTSTT: LD A,(HL) ; Get byte -1448+ 0CFC B7 OR A ; End of line? -1449+ 0CFD C8 RET Z ; Yes - Exit -1450+ 0CFE B8 CP B ; End of statement? -1451+ 0CFF C8 RET Z ; Yes - Exit -1452+ 0D00 23 INC HL ; Next byte -1453+ 0D01 FE 22 CP '"' ; Literal string? -1454+ 0D03 CA F8 0C JP Z,NXTSTL ; Yes - Look for another '"' -1455+ 0D06 C3 FB 0C JP NXTSTT ; Keep looking -1456+ 0D09 -1457+ 0D09 CD BE 11 LET: CALL GETVAR ; Get variable name -1458+ 0D0C CD D1 09 CALL CHKSYN ; Make sure "=" follows -1459+ 0D0F B4 .BYTE ZEQUAL ; "=" token -1460+ 0D10 D5 PUSH DE ; Save address of variable -1461+ 0D11 3A 5D 31 LD A,(TYPE) ; Get data type -1462+ 0D14 F5 PUSH AF ; Save type -1463+ 0D15 CD DA 0F CALL EVAL ; Evaluate expression -1464+ 0D18 F1 POP AF ; Restore type -1465+ 0D19 E3 EX (SP),HL ; Save code - Get var addr -1466+ 0D1A 22 7E 31 LD (BRKLIN),HL ; Save address of variable -1467+ 0D1D 1F RRA ; Adjust type -1468+ 0D1E CD CD 0F CALL CHKTYP ; Check types are the same -1469+ 0D21 CA 5C 0D JP Z,LETNUM ; Numeric - Move value -1470+ 0D24 E5 LETSTR: PUSH HL ; Save address of string var -1471+ 0D25 2A 94 31 LD HL,(FPREG) ; Pointer to string entry -1472+ 0D28 E5 PUSH HL ; Save it on stack -1473+ 0D29 23 INC HL ; Skip over length -1474+ 0D2A 23 INC HL -1475+ 0D2B 5E LD E,(HL) ; LSB of string address -1476+ 0D2C 23 INC HL -1477+ 0D2D 56 LD D,(HL) ; MSB of string address -1478+ 0D2E 2A 0E 31 LD HL,(BASTXT) ; Point to start of program -1479+ 0D31 CD CB 09 CALL CPDEHL ; Is string before program? -1480+ 0D34 D2 4B 0D JP NC,CRESTR ; Yes - Create string entry -1481+ 0D37 2A 0A 31 LD HL,(STRSPC) ; Point to string space -1482+ 0D3A CD CB 09 CALL CPDEHL ; Is string literal in program? -1483+ 0D3D D1 POP DE ; Restore address of string -1484+ 0D3E D2 53 0D JP NC,MVSTPT ; Yes - Set up pointer -1485+ 0D41 21 6F 31 LD HL,TMPSTR ; Temporary string pool -1486+ 0D44 CD CB 09 CALL CPDEHL ; Is string in temporary pool? -1487+ 0D47 D2 53 0D JP NC,MVSTPT ; No - Set up pointer -1488+ 0D4A 3E .BYTE 3EH ; Skip "POP DE" -1489+ 0D4B D1 CRESTR: POP DE ; Restore address of string -1490+ 0D4C CD 02 16 CALL BAKTMP ; Back to last tmp-str entry -1491+ 0D4F EB EX DE,HL ; Address of string entry -1492+ 0D50 CD 3B 14 CALL SAVSTR ; Save string in string area -1493+ 0D53 CD 02 16 MVSTPT: CALL BAKTMP ; Back to last tmp-str entry -1494+ 0D56 E1 POP HL ; Get string pointer -1495+ 0D57 CD 05 1A CALL DETHL4 ; Move string pointer to var -1496+ 0D5A E1 POP HL ; Restore code string address -1497+ 0D5B C9 RET -1498+ 0D5C -1499+ 0D5C E5 LETNUM: PUSH HL ; Save address of variable -1500+ 0D5D CD 02 1A CALL FPTHL ; Move value to variable -1501+ 0D60 D1 POP DE ; Restore address of variable -1502+ 0D61 E1 POP HL ; Restore code string address -1503+ 0D62 C9 RET -1504+ 0D63 -1505+ 0D63 CD 29 17 ON: CALL GETINT ; Get integer 0-255 -1506+ 0D66 7E LD A,(HL) ; Get "GOTO" or "GOSUB" token -1507+ 0D67 47 LD B,A ; Save in B -1508+ 0D68 FE 8C CP ZGOSUB ; "GOSUB" token? -1509+ 0D6A CA 72 0D JP Z,ONGO ; Yes - Find line number -1510+ 0D6D CD D1 09 CALL CHKSYN ; Make sure it's "GOTO" -1511+ 0D70 88 .BYTE ZGOTO ; "GOTO" token -1512+ 0D71 2B DEC HL ; Cancel increment -1513+ 0D72 4B ONGO: LD C,E ; Integer of branch value -1514+ 0D73 0D ONGOLP: DEC C ; Count branches -1515+ 0D74 78 LD A,B ; Get "GOTO" or "GOSUB" token -1516+ 0D75 CA 43 0B JP Z,ONJMP ; Go to that line if right one -1517+ 0D78 CD 28 0C CALL GETLN ; Get line number to DE -1518+ 0D7B FE 2C CP ',' ; Another line number? -1519+ 0D7D C0 RET NZ ; No - Drop through -1520+ 0D7E C3 73 0D JP ONGOLP ; Yes - loop -1521+ 0D81 -1522+ 0D81 CD DA 0F IF: CALL EVAL ; Evaluate expression -1523+ 0D84 7E LD A,(HL) ; Get token -1524+ 0D85 FE 88 CP ZGOTO ; "GOTO" token? -1525+ 0D87 CA 8F 0D JP Z,IFGO ; Yes - Get line -1526+ 0D8A CD D1 09 CALL CHKSYN ; Make sure it's "THEN" -1527+ 0D8D A9 .BYTE ZTHEN ; "THEN" token -1528+ 0D8E 2B DEC HL ; Cancel increment -1529+ 0D8F CD CB 0F IFGO: CALL TSTNUM ; Make sure it's numeric -1530+ 0D92 CD AA 19 CALL TSTSGN ; Test state of expression -1531+ 0D95 CA F4 0C JP Z,REM ; False - Drop through -1532+ 0D98 CD 5B 0B CALL GETCHR ; Get next character -1533+ 0D9B DA AF 0C JP C,GOTO ; Number - GOTO that line -1534+ 0D9E C3 42 0B JP IFJMP ; Otherwise do statement -1535+ 0DA1 -1536+ 0DA1 2B MRPRNT: DEC HL ; DEC 'cos GETCHR INCs -1537+ 0DA2 CD 5B 0B CALL GETCHR ; Get next character -1538+ 0DA5 CA 03 0E PRINT: JP Z,PRNTCRLF ; CRLF if just PRINT -1539+ 0DA8 C8 PRNTLP: RET Z ; End of list - Exit -1540+ 0DA9 FE A5 CP ZTAB ; "TAB(" token? -1541+ 0DAB CA 36 0E JP Z,DOTAB ; Yes - Do TAB routine -1542+ 0DAE FE A8 CP ZSPC ; "SPC(" token? -1543+ 0DB0 CA 36 0E JP Z,DOTAB ; Yes - Do SPC routine -1544+ 0DB3 E5 PUSH HL ; Save code string address -1545+ 0DB4 FE 2C CP ',' ; Comma? -1546+ 0DB6 CA 1F 0E JP Z,DOCOM ; Yes - Move to next zone -1547+ 0DB9 FE 3B CP 59 ;";" ; Semi-colon? -1548+ 0DBB CA 59 0E JP Z,NEXITM ; Do semi-colon routine -1549+ 0DBE C1 POP BC ; Code string address to BC -1550+ 0DBF CD DA 0F CALL EVAL ; Evaluate expression -1551+ 0DC2 E5 PUSH HL ; Save code string address -1552+ 0DC3 3A 5D 31 LD A,(TYPE) ; Get variable type -1553+ 0DC6 B7 OR A ; Is it a string variable? -1554+ 0DC7 C2 EF 0D JP NZ,PRNTST ; Yes - Output string contents -1555+ 0DCA CD 4F 1B CALL NUMASC ; Convert number to text -1556+ 0DCD CD 5F 14 CALL CRTST ; Create temporary string -1557+ 0DD0 36 20 LD (HL),' ' ; Followed by a space -1558+ 0DD2 2A 94 31 LD HL,(FPREG) ; Get length of output -1559+ 0DD5 34 INC (HL) ; Plus 1 for the space -1560+ 0DD6 2A 94 31 LD HL,(FPREG) ; < Not needed > -1561+ 0DD9 3A F2 30 LD A,(LWIDTH) ; Get width of line -1562+ 0DDC 47 LD B,A ; To B -1563+ 0DDD 04 INC B ; Width 255 (No limit)? -1564+ 0DDE CA EB 0D JP Z,PRNTNB ; Yes - Output number string -1565+ 0DE1 04 INC B ; Adjust it -1566+ 0DE2 3A 5B 31 LD A,(CURPOS) ; Get cursor position -1567+ 0DE5 86 ADD A,(HL) ; Add length of string -1568+ 0DE6 3D DEC A ; Adjust it -1569+ 0DE7 B8 CP B ; Will output fit on this line? -1570+ 0DE8 D4 03 0E CALL NC,PRNTCRLF ; No - CRLF first -1571+ 0DEB CD A4 14 PRNTNB: CALL PRS1 ; Output string at (HL) -1572+ 0DEE AF XOR A ; Skip CALL by setting 'z' flag -1573+ 0DEF C4 A4 14 PRNTST: CALL NZ,PRS1 ; Output string at (HL) -1574+ 0DF2 E1 POP HL ; Restore code string address -1575+ 0DF3 C3 A1 0D JP MRPRNT ; See if more to PRINT -1576+ 0DF6 -1577+ 0DF6 3A 5B 31 STTLIN: LD A,(CURPOS) ; Make sure on new line -1578+ 0DF9 B7 OR A ; Already at start? -1579+ 0DFA C8 RET Z ; Yes - Do nothing -1580+ 0DFB C3 03 0E JP PRNTCRLF ; Start a new line -1581+ 0DFE -1582+ 0DFE 36 00 ENDINP: LD (HL),0 ; Mark end of buffer -1583+ 0E00 21 10 31 LD HL,BUFFER-1 ; Point to buffer -1584+ 0E03 3E 0D PRNTCRLF: LD A,CR ; Load a CR -1585+ 0E05 CD DC 09 CALL OUTC ; Output character -1586+ 0E08 3E 0A LD A,LF ; Load a LF -1587+ 0E0A CD DC 09 CALL OUTC ; Output character -1588+ 0E0D AF DONULL: XOR A ; Set to position 0 -1589+ 0E0E 32 5B 31 LD (CURPOS),A ; Store it -1590+ 0E11 3A F1 30 LD A,(NULLS) ; Get number of nulls -1591+ 0E14 3D NULLP: DEC A ; Count them -1592+ 0E15 C8 RET Z ; Return if done -1593+ 0E16 F5 PUSH AF ; Save count -1594+ 0E17 AF XOR A ; Load a null -1595+ 0E18 CD DC 09 CALL OUTC ; Output it -1596+ 0E1B F1 POP AF ; Restore count -1597+ 0E1C C3 14 0E JP NULLP ; Keep counting -1598+ 0E1F -1599+ 0E1F 3A F3 30 DOCOM: LD A,(COMMAN) ; Get comma width -1600+ 0E22 47 LD B,A ; Save in B -1601+ 0E23 3A 5B 31 LD A,(CURPOS) ; Get current position -1602+ 0E26 B8 CP B ; Within the limit? -1603+ 0E27 D4 03 0E CALL NC,PRNTCRLF ; No - output CRLF -1604+ 0E2A D2 59 0E JP NC,NEXITM ; Get next item -1605+ 0E2D D6 0E ZONELP: SUB 14 ; Next zone of 14 characters -1606+ 0E2F D2 2D 0E JP NC,ZONELP ; Repeat if more zones -1607+ 0E32 2F CPL ; Number of spaces to output -1608+ 0E33 C3 4E 0E JP ASPCS ; Output them -1609+ 0E36 -1610+ 0E36 F5 DOTAB: PUSH AF ; Save token -1611+ 0E37 CD 26 17 CALL FNDNUM ; Evaluate expression -1612+ 0E3A CD D1 09 CALL CHKSYN ; Make sure ")" follows -1613+ 0E3D 29 .BYTE ")" -1614+ 0E3E 2B DEC HL ; Back space on to ")" -1615+ 0E3F F1 POP AF ; Restore token -1616+ 0E40 D6 A8 SUB ZSPC ; Was it "SPC(" ? -1617+ 0E42 E5 PUSH HL ; Save code string address -1618+ 0E43 CA 49 0E JP Z,DOSPC ; Yes - Do 'E' spaces -1619+ 0E46 3A 5B 31 LD A,(CURPOS) ; Get current position -1620+ 0E49 2F DOSPC: CPL ; Number of spaces to print to -1621+ 0E4A 83 ADD A,E ; Total number to print -1622+ 0E4B D2 59 0E JP NC,NEXITM ; TAB < Current POS(X) -1623+ 0E4E 3C ASPCS: INC A ; Output A spaces -1624+ 0E4F 47 LD B,A ; Save number to print -1625+ 0E50 3E 20 LD A,' ' ; Space -1626+ 0E52 CD DC 09 SPCLP: CALL OUTC ; Output character in A -1627+ 0E55 05 DEC B ; Count them -1628+ 0E56 C2 52 0E JP NZ,SPCLP ; Repeat if more -1629+ 0E59 E1 NEXITM: POP HL ; Restore code string address -1630+ 0E5A CD 5B 0B CALL GETCHR ; Get next character -1631+ 0E5D C3 A8 0D JP PRNTLP ; More to print -1632+ 0E60 -1633+ 0E60 3F 52 65 64 REDO: .BYTE "?Redo from start",CR,LF,0 -1633+ 0E64 6F 20 66 72 -1633+ 0E68 6F 6D 20 73 -1633+ 0E6C 74 61 72 74 -1633+ 0E70 0D 0A 00 -1634+ 0E73 -1635+ 0E73 3A 7D 31 BADINP: LD A,(READFG) ; READ or INPUT? -1636+ 0E76 B7 OR A -1637+ 0E77 C2 FD 06 JP NZ,DATSNR ; READ - ?SN Error -1638+ 0E7A C1 POP BC ; Throw away code string addr -1639+ 0E7B 21 60 0E LD HL,REDO ; "Redo from start" message -1640+ 0E7E CD A1 14 CALL PRS ; Output string -1641+ 0E81 C3 4E 08 JP DOAGN ; Do last INPUT again -1642+ 0E84 -1643+ 0E84 CD 0C 14 INPUT: CALL IDTEST ; Test for illegal direct -1644+ 0E87 7E LD A,(HL) ; Get character after "INPUT" -1645+ 0E88 FE 22 CP '"' ; Is there a prompt string? -1646+ 0E8A 3E 00 LD A,0 ; Clear A and leave flags -1647+ 0E8C 32 F5 30 LD (CTLOFG),A ; Enable output -1648+ 0E8F C2 9E 0E JP NZ,NOPMPT ; No prompt - get input -1649+ 0E92 CD 60 14 CALL QTSTR ; Get string terminated by '"' -1650+ 0E95 CD D1 09 CALL CHKSYN ; Check for ';' after prompt -1651+ 0E98 3B .BYTE ';' -1652+ 0E99 E5 PUSH HL ; Save code string address -1653+ 0E9A CD A4 14 CALL PRS1 ; Output prompt string -1654+ 0E9D 3E .BYTE 3EH ; Skip "PUSH HL" -1655+ 0E9E E5 NOPMPT: PUSH HL ; Save code string address -1656+ 0E9F CD 52 08 CALL PROMPT ; Get input with "? " prompt -1657+ 0EA2 C1 POP BC ; Restore code string address -1658+ 0EA3 DA AA 0B JP C,INPBRK ; Break pressed - Exit -1659+ 0EA6 23 INC HL ; Next byte -1660+ 0EA7 7E LD A,(HL) ; Get it -1661+ 0EA8 B7 OR A ; End of line? -1662+ 0EA9 2B DEC HL ; Back again -1663+ 0EAA C5 PUSH BC ; Re-save code string address -1664+ 0EAB CA F1 0C JP Z,NXTDTA ; Yes - Find next DATA stmt -1665+ 0EAE 36 2C LD (HL),',' ; Store comma as separator -1666+ 0EB0 C3 B8 0E JP NXTITM ; Get next item -1667+ 0EB3 -1668+ 0EB3 E5 READ: PUSH HL ; Save code string address -1669+ 0EB4 2A 8C 31 LD HL,(NXTDAT) ; Next DATA statement -1670+ 0EB7 F6 .BYTE 0F6H ; Flag "READ" -1671+ 0EB8 AF NXTITM: XOR A ; Flag "INPUT" -1672+ 0EB9 32 7D 31 LD (READFG),A ; Save "READ"/"INPUT" flag -1673+ 0EBC E3 EX (SP),HL ; Get code str' , Save pointer -1674+ 0EBD C3 C4 0E JP GTVLUS ; Get values -1675+ 0EC0 -1676+ 0EC0 CD D1 09 NEDMOR: CALL CHKSYN ; Check for comma between items -1677+ 0EC3 2C .BYTE ',' -1678+ 0EC4 CD BE 11 GTVLUS: CALL GETVAR ; Get variable name -1679+ 0EC7 E3 EX (SP),HL ; Save code str" , Get pointer -1680+ 0EC8 D5 PUSH DE ; Save variable address -1681+ 0EC9 7E LD A,(HL) ; Get next "INPUT"/"DATA" byte -1682+ 0ECA FE 2C CP ',' ; Comma? -1683+ 0ECC CA EC 0E JP Z,ANTVLU ; Yes - Get another value -1684+ 0ECF 3A 7D 31 LD A,(READFG) ; Is it READ? -1685+ 0ED2 B7 OR A -1686+ 0ED3 C2 59 0F JP NZ,FDTLP ; Yes - Find next DATA stmt -1687+ 0ED6 3E 3F LD A,'?' ; More INPUT needed -1688+ 0ED8 CD DC 09 CALL OUTC ; Output character -1689+ 0EDB CD 52 08 CALL PROMPT ; Get INPUT with prompt -1690+ 0EDE D1 POP DE ; Variable address -1691+ 0EDF C1 POP BC ; Code string address -1692+ 0EE0 DA AA 0B JP C,INPBRK ; Break pressed -1693+ 0EE3 23 INC HL ; Point to next DATA byte -1694+ 0EE4 7E LD A,(HL) ; Get byte -1695+ 0EE5 B7 OR A ; Is it zero (No input) ? -1696+ 0EE6 2B DEC HL ; Back space INPUT pointer -1697+ 0EE7 C5 PUSH BC ; Save code string address -1698+ 0EE8 CA F1 0C JP Z,NXTDTA ; Find end of buffer -1699+ 0EEB D5 PUSH DE ; Save variable address -1700+ 0EEC 3A 5D 31 ANTVLU: LD A,(TYPE) ; Check data type -1701+ 0EEF B7 OR A ; Is it numeric? -1702+ 0EF0 CA 16 0F JP Z,INPBIN ; Yes - Convert to binary -1703+ 0EF3 CD 5B 0B CALL GETCHR ; Get next character -1704+ 0EF6 57 LD D,A ; Save input character -1705+ 0EF7 47 LD B,A ; Again -1706+ 0EF8 FE 22 CP '"' ; Start of literal sting? -1707+ 0EFA CA 0A 0F JP Z,STRENT ; Yes - Create string entry -1708+ 0EFD 3A 7D 31 LD A,(READFG) ; "READ" or "INPUT" ? -1709+ 0F00 B7 OR A -1710+ 0F01 57 LD D,A ; Save 00 if "INPUT" -1711+ 0F02 CA 07 0F JP Z,ITMSEP ; "INPUT" - End with 00 -1712+ 0F05 16 3A LD D,':' ; "DATA" - End with 00 or ':' -1713+ 0F07 06 2C ITMSEP: LD B,',' ; Item separator -1714+ 0F09 2B DEC HL ; Back space for DTSTR -1715+ 0F0A CD 63 14 STRENT: CALL DTSTR ; Get string terminated by D -1716+ 0F0D EB EX DE,HL ; String address to DE -1717+ 0F0E 21 21 0F LD HL,LTSTND ; Where to go after LETSTR -1718+ 0F11 E3 EX (SP),HL ; Save HL , get input pointer -1719+ 0F12 D5 PUSH DE ; Save address of string -1720+ 0F13 C3 24 0D JP LETSTR ; Assign string to variable -1721+ 0F16 -1722+ 0F16 CD 5B 0B INPBIN: CALL GETCHR ; Get next character -1723+ 0F19 CD B1 1A CALL ASCTFP ; Convert ASCII to FP number -1724+ 0F1C E3 EX (SP),HL ; Save input ptr, Get var addr -1725+ 0F1D CD 02 1A CALL FPTHL ; Move FPREG to variable -1726+ 0F20 E1 POP HL ; Restore input pointer -1727+ 0F21 2B LTSTND: DEC HL ; DEC 'cos GETCHR INCs -1728+ 0F22 CD 5B 0B CALL GETCHR ; Get next character -1729+ 0F25 CA 2D 0F JP Z,MORDT ; End of line - More needed? -1730+ 0F28 FE 2C CP ',' ; Another value? -1731+ 0F2A C2 73 0E JP NZ,BADINP ; No - Bad input -1732+ 0F2D E3 MORDT: EX (SP),HL ; Get code string address -1733+ 0F2E 2B DEC HL ; DEC 'cos GETCHR INCs -1734+ 0F2F CD 5B 0B CALL GETCHR ; Get next character -1735+ 0F32 C2 C0 0E JP NZ,NEDMOR ; More needed - Get it -1736+ 0F35 D1 POP DE ; Restore DATA pointer -1737+ 0F36 3A 7D 31 LD A,(READFG) ; "READ" or "INPUT" ? -1738+ 0F39 B7 OR A -1739+ 0F3A EB EX DE,HL ; DATA pointer to HL -1740+ 0F3B C2 81 0B JP NZ,UPDATA ; Update DATA pointer if "READ" -1741+ 0F3E D5 PUSH DE ; Save code string address -1742+ 0F3F B6 OR (HL) ; More input given? -1743+ 0F40 21 48 0F LD HL,EXTIG ; "?Extra ignored" message -1744+ 0F43 C4 A1 14 CALL NZ,PRS ; Output string if extra given -1745+ 0F46 E1 POP HL ; Restore code string address -1746+ 0F47 C9 RET -1747+ 0F48 -1748+ 0F48 3F 45 78 74 EXTIG: .BYTE "?Extra ignored",CR,LF,0 -1748+ 0F4C 72 61 20 69 -1748+ 0F50 67 6E 6F 72 -1748+ 0F54 65 64 0D 0A -1748+ 0F58 00 -1749+ 0F59 -1750+ 0F59 CD F2 0C FDTLP: CALL DATA ; Get next statement -1751+ 0F5C B7 OR A ; End of line? -1752+ 0F5D C2 72 0F JP NZ,FANDT ; No - See if DATA statement -1753+ 0F60 23 INC HL -1754+ 0F61 7E LD A,(HL) ; End of program? -1755+ 0F62 23 INC HL -1756+ 0F63 B6 OR (HL) ; 00 00 Ends program -1757+ 0F64 1E 06 LD E,OD ; ?OD Error -1758+ 0F66 CA 17 07 JP Z,ERROR ; Yes - Out of DATA -1759+ 0F69 23 INC HL -1760+ 0F6A 5E LD E,(HL) ; LSB of line number -1761+ 0F6B 23 INC HL -1762+ 0F6C 56 LD D,(HL) ; MSB of line number -1763+ 0F6D EB EX DE,HL -1764+ 0F6E 22 79 31 LD (DATLIN),HL ; Set line of current DATA item -1765+ 0F71 EB EX DE,HL -1766+ 0F72 CD 5B 0B FANDT: CALL GETCHR ; Get next character -1767+ 0F75 FE 83 CP ZDATA ; "DATA" token -1768+ 0F77 C2 59 0F JP NZ,FDTLP ; No "DATA" - Keep looking -1769+ 0F7A C3 EC 0E JP ANTVLU ; Found - Convert input -1770+ 0F7D -1771+ 0F7D 11 00 00 NEXT: LD DE,0 ; In case no index given -1772+ 0F80 C4 BE 11 NEXT1: CALL NZ,GETVAR ; Get index address -1773+ 0F83 22 7E 31 LD (BRKLIN),HL ; Save code string address -1774+ 0F86 CD AC 06 CALL BAKSTK ; Look for "FOR" block -1775+ 0F89 C2 09 07 JP NZ,NFERR ; No "FOR" - ?NF Error -1776+ 0F8C F9 LD SP,HL ; Clear nested loops -1777+ 0F8D D5 PUSH DE ; Save index address -1778+ 0F8E 7E LD A,(HL) ; Get sign of STEP -1779+ 0F8F 23 INC HL -1780+ 0F90 F5 PUSH AF ; Save sign of STEP -1781+ 0F91 D5 PUSH DE ; Save index address -1782+ 0F92 CD E8 19 CALL PHLTFP ; Move index value to FPREG -1783+ 0F95 E3 EX (SP),HL ; Save address of TO value -1784+ 0F96 E5 PUSH HL ; Save address of index -1785+ 0F97 CD 55 17 CALL ADDPHL ; Add STEP to index value -1786+ 0F9A E1 POP HL ; Restore address of index -1787+ 0F9B CD 02 1A CALL FPTHL ; Move value to index variable -1788+ 0F9E E1 POP HL ; Restore address of TO value -1789+ 0F9F CD F9 19 CALL LOADFP ; Move TO value to BCDE -1790+ 0FA2 E5 PUSH HL ; Save address of line of FOR -1791+ 0FA3 CD 25 1A CALL CMPNUM ; Compare index with TO value -1792+ 0FA6 E1 POP HL ; Restore address of line num -1793+ 0FA7 C1 POP BC ; Address of sign of STEP -1794+ 0FA8 90 SUB B ; Compare with expected sign -1795+ 0FA9 CD F9 19 CALL LOADFP ; BC = Loop stmt,DE = Line num -1796+ 0FAC CA B8 0F JP Z,KILFOR ; Loop finished - Terminate it -1797+ 0FAF EB EX DE,HL ; Loop statement line number -1798+ 0FB0 22 0C 31 LD (LINEAT),HL ; Set loop line number -1799+ 0FB3 69 LD L,C ; Set code string to loop -1800+ 0FB4 60 LD H,B -1801+ 0FB5 C3 17 0B JP PUTFID ; Put back "FOR" and continue -1802+ 0FB8 -1803+ 0FB8 F9 KILFOR: LD SP,HL ; Remove "FOR" block -1804+ 0FB9 2A 7E 31 LD HL,(BRKLIN) ; Code string after "NEXT" -1805+ 0FBC 7E LD A,(HL) ; Get next byte in code string -1806+ 0FBD FE 2C CP ',' ; More NEXTs ? -1807+ 0FBF C2 1B 0B JP NZ,RUNCNT ; No - Do next statement -1808+ 0FC2 CD 5B 0B CALL GETCHR ; Position to index name -1809+ 0FC5 CD 80 0F CALL NEXT1 ; Re-enter NEXT routine -1810+ 0FC8 ; < will not RETurn to here , Exit to RUNCNT or Loop > -1811+ 0FC8 -1812+ 0FC8 CD DA 0F GETNUM: CALL EVAL ; Get a numeric expression -1813+ 0FCB F6 TSTNUM: .BYTE 0F6H ; Clear carry (numeric) -1814+ 0FCC 37 TSTSTR: SCF ; Set carry (string) -1815+ 0FCD 3A 5D 31 CHKTYP: LD A,(TYPE) ; Check types match -1816+ 0FD0 8F ADC A,A ; Expected + actual -1817+ 0FD1 B7 OR A ; Clear carry , set parity -1818+ 0FD2 E8 RET PE ; Even parity - Types match -1819+ 0FD3 C3 15 07 JP TMERR ; Different types - Error -1820+ 0FD6 -1821+ 0FD6 CD D1 09 OPNPAR: CALL CHKSYN ; Make sure "(" follows -1822+ 0FD9 28 .BYTE "(" -1823+ 0FDA 2B EVAL: DEC HL ; Evaluate expression & save -1824+ 0FDB 16 00 LD D,0 ; Precedence value -1825+ 0FDD D5 EVAL1: PUSH DE ; Save precedence -1826+ 0FDE 0E 01 LD C,1 -1827+ 0FE0 CD E0 06 CALL CHKSTK ; Check for 1 level of stack -1828+ 0FE3 CD 51 10 CALL OPRND ; Get next expression value -1829+ 0FE6 22 80 31 EVAL2: LD (NXTOPR),HL ; Save address of next operator -1830+ 0FE9 2A 80 31 EVAL3: LD HL,(NXTOPR) ; Restore address of next opr -1831+ 0FEC C1 POP BC ; Precedence value and operator -1832+ 0FED 78 LD A,B ; Get precedence value -1833+ 0FEE FE 78 CP 78H ; "AND" or "OR" ? -1834+ 0FF0 D4 CB 0F CALL NC,TSTNUM ; No - Make sure it's a number -1835+ 0FF3 7E LD A,(HL) ; Get next operator / function -1836+ 0FF4 16 00 LD D,0 ; Clear Last relation -1837+ 0FF6 D6 B3 RLTLP: SUB ZGTR ; ">" Token -1838+ 0FF8 DA 12 10 JP C,FOPRND ; + - * / ^ AND OR - Test it -1839+ 0FFB FE 03 CP ZLTH+1-ZGTR ; < = > -1840+ 0FFD D2 12 10 JP NC,FOPRND ; Function - Call it -1841+ 1000 FE 01 CP ZEQUAL-ZGTR ; "=" -1842+ 1002 17 RLA ; <- Test for legal -1843+ 1003 AA XOR D ; <- combinations of < = > -1844+ 1004 BA CP D ; <- by combining last token -1845+ 1005 57 LD D,A ; <- with current one -1846+ 1006 DA 03 07 JP C,SNERR ; Error if "<<' '==" or ">>" -1847+ 1009 22 75 31 LD (CUROPR),HL ; Save address of current token -1848+ 100C CD 5B 0B CALL GETCHR ; Get next character -1849+ 100F C3 F6 0F JP RLTLP ; Treat the two as one -1850+ 1012 -1851+ 1012 7A FOPRND: LD A,D ; < = > found ? -1852+ 1013 B7 OR A -1853+ 1014 C2 39 11 JP NZ,TSTRED ; Yes - Test for reduction -1854+ 1017 7E LD A,(HL) ; Get operator token -1855+ 1018 22 75 31 LD (CUROPR),HL ; Save operator address -1856+ 101B D6 AC SUB ZPLUS ; Operator or function? -1857+ 101D D8 RET C ; Neither - Exit -1858+ 101E FE 07 CP ZOR+1-ZPLUS ; Is it + - * / ^ AND OR ? -1859+ 1020 D0 RET NC ; No - Exit -1860+ 1021 5F LD E,A ; Coded operator -1861+ 1022 3A 5D 31 LD A,(TYPE) ; Get data type -1862+ 1025 3D DEC A ; FF = numeric , 00 = string -1863+ 1026 B3 OR E ; Combine with coded operator -1864+ 1027 7B LD A,E ; Get coded operator -1865+ 1028 CA 97 15 JP Z,CONCAT ; String concatenation -1866+ 102B 07 RLCA ; Times 2 -1867+ 102C 83 ADD A,E ; Times 3 -1868+ 102D 5F LD E,A ; To DE (D is 0) -1869+ 102E 21 F5 05 LD HL,PRITAB ; Precedence table -1870+ 1031 19 ADD HL,DE ; To the operator concerned -1871+ 1032 78 LD A,B ; Last operator precedence -1872+ 1033 56 LD D,(HL) ; Get evaluation precedence -1873+ 1034 BA CP D ; Compare with eval precedence -1874+ 1035 D0 RET NC ; Exit if higher precedence -1875+ 1036 23 INC HL ; Point to routine address -1876+ 1037 CD CB 0F CALL TSTNUM ; Make sure it's a number -1877+ 103A -1878+ 103A C5 STKTHS: PUSH BC ; Save last precedence & token -1879+ 103B 01 E9 0F LD BC,EVAL3 ; Where to go on prec' break -1880+ 103E C5 PUSH BC ; Save on stack for return -1881+ 103F 43 LD B,E ; Save operator -1882+ 1040 4A LD C,D ; Save precedence -1883+ 1041 CD DB 19 CALL STAKFP ; Move value to stack -1884+ 1044 58 LD E,B ; Restore operator -1885+ 1045 51 LD D,C ; Restore precedence -1886+ 1046 4E LD C,(HL) ; Get LSB of routine address -1887+ 1047 23 INC HL -1888+ 1048 46 LD B,(HL) ; Get MSB of routine address -1889+ 1049 23 INC HL -1890+ 104A C5 PUSH BC ; Save routine address -1891+ 104B 2A 75 31 LD HL,(CUROPR) ; Address of current operator -1892+ 104E C3 DD 0F JP EVAL1 ; Loop until prec' break -1893+ 1051 -1894+ 1051 AF OPRND: XOR A ; Get operand routine -1895+ 1052 32 5D 31 LD (TYPE),A ; Set numeric expected -1896+ 1055 CD 5B 0B CALL GETCHR ; Get next character -1897+ 1058 1E 24 LD E,MO ; ?MO Error -1898+ 105A CA 17 07 JP Z,ERROR ; No operand - Error -1899+ 105D DA B1 1A JP C,ASCTFP ; Number - Get value -1900+ 1060 CD F9 0B CALL CHKLTR ; See if a letter -1901+ 1063 D2 B8 10 JP NC,CONVAR ; Letter - Find variable -1902+ 1066 FE 26 CP '&' ; &H = HEX, &B = BINARY -1903+ 1068 20 12 JR NZ, NOTAMP -1904+ 106A CD 5B 0B CALL GETCHR ; Get next character -1905+ 106D FE 48 CP 'H' ; Hex number indicated? [function added] -1906+ 106F CA F5 1E JP Z,HEXTFP ; Convert Hex to FPREG -1907+ 1072 FE 42 CP 'B' ; Binary number indicated? [function added] -1908+ 1074 CA 65 1F JP Z,BINTFP ; Convert Bin to FPREG -1909+ 1077 1E 02 LD E,SN ; If neither then a ?SN Error -1910+ 1079 CA 17 07 JP Z,ERROR ; -1911+ 107C FE AC NOTAMP: CP ZPLUS ; '+' Token ? -1912+ 107E CA 51 10 JP Z,OPRND ; Yes - Look for operand -1913+ 1081 FE 2E CP '.' ; '.' ? -1914+ 1083 CA B1 1A JP Z,ASCTFP ; Yes - Create FP number -1915+ 1086 FE AD CP ZMINUS ; '-' Token ? -1916+ 1088 CA A7 10 JP Z,MINUS ; Yes - Do minus -1917+ 108B FE 22 CP '"' ; Literal string ? -1918+ 108D CA 60 14 JP Z,QTSTR ; Get string terminated by '"' -1919+ 1090 FE AA CP ZNOT ; "NOT" Token ? -1920+ 1092 CA 99 11 JP Z,EVNOT ; Yes - Eval NOT expression -1921+ 1095 FE A7 CP ZFN ; "FN" Token ? -1922+ 1097 CA C4 13 JP Z,DOFN ; Yes - Do FN routine -1923+ 109A D6 B6 SUB ZSGN ; Is it a function? -1924+ 109C D2 C9 10 JP NC,FNOFST ; Yes - Evaluate function -1925+ 109F CD D6 0F EVLPAR: CALL OPNPAR ; Evaluate expression in "()" -1926+ 10A2 CD D1 09 CALL CHKSYN ; Make sure ")" follows -1927+ 10A5 29 .BYTE ")" -1928+ 10A6 C9 RET -1929+ 10A7 -1930+ 10A7 16 7D MINUS: LD D,7DH ; '-' precedence -1931+ 10A9 CD DD 0F CALL EVAL1 ; Evaluate until prec' break -1932+ 10AC 2A 80 31 LD HL,(NXTOPR) ; Get next operator address -1933+ 10AF E5 PUSH HL ; Save next operator address -1934+ 10B0 CD D3 19 CALL INVSGN ; Negate value -1935+ 10B3 CD CB 0F RETNUM: CALL TSTNUM ; Make sure it's a number -1936+ 10B6 E1 POP HL ; Restore next operator address -1937+ 10B7 C9 RET -1938+ 10B8 -1939+ 10B8 CD BE 11 CONVAR: CALL GETVAR ; Get variable address to DE -1940+ 10BB E5 FRMEVL: PUSH HL ; Save code string address -1941+ 10BC EB EX DE,HL ; Variable address to HL -1942+ 10BD 22 94 31 LD (FPREG),HL ; Save address of variable -1943+ 10C0 3A 5D 31 LD A,(TYPE) ; Get type -1944+ 10C3 B7 OR A ; Numeric? -1945+ 10C4 CC E8 19 CALL Z,PHLTFP ; Yes - Move contents to FPREG -1946+ 10C7 E1 POP HL ; Restore code string address -1947+ 10C8 C9 RET -1948+ 10C9 -1949+ 10C9 06 00 FNOFST: LD B,0 ; Get address of function -1950+ 10CB 07 RLCA ; Double function offset -1951+ 10CC 4F LD C,A ; BC = Offset in function table -1952+ 10CD C5 PUSH BC ; Save adjusted token value -1953+ 10CE CD 5B 0B CALL GETCHR ; Get next character -1954+ 10D1 79 LD A,C ; Get adjusted token value -1955+ 10D2 FE 31 CP 2*(ZLEFT-ZSGN)-1; Adj' LEFT$,RIGHT$ or MID$ ? -1956+ 10D4 DA F0 10 JP C,FNVAL ; No - Do function -1957+ 10D7 CD D6 0F CALL OPNPAR ; Evaluate expression (X,... -1958+ 10DA CD D1 09 CALL CHKSYN ; Make sure ',' follows -1959+ 10DD 2C .BYTE ',' -1960+ 10DE CD CC 0F CALL TSTSTR ; Make sure it's a string -1961+ 10E1 EB EX DE,HL ; Save code string address -1962+ 10E2 2A 94 31 LD HL,(FPREG) ; Get address of string -1963+ 10E5 E3 EX (SP),HL ; Save address of string -1964+ 10E6 E5 PUSH HL ; Save adjusted token value -1965+ 10E7 EB EX DE,HL ; Restore code string address -1966+ 10E8 CD 29 17 CALL GETINT ; Get integer 0-255 -1967+ 10EB EB EX DE,HL ; Save code string address -1968+ 10EC E3 EX (SP),HL ; Save integer,HL = adj' token -1969+ 10ED C3 F8 10 JP GOFUNC ; Jump to string function -1970+ 10F0 -1971+ 10F0 CD 9F 10 FNVAL: CALL EVLPAR ; Evaluate expression -1972+ 10F3 E3 EX (SP),HL ; HL = Adjusted token value -1973+ 10F4 11 B3 10 LD DE,RETNUM ; Return number from function -1974+ 10F7 D5 PUSH DE ; Save on stack -1975+ 10F8 01 54 04 GOFUNC: LD BC,FNCTAB ; Function routine addresses -1976+ 10FB 09 ADD HL,BC ; Point to right address -1977+ 10FC 4E LD C,(HL) ; Get LSB of address -1978+ 10FD 23 INC HL ; -1979+ 10FE 66 LD H,(HL) ; Get MSB of address -1980+ 10FF 69 LD L,C ; Address to HL -1981+ 1100 E9 JP (HL) ; Jump to function -1982+ 1101 -1983+ 1101 15 SGNEXP: DEC D ; Dee to flag negative exponent -1984+ 1102 FE AD CP ZMINUS ; '-' token ? -1985+ 1104 C8 RET Z ; Yes - Return -1986+ 1105 FE 2D CP '-' ; '-' ASCII ? -1987+ 1107 C8 RET Z ; Yes - Return -1988+ 1108 14 INC D ; Inc to flag positive exponent -1989+ 1109 FE 2B CP '+' ; '+' ASCII ? -1990+ 110B C8 RET Z ; Yes - Return -1991+ 110C FE AC CP ZPLUS ; '+' token ? -1992+ 110E C8 RET Z ; Yes - Return -1993+ 110F 2B DEC HL ; DEC 'cos GETCHR INCs -1994+ 1110 C9 RET ; Return "NZ" -1995+ 1111 -1996+ 1111 F6 POR: .BYTE 0F6H ; Flag "OR" -1997+ 1112 AF PAND: XOR A ; Flag "AND" -1998+ 1113 F5 PUSH AF ; Save "AND" / "OR" flag -1999+ 1114 CD CB 0F CALL TSTNUM ; Make sure it's a number -2000+ 1117 CD 0D 0C CALL DEINT ; Get integer -32768 to 32767 -2001+ 111A F1 POP AF ; Restore "AND" / "OR" flag -2002+ 111B EB EX DE,HL ; <- Get last -2003+ 111C C1 POP BC ; <- value -2004+ 111D E3 EX (SP),HL ; <- from -2005+ 111E EB EX DE,HL ; <- stack -2006+ 111F CD EB 19 CALL FPBCDE ; Move last value to FPREG -2007+ 1122 F5 PUSH AF ; Save "AND" / "OR" flag -2008+ 1123 CD 0D 0C CALL DEINT ; Get integer -32768 to 32767 -2009+ 1126 F1 POP AF ; Restore "AND" / "OR" flag -2010+ 1127 C1 POP BC ; Get value -2011+ 1128 79 LD A,C ; Get LSB -2012+ 1129 21 82 13 LD HL,ACPASS ; Address of save AC as current -2013+ 112C C2 34 11 JP NZ,POR1 ; Jump if OR -2014+ 112F A3 AND E ; "AND" LSBs -2015+ 1130 4F LD C,A ; Save LSB -2016+ 1131 78 LD A,B ; Get MBS -2017+ 1132 A2 AND D ; "AND" MSBs -2018+ 1133 E9 JP (HL) ; Save AC as current (ACPASS) -2019+ 1134 -2020+ 1134 B3 POR1: OR E ; "OR" LSBs -2021+ 1135 4F LD C,A ; Save LSB -2022+ 1136 78 LD A,B ; Get MSB -2023+ 1137 B2 OR D ; "OR" MSBs -2024+ 1138 E9 JP (HL) ; Save AC as current (ACPASS) -2025+ 1139 -2026+ 1139 21 4B 11 TSTRED: LD HL,CMPLOG ; Logical compare routine -2027+ 113C 3A 5D 31 LD A,(TYPE) ; Get data type -2028+ 113F 1F RRA ; Carry set = string -2029+ 1140 7A LD A,D ; Get last precedence value -2030+ 1141 17 RLA ; Times 2 plus carry -2031+ 1142 5F LD E,A ; To E -2032+ 1143 16 64 LD D,64H ; Relational precedence -2033+ 1145 78 LD A,B ; Get current precedence -2034+ 1146 BA CP D ; Compare with last -2035+ 1147 D0 RET NC ; Eval if last was rel' or log' -2036+ 1148 C3 3A 10 JP STKTHS ; Stack this one and get next -2037+ 114B -2038+ 114B 4D 11 CMPLOG: .WORD CMPLG1 ; Compare two values / strings -2039+ 114D 79 CMPLG1: LD A,C ; Get data type -2040+ 114E B7 OR A -2041+ 114F 1F RRA -2042+ 1150 C1 POP BC ; Get last expression to BCDE -2043+ 1151 D1 POP DE -2044+ 1152 F5 PUSH AF ; Save status -2045+ 1153 CD CD 0F CALL CHKTYP ; Check that types match -2046+ 1156 21 8F 11 LD HL,CMPRES ; Result to comparison -2047+ 1159 E5 PUSH HL ; Save for RETurn -2048+ 115A CA 25 1A JP Z,CMPNUM ; Compare values if numeric -2049+ 115D AF XOR A ; Compare two strings -2050+ 115E 32 5D 31 LD (TYPE),A ; Set type to numeric -2051+ 1161 D5 PUSH DE ; Save string name -2052+ 1162 CD E4 15 CALL GSTRCU ; Get current string -2053+ 1165 7E LD A,(HL) ; Get length of string -2054+ 1166 23 INC HL -2055+ 1167 23 INC HL -2056+ 1168 4E LD C,(HL) ; Get LSB of address -2057+ 1169 23 INC HL -2058+ 116A 46 LD B,(HL) ; Get MSB of address -2059+ 116B D1 POP DE ; Restore string name -2060+ 116C C5 PUSH BC ; Save address of string -2061+ 116D F5 PUSH AF ; Save length of string -2062+ 116E CD E8 15 CALL GSTRDE ; Get second string -2063+ 1171 CD F9 19 CALL LOADFP ; Get address of second string -2064+ 1174 F1 POP AF ; Restore length of string 1 -2065+ 1175 57 LD D,A ; Length to D -2066+ 1176 E1 POP HL ; Restore address of string 1 -2067+ 1177 7B CMPSTR: LD A,E ; Bytes of string 2 to do -2068+ 1178 B2 OR D ; Bytes of string 1 to do -2069+ 1179 C8 RET Z ; Exit if all bytes compared -2070+ 117A 7A LD A,D ; Get bytes of string 1 to do -2071+ 117B D6 01 SUB 1 -2072+ 117D D8 RET C ; Exit if end of string 1 -2073+ 117E AF XOR A -2074+ 117F BB CP E ; Bytes of string 2 to do -2075+ 1180 3C INC A -2076+ 1181 D0 RET NC ; Exit if end of string 2 -2077+ 1182 15 DEC D ; Count bytes in string 1 -2078+ 1183 1D DEC E ; Count bytes in string 2 -2079+ 1184 0A LD A,(BC) ; Byte in string 2 -2080+ 1185 BE CP (HL) ; Compare to byte in string 1 -2081+ 1186 23 INC HL ; Move up string 1 -2082+ 1187 03 INC BC ; Move up string 2 -2083+ 1188 CA 77 11 JP Z,CMPSTR ; Same - Try next bytes -2084+ 118B 3F CCF ; Flag difference (">" or "<") -2085+ 118C C3 B5 19 JP FLGDIF ; "<" gives -1 , ">" gives +1 -2086+ 118F -2087+ 118F 3C CMPRES: INC A ; Increment current value -2088+ 1190 8F ADC A,A ; Double plus carry -2089+ 1191 C1 POP BC ; Get other value -2090+ 1192 A0 AND B ; Combine them -2091+ 1193 C6 FF ADD A,-1 ; Carry set if different -2092+ 1195 9F SBC A,A ; 00 - Equal , FF - Different -2093+ 1196 C3 BC 19 JP FLGREL ; Set current value & continue -2094+ 1199 -2095+ 1199 16 5A EVNOT: LD D,5AH ; Precedence value for "NOT" -2096+ 119B CD DD 0F CALL EVAL1 ; Eval until precedence break -2097+ 119E CD CB 0F CALL TSTNUM ; Make sure it's a number -2098+ 11A1 CD 0D 0C CALL DEINT ; Get integer -32768 - 32767 -2099+ 11A4 7B LD A,E ; Get LSB -2100+ 11A5 2F CPL ; Invert LSB -2101+ 11A6 4F LD C,A ; Save "NOT" of LSB -2102+ 11A7 7A LD A,D ; Get MSB -2103+ 11A8 2F CPL ; Invert MSB -2104+ 11A9 CD 82 13 CALL ACPASS ; Save AC as current -2105+ 11AC C1 POP BC ; Clean up stack -2106+ 11AD C3 E9 0F JP EVAL3 ; Continue evaluation -2107+ 11B0 -2108+ 11B0 2B DIMRET: DEC HL ; DEC 'cos GETCHR INCs -2109+ 11B1 CD 5B 0B CALL GETCHR ; Get next character -2110+ 11B4 C8 RET Z ; End of DIM statement -2111+ 11B5 CD D1 09 CALL CHKSYN ; Make sure ',' follows -2112+ 11B8 2C .BYTE ',' -2113+ 11B9 01 B0 11 DIM: LD BC,DIMRET ; Return to "DIMRET" -2114+ 11BC C5 PUSH BC ; Save on stack -2115+ 11BD F6 .BYTE 0F6H ; Flag "Create" variable -2116+ 11BE AF GETVAR: XOR A ; Find variable address,to DE -2117+ 11BF 32 5C 31 LD (LCRFLG),A ; Set locate / create flag -2118+ 11C2 46 LD B,(HL) ; Get First byte of name -2119+ 11C3 CD F9 0B GTFNAM: CALL CHKLTR ; See if a letter -2120+ 11C6 DA 03 07 JP C,SNERR ; ?SN Error if not a letter -2121+ 11C9 AF XOR A -2122+ 11CA 4F LD C,A ; Clear second byte of name -2123+ 11CB 32 5D 31 LD (TYPE),A ; Set type to numeric -2124+ 11CE CD 5B 0B CALL GETCHR ; Get next character -2125+ 11D1 DA DA 11 JP C,SVNAM2 ; Numeric - Save in name -2126+ 11D4 CD F9 0B CALL CHKLTR ; See if a letter -2127+ 11D7 DA E7 11 JP C,CHARTY ; Not a letter - Check type -2128+ 11DA 4F SVNAM2: LD C,A ; Save second byte of name -2129+ 11DB CD 5B 0B ENDNAM: CALL GETCHR ; Get next character -2130+ 11DE DA DB 11 JP C,ENDNAM ; Numeric - Get another -2131+ 11E1 CD F9 0B CALL CHKLTR ; See if a letter -2132+ 11E4 D2 DB 11 JP NC,ENDNAM ; Letter - Get another -2133+ 11E7 D6 24 CHARTY: SUB '$' ; String variable? -2134+ 11E9 C2 F6 11 JP NZ,NOTSTR ; No - Numeric variable -2135+ 11EC 3C INC A ; A = 1 (string type) -2136+ 11ED 32 5D 31 LD (TYPE),A ; Set type to string -2137+ 11F0 0F RRCA ; A = 80H , Flag for string -2138+ 11F1 81 ADD A,C ; 2nd byte of name has bit 7 on -2139+ 11F2 4F LD C,A ; Resave second byte on name -2140+ 11F3 CD 5B 0B CALL GETCHR ; Get next character -2141+ 11F6 3A 7B 31 NOTSTR: LD A,(FORFLG) ; Array name needed ? -2142+ 11F9 3D DEC A -2143+ 11FA CA A3 12 JP Z,ARLDSV ; Yes - Get array name -2144+ 11FD F2 06 12 JP P,NSCFOR ; No array with "FOR" or "FN" -2145+ 1200 7E LD A,(HL) ; Get byte again -2146+ 1201 D6 28 SUB '(' ; Subscripted variable? -2147+ 1203 CA 7B 12 JP Z,SBSCPT ; Yes - Sort out subscript -2148+ 1206 -2149+ 1206 AF NSCFOR: XOR A ; Simple variable -2150+ 1207 32 7B 31 LD (FORFLG),A ; Clear "FOR" flag -2151+ 120A E5 PUSH HL ; Save code string address -2152+ 120B 50 LD D,B ; DE = Variable name to find -2153+ 120C 59 LD E,C -2154+ 120D 2A 8E 31 LD HL,(FNRGNM) ; FN argument name -2155+ 1210 CD CB 09 CALL CPDEHL ; Is it the FN argument? -2156+ 1213 11 90 31 LD DE,FNARG ; Point to argument value -2157+ 1216 CA EB 18 JP Z,POPHRT ; Yes - Return FN argument value -2158+ 1219 2A 88 31 LD HL,(VAREND) ; End of variables -2159+ 121C EB EX DE,HL ; Address of end of search -2160+ 121D 2A 86 31 LD HL,(PROGND) ; Start of variables address -2161+ 1220 CD CB 09 FNDVAR: CALL CPDEHL ; End of variable list table? -2162+ 1223 CA 39 12 JP Z,CFEVAL ; Yes - Called from EVAL? -2163+ 1226 79 LD A,C ; Get second byte of name -2164+ 1227 96 SUB (HL) ; Compare with name in list -2165+ 1228 23 INC HL ; Move on to first byte -2166+ 1229 C2 2E 12 JP NZ,FNTHR ; Different - Find another -2167+ 122C 78 LD A,B ; Get first byte of name -2168+ 122D 96 SUB (HL) ; Compare with name in list -2169+ 122E 23 FNTHR: INC HL ; Move on to LSB of value -2170+ 122F CA 6D 12 JP Z,RETADR ; Found - Return address -2171+ 1232 23 INC HL ; <- Skip -2172+ 1233 23 INC HL ; <- over -2173+ 1234 23 INC HL ; <- F.P. -2174+ 1235 23 INC HL ; <- value -2175+ 1236 C3 20 12 JP FNDVAR ; Keep looking -2176+ 1239 -2177+ 1239 E1 CFEVAL: POP HL ; Restore code string address -2178+ 123A E3 EX (SP),HL ; Get return address -2179+ 123B D5 PUSH DE ; Save address of variable -2180+ 123C 11 BB 10 LD DE,FRMEVL ; Return address in EVAL -2181+ 123F CD CB 09 CALL CPDEHL ; Called from EVAL ? -2182+ 1242 D1 POP DE ; Restore address of variable -2183+ 1243 CA 70 12 JP Z,RETNUL ; Yes - Return null variable -2184+ 1246 E3 EX (SP),HL ; Put back return -2185+ 1247 E5 PUSH HL ; Save code string address -2186+ 1248 C5 PUSH BC ; Save variable name -2187+ 1249 01 06 00 LD BC,6 ; 2 byte name plus 4 byte data -2188+ 124C 2A 8A 31 LD HL,(ARREND) ; End of arrays -2189+ 124F E5 PUSH HL ; Save end of arrays -2190+ 1250 09 ADD HL,BC ; Move up 6 bytes -2191+ 1251 C1 POP BC ; Source address in BC -2192+ 1252 E5 PUSH HL ; Save new end address -2193+ 1253 CD CF 06 CALL MOVUP ; Move arrays up -2194+ 1256 E1 POP HL ; Restore new end address -2195+ 1257 22 8A 31 LD (ARREND),HL ; Set new end address -2196+ 125A 60 LD H,B ; End of variables to HL -2197+ 125B 69 LD L,C -2198+ 125C 22 88 31 LD (VAREND),HL ; Set new end address -2199+ 125F -2200+ 125F 2B ZEROLP: DEC HL ; Back through to zero variable -2201+ 1260 36 00 LD (HL),0 ; Zero byte in variable -2202+ 1262 CD CB 09 CALL CPDEHL ; Done them all? -2203+ 1265 C2 5F 12 JP NZ,ZEROLP ; No - Keep on going -2204+ 1268 D1 POP DE ; Get variable name -2205+ 1269 73 LD (HL),E ; Store second character -2206+ 126A 23 INC HL -2207+ 126B 72 LD (HL),D ; Store first character -2208+ 126C 23 INC HL -2209+ 126D EB RETADR: EX DE,HL ; Address of variable in DE -2210+ 126E E1 POP HL ; Restore code string address -2211+ 126F C9 RET -2212+ 1270 -2213+ 1270 32 97 31 RETNUL: LD (FPEXP),A ; Set result to zero -2214+ 1273 21 9F 06 LD HL,ZERBYT ; Also set a null string -2215+ 1276 22 94 31 LD (FPREG),HL ; Save for EVAL -2216+ 1279 E1 POP HL ; Restore code string address -2217+ 127A C9 RET -2218+ 127B -2219+ 127B E5 SBSCPT: PUSH HL ; Save code string address -2220+ 127C 2A 5C 31 LD HL,(LCRFLG) ; Locate/Create and Type -2221+ 127F E3 EX (SP),HL ; Save and get code string -2222+ 1280 57 LD D,A ; Zero number of dimensions -2223+ 1281 D5 SCPTLP: PUSH DE ; Save number of dimensions -2224+ 1282 C5 PUSH BC ; Save array name -2225+ 1283 CD 01 0C CALL FPSINT ; Get subscript (0-32767) -2226+ 1286 C1 POP BC ; Restore array name -2227+ 1287 F1 POP AF ; Get number of dimensions -2228+ 1288 EB EX DE,HL -2229+ 1289 E3 EX (SP),HL ; Save subscript value -2230+ 128A E5 PUSH HL ; Save LCRFLG and TYPE -2231+ 128B EB EX DE,HL -2232+ 128C 3C INC A ; Count dimensions -2233+ 128D 57 LD D,A ; Save in D -2234+ 128E 7E LD A,(HL) ; Get next byte in code string -2235+ 128F FE 2C CP ',' ; Comma (more to come)? -2236+ 1291 CA 81 12 JP Z,SCPTLP ; Yes - More subscripts -2237+ 1294 CD D1 09 CALL CHKSYN ; Make sure ")" follows -2238+ 1297 29 .BYTE ")" -2239+ 1298 22 80 31 LD (NXTOPR),HL ; Save code string address -2240+ 129B E1 POP HL ; Get LCRFLG and TYPE -2241+ 129C 22 5C 31 LD (LCRFLG),HL ; Restore Locate/create & type -2242+ 129F 1E 00 LD E,0 ; Flag not CSAVE* or CLOAD* -2243+ 12A1 D5 PUSH DE ; Save number of dimensions (D) -2244+ 12A2 11 .BYTE 11H ; Skip "PUSH HL" and "PUSH AF' -2245+ 12A3 -2246+ 12A3 E5 ARLDSV: PUSH HL ; Save code string address -2247+ 12A4 F5 PUSH AF ; A = 00 , Flags set = Z,N -2248+ 12A5 2A 88 31 LD HL,(VAREND) ; Start of arrays -2249+ 12A8 3E .BYTE 3EH ; Skip "ADD HL,DE" -2250+ 12A9 19 FNDARY: ADD HL,DE ; Move to next array start -2251+ 12AA EB EX DE,HL -2252+ 12AB 2A 8A 31 LD HL,(ARREND) ; End of arrays -2253+ 12AE EB EX DE,HL ; Current array pointer -2254+ 12AF CD CB 09 CALL CPDEHL ; End of arrays found? -2255+ 12B2 CA DB 12 JP Z,CREARY ; Yes - Create array -2256+ 12B5 7E LD A,(HL) ; Get second byte of name -2257+ 12B6 B9 CP C ; Compare with name given -2258+ 12B7 23 INC HL ; Move on -2259+ 12B8 C2 BD 12 JP NZ,NXTARY ; Different - Find next array -2260+ 12BB 7E LD A,(HL) ; Get first byte of name -2261+ 12BC B8 CP B ; Compare with name given -2262+ 12BD 23 NXTARY: INC HL ; Move on -2263+ 12BE 5E LD E,(HL) ; Get LSB of next array address -2264+ 12BF 23 INC HL -2265+ 12C0 56 LD D,(HL) ; Get MSB of next array address -2266+ 12C1 23 INC HL -2267+ 12C2 C2 A9 12 JP NZ,FNDARY ; Not found - Keep looking -2268+ 12C5 3A 5C 31 LD A,(LCRFLG) ; Found Locate or Create it? -2269+ 12C8 B7 OR A -2270+ 12C9 C2 0C 07 JP NZ,DDERR ; Create - ?DD Error -2271+ 12CC F1 POP AF ; Locate - Get number of dim'ns -2272+ 12CD 44 LD B,H ; BC Points to array dim'ns -2273+ 12CE 4D LD C,L -2274+ 12CF CA EB 18 JP Z,POPHRT ; Jump if array load/save -2275+ 12D2 96 SUB (HL) ; Same number of dimensions? -2276+ 12D3 CA 39 13 JP Z,FINDEL ; Yes - Find element -2277+ 12D6 1E 10 BSERR: LD E,BS ; ?BS Error -2278+ 12D8 C3 17 07 JP ERROR ; Output error -2279+ 12DB -2280+ 12DB 11 04 00 CREARY: LD DE,4 ; 4 Bytes per entry -2281+ 12DE F1 POP AF ; Array to save or 0 dim'ns? -2282+ 12DF CA 22 0C JP Z,FCERR ; Yes - ?FC Error -2283+ 12E2 71 LD (HL),C ; Save second byte of name -2284+ 12E3 23 INC HL -2285+ 12E4 70 LD (HL),B ; Save first byte of name -2286+ 12E5 23 INC HL -2287+ 12E6 4F LD C,A ; Number of dimensions to C -2288+ 12E7 CD E0 06 CALL CHKSTK ; Check if enough memory -2289+ 12EA 23 INC HL ; Point to number of dimensions -2290+ 12EB 23 INC HL -2291+ 12EC 22 75 31 LD (CUROPR),HL ; Save address of pointer -2292+ 12EF 71 LD (HL),C ; Set number of dimensions -2293+ 12F0 23 INC HL -2294+ 12F1 3A 5C 31 LD A,(LCRFLG) ; Locate of Create? -2295+ 12F4 17 RLA ; Carry set = Create -2296+ 12F5 79 LD A,C ; Get number of dimensions -2297+ 12F6 01 0B 00 CRARLP: LD BC,10+1 ; Default dimension size 10 -2298+ 12F9 D2 FE 12 JP NC,DEFSIZ ; Locate - Set default size -2299+ 12FC C1 POP BC ; Get specified dimension size -2300+ 12FD 03 INC BC ; Include zero element -2301+ 12FE 71 DEFSIZ: LD (HL),C ; Save LSB of dimension size -2302+ 12FF 23 INC HL -2303+ 1300 70 LD (HL),B ; Save MSB of dimension size -2304+ 1301 23 INC HL -2305+ 1302 F5 PUSH AF ; Save num' of dim'ns an status -2306+ 1303 E5 PUSH HL ; Save address of dim'n size -2307+ 1304 CD 96 1A CALL MLDEBC ; Multiply DE by BC to find -2308+ 1307 EB EX DE,HL ; amount of mem needed (to DE) -2309+ 1308 E1 POP HL ; Restore address of dimension -2310+ 1309 F1 POP AF ; Restore number of dimensions -2311+ 130A 3D DEC A ; Count them -2312+ 130B C2 F6 12 JP NZ,CRARLP ; Do next dimension if more -2313+ 130E F5 PUSH AF ; Save locate/create flag -2314+ 130F 42 LD B,D ; MSB of memory needed -2315+ 1310 4B LD C,E ; LSB of memory needed -2316+ 1311 EB EX DE,HL -2317+ 1312 19 ADD HL,DE ; Add bytes to array start -2318+ 1313 DA F8 06 JP C,OMERR ; Too big - Error -2319+ 1316 CD E9 06 CALL ENFMEM ; See if enough memory -2320+ 1319 22 8A 31 LD (ARREND),HL ; Save new end of array -2321+ 131C -2322+ 131C 2B ZERARY: DEC HL ; Back through array data -2323+ 131D 36 00 LD (HL),0 ; Set array element to zero -2324+ 131F CD CB 09 CALL CPDEHL ; All elements zeroed? -2325+ 1322 C2 1C 13 JP NZ,ZERARY ; No - Keep on going -2326+ 1325 03 INC BC ; Number of bytes + 1 -2327+ 1326 57 LD D,A ; A=0 -2328+ 1327 2A 75 31 LD HL,(CUROPR) ; Get address of array -2329+ 132A 5E LD E,(HL) ; Number of dimensions -2330+ 132B EB EX DE,HL ; To HL -2331+ 132C 29 ADD HL,HL ; Two bytes per dimension size -2332+ 132D 09 ADD HL,BC ; Add number of bytes -2333+ 132E EB EX DE,HL ; Bytes needed to DE -2334+ 132F 2B DEC HL -2335+ 1330 2B DEC HL -2336+ 1331 73 LD (HL),E ; Save LSB of bytes needed -2337+ 1332 23 INC HL -2338+ 1333 72 LD (HL),D ; Save MSB of bytes needed -2339+ 1334 23 INC HL -2340+ 1335 F1 POP AF ; Locate / Create? -2341+ 1336 DA 5D 13 JP C,ENDDIM ; A is 0 , End if create -2342+ 1339 47 FINDEL: LD B,A ; Find array element -2343+ 133A 4F LD C,A -2344+ 133B 7E LD A,(HL) ; Number of dimensions -2345+ 133C 23 INC HL -2346+ 133D 16 .BYTE 16H ; Skip "POP HL" -2347+ 133E E1 FNDELP: POP HL ; Address of next dim' size -2348+ 133F 5E LD E,(HL) ; Get LSB of dim'n size -2349+ 1340 23 INC HL -2350+ 1341 56 LD D,(HL) ; Get MSB of dim'n size -2351+ 1342 23 INC HL -2352+ 1343 E3 EX (SP),HL ; Save address - Get index -2353+ 1344 F5 PUSH AF ; Save number of dim'ns -2354+ 1345 CD CB 09 CALL CPDEHL ; Dimension too large? -2355+ 1348 D2 D6 12 JP NC,BSERR ; Yes - ?BS Error -2356+ 134B E5 PUSH HL ; Save index -2357+ 134C CD 96 1A CALL MLDEBC ; Multiply previous by size -2358+ 134F D1 POP DE ; Index supplied to DE -2359+ 1350 19 ADD HL,DE ; Add index to pointer -2360+ 1351 F1 POP AF ; Number of dimensions -2361+ 1352 3D DEC A ; Count them -2362+ 1353 44 LD B,H ; MSB of pointer -2363+ 1354 4D LD C,L ; LSB of pointer -2364+ 1355 C2 3E 13 JP NZ,FNDELP ; More - Keep going -2365+ 1358 29 ADD HL,HL ; 4 Bytes per element -2366+ 1359 29 ADD HL,HL -2367+ 135A C1 POP BC ; Start of array -2368+ 135B 09 ADD HL,BC ; Point to element -2369+ 135C EB EX DE,HL ; Address of element to DE -2370+ 135D 2A 80 31 ENDDIM: LD HL,(NXTOPR) ; Got code string address -2371+ 1360 C9 RET -2372+ 1361 -2373+ 1361 2A 8A 31 FRE: LD HL,(ARREND) ; Start of free memory -2374+ 1364 EB EX DE,HL ; To DE -2375+ 1365 21 00 00 LD HL,0 ; End of free memory -2376+ 1368 39 ADD HL,SP ; Current stack value -2377+ 1369 3A 5D 31 LD A,(TYPE) ; Dummy argument type -2378+ 136C B7 OR A -2379+ 136D CA 7D 13 JP Z,FRENUM ; Numeric - Free variable space -2380+ 1370 CD E4 15 CALL GSTRCU ; Current string to pool -2381+ 1373 CD E4 14 CALL GARBGE ; Garbage collection -2382+ 1376 2A 0A 31 LD HL,(STRSPC) ; Bottom of string space in use -2383+ 1379 EB EX DE,HL ; To DE -2384+ 137A 2A 73 31 LD HL,(STRBOT) ; Bottom of string space -2385+ 137D 7D FRENUM: LD A,L ; Get LSB of end -2386+ 137E 93 SUB E ; Subtract LSB of beginning -2387+ 137F 4F LD C,A ; Save difference if C -2388+ 1380 7C LD A,H ; Get MSB of end -2389+ 1381 9A SBC A,D ; Subtract MSB of beginning -2390+ 1382 41 ACPASS: LD B,C ; Return integer AC -2391+ 1383 50 ABPASS: LD D,B ; Return integer AB -2392+ 1384 1E 00 LD E,0 -2393+ 1386 21 5D 31 LD HL,TYPE ; Point to type -2394+ 1389 73 LD (HL),E ; Set type to numeric -2395+ 138A 06 90 LD B,80H+16 ; 16 bit integer -2396+ 138C C3 C1 19 JP RETINT ; Return the integr -2397+ 138F -2398+ 138F 3A 5B 31 POS: LD A,(CURPOS) ; Get cursor position -2399+ 1392 47 PASSA: LD B,A ; Put A into AB -2400+ 1393 AF XOR A ; Zero A -2401+ 1394 C3 83 13 JP ABPASS ; Return integer AB -2402+ 1397 -2403+ 1397 CD 1A 14 DEF: CALL CHEKFN ; Get "FN" and name -2404+ 139A CD 0C 14 CALL IDTEST ; Test for illegal direct -2405+ 139D 01 F2 0C LD BC,DATA ; To get next statement -2406+ 13A0 C5 PUSH BC ; Save address for RETurn -2407+ 13A1 D5 PUSH DE ; Save address of function ptr -2408+ 13A2 CD D1 09 CALL CHKSYN ; Make sure "(" follows -2409+ 13A5 28 .BYTE "(" -2410+ 13A6 CD BE 11 CALL GETVAR ; Get argument variable name -2411+ 13A9 E5 PUSH HL ; Save code string address -2412+ 13AA EB EX DE,HL ; Argument address to HL -2413+ 13AB 2B DEC HL -2414+ 13AC 56 LD D,(HL) ; Get first byte of arg name -2415+ 13AD 2B DEC HL -2416+ 13AE 5E LD E,(HL) ; Get second byte of arg name -2417+ 13AF E1 POP HL ; Restore code string address -2418+ 13B0 CD CB 0F CALL TSTNUM ; Make sure numeric argument -2419+ 13B3 CD D1 09 CALL CHKSYN ; Make sure ")" follows -2420+ 13B6 29 .BYTE ")" -2421+ 13B7 CD D1 09 CALL CHKSYN ; Make sure "=" follows -2422+ 13BA B4 .BYTE ZEQUAL ; "=" token -2423+ 13BB 44 LD B,H ; Code string address to BC -2424+ 13BC 4D LD C,L -2425+ 13BD E3 EX (SP),HL ; Save code str , Get FN ptr -2426+ 13BE 71 LD (HL),C ; Save LSB of FN code string -2427+ 13BF 23 INC HL -2428+ 13C0 70 LD (HL),B ; Save MSB of FN code string -2429+ 13C1 C3 59 14 JP SVSTAD ; Save address and do function -2430+ 13C4 -2431+ 13C4 CD 1A 14 DOFN: CALL CHEKFN ; Make sure FN follows -2432+ 13C7 D5 PUSH DE ; Save function pointer address -2433+ 13C8 CD 9F 10 CALL EVLPAR ; Evaluate expression in "()" -2434+ 13CB CD CB 0F CALL TSTNUM ; Make sure numeric result -2435+ 13CE E3 EX (SP),HL ; Save code str , Get FN ptr -2436+ 13CF 5E LD E,(HL) ; Get LSB of FN code string -2437+ 13D0 23 INC HL -2438+ 13D1 56 LD D,(HL) ; Get MSB of FN code string -2439+ 13D2 23 INC HL -2440+ 13D3 7A LD A,D ; And function DEFined? -2441+ 13D4 B3 OR E -2442+ 13D5 CA 0F 07 JP Z,UFERR ; No - ?UF Error -2443+ 13D8 7E LD A,(HL) ; Get LSB of argument address -2444+ 13D9 23 INC HL -2445+ 13DA 66 LD H,(HL) ; Get MSB of argument address -2446+ 13DB 6F LD L,A ; HL = Arg variable address -2447+ 13DC E5 PUSH HL ; Save it -2448+ 13DD 2A 8E 31 LD HL,(FNRGNM) ; Get old argument name -2449+ 13E0 E3 EX (SP),HL ; ; Save old , Get new -2450+ 13E1 22 8E 31 LD (FNRGNM),HL ; Set new argument name -2451+ 13E4 2A 92 31 LD HL,(FNARG+2) ; Get LSB,NLSB of old arg value -2452+ 13E7 E5 PUSH HL ; Save it -2453+ 13E8 2A 90 31 LD HL,(FNARG) ; Get MSB,EXP of old arg value -2454+ 13EB E5 PUSH HL ; Save it -2455+ 13EC 21 90 31 LD HL,FNARG ; HL = Value of argument -2456+ 13EF D5 PUSH DE ; Save FN code string address -2457+ 13F0 CD 02 1A CALL FPTHL ; Move FPREG to argument -2458+ 13F3 E1 POP HL ; Get FN code string address -2459+ 13F4 CD C8 0F CALL GETNUM ; Get value from function -2460+ 13F7 2B DEC HL ; DEC 'cos GETCHR INCs -2461+ 13F8 CD 5B 0B CALL GETCHR ; Get next character -2462+ 13FB C2 03 07 JP NZ,SNERR ; Bad character in FN - Error -2463+ 13FE E1 POP HL ; Get MSB,EXP of old arg -2464+ 13FF 22 90 31 LD (FNARG),HL ; Restore it -2465+ 1402 E1 POP HL ; Get LSB,NLSB of old arg -2466+ 1403 22 92 31 LD (FNARG+2),HL ; Restore it -2467+ 1406 E1 POP HL ; Get name of old arg -2468+ 1407 22 8E 31 LD (FNRGNM),HL ; Restore it -2469+ 140A E1 POP HL ; Restore code string address -2470+ 140B C9 RET -2471+ 140C -2472+ 140C E5 IDTEST: PUSH HL ; Save code string address -2473+ 140D 2A 0C 31 LD HL,(LINEAT) ; Get current line number -2474+ 1410 23 INC HL ; -1 means direct statement -2475+ 1411 7C LD A,H -2476+ 1412 B5 OR L -2477+ 1413 E1 POP HL ; Restore code string address -2478+ 1414 C0 RET NZ ; Return if in program -2479+ 1415 1E 16 LD E,ID ; ?ID Error -2480+ 1417 C3 17 07 JP ERROR -2481+ 141A -2482+ 141A CD D1 09 CHEKFN: CALL CHKSYN ; Make sure FN follows -2483+ 141D A7 .BYTE ZFN ; "FN" token -2484+ 141E 3E 80 LD A,80H -2485+ 1420 32 7B 31 LD (FORFLG),A ; Flag FN name to find -2486+ 1423 B6 OR (HL) ; FN name has bit 7 set -2487+ 1424 47 LD B,A ; in first byte of name -2488+ 1425 CD C3 11 CALL GTFNAM ; Get FN name -2489+ 1428 C3 CB 0F JP TSTNUM ; Make sure numeric function -2490+ 142B -2491+ 142B CD CB 0F STR: CALL TSTNUM ; Make sure it's a number -2492+ 142E CD 4F 1B CALL NUMASC ; Turn number into text -2493+ 1431 CD 5F 14 STR1: CALL CRTST ; Create string entry for it -2494+ 1434 CD E4 15 CALL GSTRCU ; Current string to pool -2495+ 1437 01 3F 16 LD BC,TOPOOL ; Save in string pool -2496+ 143A C5 PUSH BC ; Save address on stack -2497+ 143B -2498+ 143B 7E SAVSTR: LD A,(HL) ; Get string length -2499+ 143C 23 INC HL -2500+ 143D 23 INC HL -2501+ 143E E5 PUSH HL ; Save pointer to string -2502+ 143F CD BA 14 CALL TESTR ; See if enough string space -2503+ 1442 E1 POP HL ; Restore pointer to string -2504+ 1443 4E LD C,(HL) ; Get LSB of address -2505+ 1444 23 INC HL -2506+ 1445 46 LD B,(HL) ; Get MSB of address -2507+ 1446 CD 53 14 CALL CRTMST ; Create string entry -2508+ 1449 E5 PUSH HL ; Save pointer to MSB of addr -2509+ 144A 6F LD L,A ; Length of string -2510+ 144B CD D7 15 CALL TOSTRA ; Move to string area -2511+ 144E D1 POP DE ; Restore pointer to MSB -2512+ 144F C9 RET -2513+ 1450 -2514+ 1450 CD BA 14 MKTMST: CALL TESTR ; See if enough string space -2515+ 1453 21 6F 31 CRTMST: LD HL,TMPSTR ; Temporary string -2516+ 1456 E5 PUSH HL ; Save it -2517+ 1457 77 LD (HL),A ; Save length of string -2518+ 1458 23 INC HL -2519+ 1459 23 SVSTAD: INC HL -2520+ 145A 73 LD (HL),E ; Save LSB of address -2521+ 145B 23 INC HL -2522+ 145C 72 LD (HL),D ; Save MSB of address -2523+ 145D E1 POP HL ; Restore pointer -2524+ 145E C9 RET -2525+ 145F -2526+ 145F 2B CRTST: DEC HL ; DEC - INCed after -2527+ 1460 06 22 QTSTR: LD B,'"' ; Terminating quote -2528+ 1462 50 LD D,B ; Quote to D -2529+ 1463 E5 DTSTR: PUSH HL ; Save start -2530+ 1464 0E FF LD C,-1 ; Set counter to -1 -2531+ 1466 23 QTSTLP: INC HL ; Move on -2532+ 1467 7E LD A,(HL) ; Get byte -2533+ 1468 0C INC C ; Count bytes -2534+ 1469 B7 OR A ; End of line? -2535+ 146A CA 75 14 JP Z,CRTSTE ; Yes - Create string entry -2536+ 146D BA CP D ; Terminator D found? -2537+ 146E CA 75 14 JP Z,CRTSTE ; Yes - Create string entry -2538+ 1471 B8 CP B ; Terminator B found? -2539+ 1472 C2 66 14 JP NZ,QTSTLP ; No - Keep looking -2540+ 1475 FE 22 CRTSTE: CP '"' ; End with '"'? -2541+ 1477 CC 5B 0B CALL Z,GETCHR ; Yes - Get next character -2542+ 147A E3 EX (SP),HL ; Starting quote -2543+ 147B 23 INC HL ; First byte of string -2544+ 147C EB EX DE,HL ; To DE -2545+ 147D 79 LD A,C ; Get length -2546+ 147E CD 53 14 CALL CRTMST ; Create string entry -2547+ 1481 11 6F 31 TSTOPL: LD DE,TMPSTR ; Temporary string -2548+ 1484 2A 61 31 LD HL,(TMSTPT) ; Temporary string pool pointer -2549+ 1487 22 94 31 LD (FPREG),HL ; Save address of string ptr -2550+ 148A 3E 01 LD A,1 -2551+ 148C 32 5D 31 LD (TYPE),A ; Set type to string -2552+ 148F CD 05 1A CALL DETHL4 ; Move string to pool -2553+ 1492 CD CB 09 CALL CPDEHL ; Out of string pool? -2554+ 1495 22 61 31 LD (TMSTPT),HL ; Save new pointer -2555+ 1498 E1 POP HL ; Restore code string address -2556+ 1499 7E LD A,(HL) ; Get next code byte -2557+ 149A C0 RET NZ ; Return if pool OK -2558+ 149B 1E 1E LD E,ST ; ?ST Error -2559+ 149D C3 17 07 JP ERROR ; String pool overflow -2560+ 14A0 -2561+ 14A0 23 PRNUMS: INC HL ; Skip leading space -2562+ 14A1 CD 5F 14 PRS: CALL CRTST ; Create string entry for it -2563+ 14A4 CD E4 15 PRS1: CALL GSTRCU ; Current string to pool -2564+ 14A7 CD F9 19 CALL LOADFP ; Move string block to BCDE -2565+ 14AA 1C INC E ; Length + 1 -2566+ 14AB 1D PRSLP: DEC E ; Count characters -2567+ 14AC C8 RET Z ; End of string -2568+ 14AD 0A LD A,(BC) ; Get byte to output -2569+ 14AE CD DC 09 CALL OUTC ; Output character in A -2570+ 14B1 FE 0D CP CR ; Return? -2571+ 14B3 CC 0D 0E CALL Z,DONULL ; Yes - Do nulls -2572+ 14B6 03 INC BC ; Next byte in string -2573+ 14B7 C3 AB 14 JP PRSLP ; More characters to output -2574+ 14BA -2575+ 14BA B7 TESTR: OR A ; Test if enough room -2576+ 14BB 0E .BYTE 0EH ; No garbage collection done -2577+ 14BC F1 GRBDON: POP AF ; Garbage collection done -2578+ 14BD F5 PUSH AF ; Save status -2579+ 14BE 2A 0A 31 LD HL,(STRSPC) ; Bottom of string space in use -2580+ 14C1 EB EX DE,HL ; To DE -2581+ 14C2 2A 73 31 LD HL,(STRBOT) ; Bottom of string area -2582+ 14C5 2F CPL ; Negate length (Top down) -2583+ 14C6 4F LD C,A ; -Length to BC -2584+ 14C7 06 FF LD B,-1 ; BC = -ve length of string -2585+ 14C9 09 ADD HL,BC ; Add to bottom of space in use -2586+ 14CA 23 INC HL ; Plus one for 2's complement -2587+ 14CB CD CB 09 CALL CPDEHL ; Below string RAM area? -2588+ 14CE DA D8 14 JP C,TESTOS ; Tidy up if not done else err -2589+ 14D1 22 73 31 LD (STRBOT),HL ; Save new bottom of area -2590+ 14D4 23 INC HL ; Point to first byte of string -2591+ 14D5 EB EX DE,HL ; Address to DE -2592+ 14D6 F1 POPAF: POP AF ; Throw away status push -2593+ 14D7 C9 RET -2594+ 14D8 -2595+ 14D8 F1 TESTOS: POP AF ; Garbage collect been done? -2596+ 14D9 1E 1A LD E,OS ; ?OS Error -2597+ 14DB CA 17 07 JP Z,ERROR ; Yes - Not enough string apace -2598+ 14DE BF CP A ; Flag garbage collect done -2599+ 14DF F5 PUSH AF ; Save status -2600+ 14E0 01 BC 14 LD BC,GRBDON ; Garbage collection done -2601+ 14E3 C5 PUSH BC ; Save for RETurn -2602+ 14E4 2A 5F 31 GARBGE: LD HL,(LSTRAM) ; Get end of RAM pointer -2603+ 14E7 22 73 31 GARBLP: LD (STRBOT),HL ; Reset string pointer -2604+ 14EA 21 00 00 LD HL,0 -2605+ 14ED E5 PUSH HL ; Flag no string found -2606+ 14EE 2A 0A 31 LD HL,(STRSPC) ; Get bottom of string space -2607+ 14F1 E5 PUSH HL ; Save bottom of string space -2608+ 14F2 21 63 31 LD HL,TMSTPL ; Temporary string pool -2609+ 14F5 EB GRBLP: EX DE,HL -2610+ 14F6 2A 61 31 LD HL,(TMSTPT) ; Temporary string pool pointer -2611+ 14F9 EB EX DE,HL -2612+ 14FA CD CB 09 CALL CPDEHL ; Temporary string pool done? -2613+ 14FD 01 F5 14 LD BC,GRBLP ; Loop until string pool done -2614+ 1500 C2 49 15 JP NZ,STPOOL ; No - See if in string area -2615+ 1503 2A 86 31 LD HL,(PROGND) ; Start of simple variables -2616+ 1506 EB SMPVAR: EX DE,HL -2617+ 1507 2A 88 31 LD HL,(VAREND) ; End of simple variables -2618+ 150A EB EX DE,HL -2619+ 150B CD CB 09 CALL CPDEHL ; All simple strings done? -2620+ 150E CA 1C 15 JP Z,ARRLP ; Yes - Do string arrays -2621+ 1511 7E LD A,(HL) ; Get type of variable -2622+ 1512 23 INC HL -2623+ 1513 23 INC HL -2624+ 1514 B7 OR A ; "S" flag set if string -2625+ 1515 CD 4C 15 CALL STRADD ; See if string in string area -2626+ 1518 C3 06 15 JP SMPVAR ; Loop until simple ones done -2627+ 151B -2628+ 151B C1 GNXARY: POP BC ; Scrap address of this array -2629+ 151C EB ARRLP: EX DE,HL -2630+ 151D 2A 8A 31 LD HL,(ARREND) ; End of string arrays -2631+ 1520 EB EX DE,HL -2632+ 1521 CD CB 09 CALL CPDEHL ; All string arrays done? -2633+ 1524 CA 72 15 JP Z,SCNEND ; Yes - Move string if found -2634+ 1527 CD F9 19 CALL LOADFP ; Get array name to BCDE -2635+ 152A 7B LD A,E ; Get type of array -2636+ 152B E5 PUSH HL ; Save address of num of dim'ns -2637+ 152C 09 ADD HL,BC ; Start of next array -2638+ 152D B7 OR A ; Test type of array -2639+ 152E F2 1B 15 JP P,GNXARY ; Numeric array - Ignore it -2640+ 1531 22 75 31 LD (CUROPR),HL ; Save address of next array -2641+ 1534 E1 POP HL ; Get address of num of dim'ns -2642+ 1535 4E LD C,(HL) ; BC = Number of dimensions -2643+ 1536 06 00 LD B,0 -2644+ 1538 09 ADD HL,BC ; Two bytes per dimension size -2645+ 1539 09 ADD HL,BC -2646+ 153A 23 INC HL ; Plus one for number of dim'ns -2647+ 153B EB GRBARY: EX DE,HL -2648+ 153C 2A 75 31 LD HL,(CUROPR) ; Get address of next array -2649+ 153F EB EX DE,HL -2650+ 1540 CD CB 09 CALL CPDEHL ; Is this array finished? -2651+ 1543 CA 1C 15 JP Z,ARRLP ; Yes - Get next one -2652+ 1546 01 3B 15 LD BC,GRBARY ; Loop until array all done -2653+ 1549 C5 STPOOL: PUSH BC ; Save return address -2654+ 154A F6 80 OR 80H ; Flag string type -2655+ 154C 7E STRADD: LD A,(HL) ; Get string length -2656+ 154D 23 INC HL -2657+ 154E 23 INC HL -2658+ 154F 5E LD E,(HL) ; Get LSB of string address -2659+ 1550 23 INC HL -2660+ 1551 56 LD D,(HL) ; Get MSB of string address -2661+ 1552 23 INC HL -2662+ 1553 F0 RET P ; Not a string - Return -2663+ 1554 B7 OR A ; Set flags on string length -2664+ 1555 C8 RET Z ; Null string - Return -2665+ 1556 44 LD B,H ; Save variable pointer -2666+ 1557 4D LD C,L -2667+ 1558 2A 73 31 LD HL,(STRBOT) ; Bottom of new area -2668+ 155B CD CB 09 CALL CPDEHL ; String been done? -2669+ 155E 60 LD H,B ; Restore variable pointer -2670+ 155F 69 LD L,C -2671+ 1560 D8 RET C ; String done - Ignore -2672+ 1561 E1 POP HL ; Return address -2673+ 1562 E3 EX (SP),HL ; Lowest available string area -2674+ 1563 CD CB 09 CALL CPDEHL ; String within string area? -2675+ 1566 E3 EX (SP),HL ; Lowest available string area -2676+ 1567 E5 PUSH HL ; Re-save return address -2677+ 1568 60 LD H,B ; Restore variable pointer -2678+ 1569 69 LD L,C -2679+ 156A D0 RET NC ; Outside string area - Ignore -2680+ 156B C1 POP BC ; Get return , Throw 2 away -2681+ 156C F1 POP AF ; -2682+ 156D F1 POP AF ; -2683+ 156E E5 PUSH HL ; Save variable pointer -2684+ 156F D5 PUSH DE ; Save address of current -2685+ 1570 C5 PUSH BC ; Put back return address -2686+ 1571 C9 RET ; Go to it -2687+ 1572 -2688+ 1572 D1 SCNEND: POP DE ; Addresses of strings -2689+ 1573 E1 POP HL ; -2690+ 1574 7D LD A,L ; HL = 0 if no more to do -2691+ 1575 B4 OR H -2692+ 1576 C8 RET Z ; No more to do - Return -2693+ 1577 2B DEC HL -2694+ 1578 46 LD B,(HL) ; MSB of address of string -2695+ 1579 2B DEC HL -2696+ 157A 4E LD C,(HL) ; LSB of address of string -2697+ 157B E5 PUSH HL ; Save variable address -2698+ 157C 2B DEC HL -2699+ 157D 2B DEC HL -2700+ 157E 6E LD L,(HL) ; HL = Length of string -2701+ 157F 26 00 LD H,0 -2702+ 1581 09 ADD HL,BC ; Address of end of string+1 -2703+ 1582 50 LD D,B ; String address to DE -2704+ 1583 59 LD E,C -2705+ 1584 2B DEC HL ; Last byte in string -2706+ 1585 44 LD B,H ; Address to BC -2707+ 1586 4D LD C,L -2708+ 1587 2A 73 31 LD HL,(STRBOT) ; Current bottom of string area -2709+ 158A CD D2 06 CALL MOVSTR ; Move string to new address -2710+ 158D E1 POP HL ; Restore variable address -2711+ 158E 71 LD (HL),C ; Save new LSB of address -2712+ 158F 23 INC HL -2713+ 1590 70 LD (HL),B ; Save new MSB of address -2714+ 1591 69 LD L,C ; Next string area+1 to HL -2715+ 1592 60 LD H,B -2716+ 1593 2B DEC HL ; Next string area address -2717+ 1594 C3 E7 14 JP GARBLP ; Look for more strings -2718+ 1597 -2719+ 1597 C5 CONCAT: PUSH BC ; Save prec' opr & code string -2720+ 1598 E5 PUSH HL ; -2721+ 1599 2A 94 31 LD HL,(FPREG) ; Get first string -2722+ 159C E3 EX (SP),HL ; Save first string -2723+ 159D CD 51 10 CALL OPRND ; Get second string -2724+ 15A0 E3 EX (SP),HL ; Restore first string -2725+ 15A1 CD CC 0F CALL TSTSTR ; Make sure it's a string -2726+ 15A4 7E LD A,(HL) ; Get length of second string -2727+ 15A5 E5 PUSH HL ; Save first string -2728+ 15A6 2A 94 31 LD HL,(FPREG) ; Get second string -2729+ 15A9 E5 PUSH HL ; Save second string -2730+ 15AA 86 ADD A,(HL) ; Add length of second string -2731+ 15AB 1E 1C LD E,LS ; ?LS Error -2732+ 15AD DA 17 07 JP C,ERROR ; String too long - Error -2733+ 15B0 CD 50 14 CALL MKTMST ; Make temporary string -2734+ 15B3 D1 POP DE ; Get second string to DE -2735+ 15B4 CD E8 15 CALL GSTRDE ; Move to string pool if needed -2736+ 15B7 E3 EX (SP),HL ; Get first string -2737+ 15B8 CD E7 15 CALL GSTRHL ; Move to string pool if needed -2738+ 15BB E5 PUSH HL ; Save first string -2739+ 15BC 2A 71 31 LD HL,(TMPSTR+2) ; Temporary string address -2740+ 15BF EB EX DE,HL ; To DE -2741+ 15C0 CD CE 15 CALL SSTSA ; First string to string area -2742+ 15C3 CD CE 15 CALL SSTSA ; Second string to string area -2743+ 15C6 21 E6 0F LD HL,EVAL2 ; Return to evaluation loop -2744+ 15C9 E3 EX (SP),HL ; Save return,get code string -2745+ 15CA E5 PUSH HL ; Save code string address -2746+ 15CB C3 81 14 JP TSTOPL ; To temporary string to pool -2747+ 15CE -2748+ 15CE E1 SSTSA: POP HL ; Return address -2749+ 15CF E3 EX (SP),HL ; Get string block,save return -2750+ 15D0 7E LD A,(HL) ; Get length of string -2751+ 15D1 23 INC HL -2752+ 15D2 23 INC HL -2753+ 15D3 4E LD C,(HL) ; Get LSB of string address -2754+ 15D4 23 INC HL -2755+ 15D5 46 LD B,(HL) ; Get MSB of string address -2756+ 15D6 6F LD L,A ; Length to L -2757+ 15D7 2C TOSTRA: INC L ; INC - DECed after -2758+ 15D8 2D TSALP: DEC L ; Count bytes moved -2759+ 15D9 C8 RET Z ; End of string - Return -2760+ 15DA 0A LD A,(BC) ; Get source -2761+ 15DB 12 LD (DE),A ; Save destination -2762+ 15DC 03 INC BC ; Next source -2763+ 15DD 13 INC DE ; Next destination -2764+ 15DE C3 D8 15 JP TSALP ; Loop until string moved -2765+ 15E1 -2766+ 15E1 CD CC 0F GETSTR: CALL TSTSTR ; Make sure it's a string -2767+ 15E4 2A 94 31 GSTRCU: LD HL,(FPREG) ; Get current string -2768+ 15E7 EB GSTRHL: EX DE,HL ; Save DE -2769+ 15E8 CD 02 16 GSTRDE: CALL BAKTMP ; Was it last tmp-str? -2770+ 15EB EB EX DE,HL ; Restore DE -2771+ 15EC C0 RET NZ ; No - Return -2772+ 15ED D5 PUSH DE ; Save string -2773+ 15EE 50 LD D,B ; String block address to DE -2774+ 15EF 59 LD E,C -2775+ 15F0 1B DEC DE ; Point to length -2776+ 15F1 4E LD C,(HL) ; Get string length -2777+ 15F2 2A 73 31 LD HL,(STRBOT) ; Current bottom of string area -2778+ 15F5 CD CB 09 CALL CPDEHL ; Last one in string area? -2779+ 15F8 C2 00 16 JP NZ,POPHL ; No - Return -2780+ 15FB 47 LD B,A ; Clear B (A=0) -2781+ 15FC 09 ADD HL,BC ; Remove string from str' area -2782+ 15FD 22 73 31 LD (STRBOT),HL ; Save new bottom of str' area -2783+ 1600 E1 POPHL: POP HL ; Restore string -2784+ 1601 C9 RET -2785+ 1602 -2786+ 1602 2A 61 31 BAKTMP: LD HL,(TMSTPT) ; Get temporary string pool top -2787+ 1605 2B DEC HL ; Back -2788+ 1606 46 LD B,(HL) ; Get MSB of address -2789+ 1607 2B DEC HL ; Back -2790+ 1608 4E LD C,(HL) ; Get LSB of address -2791+ 1609 2B DEC HL ; Back -2792+ 160A 2B DEC HL ; Back -2793+ 160B CD CB 09 CALL CPDEHL ; String last in string pool? -2794+ 160E C0 RET NZ ; Yes - Leave it -2795+ 160F 22 61 31 LD (TMSTPT),HL ; Save new string pool top -2796+ 1612 C9 RET -2797+ 1613 -2798+ 1613 01 92 13 LEN: LD BC,PASSA ; To return integer A -2799+ 1616 C5 PUSH BC ; Save address -2800+ 1617 CD E1 15 GETLEN: CALL GETSTR ; Get string and its length -2801+ 161A AF XOR A -2802+ 161B 57 LD D,A ; Clear D -2803+ 161C 32 5D 31 LD (TYPE),A ; Set type to numeric -2804+ 161F 7E LD A,(HL) ; Get length of string -2805+ 1620 B7 OR A ; Set status flags -2806+ 1621 C9 RET -2807+ 1622 -2808+ 1622 01 92 13 ASC: LD BC,PASSA ; To return integer A -2809+ 1625 C5 PUSH BC ; Save address -2810+ 1626 CD 17 16 GTFLNM: CALL GETLEN ; Get length of string -2811+ 1629 CA 22 0C JP Z,FCERR ; Null string - Error -2812+ 162C 23 INC HL -2813+ 162D 23 INC HL -2814+ 162E 5E LD E,(HL) ; Get LSB of address -2815+ 162F 23 INC HL -2816+ 1630 56 LD D,(HL) ; Get MSB of address -2817+ 1631 1A LD A,(DE) ; Get first byte of string -2818+ 1632 C9 RET -2819+ 1633 -2820+ 1633 3E 01 CHR: LD A,1 ; One character string -2821+ 1635 CD 50 14 CALL MKTMST ; Make a temporary string -2822+ 1638 CD 2C 17 CALL MAKINT ; Make it integer A -2823+ 163B 2A 71 31 LD HL,(TMPSTR+2) ; Get address of string -2824+ 163E 73 LD (HL),E ; Save character -2825+ 163F C1 TOPOOL: POP BC ; Clean up stack -2826+ 1640 C3 81 14 JP TSTOPL ; Temporary string to pool -2827+ 1643 -2828+ 1643 CD DC 16 LEFT: CALL LFRGNM ; Get number and ending ")" -2829+ 1646 AF XOR A ; Start at first byte in string -2830+ 1647 E3 RIGHT1: EX (SP),HL ; Save code string,Get string -2831+ 1648 4F LD C,A ; Starting position in string -2832+ 1649 E5 MID1: PUSH HL ; Save string block address -2833+ 164A 7E LD A,(HL) ; Get length of string -2834+ 164B B8 CP B ; Compare with number given -2835+ 164C DA 51 16 JP C,ALLFOL ; All following bytes required -2836+ 164F 78 LD A,B ; Get new length -2837+ 1650 11 .BYTE 11H ; Skip "LD C,0" -2838+ 1651 0E 00 ALLFOL: LD C,0 ; First byte of string -2839+ 1653 C5 PUSH BC ; Save position in string -2840+ 1654 CD BA 14 CALL TESTR ; See if enough string space -2841+ 1657 C1 POP BC ; Get position in string -2842+ 1658 E1 POP HL ; Restore string block address -2843+ 1659 E5 PUSH HL ; And re-save it -2844+ 165A 23 INC HL -2845+ 165B 23 INC HL -2846+ 165C 46 LD B,(HL) ; Get LSB of address -2847+ 165D 23 INC HL -2848+ 165E 66 LD H,(HL) ; Get MSB of address -2849+ 165F 68 LD L,B ; HL = address of string -2850+ 1660 06 00 LD B,0 ; BC = starting address -2851+ 1662 09 ADD HL,BC ; Point to that byte -2852+ 1663 44 LD B,H ; BC = source string -2853+ 1664 4D LD C,L -2854+ 1665 CD 53 14 CALL CRTMST ; Create a string entry -2855+ 1668 6F LD L,A ; Length of new string -2856+ 1669 CD D7 15 CALL TOSTRA ; Move string to string area -2857+ 166C D1 POP DE ; Clear stack -2858+ 166D CD E8 15 CALL GSTRDE ; Move to string pool if needed -2859+ 1670 C3 81 14 JP TSTOPL ; Temporary string to pool -2860+ 1673 -2861+ 1673 CD DC 16 RIGHT: CALL LFRGNM ; Get number and ending ")" -2862+ 1676 D1 POP DE ; Get string length -2863+ 1677 D5 PUSH DE ; And re-save -2864+ 1678 1A LD A,(DE) ; Get length -2865+ 1679 90 SUB B ; Move back N bytes -2866+ 167A C3 47 16 JP RIGHT1 ; Go and get sub-string -2867+ 167D -2868+ 167D EB MID: EX DE,HL ; Get code string address -2869+ 167E 7E LD A,(HL) ; Get next byte ',' or ")" -2870+ 167F CD E1 16 CALL MIDNUM ; Get number supplied -2871+ 1682 04 INC B ; Is it character zero? -2872+ 1683 05 DEC B -2873+ 1684 CA 22 0C JP Z,FCERR ; Yes - Error -2874+ 1687 C5 PUSH BC ; Save starting position -2875+ 1688 1E FF LD E,255 ; All of string -2876+ 168A FE 29 CP ')' ; Any length given? -2877+ 168C CA 96 16 JP Z,RSTSTR ; No - Rest of string -2878+ 168F CD D1 09 CALL CHKSYN ; Make sure ',' follows -2879+ 1692 2C .BYTE ',' -2880+ 1693 CD 29 17 CALL GETINT ; Get integer 0-255 -2881+ 1696 CD D1 09 RSTSTR: CALL CHKSYN ; Make sure ")" follows -2882+ 1699 29 .BYTE ")" -2883+ 169A F1 POP AF ; Restore starting position -2884+ 169B E3 EX (SP),HL ; Get string,8ave code string -2885+ 169C 01 49 16 LD BC,MID1 ; Continuation of MID$ routine -2886+ 169F C5 PUSH BC ; Save for return -2887+ 16A0 3D DEC A ; Starting position-1 -2888+ 16A1 BE CP (HL) ; Compare with length -2889+ 16A2 06 00 LD B,0 ; Zero bytes length -2890+ 16A4 D0 RET NC ; Null string if start past end -2891+ 16A5 4F LD C,A ; Save starting position-1 -2892+ 16A6 7E LD A,(HL) ; Get length of string -2893+ 16A7 91 SUB C ; Subtract start -2894+ 16A8 BB CP E ; Enough string for it? -2895+ 16A9 47 LD B,A ; Save maximum length available -2896+ 16AA D8 RET C ; Truncate string if needed -2897+ 16AB 43 LD B,E ; Set specified length -2898+ 16AC C9 RET ; Go and create string -2899+ 16AD -2900+ 16AD CD 17 16 VAL: CALL GETLEN ; Get length of string -2901+ 16B0 CA CA 17 JP Z,RESZER ; Result zero -2902+ 16B3 5F LD E,A ; Save length -2903+ 16B4 23 INC HL -2904+ 16B5 23 INC HL -2905+ 16B6 7E LD A,(HL) ; Get LSB of address -2906+ 16B7 23 INC HL -2907+ 16B8 66 LD H,(HL) ; Get MSB of address -2908+ 16B9 6F LD L,A ; HL = String address -2909+ 16BA E5 PUSH HL ; Save string address -2910+ 16BB 19 ADD HL,DE -2911+ 16BC 46 LD B,(HL) ; Get end of string+1 byte -2912+ 16BD 72 LD (HL),D ; Zero it to terminate -2913+ 16BE E3 EX (SP),HL ; Save string end,get start -2914+ 16BF C5 PUSH BC ; Save end+1 byte -2915+ 16C0 7E LD A,(HL) ; Get starting byte -2916+ 16C1 FE 24 CP '$' ; Hex number indicated? [function added] -2917+ 16C3 C2 CB 16 JP NZ,VAL1 -2918+ 16C6 CD F5 1E CALL HEXTFP ; Convert Hex to FPREG -2919+ 16C9 18 0D JR VAL3 -2920+ 16CB FE 25 VAL1: CP '%' ; Binary number indicated? [function added] -2921+ 16CD C2 D5 16 JP NZ,VAL2 -2922+ 16D0 CD 65 1F CALL BINTFP ; Convert Bin to FPREG -2923+ 16D3 18 03 JR VAL3 -2924+ 16D5 CD B1 1A VAL2: CALL ASCTFP ; Convert ASCII string to FP -2925+ 16D8 C1 VAL3: POP BC ; Restore end+1 byte -2926+ 16D9 E1 POP HL ; Restore end+1 address -2927+ 16DA 70 LD (HL),B ; Put back original byte -2928+ 16DB C9 RET -2929+ 16DC -2930+ 16DC EB LFRGNM: EX DE,HL ; Code string address to HL -2931+ 16DD CD D1 09 CALL CHKSYN ; Make sure ")" follows -2932+ 16E0 29 .BYTE ")" -2933+ 16E1 C1 MIDNUM: POP BC ; Get return address -2934+ 16E2 D1 POP DE ; Get number supplied -2935+ 16E3 C5 PUSH BC ; Re-save return address -2936+ 16E4 43 LD B,E ; Number to B -2937+ 16E5 C9 RET -2938+ 16E6 -2939+ 16E6 CD 2C 17 INP: CALL MAKINT ; Make it integer A -2940+ 16E9 32 EF 30 LD (INPORT),A ; Set input port -2941+ 16EC CD EE 30 CALL INPSUB ; Get input from port -2942+ 16EF C3 92 13 JP PASSA ; Return integer A -2943+ 16F2 -2944+ 16F2 CD 16 17 POUT: CALL SETIO ; Set up port number -2945+ 16F5 C3 B6 30 JP OUTSUB ; Output data and return -2946+ 16F8 -2947+ 16F8 CD 16 17 WAIT: CALL SETIO ; Set up port number -2948+ 16FB F5 PUSH AF ; Save AND mask -2949+ 16FC 1E 00 LD E,0 ; Assume zero if none given -2950+ 16FE 2B DEC HL ; DEC 'cos GETCHR INCs -2951+ 16FF CD 5B 0B CALL GETCHR ; Get next character -2952+ 1702 CA 0C 17 JP Z,NOXOR ; No XOR byte given -2953+ 1705 CD D1 09 CALL CHKSYN ; Make sure ',' follows -2954+ 1708 2C .BYTE ',' -2955+ 1709 CD 29 17 CALL GETINT ; Get integer 0-255 to XOR with -2956+ 170C C1 NOXOR: POP BC ; Restore AND mask -2957+ 170D CD EE 30 WAITLP: CALL INPSUB ; Get input -2958+ 1710 AB XOR E ; Flip selected bits -2959+ 1711 A0 AND B ; Result non-zero? -2960+ 1712 CA 0D 17 JP Z,WAITLP ; No = keep waiting -2961+ 1715 C9 RET -2962+ 1716 -2963+ 1716 CD 29 17 SETIO: CALL GETINT ; Get integer 0-255 -2964+ 1719 32 EF 30 LD (INPORT),A ; Set input port -2965+ 171C 32 B7 30 LD (OTPORT),A ; Set output port -2966+ 171F CD D1 09 CALL CHKSYN ; Make sure ',' follows -2967+ 1722 2C .BYTE ',' -2968+ 1723 C3 29 17 JP GETINT ; Get integer 0-255 and return -2969+ 1726 -2970+ 1726 CD 5B 0B FNDNUM: CALL GETCHR ; Get next character -2971+ 1729 CD C8 0F GETINT: CALL GETNUM ; Get a number from 0 to 255 -2972+ 172C CD 07 0C MAKINT: CALL DEPINT ; Make sure value 0 - 255 -2973+ 172F 7A LD A,D ; Get MSB of number -2974+ 1730 B7 OR A ; Zero? -2975+ 1731 C2 22 0C JP NZ,FCERR ; No - Error -2976+ 1734 2B DEC HL ; DEC 'cos GETCHR INCs -2977+ 1735 CD 5B 0B CALL GETCHR ; Get next character -2978+ 1738 7B LD A,E ; Get number to A -2979+ 1739 C9 RET -2980+ 173A -2981+ 173A CD 0D 0C PEEK: CALL DEINT ; Get memory address -2982+ 173D 1A LD A,(DE) ; Get byte in memory -2983+ 173E C3 92 13 JP PASSA ; Return integer A -2984+ 1741 -2985+ 1741 CD C8 0F POKE: CALL GETNUM ; Get memory address -2986+ 1744 CD 0D 0C CALL DEINT ; Get integer -32768 to 3276 -2987+ 1747 D5 PUSH DE ; Save memory address -2988+ 1748 CD D1 09 CALL CHKSYN ; Make sure ',' follows -2989+ 174B 2C .BYTE ',' -2990+ 174C CD 29 17 CALL GETINT ; Get integer 0-255 -2991+ 174F D1 POP DE ; Restore memory address -2992+ 1750 12 LD (DE),A ; Load it into memory -2993+ 1751 C9 RET -2994+ 1752 -2995+ 1752 21 28 1C ROUND: LD HL,HALF ; Add 0.5 to FPREG -2996+ 1755 CD F9 19 ADDPHL: CALL LOADFP ; Load FP at (HL) to BCDE -2997+ 1758 C3 64 17 JP FPADD ; Add BCDE to FPREG -2998+ 175B -2999+ 175B CD F9 19 SUBPHL: CALL LOADFP ; FPREG = -FPREG + number at HL -3000+ 175E 21 .BYTE 21H ; Skip "POP BC" and "POP DE" -3001+ 175F C1 PSUB: POP BC ; Get FP number from stack -3002+ 1760 D1 POP DE -3003+ 1761 CD D3 19 SUBCDE: CALL INVSGN ; Negate FPREG -3004+ 1764 78 FPADD: LD A,B ; Get FP exponent -3005+ 1765 B7 OR A ; Is number zero? -3006+ 1766 C8 RET Z ; Yes - Nothing to add -3007+ 1767 3A 97 31 LD A,(FPEXP) ; Get FPREG exponent -3008+ 176A B7 OR A ; Is this number zero? -3009+ 176B CA EB 19 JP Z,FPBCDE ; Yes - Move BCDE to FPREG -3010+ 176E 90 SUB B ; BCDE number larger? -3011+ 176F D2 7E 17 JP NC,NOSWAP ; No - Don't swap them -3012+ 1772 2F CPL ; Two's complement -3013+ 1773 3C INC A ; FP exponent -3014+ 1774 EB EX DE,HL -3015+ 1775 CD DB 19 CALL STAKFP ; Put FPREG on stack -3016+ 1778 EB EX DE,HL -3017+ 1779 CD EB 19 CALL FPBCDE ; Move BCDE to FPREG -3018+ 177C C1 POP BC ; Restore number from stack -3019+ 177D D1 POP DE -3020+ 177E FE 19 NOSWAP: CP 24+1 ; Second number insignificant? -3021+ 1780 D0 RET NC ; Yes - First number is result -3022+ 1781 F5 PUSH AF ; Save number of bits to scale -3023+ 1782 CD 10 1A CALL SIGNS ; Set MSBs & sign of result -3024+ 1785 67 LD H,A ; Save sign of result -3025+ 1786 F1 POP AF ; Restore scaling factor -3026+ 1787 CD 29 18 CALL SCALE ; Scale BCDE to same exponent -3027+ 178A B4 OR H ; Result to be positive? -3028+ 178B 21 94 31 LD HL,FPREG ; Point to FPREG -3029+ 178E F2 A4 17 JP P,MINCDE ; No - Subtract FPREG from CDE -3030+ 1791 CD 09 18 CALL PLUCDE ; Add FPREG to CDE -3031+ 1794 D2 EA 17 JP NC,RONDUP ; No overflow - Round it up -3032+ 1797 23 INC HL ; Point to exponent -3033+ 1798 34 INC (HL) ; Increment it -3034+ 1799 CA 12 07 JP Z,OVERR ; Number overflowed - Error -3035+ 179C 2E 01 LD L,1 ; 1 bit to shift right -3036+ 179E CD 3F 18 CALL SHRT1 ; Shift result right -3037+ 17A1 C3 EA 17 JP RONDUP ; Round it up -3038+ 17A4 -3039+ 17A4 AF MINCDE: XOR A ; Clear A and carry -3040+ 17A5 90 SUB B ; Negate exponent -3041+ 17A6 47 LD B,A ; Re-save exponent -3042+ 17A7 7E LD A,(HL) ; Get LSB of FPREG -3043+ 17A8 9B SBC A, E ; Subtract LSB of BCDE -3044+ 17A9 5F LD E,A ; Save LSB of BCDE -3045+ 17AA 23 INC HL -3046+ 17AB 7E LD A,(HL) ; Get NMSB of FPREG -3047+ 17AC 9A SBC A,D ; Subtract NMSB of BCDE -3048+ 17AD 57 LD D,A ; Save NMSB of BCDE -3049+ 17AE 23 INC HL -3050+ 17AF 7E LD A,(HL) ; Get MSB of FPREG -3051+ 17B0 99 SBC A,C ; Subtract MSB of BCDE -3052+ 17B1 4F LD C,A ; Save MSB of BCDE -3053+ 17B2 DC 15 18 CONPOS: CALL C,COMPL ; Overflow - Make it positive -3054+ 17B5 -3055+ 17B5 68 BNORM: LD L,B ; L = Exponent -3056+ 17B6 63 LD H,E ; H = LSB -3057+ 17B7 AF XOR A -3058+ 17B8 47 BNRMLP: LD B,A ; Save bit count -3059+ 17B9 79 LD A,C ; Get MSB -3060+ 17BA B7 OR A ; Is it zero? -3061+ 17BB C2 D7 17 JP NZ,PNORM ; No - Do it bit at a time -3062+ 17BE 4A LD C,D ; MSB = NMSB -3063+ 17BF 54 LD D,H ; NMSB= LSB -3064+ 17C0 65 LD H,L ; LSB = VLSB -3065+ 17C1 6F LD L,A ; VLSB= 0 -3066+ 17C2 78 LD A,B ; Get exponent -3067+ 17C3 D6 08 SUB 8 ; Count 8 bits -3068+ 17C5 FE E0 CP -24-8 ; Was number zero? -3069+ 17C7 C2 B8 17 JP NZ,BNRMLP ; No - Keep normalising -3070+ 17CA AF RESZER: XOR A ; Result is zero -3071+ 17CB 32 97 31 SAVEXP: LD (FPEXP),A ; Save result as zero -3072+ 17CE C9 RET -3073+ 17CF -3074+ 17CF 05 NORMAL: DEC B ; Count bits -3075+ 17D0 29 ADD HL,HL ; Shift HL left -3076+ 17D1 7A LD A,D ; Get NMSB -3077+ 17D2 17 RLA ; Shift left with last bit -3078+ 17D3 57 LD D,A ; Save NMSB -3079+ 17D4 79 LD A,C ; Get MSB -3080+ 17D5 8F ADC A,A ; Shift left with last bit -3081+ 17D6 4F LD C,A ; Save MSB -3082+ 17D7 F2 CF 17 PNORM: JP P,NORMAL ; Not done - Keep going -3083+ 17DA 78 LD A,B ; Number of bits shifted -3084+ 17DB 5C LD E,H ; Save HL in EB -3085+ 17DC 45 LD B,L -3086+ 17DD B7 OR A ; Any shifting done? -3087+ 17DE CA EA 17 JP Z,RONDUP ; No - Round it up -3088+ 17E1 21 97 31 LD HL,FPEXP ; Point to exponent -3089+ 17E4 86 ADD A,(HL) ; Add shifted bits -3090+ 17E5 77 LD (HL),A ; Re-save exponent -3091+ 17E6 D2 CA 17 JP NC,RESZER ; Underflow - Result is zero -3092+ 17E9 C8 RET Z ; Result is zero -3093+ 17EA 78 RONDUP: LD A,B ; Get VLSB of number -3094+ 17EB 21 97 31 RONDB: LD HL,FPEXP ; Point to exponent -3095+ 17EE B7 OR A ; Any rounding? -3096+ 17EF FC FC 17 CALL M,FPROND ; Yes - Round number up -3097+ 17F2 46 LD B,(HL) ; B = Exponent -3098+ 17F3 23 INC HL -3099+ 17F4 7E LD A,(HL) ; Get sign of result -3100+ 17F5 E6 80 AND 10000000B ; Only bit 7 needed -3101+ 17F7 A9 XOR C ; Set correct sign -3102+ 17F8 4F LD C,A ; Save correct sign in number -3103+ 17F9 C3 EB 19 JP FPBCDE ; Move BCDE to FPREG -3104+ 17FC -3105+ 17FC 1C FPROND: INC E ; Round LSB -3106+ 17FD C0 RET NZ ; Return if ok -3107+ 17FE 14 INC D ; Round NMSB -3108+ 17FF C0 RET NZ ; Return if ok -3109+ 1800 0C INC C ; Round MSB -3110+ 1801 C0 RET NZ ; Return if ok -3111+ 1802 0E 80 LD C,80H ; Set normal value -3112+ 1804 34 INC (HL) ; Increment exponent -3113+ 1805 C0 RET NZ ; Return if ok -3114+ 1806 C3 12 07 JP OVERR ; Overflow error -3115+ 1809 -3116+ 1809 7E PLUCDE: LD A,(HL) ; Get LSB of FPREG -3117+ 180A 83 ADD A,E ; Add LSB of BCDE -3118+ 180B 5F LD E,A ; Save LSB of BCDE -3119+ 180C 23 INC HL -3120+ 180D 7E LD A,(HL) ; Get NMSB of FPREG -3121+ 180E 8A ADC A,D ; Add NMSB of BCDE -3122+ 180F 57 LD D,A ; Save NMSB of BCDE -3123+ 1810 23 INC HL -3124+ 1811 7E LD A,(HL) ; Get MSB of FPREG -3125+ 1812 89 ADC A,C ; Add MSB of BCDE -3126+ 1813 4F LD C,A ; Save MSB of BCDE -3127+ 1814 C9 RET -3128+ 1815 -3129+ 1815 21 98 31 COMPL: LD HL,SGNRES ; Sign of result -3130+ 1818 7E LD A,(HL) ; Get sign of result -3131+ 1819 2F CPL ; Negate it -3132+ 181A 77 LD (HL),A ; Put it back -3133+ 181B AF XOR A -3134+ 181C 6F LD L,A ; Set L to zero -3135+ 181D 90 SUB B ; Negate exponent,set carry -3136+ 181E 47 LD B,A ; Re-save exponent -3137+ 181F 7D LD A,L ; Load zero -3138+ 1820 9B SBC A,E ; Negate LSB -3139+ 1821 5F LD E,A ; Re-save LSB -3140+ 1822 7D LD A,L ; Load zero -3141+ 1823 9A SBC A,D ; Negate NMSB -3142+ 1824 57 LD D,A ; Re-save NMSB -3143+ 1825 7D LD A,L ; Load zero -3144+ 1826 99 SBC A,C ; Negate MSB -3145+ 1827 4F LD C,A ; Re-save MSB -3146+ 1828 C9 RET -3147+ 1829 -3148+ 1829 06 00 SCALE: LD B,0 ; Clear underflow -3149+ 182B D6 08 SCALLP: SUB 8 ; 8 bits (a whole byte)? -3150+ 182D DA 38 18 JP C,SHRITE ; No - Shift right A bits -3151+ 1830 43 LD B,E ; <- Shift -3152+ 1831 5A LD E,D ; <- right -3153+ 1832 51 LD D,C ; <- eight -3154+ 1833 0E 00 LD C,0 ; <- bits -3155+ 1835 C3 2B 18 JP SCALLP ; More bits to shift -3156+ 1838 -3157+ 1838 C6 09 SHRITE: ADD A,8+1 ; Adjust count -3158+ 183A 6F LD L,A ; Save bits to shift -3159+ 183B AF SHRLP: XOR A ; Flag for all done -3160+ 183C 2D DEC L ; All shifting done? -3161+ 183D C8 RET Z ; Yes - Return -3162+ 183E 79 LD A,C ; Get MSB -3163+ 183F 1F SHRT1: RRA ; Shift it right -3164+ 1840 4F LD C,A ; Re-save -3165+ 1841 7A LD A,D ; Get NMSB -3166+ 1842 1F RRA ; Shift right with last bit -3167+ 1843 57 LD D,A ; Re-save it -3168+ 1844 7B LD A,E ; Get LSB -3169+ 1845 1F RRA ; Shift right with last bit -3170+ 1846 5F LD E,A ; Re-save it -3171+ 1847 78 LD A,B ; Get underflow -3172+ 1848 1F RRA ; Shift right with last bit -3173+ 1849 47 LD B,A ; Re-save underflow -3174+ 184A C3 3B 18 JP SHRLP ; More bits to do -3175+ 184D -3176+ 184D 00 00 00 81 UNITY: .BYTE 000H,000H,000H,081H ; 1.00000 -3177+ 1851 -3178+ 1851 03 LOGTAB: .BYTE 3 ; Table used by LOG -3179+ 1852 AA 56 19 80 .BYTE 0AAH,056H,019H,080H ; 0.59898 -3180+ 1856 F1 22 76 80 .BYTE 0F1H,022H,076H,080H ; 0.96147 -3181+ 185A 45 AA 38 82 .BYTE 045H,0AAH,038H,082H ; 2.88539 -3182+ 185E -3183+ 185E CD AA 19 LOG: CALL TSTSGN ; Test sign of value -3184+ 1861 B7 OR A -3185+ 1862 EA 22 0C JP PE,FCERR ; ?FC Error if <= zero -3186+ 1865 21 97 31 LD HL,FPEXP ; Point to exponent -3187+ 1868 7E LD A,(HL) ; Get exponent -3188+ 1869 01 35 80 LD BC,8035H ; BCDE = SQR(1/2) -3189+ 186C 11 F3 04 LD DE,04F3H -3190+ 186F 90 SUB B ; Scale value to be < 1 -3191+ 1870 F5 PUSH AF ; Save scale factor -3192+ 1871 70 LD (HL),B ; Save new exponent -3193+ 1872 D5 PUSH DE ; Save SQR(1/2) -3194+ 1873 C5 PUSH BC -3195+ 1874 CD 64 17 CALL FPADD ; Add SQR(1/2) to value -3196+ 1877 C1 POP BC ; Restore SQR(1/2) -3197+ 1878 D1 POP DE -3198+ 1879 04 INC B ; Make it SQR(2) -3199+ 187A CD 00 19 CALL DVBCDE ; Divide by SQR(2) -3200+ 187D 21 4D 18 LD HL,UNITY ; Point to 1. -3201+ 1880 CD 5B 17 CALL SUBPHL ; Subtract FPREG from 1 -3202+ 1883 21 51 18 LD HL,LOGTAB ; Coefficient table -3203+ 1886 CD F2 1C CALL SUMSER ; Evaluate sum of series -3204+ 1889 01 80 80 LD BC,8080H ; BCDE = -0.5 -3205+ 188C 11 00 00 LD DE,0000H -3206+ 188F CD 64 17 CALL FPADD ; Subtract 0.5 from FPREG -3207+ 1892 F1 POP AF ; Restore scale factor -3208+ 1893 CD 25 1B CALL RSCALE ; Re-scale number -3209+ 1896 01 31 80 MULLN2: LD BC,8031H ; BCDE = Ln(2) -3210+ 1899 11 18 72 LD DE,7218H -3211+ 189C 21 .BYTE 21H ; Skip "POP BC" and "POP DE" -3212+ 189D -3213+ 189D C1 MULT: POP BC ; Get number from stack -3214+ 189E D1 POP DE -3215+ 189F CD AA 19 FPMULT: CALL TSTSGN ; Test sign of FPREG -3216+ 18A2 C8 RET Z ; Return zero if zero -3217+ 18A3 2E 00 LD L,0 ; Flag add exponents -3218+ 18A5 CD 68 19 CALL ADDEXP ; Add exponents -3219+ 18A8 79 LD A,C ; Get MSB of multiplier -3220+ 18A9 32 A6 31 LD (MULVAL),A ; Save MSB of multiplier -3221+ 18AC EB EX DE,HL -3222+ 18AD 22 A7 31 LD (MULVAL+1),HL ; Save rest of multiplier -3223+ 18B0 01 00 00 LD BC,0 ; Partial product (BCDE) = zero -3224+ 18B3 50 LD D,B -3225+ 18B4 58 LD E,B -3226+ 18B5 21 B5 17 LD HL,BNORM ; Address of normalise -3227+ 18B8 E5 PUSH HL ; Save for return -3228+ 18B9 21 C1 18 LD HL,MULT8 ; Address of 8 bit multiply -3229+ 18BC E5 PUSH HL ; Save for NMSB,MSB -3230+ 18BD E5 PUSH HL ; -3231+ 18BE 21 94 31 LD HL,FPREG ; Point to number -3232+ 18C1 7E MULT8: LD A,(HL) ; Get LSB of number -3233+ 18C2 23 INC HL ; Point to NMSB -3234+ 18C3 B7 OR A ; Test LSB -3235+ 18C4 CA ED 18 JP Z,BYTSFT ; Zero - shift to next byte -3236+ 18C7 E5 PUSH HL ; Save address of number -3237+ 18C8 2E 08 LD L,8 ; 8 bits to multiply by -3238+ 18CA 1F MUL8LP: RRA ; Shift LSB right -3239+ 18CB 67 LD H,A ; Save LSB -3240+ 18CC 79 LD A,C ; Get MSB -3241+ 18CD D2 DB 18 JP NC,NOMADD ; Bit was zero - Don't add -3242+ 18D0 E5 PUSH HL ; Save LSB and count -3243+ 18D1 2A A7 31 LD HL,(MULVAL+1) ; Get LSB and NMSB -3244+ 18D4 19 ADD HL,DE ; Add NMSB and LSB -3245+ 18D5 EB EX DE,HL ; Leave sum in DE -3246+ 18D6 E1 POP HL ; Restore MSB and count -3247+ 18D7 3A A6 31 LD A,(MULVAL) ; Get MSB of multiplier -3248+ 18DA 89 ADC A,C ; Add MSB -3249+ 18DB 1F NOMADD: RRA ; Shift MSB right -3250+ 18DC 4F LD C,A ; Re-save MSB -3251+ 18DD 7A LD A,D ; Get NMSB -3252+ 18DE 1F RRA ; Shift NMSB right -3253+ 18DF 57 LD D,A ; Re-save NMSB -3254+ 18E0 7B LD A,E ; Get LSB -3255+ 18E1 1F RRA ; Shift LSB right -3256+ 18E2 5F LD E,A ; Re-save LSB -3257+ 18E3 78 LD A,B ; Get VLSB -3258+ 18E4 1F RRA ; Shift VLSB right -3259+ 18E5 47 LD B,A ; Re-save VLSB -3260+ 18E6 2D DEC L ; Count bits multiplied -3261+ 18E7 7C LD A,H ; Get LSB of multiplier -3262+ 18E8 C2 CA 18 JP NZ,MUL8LP ; More - Do it -3263+ 18EB E1 POPHRT: POP HL ; Restore address of number -3264+ 18EC C9 RET -3265+ 18ED -3266+ 18ED 43 BYTSFT: LD B,E ; Shift partial product left -3267+ 18EE 5A LD E,D -3268+ 18EF 51 LD D,C -3269+ 18F0 4F LD C,A -3270+ 18F1 C9 RET -3271+ 18F2 -3272+ 18F2 CD DB 19 DIV10: CALL STAKFP ; Save FPREG on stack -3273+ 18F5 01 20 84 LD BC,8420H ; BCDE = 10. -3274+ 18F8 11 00 00 LD DE,0000H -3275+ 18FB CD EB 19 CALL FPBCDE ; Move 10 to FPREG -3276+ 18FE -3277+ 18FE C1 DIV: POP BC ; Get number from stack -3278+ 18FF D1 POP DE -3279+ 1900 CD AA 19 DVBCDE: CALL TSTSGN ; Test sign of FPREG -3280+ 1903 CA 06 07 JP Z,DZERR ; Error if division by zero -3281+ 1906 2E FF LD L,-1 ; Flag subtract exponents -3282+ 1908 CD 68 19 CALL ADDEXP ; Subtract exponents -3283+ 190B 34 INC (HL) ; Add 2 to exponent to adjust -3284+ 190C 34 INC (HL) -3285+ 190D 2B DEC HL ; Point to MSB -3286+ 190E 7E LD A,(HL) ; Get MSB of dividend -3287+ 190F 32 C2 30 LD (DIV3),A ; Save for subtraction -3288+ 1912 2B DEC HL -3289+ 1913 7E LD A,(HL) ; Get NMSB of dividend -3290+ 1914 32 BE 30 LD (DIV2),A ; Save for subtraction -3291+ 1917 2B DEC HL -3292+ 1918 7E LD A,(HL) ; Get MSB of dividend -3293+ 1919 32 BA 30 LD (DIV1),A ; Save for subtraction -3294+ 191C 41 LD B,C ; Get MSB -3295+ 191D EB EX DE,HL ; NMSB,LSB to HL -3296+ 191E AF XOR A -3297+ 191F 4F LD C,A ; Clear MSB of quotient -3298+ 1920 57 LD D,A ; Clear NMSB of quotient -3299+ 1921 5F LD E,A ; Clear LSB of quotient -3300+ 1922 32 C5 30 LD (DIV4),A ; Clear overflow count -3301+ 1925 E5 DIVLP: PUSH HL ; Save divisor -3302+ 1926 C5 PUSH BC -3303+ 1927 7D LD A,L ; Get LSB of number -3304+ 1928 CD B9 30 CALL DIVSUP ; Subt' divisor from dividend -3305+ 192B DE 00 SBC A,0 ; Count for overflows -3306+ 192D 3F CCF -3307+ 192E D2 38 19 JP NC,RESDIV ; Restore divisor if borrow -3308+ 1931 32 C5 30 LD (DIV4),A ; Re-save overflow count -3309+ 1934 F1 POP AF ; Scrap divisor -3310+ 1935 F1 POP AF -3311+ 1936 37 SCF ; Set carry to -3312+ 1937 D2 .BYTE 0D2H ; Skip "POP BC" and "POP HL" -3313+ 1938 -3314+ 1938 C1 RESDIV: POP BC ; Restore divisor -3315+ 1939 E1 POP HL -3316+ 193A 79 LD A,C ; Get MSB of quotient -3317+ 193B 3C INC A -3318+ 193C 3D DEC A -3319+ 193D 1F RRA ; Bit 0 to bit 7 -3320+ 193E FA EB 17 JP M,RONDB ; Done - Normalise result -3321+ 1941 17 RLA ; Restore carry -3322+ 1942 7B LD A,E ; Get LSB of quotient -3323+ 1943 17 RLA ; Double it -3324+ 1944 5F LD E,A ; Put it back -3325+ 1945 7A LD A,D ; Get NMSB of quotient -3326+ 1946 17 RLA ; Double it -3327+ 1947 57 LD D,A ; Put it back -3328+ 1948 79 LD A,C ; Get MSB of quotient -3329+ 1949 17 RLA ; Double it -3330+ 194A 4F LD C,A ; Put it back -3331+ 194B 29 ADD HL,HL ; Double NMSB,LSB of divisor -3332+ 194C 78 LD A,B ; Get MSB of divisor -3333+ 194D 17 RLA ; Double it -3334+ 194E 47 LD B,A ; Put it back -3335+ 194F 3A C5 30 LD A,(DIV4) ; Get VLSB of quotient -3336+ 1952 17 RLA ; Double it -3337+ 1953 32 C5 30 LD (DIV4),A ; Put it back -3338+ 1956 79 LD A,C ; Get MSB of quotient -3339+ 1957 B2 OR D ; Merge NMSB -3340+ 1958 B3 OR E ; Merge LSB -3341+ 1959 C2 25 19 JP NZ,DIVLP ; Not done - Keep dividing -3342+ 195C E5 PUSH HL ; Save divisor -3343+ 195D 21 97 31 LD HL,FPEXP ; Point to exponent -3344+ 1960 35 DEC (HL) ; Divide by 2 -3345+ 1961 E1 POP HL ; Restore divisor -3346+ 1962 C2 25 19 JP NZ,DIVLP ; Ok - Keep going -3347+ 1965 C3 12 07 JP OVERR ; Overflow error -3348+ 1968 -3349+ 1968 78 ADDEXP: LD A,B ; Get exponent of dividend -3350+ 1969 B7 OR A ; Test it -3351+ 196A CA 8C 19 JP Z,OVTST3 ; Zero - Result zero -3352+ 196D 7D LD A,L ; Get add/subtract flag -3353+ 196E 21 97 31 LD HL,FPEXP ; Point to exponent -3354+ 1971 AE XOR (HL) ; Add or subtract it -3355+ 1972 80 ADD A,B ; Add the other exponent -3356+ 1973 47 LD B,A ; Save new exponent -3357+ 1974 1F RRA ; Test exponent for overflow -3358+ 1975 A8 XOR B -3359+ 1976 78 LD A,B ; Get exponent -3360+ 1977 F2 8B 19 JP P,OVTST2 ; Positive - Test for overflow -3361+ 197A C6 80 ADD A,80H ; Add excess 128 -3362+ 197C 77 LD (HL),A ; Save new exponent -3363+ 197D CA EB 18 JP Z,POPHRT ; Zero - Result zero -3364+ 1980 CD 10 1A CALL SIGNS ; Set MSBs and sign of result -3365+ 1983 77 LD (HL),A ; Save new exponent -3366+ 1984 2B DEC HL ; Point to MSB -3367+ 1985 C9 RET -3368+ 1986 -3369+ 1986 CD AA 19 OVTST1: CALL TSTSGN ; Test sign of FPREG -3370+ 1989 2F CPL ; Invert sign -3371+ 198A E1 POP HL ; Clean up stack -3372+ 198B B7 OVTST2: OR A ; Test if new exponent zero -3373+ 198C E1 OVTST3: POP HL ; Clear off return address -3374+ 198D F2 CA 17 JP P,RESZER ; Result zero -3375+ 1990 C3 12 07 JP OVERR ; Overflow error -3376+ 1993 -3377+ 1993 CD F6 19 MLSP10: CALL BCDEFP ; Move FPREG to BCDE -3378+ 1996 78 LD A,B ; Get exponent -3379+ 1997 B7 OR A ; Is it zero? -3380+ 1998 C8 RET Z ; Yes - Result is zero -3381+ 1999 C6 02 ADD A,2 ; Multiply by 4 -3382+ 199B DA 12 07 JP C,OVERR ; Overflow - ?OV Error -3383+ 199E 47 LD B,A ; Re-save exponent -3384+ 199F CD 64 17 CALL FPADD ; Add BCDE to FPREG (Times 5) -3385+ 19A2 21 97 31 LD HL,FPEXP ; Point to exponent -3386+ 19A5 34 INC (HL) ; Double number (Times 10) -3387+ 19A6 C0 RET NZ ; Ok - Return -3388+ 19A7 C3 12 07 JP OVERR ; Overflow error -3389+ 19AA -3390+ 19AA 3A 97 31 TSTSGN: LD A,(FPEXP) ; Get sign of FPREG -3391+ 19AD B7 OR A -3392+ 19AE C8 RET Z ; RETurn if number is zero -3393+ 19AF 3A 96 31 LD A,(FPREG+2) ; Get MSB of FPREG -3394+ 19B2 FE .BYTE 0FEH ; Test sign -3395+ 19B3 2F RETREL: CPL ; Invert sign -3396+ 19B4 17 RLA ; Sign bit to carry -3397+ 19B5 9F FLGDIF: SBC A,A ; Carry to all bits of A -3398+ 19B6 C0 RET NZ ; Return -1 if negative -3399+ 19B7 3C INC A ; Bump to +1 -3400+ 19B8 C9 RET ; Positive - Return +1 -3401+ 19B9 -3402+ 19B9 CD AA 19 SGN: CALL TSTSGN ; Test sign of FPREG -3403+ 19BC 06 88 FLGREL: LD B,80H+8 ; 8 bit integer in exponent -3404+ 19BE 11 00 00 LD DE,0 ; Zero NMSB and LSB -3405+ 19C1 21 97 31 RETINT: LD HL,FPEXP ; Point to exponent -3406+ 19C4 4F LD C,A ; CDE = MSB,NMSB and LSB -3407+ 19C5 70 LD (HL),B ; Save exponent -3408+ 19C6 06 00 LD B,0 ; CDE = integer to normalise -3409+ 19C8 23 INC HL ; Point to sign of result -3410+ 19C9 36 80 LD (HL),80H ; Set sign of result -3411+ 19CB 17 RLA ; Carry = sign of integer -3412+ 19CC C3 B2 17 JP CONPOS ; Set sign of result -3413+ 19CF -3414+ 19CF CD AA 19 ABS: CALL TSTSGN ; Test sign of FPREG -3415+ 19D2 F0 RET P ; Return if positive -3416+ 19D3 21 96 31 INVSGN: LD HL,FPREG+2 ; Point to MSB -3417+ 19D6 7E LD A,(HL) ; Get sign of mantissa -3418+ 19D7 EE 80 XOR 80H ; Invert sign of mantissa -3419+ 19D9 77 LD (HL),A ; Re-save sign of mantissa -3420+ 19DA C9 RET -3421+ 19DB -3422+ 19DB EB STAKFP: EX DE,HL ; Save code string address -3423+ 19DC 2A 94 31 LD HL,(FPREG) ; LSB,NLSB of FPREG -3424+ 19DF E3 EX (SP),HL ; Stack them,get return -3425+ 19E0 E5 PUSH HL ; Re-save return -3426+ 19E1 2A 96 31 LD HL,(FPREG+2) ; MSB and exponent of FPREG -3427+ 19E4 E3 EX (SP),HL ; Stack them,get return -3428+ 19E5 E5 PUSH HL ; Re-save return -3429+ 19E6 EB EX DE,HL ; Restore code string address -3430+ 19E7 C9 RET -3431+ 19E8 -3432+ 19E8 CD F9 19 PHLTFP: CALL LOADFP ; Number at HL to BCDE -3433+ 19EB EB FPBCDE: EX DE,HL ; Save code string address -3434+ 19EC 22 94 31 LD (FPREG),HL ; Save LSB,NLSB of number -3435+ 19EF 60 LD H,B ; Exponent of number -3436+ 19F0 69 LD L,C ; MSB of number -3437+ 19F1 22 96 31 LD (FPREG+2),HL ; Save MSB and exponent -3438+ 19F4 EB EX DE,HL ; Restore code string address -3439+ 19F5 C9 RET -3440+ 19F6 -3441+ 19F6 21 94 31 BCDEFP: LD HL,FPREG ; Point to FPREG -3442+ 19F9 5E LOADFP: LD E,(HL) ; Get LSB of number -3443+ 19FA 23 INC HL -3444+ 19FB 56 LD D,(HL) ; Get NMSB of number -3445+ 19FC 23 INC HL -3446+ 19FD 4E LD C,(HL) ; Get MSB of number -3447+ 19FE 23 INC HL -3448+ 19FF 46 LD B,(HL) ; Get exponent of number -3449+ 1A00 23 INCHL: INC HL ; Used for conditional "INC HL" -3450+ 1A01 C9 RET -3451+ 1A02 -3452+ 1A02 11 94 31 FPTHL: LD DE,FPREG ; Point to FPREG -3453+ 1A05 06 04 DETHL4: LD B,4 ; 4 bytes to move -3454+ 1A07 1A DETHLB: LD A,(DE) ; Get source -3455+ 1A08 77 LD (HL),A ; Save destination -3456+ 1A09 13 INC DE ; Next source -3457+ 1A0A 23 INC HL ; Next destination -3458+ 1A0B 05 DEC B ; Count bytes -3459+ 1A0C C2 07 1A JP NZ,DETHLB ; Loop if more -3460+ 1A0F C9 RET -3461+ 1A10 -3462+ 1A10 21 96 31 SIGNS: LD HL,FPREG+2 ; Point to MSB of FPREG -3463+ 1A13 7E LD A,(HL) ; Get MSB -3464+ 1A14 07 RLCA ; Old sign to carry -3465+ 1A15 37 SCF ; Set MSBit -3466+ 1A16 1F RRA ; Set MSBit of MSB -3467+ 1A17 77 LD (HL),A ; Save new MSB -3468+ 1A18 3F CCF ; Complement sign -3469+ 1A19 1F RRA ; Old sign to carry -3470+ 1A1A 23 INC HL -3471+ 1A1B 23 INC HL -3472+ 1A1C 77 LD (HL),A ; Set sign of result -3473+ 1A1D 79 LD A,C ; Get MSB -3474+ 1A1E 07 RLCA ; Old sign to carry -3475+ 1A1F 37 SCF ; Set MSBit -3476+ 1A20 1F RRA ; Set MSBit of MSB -3477+ 1A21 4F LD C,A ; Save MSB -3478+ 1A22 1F RRA -3479+ 1A23 AE XOR (HL) ; New sign of result -3480+ 1A24 C9 RET -3481+ 1A25 -3482+ 1A25 78 CMPNUM: LD A,B ; Get exponent of number -3483+ 1A26 B7 OR A -3484+ 1A27 CA AA 19 JP Z,TSTSGN ; Zero - Test sign of FPREG -3485+ 1A2A 21 B3 19 LD HL,RETREL ; Return relation routine -3486+ 1A2D E5 PUSH HL ; Save for return -3487+ 1A2E CD AA 19 CALL TSTSGN ; Test sign of FPREG -3488+ 1A31 79 LD A,C ; Get MSB of number -3489+ 1A32 C8 RET Z ; FPREG zero - Number's MSB -3490+ 1A33 21 96 31 LD HL,FPREG+2 ; MSB of FPREG -3491+ 1A36 AE XOR (HL) ; Combine signs -3492+ 1A37 79 LD A,C ; Get MSB of number -3493+ 1A38 F8 RET M ; Exit if signs different -3494+ 1A39 CD 3F 1A CALL CMPFP ; Compare FP numbers -3495+ 1A3C 1F RRA ; Get carry to sign -3496+ 1A3D A9 XOR C ; Combine with MSB of number -3497+ 1A3E C9 RET -3498+ 1A3F -3499+ 1A3F 23 CMPFP: INC HL ; Point to exponent -3500+ 1A40 78 LD A,B ; Get exponent -3501+ 1A41 BE CP (HL) ; Compare exponents -3502+ 1A42 C0 RET NZ ; Different -3503+ 1A43 2B DEC HL ; Point to MBS -3504+ 1A44 79 LD A,C ; Get MSB -3505+ 1A45 BE CP (HL) ; Compare MSBs -3506+ 1A46 C0 RET NZ ; Different -3507+ 1A47 2B DEC HL ; Point to NMSB -3508+ 1A48 7A LD A,D ; Get NMSB -3509+ 1A49 BE CP (HL) ; Compare NMSBs -3510+ 1A4A C0 RET NZ ; Different -3511+ 1A4B 2B DEC HL ; Point to LSB -3512+ 1A4C 7B LD A,E ; Get LSB -3513+ 1A4D 96 SUB (HL) ; Compare LSBs -3514+ 1A4E C0 RET NZ ; Different -3515+ 1A4F E1 POP HL ; Drop RETurn -3516+ 1A50 E1 POP HL ; Drop another RETurn -3517+ 1A51 C9 RET -3518+ 1A52 -3519+ 1A52 47 FPINT: LD B,A ; <- Move -3520+ 1A53 4F LD C,A ; <- exponent -3521+ 1A54 57 LD D,A ; <- to all -3522+ 1A55 5F LD E,A ; <- bits -3523+ 1A56 B7 OR A ; Test exponent -3524+ 1A57 C8 RET Z ; Zero - Return zero -3525+ 1A58 E5 PUSH HL ; Save pointer to number -3526+ 1A59 CD F6 19 CALL BCDEFP ; Move FPREG to BCDE -3527+ 1A5C CD 10 1A CALL SIGNS ; Set MSBs & sign of result -3528+ 1A5F AE XOR (HL) ; Combine with sign of FPREG -3529+ 1A60 67 LD H,A ; Save combined signs -3530+ 1A61 FC 76 1A CALL M,DCBCDE ; Negative - Decrement BCDE -3531+ 1A64 3E 98 LD A,80H+24 ; 24 bits -3532+ 1A66 90 SUB B ; Bits to shift -3533+ 1A67 CD 29 18 CALL SCALE ; Shift BCDE -3534+ 1A6A 7C LD A,H ; Get combined sign -3535+ 1A6B 17 RLA ; Sign to carry -3536+ 1A6C DC FC 17 CALL C,FPROND ; Negative - Round number up -3537+ 1A6F 06 00 LD B,0 ; Zero exponent -3538+ 1A71 DC 15 18 CALL C,COMPL ; If negative make positive -3539+ 1A74 E1 POP HL ; Restore pointer to number -3540+ 1A75 C9 RET -3541+ 1A76 -3542+ 1A76 1B DCBCDE: DEC DE ; Decrement BCDE -3543+ 1A77 7A LD A,D ; Test LSBs -3544+ 1A78 A3 AND E -3545+ 1A79 3C INC A -3546+ 1A7A C0 RET NZ ; Exit if LSBs not FFFF -3547+ 1A7B 0B DEC BC ; Decrement MSBs -3548+ 1A7C C9 RET -3549+ 1A7D -3550+ 1A7D 21 97 31 INT: LD HL,FPEXP ; Point to exponent -3551+ 1A80 7E LD A,(HL) ; Get exponent -3552+ 1A81 FE 98 CP 80H+24 ; Integer accuracy only? -3553+ 1A83 3A 94 31 LD A,(FPREG) ; Get LSB -3554+ 1A86 D0 RET NC ; Yes - Already integer -3555+ 1A87 7E LD A,(HL) ; Get exponent -3556+ 1A88 CD 52 1A CALL FPINT ; F.P to integer -3557+ 1A8B 36 98 LD (HL),80H+24 ; Save 24 bit integer -3558+ 1A8D 7B LD A,E ; Get LSB of number -3559+ 1A8E F5 PUSH AF ; Save LSB -3560+ 1A8F 79 LD A,C ; Get MSB of number -3561+ 1A90 17 RLA ; Sign to carry -3562+ 1A91 CD B2 17 CALL CONPOS ; Set sign of result -3563+ 1A94 F1 POP AF ; Restore LSB of number -3564+ 1A95 C9 RET -3565+ 1A96 -3566+ 1A96 21 00 00 MLDEBC: LD HL,0 ; Clear partial product -3567+ 1A99 78 LD A,B ; Test multiplier -3568+ 1A9A B1 OR C -3569+ 1A9B C8 RET Z ; Return zero if zero -3570+ 1A9C 3E 10 LD A,16 ; 16 bits -3571+ 1A9E 29 MLDBLP: ADD HL,HL ; Shift P.P left -3572+ 1A9F DA D6 12 JP C,BSERR ; ?BS Error if overflow -3573+ 1AA2 EB EX DE,HL -3574+ 1AA3 29 ADD HL,HL ; Shift multiplier left -3575+ 1AA4 EB EX DE,HL -3576+ 1AA5 D2 AC 1A JP NC,NOMLAD ; Bit was zero - No add -3577+ 1AA8 09 ADD HL,BC ; Add multiplicand -3578+ 1AA9 DA D6 12 JP C,BSERR ; ?BS Error if overflow -3579+ 1AAC 3D NOMLAD: DEC A ; Count bits -3580+ 1AAD C2 9E 1A JP NZ,MLDBLP ; More -3581+ 1AB0 C9 RET -3582+ 1AB1 -3583+ 1AB1 FE 2D ASCTFP: CP '-' ; Negative? -3584+ 1AB3 F5 PUSH AF ; Save it and flags -3585+ 1AB4 CA BD 1A JP Z,CNVNUM ; Yes - Convert number -3586+ 1AB7 FE 2B CP '+' ; Positive? -3587+ 1AB9 CA BD 1A JP Z,CNVNUM ; Yes - Convert number -3588+ 1ABC 2B DEC HL ; DEC 'cos GETCHR INCs -3589+ 1ABD CD CA 17 CNVNUM: CALL RESZER ; Set result to zero -3590+ 1AC0 47 LD B,A ; Digits after point counter -3591+ 1AC1 57 LD D,A ; Sign of exponent -3592+ 1AC2 5F LD E,A ; Exponent of ten -3593+ 1AC3 2F CPL -3594+ 1AC4 4F LD C,A ; Before or after point flag -3595+ 1AC5 CD 5B 0B MANLP: CALL GETCHR ; Get next character -3596+ 1AC8 DA 0E 1B JP C,ADDIG ; Digit - Add to number -3597+ 1ACB FE 2E CP '.' -3598+ 1ACD CA E9 1A JP Z,DPOINT ; '.' - Flag point -3599+ 1AD0 FE 45 CP 'E' -3600+ 1AD2 C2 ED 1A JP NZ,CONEXP ; Not 'E' - Scale number -3601+ 1AD5 CD 5B 0B CALL GETCHR ; Get next character -3602+ 1AD8 CD 01 11 CALL SGNEXP ; Get sign of exponent -3603+ 1ADB CD 5B 0B EXPLP: CALL GETCHR ; Get next character -3604+ 1ADE DA 30 1B JP C,EDIGIT ; Digit - Add to exponent -3605+ 1AE1 14 INC D ; Is sign negative? -3606+ 1AE2 C2 ED 1A JP NZ,CONEXP ; No - Scale number -3607+ 1AE5 AF XOR A -3608+ 1AE6 93 SUB E ; Negate exponent -3609+ 1AE7 5F LD E,A ; And re-save it -3610+ 1AE8 0C INC C ; Flag end of number -3611+ 1AE9 0C DPOINT: INC C ; Flag point passed -3612+ 1AEA CA C5 1A JP Z,MANLP ; Zero - Get another digit -3613+ 1AED E5 CONEXP: PUSH HL ; Save code string address -3614+ 1AEE 7B LD A,E ; Get exponent -3615+ 1AEF 90 SUB B ; Subtract digits after point -3616+ 1AF0 F4 06 1B SCALMI: CALL P,SCALPL ; Positive - Multiply number -3617+ 1AF3 F2 FC 1A JP P,ENDCON ; Positive - All done -3618+ 1AF6 F5 PUSH AF ; Save number of times to /10 -3619+ 1AF7 CD F2 18 CALL DIV10 ; Divide by 10 -3620+ 1AFA F1 POP AF ; Restore count -3621+ 1AFB 3C INC A ; Count divides -3622+ 1AFC -3623+ 1AFC C2 F0 1A ENDCON: JP NZ,SCALMI ; More to do -3624+ 1AFF D1 POP DE ; Restore code string address -3625+ 1B00 F1 POP AF ; Restore sign of number -3626+ 1B01 CC D3 19 CALL Z,INVSGN ; Negative - Negate number -3627+ 1B04 EB EX DE,HL ; Code string address to HL -3628+ 1B05 C9 RET -3629+ 1B06 -3630+ 1B06 C8 SCALPL: RET Z ; Exit if no scaling needed -3631+ 1B07 F5 MULTEN: PUSH AF ; Save count -3632+ 1B08 CD 93 19 CALL MLSP10 ; Multiply number by 10 -3633+ 1B0B F1 POP AF ; Restore count -3634+ 1B0C 3D DEC A ; Count multiplies -3635+ 1B0D C9 RET -3636+ 1B0E -3637+ 1B0E D5 ADDIG: PUSH DE ; Save sign of exponent -3638+ 1B0F 57 LD D,A ; Save digit -3639+ 1B10 78 LD A,B ; Get digits after point -3640+ 1B11 89 ADC A,C ; Add one if after point -3641+ 1B12 47 LD B,A ; Re-save counter -3642+ 1B13 C5 PUSH BC ; Save point flags -3643+ 1B14 E5 PUSH HL ; Save code string address -3644+ 1B15 D5 PUSH DE ; Save digit -3645+ 1B16 CD 93 19 CALL MLSP10 ; Multiply number by 10 -3646+ 1B19 F1 POP AF ; Restore digit -3647+ 1B1A D6 30 SUB '0' ; Make it absolute -3648+ 1B1C CD 25 1B CALL RSCALE ; Re-scale number -3649+ 1B1F E1 POP HL ; Restore code string address -3650+ 1B20 C1 POP BC ; Restore point flags -3651+ 1B21 D1 POP DE ; Restore sign of exponent -3652+ 1B22 C3 C5 1A JP MANLP ; Get another digit -3653+ 1B25 -3654+ 1B25 CD DB 19 RSCALE: CALL STAKFP ; Put number on stack -3655+ 1B28 CD BC 19 CALL FLGREL ; Digit to add to FPREG -3656+ 1B2B C1 PADD: POP BC ; Restore number -3657+ 1B2C D1 POP DE -3658+ 1B2D C3 64 17 JP FPADD ; Add BCDE to FPREG and return -3659+ 1B30 -3660+ 1B30 7B EDIGIT: LD A,E ; Get digit -3661+ 1B31 07 RLCA ; Times 2 -3662+ 1B32 07 RLCA ; Times 4 -3663+ 1B33 83 ADD A,E ; Times 5 -3664+ 1B34 07 RLCA ; Times 10 -3665+ 1B35 86 ADD A,(HL) ; Add next digit -3666+ 1B36 D6 30 SUB '0' ; Make it absolute -3667+ 1B38 5F LD E,A ; Save new digit -3668+ 1B39 C3 DB 1A JP EXPLP ; Look for another digit -3669+ 1B3C -3670+ 1B3C E5 LINEIN: PUSH HL ; Save code string address -3671+ 1B3D 21 9B 06 LD HL,INMSG ; Output " in " -3672+ 1B40 CD A1 14 CALL PRS ; Output string at HL -3673+ 1B43 E1 POP HL ; Restore code string address -3674+ 1B44 EB PRNTHL: EX DE,HL ; Code string address to DE -3675+ 1B45 AF XOR A -3676+ 1B46 06 98 LD B,80H+24 ; 24 bits -3677+ 1B48 CD C1 19 CALL RETINT ; Return the integer -3678+ 1B4B 21 A0 14 LD HL,PRNUMS ; Print number string -3679+ 1B4E E5 PUSH HL ; Save for return -3680+ 1B4F 21 99 31 NUMASC: LD HL,PBUFF ; Convert number to ASCII -3681+ 1B52 E5 PUSH HL ; Save for return -3682+ 1B53 CD AA 19 CALL TSTSGN ; Test sign of FPREG -3683+ 1B56 36 20 LD (HL),' ' ; Space at start -3684+ 1B58 F2 5D 1B JP P,SPCFST ; Positive - Space to start -3685+ 1B5B 36 2D LD (HL),'-' ; '-' sign at start -3686+ 1B5D 23 SPCFST: INC HL ; First byte of number -3687+ 1B5E 36 30 LD (HL),'0' ; '0' if zero -3688+ 1B60 CA 13 1C JP Z,JSTZER ; Return '0' if zero -3689+ 1B63 E5 PUSH HL ; Save buffer address -3690+ 1B64 FC D3 19 CALL M,INVSGN ; Negate FPREG if negative -3691+ 1B67 AF XOR A ; Zero A -3692+ 1B68 F5 PUSH AF ; Save it -3693+ 1B69 CD 19 1C CALL RNGTST ; Test number is in range -3694+ 1B6C 01 43 91 SIXDIG: LD BC,9143H ; BCDE - 99999.9 -3695+ 1B6F 11 F8 4F LD DE,4FF8H -3696+ 1B72 CD 25 1A CALL CMPNUM ; Compare numbers -3697+ 1B75 B7 OR A -3698+ 1B76 E2 8A 1B JP PO,INRNG ; > 99999.9 - Sort it out -3699+ 1B79 F1 POP AF ; Restore count -3700+ 1B7A CD 07 1B CALL MULTEN ; Multiply by ten -3701+ 1B7D F5 PUSH AF ; Re-save count -3702+ 1B7E C3 6C 1B JP SIXDIG ; Test it again -3703+ 1B81 -3704+ 1B81 CD F2 18 GTSIXD: CALL DIV10 ; Divide by 10 -3705+ 1B84 F1 POP AF ; Get count -3706+ 1B85 3C INC A ; Count divides -3707+ 1B86 F5 PUSH AF ; Re-save count -3708+ 1B87 CD 19 1C CALL RNGTST ; Test number is in range -3709+ 1B8A CD 52 17 INRNG: CALL ROUND ; Add 0.5 to FPREG -3710+ 1B8D 3C INC A -3711+ 1B8E CD 52 1A CALL FPINT ; F.P to integer -3712+ 1B91 CD EB 19 CALL FPBCDE ; Move BCDE to FPREG -3713+ 1B94 01 06 03 LD BC,0306H ; 1E+06 to 1E-03 range -3714+ 1B97 F1 POP AF ; Restore count -3715+ 1B98 81 ADD A,C ; 6 digits before point -3716+ 1B99 3C INC A ; Add one -3717+ 1B9A FA A6 1B JP M,MAKNUM ; Do it in 'E' form if < 1E-02 -3718+ 1B9D FE 08 CP 6+1+1 ; More than 999999 ? -3719+ 1B9F D2 A6 1B JP NC,MAKNUM ; Yes - Do it in 'E' form -3720+ 1BA2 3C INC A ; Adjust for exponent -3721+ 1BA3 47 LD B,A ; Exponent of number -3722+ 1BA4 3E 02 LD A,2 ; Make it zero after -3723+ 1BA6 -3724+ 1BA6 3D MAKNUM: DEC A ; Adjust for digits to do -3725+ 1BA7 3D DEC A -3726+ 1BA8 E1 POP HL ; Restore buffer address -3727+ 1BA9 F5 PUSH AF ; Save count -3728+ 1BAA 11 2C 1C LD DE,POWERS ; Powers of ten -3729+ 1BAD 05 DEC B ; Count digits before point -3730+ 1BAE C2 B7 1B JP NZ,DIGTXT ; Not zero - Do number -3731+ 1BB1 36 2E LD (HL),'.' ; Save point -3732+ 1BB3 23 INC HL ; Move on -3733+ 1BB4 36 30 LD (HL),'0' ; Save zero -3734+ 1BB6 23 INC HL ; Move on -3735+ 1BB7 05 DIGTXT: DEC B ; Count digits before point -3736+ 1BB8 36 2E LD (HL),'.' ; Save point in case -3737+ 1BBA CC 00 1A CALL Z,INCHL ; Last digit - move on -3738+ 1BBD C5 PUSH BC ; Save digits before point -3739+ 1BBE E5 PUSH HL ; Save buffer address -3740+ 1BBF D5 PUSH DE ; Save powers of ten -3741+ 1BC0 CD F6 19 CALL BCDEFP ; Move FPREG to BCDE -3742+ 1BC3 E1 POP HL ; Powers of ten table -3743+ 1BC4 06 2F LD B, '0'-1 ; ASCII '0' - 1 -3744+ 1BC6 04 TRYAGN: INC B ; Count subtractions -3745+ 1BC7 7B LD A,E ; Get LSB -3746+ 1BC8 96 SUB (HL) ; Subtract LSB -3747+ 1BC9 5F LD E,A ; Save LSB -3748+ 1BCA 23 INC HL -3749+ 1BCB 7A LD A,D ; Get NMSB -3750+ 1BCC 9E SBC A,(HL) ; Subtract NMSB -3751+ 1BCD 57 LD D,A ; Save NMSB -3752+ 1BCE 23 INC HL -3753+ 1BCF 79 LD A,C ; Get MSB -3754+ 1BD0 9E SBC A,(HL) ; Subtract MSB -3755+ 1BD1 4F LD C,A ; Save MSB -3756+ 1BD2 2B DEC HL ; Point back to start -3757+ 1BD3 2B DEC HL -3758+ 1BD4 D2 C6 1B JP NC,TRYAGN ; No overflow - Try again -3759+ 1BD7 CD 09 18 CALL PLUCDE ; Restore number -3760+ 1BDA 23 INC HL ; Start of next number -3761+ 1BDB CD EB 19 CALL FPBCDE ; Move BCDE to FPREG -3762+ 1BDE EB EX DE,HL ; Save point in table -3763+ 1BDF E1 POP HL ; Restore buffer address -3764+ 1BE0 70 LD (HL),B ; Save digit in buffer -3765+ 1BE1 23 INC HL ; And move on -3766+ 1BE2 C1 POP BC ; Restore digit count -3767+ 1BE3 0D DEC C ; Count digits -3768+ 1BE4 C2 B7 1B JP NZ,DIGTXT ; More - Do them -3769+ 1BE7 05 DEC B ; Any decimal part? -3770+ 1BE8 CA F7 1B JP Z,DOEBIT ; No - Do 'E' bit -3771+ 1BEB 2B SUPTLZ: DEC HL ; Move back through buffer -3772+ 1BEC 7E LD A,(HL) ; Get character -3773+ 1BED FE 30 CP '0' ; '0' character? -3774+ 1BEF CA EB 1B JP Z,SUPTLZ ; Yes - Look back for more -3775+ 1BF2 FE 2E CP '.' ; A decimal point? -3776+ 1BF4 C4 00 1A CALL NZ,INCHL ; Move back over digit -3777+ 1BF7 -3778+ 1BF7 F1 DOEBIT: POP AF ; Get 'E' flag -3779+ 1BF8 CA 16 1C JP Z,NOENED ; No 'E' needed - End buffer -3780+ 1BFB 36 45 LD (HL),'E' ; Put 'E' in buffer -3781+ 1BFD 23 INC HL ; And move on -3782+ 1BFE 36 2B LD (HL),'+' ; Put '+' in buffer -3783+ 1C00 F2 07 1C JP P,OUTEXP ; Positive - Output exponent -3784+ 1C03 36 2D LD (HL),'-' ; Put '-' in buffer -3785+ 1C05 2F CPL ; Negate exponent -3786+ 1C06 3C INC A -3787+ 1C07 06 2F OUTEXP: LD B,'0'-1 ; ASCII '0' - 1 -3788+ 1C09 04 EXPTEN: INC B ; Count subtractions -3789+ 1C0A D6 0A SUB 10 ; Tens digit -3790+ 1C0C D2 09 1C JP NC,EXPTEN ; More to do -3791+ 1C0F C6 3A ADD A,'0'+10 ; Restore and make ASCII -3792+ 1C11 23 INC HL ; Move on -3793+ 1C12 70 LD (HL),B ; Save MSB of exponent -3794+ 1C13 23 JSTZER: INC HL ; -3795+ 1C14 77 LD (HL),A ; Save LSB of exponent -3796+ 1C15 23 INC HL -3797+ 1C16 71 NOENED: LD (HL),C ; Mark end of buffer -3798+ 1C17 E1 POP HL ; Restore code string address -3799+ 1C18 C9 RET -3800+ 1C19 -3801+ 1C19 01 74 94 RNGTST: LD BC,9474H ; BCDE = 999999. -3802+ 1C1C 11 F7 23 LD DE,23F7H -3803+ 1C1F CD 25 1A CALL CMPNUM ; Compare numbers -3804+ 1C22 B7 OR A -3805+ 1C23 E1 POP HL ; Return address to HL -3806+ 1C24 E2 81 1B JP PO,GTSIXD ; Too big - Divide by ten -3807+ 1C27 E9 JP (HL) ; Otherwise return to caller -3808+ 1C28 -3809+ 1C28 00 00 00 80 HALF: .BYTE 00H,00H,00H,80H ; 0.5 -3810+ 1C2C -3811+ 1C2C A0 86 01 POWERS: .BYTE 0A0H,086H,001H ; 100000 -3812+ 1C2F 10 27 00 .BYTE 010H,027H,000H ; 10000 -3813+ 1C32 E8 03 00 .BYTE 0E8H,003H,000H ; 1000 -3814+ 1C35 64 00 00 .BYTE 064H,000H,000H ; 100 -3815+ 1C38 0A 00 00 .BYTE 00AH,000H,000H ; 10 -3816+ 1C3B 01 00 00 .BYTE 001H,000H,000H ; 1 -3817+ 1C3E -3818+ 1C3E 21 D3 19 NEGAFT: LD HL,INVSGN ; Negate result -3819+ 1C41 E3 EX (SP),HL ; To be done after caller -3820+ 1C42 E9 JP (HL) ; Return to caller -3821+ 1C43 -3822+ 1C43 CD DB 19 SQR: CALL STAKFP ; Put value on stack -3823+ 1C46 21 28 1C LD HL,HALF ; Set power to 1/2 -3824+ 1C49 CD E8 19 CALL PHLTFP ; Move 1/2 to FPREG -3825+ 1C4C -3826+ 1C4C C1 POWER: POP BC ; Get base -3827+ 1C4D D1 POP DE -3828+ 1C4E CD AA 19 CALL TSTSGN ; Test sign of power -3829+ 1C51 78 LD A,B ; Get exponent of base -3830+ 1C52 CA 91 1C JP Z,EXP ; Make result 1 if zero -3831+ 1C55 F2 5C 1C JP P,POWER1 ; Positive base - Ok -3832+ 1C58 B7 OR A ; Zero to negative power? -3833+ 1C59 CA 06 07 JP Z,DZERR ; Yes - ?/0 Error -3834+ 1C5C B7 POWER1: OR A ; Base zero? -3835+ 1C5D CA CB 17 JP Z,SAVEXP ; Yes - Return zero -3836+ 1C60 D5 PUSH DE ; Save base -3837+ 1C61 C5 PUSH BC -3838+ 1C62 79 LD A,C ; Get MSB of base -3839+ 1C63 F6 7F OR 01111111B ; Get sign status -3840+ 1C65 CD F6 19 CALL BCDEFP ; Move power to BCDE -3841+ 1C68 F2 79 1C JP P,POWER2 ; Positive base - Ok -3842+ 1C6B D5 PUSH DE ; Save power -3843+ 1C6C C5 PUSH BC -3844+ 1C6D CD 7D 1A CALL INT ; Get integer of power -3845+ 1C70 C1 POP BC ; Restore power -3846+ 1C71 D1 POP DE -3847+ 1C72 F5 PUSH AF ; MSB of base -3848+ 1C73 CD 25 1A CALL CMPNUM ; Power an integer? -3849+ 1C76 E1 POP HL ; Restore MSB of base -3850+ 1C77 7C LD A,H ; but don't affect flags -3851+ 1C78 1F RRA ; Exponent odd or even? -3852+ 1C79 E1 POWER2: POP HL ; Restore MSB and exponent -3853+ 1C7A 22 96 31 LD (FPREG+2),HL ; Save base in FPREG -3854+ 1C7D E1 POP HL ; LSBs of base -3855+ 1C7E 22 94 31 LD (FPREG),HL ; Save in FPREG -3856+ 1C81 DC 3E 1C CALL C,NEGAFT ; Odd power - Negate result -3857+ 1C84 CC D3 19 CALL Z,INVSGN ; Negative base - Negate it -3858+ 1C87 D5 PUSH DE ; Save power -3859+ 1C88 C5 PUSH BC -3860+ 1C89 CD 5E 18 CALL LOG ; Get LOG of base -3861+ 1C8C C1 POP BC ; Restore power -3862+ 1C8D D1 POP DE -3863+ 1C8E CD 9F 18 CALL FPMULT ; Multiply LOG by power -3864+ 1C91 -3865+ 1C91 CD DB 19 EXP: CALL STAKFP ; Put value on stack -3866+ 1C94 01 38 81 LD BC,08138H ; BCDE = 1/Ln(2) -3867+ 1C97 11 3B AA LD DE,0AA3BH -3868+ 1C9A CD 9F 18 CALL FPMULT ; Multiply value by 1/LN(2) -3869+ 1C9D 3A 97 31 LD A,(FPEXP) ; Get exponent -3870+ 1CA0 FE 88 CP 80H+8 ; Is it in range? -3871+ 1CA2 D2 86 19 JP NC,OVTST1 ; No - Test for overflow -3872+ 1CA5 CD 7D 1A CALL INT ; Get INT of FPREG -3873+ 1CA8 C6 80 ADD A,80H ; For excess 128 -3874+ 1CAA C6 02 ADD A,2 ; Exponent > 126? -3875+ 1CAC DA 86 19 JP C,OVTST1 ; Yes - Test for overflow -3876+ 1CAF F5 PUSH AF ; Save scaling factor -3877+ 1CB0 21 4D 18 LD HL,UNITY ; Point to 1. -3878+ 1CB3 CD 55 17 CALL ADDPHL ; Add 1 to FPREG -3879+ 1CB6 CD 96 18 CALL MULLN2 ; Multiply by LN(2) -3880+ 1CB9 F1 POP AF ; Restore scaling factor -3881+ 1CBA C1 POP BC ; Restore exponent -3882+ 1CBB D1 POP DE -3883+ 1CBC F5 PUSH AF ; Save scaling factor -3884+ 1CBD CD 61 17 CALL SUBCDE ; Subtract exponent from FPREG -3885+ 1CC0 CD D3 19 CALL INVSGN ; Negate result -3886+ 1CC3 21 D1 1C LD HL,EXPTAB ; Coefficient table -3887+ 1CC6 CD 01 1D CALL SMSER1 ; Sum the series -3888+ 1CC9 11 00 00 LD DE,0 ; Zero LSBs -3889+ 1CCC C1 POP BC ; Scaling factor -3890+ 1CCD 4A LD C,D ; Zero MSB -3891+ 1CCE C3 9F 18 JP FPMULT ; Scale result to correct value -3892+ 1CD1 -3893+ 1CD1 08 EXPTAB: .BYTE 8 ; Table used by EXP -3894+ 1CD2 40 2E 94 74 .BYTE 040H,02EH,094H,074H ; -1/7! (-1/5040) -3895+ 1CD6 70 4F 2E 77 .BYTE 070H,04FH,02EH,077H ; 1/6! ( 1/720) -3896+ 1CDA 6E 02 88 7A .BYTE 06EH,002H,088H,07AH ; -1/5! (-1/120) -3897+ 1CDE E6 A0 2A 7C .BYTE 0E6H,0A0H,02AH,07CH ; 1/4! ( 1/24) -3898+ 1CE2 50 AA AA 7E .BYTE 050H,0AAH,0AAH,07EH ; -1/3! (-1/6) -3899+ 1CE6 FF FF 7F 7F .BYTE 0FFH,0FFH,07FH,07FH ; 1/2! ( 1/2) -3900+ 1CEA 00 00 80 81 .BYTE 000H,000H,080H,081H ; -1/1! (-1/1) -3901+ 1CEE 00 00 00 81 .BYTE 000H,000H,000H,081H ; 1/0! ( 1/1) -3902+ 1CF2 -3903+ 1CF2 CD DB 19 SUMSER: CALL STAKFP ; Put FPREG on stack -3904+ 1CF5 11 9D 18 LD DE,MULT ; Multiply by "X" -3905+ 1CF8 D5 PUSH DE ; To be done after -3906+ 1CF9 E5 PUSH HL ; Save address of table -3907+ 1CFA CD F6 19 CALL BCDEFP ; Move FPREG to BCDE -3908+ 1CFD CD 9F 18 CALL FPMULT ; Square the value -3909+ 1D00 E1 POP HL ; Restore address of table -3910+ 1D01 CD DB 19 SMSER1: CALL STAKFP ; Put value on stack -3911+ 1D04 7E LD A,(HL) ; Get number of coefficients -3912+ 1D05 23 INC HL ; Point to start of table -3913+ 1D06 CD E8 19 CALL PHLTFP ; Move coefficient to FPREG -3914+ 1D09 06 .BYTE 06H ; Skip "POP AF" -3915+ 1D0A F1 SUMLP: POP AF ; Restore count -3916+ 1D0B C1 POP BC ; Restore number -3917+ 1D0C D1 POP DE -3918+ 1D0D 3D DEC A ; Cont coefficients -3919+ 1D0E C8 RET Z ; All done -3920+ 1D0F D5 PUSH DE ; Save number -3921+ 1D10 C5 PUSH BC -3922+ 1D11 F5 PUSH AF ; Save count -3923+ 1D12 E5 PUSH HL ; Save address in table -3924+ 1D13 CD 9F 18 CALL FPMULT ; Multiply FPREG by BCDE -3925+ 1D16 E1 POP HL ; Restore address in table -3926+ 1D17 CD F9 19 CALL LOADFP ; Number at HL to BCDE -3927+ 1D1A E5 PUSH HL ; Save address in table -3928+ 1D1B CD 64 17 CALL FPADD ; Add coefficient to FPREG -3929+ 1D1E E1 POP HL ; Restore address in table -3930+ 1D1F C3 0A 1D JP SUMLP ; More coefficients -3931+ 1D22 -3932+ 1D22 CD AA 19 RND: CALL TSTSGN ; Test sign of FPREG -3933+ 1D25 21 C9 30 LD HL,SEED+2 ; Random number seed -3934+ 1D28 FA 83 1D JP M,RESEED ; Negative - Re-seed -3935+ 1D2B 21 EA 30 LD HL,LSTRND ; Last random number -3936+ 1D2E CD E8 19 CALL PHLTFP ; Move last RND to FPREG -3937+ 1D31 21 C9 30 LD HL,SEED+2 ; Random number seed -3938+ 1D34 C8 RET Z ; Return if RND(0) -3939+ 1D35 86 ADD A,(HL) ; Add (SEED)+2) -3940+ 1D36 E6 07 AND 00000111B ; 0 to 7 -3941+ 1D38 06 00 LD B,0 -3942+ 1D3A 77 LD (HL),A ; Re-save seed -3943+ 1D3B 23 INC HL ; Move to coefficient table -3944+ 1D3C 87 ADD A,A ; 4 bytes -3945+ 1D3D 87 ADD A,A ; per entry -3946+ 1D3E 4F LD C,A ; BC = Offset into table -3947+ 1D3F 09 ADD HL,BC ; Point to coefficient -3948+ 1D40 CD F9 19 CALL LOADFP ; Coefficient to BCDE -3949+ 1D43 CD 9F 18 CALL FPMULT ; ; Multiply FPREG by coefficient -3950+ 1D46 3A C8 30 LD A,(SEED+1) ; Get (SEED+1) -3951+ 1D49 3C INC A ; Add 1 -3952+ 1D4A E6 03 AND 00000011B ; 0 to 3 -3953+ 1D4C 06 00 LD B,0 -3954+ 1D4E FE 01 CP 1 ; Is it zero? -3955+ 1D50 88 ADC A,B ; Yes - Make it 1 -3956+ 1D51 32 C8 30 LD (SEED+1),A ; Re-save seed -3957+ 1D54 21 87 1D LD HL,RNDTAB-4 ; Addition table -3958+ 1D57 87 ADD A,A ; 4 bytes -3959+ 1D58 87 ADD A,A ; per entry -3960+ 1D59 4F LD C,A ; BC = Offset into table -3961+ 1D5A 09 ADD HL,BC ; Point to value -3962+ 1D5B CD 55 17 CALL ADDPHL ; Add value to FPREG -3963+ 1D5E CD F6 19 RND1: CALL BCDEFP ; Move FPREG to BCDE -3964+ 1D61 7B LD A,E ; Get LSB -3965+ 1D62 59 LD E,C ; LSB = MSB -3966+ 1D63 EE 4F XOR 01001111B ; Fiddle around -3967+ 1D65 4F LD C,A ; New MSB -3968+ 1D66 36 80 LD (HL),80H ; Set exponent -3969+ 1D68 2B DEC HL ; Point to MSB -3970+ 1D69 46 LD B,(HL) ; Get MSB -3971+ 1D6A 36 80 LD (HL),80H ; Make value -0.5 -3972+ 1D6C 21 C7 30 LD HL,SEED ; Random number seed -3973+ 1D6F 34 INC (HL) ; Count seed -3974+ 1D70 7E LD A,(HL) ; Get seed -3975+ 1D71 D6 AB SUB 171 ; Do it modulo 171 -3976+ 1D73 C2 7A 1D JP NZ,RND2 ; Non-zero - Ok -3977+ 1D76 77 LD (HL),A ; Zero seed -3978+ 1D77 0C INC C ; Fillde about -3979+ 1D78 15 DEC D ; with the -3980+ 1D79 1C INC E ; number -3981+ 1D7A CD B5 17 RND2: CALL BNORM ; Normalise number -3982+ 1D7D 21 EA 30 LD HL,LSTRND ; Save random number -3983+ 1D80 C3 02 1A JP FPTHL ; Move FPREG to last and return -3984+ 1D83 -3985+ 1D83 77 RESEED: LD (HL),A ; Re-seed random numbers -3986+ 1D84 2B DEC HL -3987+ 1D85 77 LD (HL),A -3988+ 1D86 2B DEC HL -3989+ 1D87 77 LD (HL),A -3990+ 1D88 C3 5E 1D JP RND1 ; Return RND seed -3991+ 1D8B -3992+ 1D8B 68 B1 46 68 RNDTAB: .BYTE 068H,0B1H,046H,068H ; Table used by RND -3993+ 1D8F 99 E9 92 69 .BYTE 099H,0E9H,092H,069H -3994+ 1D93 10 D1 75 68 .BYTE 010H,0D1H,075H,068H -3995+ 1D97 -3996+ 1D97 21 E1 1D COS: LD HL,HALFPI ; Point to PI/2 -3997+ 1D9A CD 55 17 CALL ADDPHL ; Add it to PPREG -3998+ 1D9D CD DB 19 SIN: CALL STAKFP ; Put angle on stack -3999+ 1DA0 01 49 83 LD BC,8349H ; BCDE = 2 PI -4000+ 1DA3 11 DB 0F LD DE,0FDBH -4001+ 1DA6 CD EB 19 CALL FPBCDE ; Move 2 PI to FPREG -4002+ 1DA9 C1 POP BC ; Restore angle -4003+ 1DAA D1 POP DE -4004+ 1DAB CD 00 19 CALL DVBCDE ; Divide angle by 2 PI -4005+ 1DAE CD DB 19 CALL STAKFP ; Put it on stack -4006+ 1DB1 CD 7D 1A CALL INT ; Get INT of result -4007+ 1DB4 C1 POP BC ; Restore number -4008+ 1DB5 D1 POP DE -4009+ 1DB6 CD 61 17 CALL SUBCDE ; Make it 0 <= value < 1 -4010+ 1DB9 21 E5 1D LD HL,QUARTR ; Point to 0.25 -4011+ 1DBC CD 5B 17 CALL SUBPHL ; Subtract value from 0.25 -4012+ 1DBF CD AA 19 CALL TSTSGN ; Test sign of value -4013+ 1DC2 37 SCF ; Flag positive -4014+ 1DC3 F2 CD 1D JP P,SIN1 ; Positive - Ok -4015+ 1DC6 CD 52 17 CALL ROUND ; Add 0.5 to value -4016+ 1DC9 CD AA 19 CALL TSTSGN ; Test sign of value -4017+ 1DCC B7 OR A ; Flag negative -4018+ 1DCD F5 SIN1: PUSH AF ; Save sign -4019+ 1DCE F4 D3 19 CALL P,INVSGN ; Negate value if positive -4020+ 1DD1 21 E5 1D LD HL,QUARTR ; Point to 0.25 -4021+ 1DD4 CD 55 17 CALL ADDPHL ; Add 0.25 to value -4022+ 1DD7 F1 POP AF ; Restore sign -4023+ 1DD8 D4 D3 19 CALL NC,INVSGN ; Negative - Make positive -4024+ 1DDB 21 E9 1D LD HL,SINTAB ; Coefficient table -4025+ 1DDE C3 F2 1C JP SUMSER ; Evaluate sum of series -4026+ 1DE1 -4027+ 1DE1 DB 0F 49 81 HALFPI: .BYTE 0DBH,00FH,049H,081H ; 1.5708 (PI/2) -4028+ 1DE5 -4029+ 1DE5 00 00 00 7F QUARTR: .BYTE 000H,000H,000H,07FH ; 0.25 -4030+ 1DE9 -4031+ 1DE9 05 SINTAB: .BYTE 5 ; Table used by SIN -4032+ 1DEA BA D7 1E 86 .BYTE 0BAH,0D7H,01EH,086H ; 39.711 -4033+ 1DEE 64 26 99 87 .BYTE 064H,026H,099H,087H ;-76.575 -4034+ 1DF2 58 34 23 87 .BYTE 058H,034H,023H,087H ; 81.602 -4035+ 1DF6 E0 5D A5 86 .BYTE 0E0H,05DH,0A5H,086H ;-41.342 -4036+ 1DFA DA 0F 49 83 .BYTE 0DAH,00FH,049H,083H ; 6.2832 -4037+ 1DFE -4038+ 1DFE CD DB 19 TAN: CALL STAKFP ; Put angle on stack -4039+ 1E01 CD 9D 1D CALL SIN ; Get SIN of angle -4040+ 1E04 C1 POP BC ; Restore angle -4041+ 1E05 E1 POP HL -4042+ 1E06 CD DB 19 CALL STAKFP ; Save SIN of angle -4043+ 1E09 EB EX DE,HL ; BCDE = Angle -4044+ 1E0A CD EB 19 CALL FPBCDE ; Angle to FPREG -4045+ 1E0D CD 97 1D CALL COS ; Get COS of angle -4046+ 1E10 C3 FE 18 JP DIV ; TAN = SIN / COS -4047+ 1E13 -4048+ 1E13 CD AA 19 ATN: CALL TSTSGN ; Test sign of value -4049+ 1E16 FC 3E 1C CALL M,NEGAFT ; Negate result after if -ve -4050+ 1E19 FC D3 19 CALL M,INVSGN ; Negate value if -ve -4051+ 1E1C 3A 97 31 LD A,(FPEXP) ; Get exponent -4052+ 1E1F FE 81 CP 81H ; Number less than 1? -4053+ 1E21 DA 30 1E JP C,ATN1 ; Yes - Get arc tangnt -4054+ 1E24 01 00 81 LD BC,8100H ; BCDE = 1 -4055+ 1E27 51 LD D,C -4056+ 1E28 59 LD E,C -4057+ 1E29 CD 00 19 CALL DVBCDE ; Get reciprocal of number -4058+ 1E2C 21 5B 17 LD HL,SUBPHL ; Sub angle from PI/2 -4059+ 1E2F E5 PUSH HL ; Save for angle > 1 -4060+ 1E30 21 3A 1E ATN1: LD HL,ATNTAB ; Coefficient table -4061+ 1E33 CD F2 1C CALL SUMSER ; Evaluate sum of series -4062+ 1E36 21 E1 1D LD HL,HALFPI ; PI/2 - angle in case > 1 -4063+ 1E39 C9 RET ; Number > 1 - Sub from PI/2 -4064+ 1E3A -4065+ 1E3A 09 ATNTAB: .BYTE 9 ; Table used by ATN -4066+ 1E3B 4A D7 3B 78 .BYTE 04AH,0D7H,03BH,078H ; 1/17 -4067+ 1E3F 02 6E 84 7B .BYTE 002H,06EH,084H,07BH ;-1/15 -4068+ 1E43 FE C1 2F 7C .BYTE 0FEH,0C1H,02FH,07CH ; 1/13 -4069+ 1E47 74 31 9A 7D .BYTE 074H,031H,09AH,07DH ;-1/11 -4070+ 1E4B 84 3D 5A 7D .BYTE 084H,03DH,05AH,07DH ; 1/9 -4071+ 1E4F C8 7F 91 7E .BYTE 0C8H,07FH,091H,07EH ;-1/7 -4072+ 1E53 E4 BB 4C 7E .BYTE 0E4H,0BBH,04CH,07EH ; 1/5 -4073+ 1E57 6C AA AA 7F .BYTE 06CH,0AAH,0AAH,07FH ;-1/3 -4074+ 1E5B 00 00 00 81 .BYTE 000H,000H,000H,081H ; 1/1 -4075+ 1E5F -4076+ 1E5F -4077+ 1E5F C9 ARET: RET ; A RETurn instruction -4078+ 1E60 -4079+ 1E60 D7 GETINP: RST 10H ;input a character -4080+ 1E61 C9 RET -4081+ 1E62 -4082+ 1E62 CLS: -4083+ 1E62 3E 0C LD A,CS ; ASCII Clear screen -4084+ 1E64 C3 9C 1F JP MONOUT ; Output character -4085+ 1E67 -4086+ 1E67 CD 29 17 WIDTH: CALL GETINT ; Get integer 0-255 -4087+ 1E6A 7B LD A,E ; Width to A -4088+ 1E6B 32 F2 30 LD (LWIDTH),A ; Set width -4089+ 1E6E C9 RET -4090+ 1E6F -4091+ 1E6F CD C8 0F LINES: CALL GETNUM ; Get a number -4092+ 1E72 CD 0D 0C CALL DEINT ; Get integer -32768 to 32767 -4093+ 1E75 ED 53 F6 30 LD (LINESC),DE ; Set lines counter -4094+ 1E79 ED 53 F8 30 LD (LINESN),DE ; Set lines number -4095+ 1E7D C9 RET -4096+ 1E7E -4097+ 1E7E CD 0D 0C DEEK: CALL DEINT ; Get integer -32768 to 32767 -4098+ 1E81 D5 PUSH DE ; Save number -4099+ 1E82 E1 POP HL ; Number to HL -4100+ 1E83 46 LD B,(HL) ; Get LSB of contents -4101+ 1E84 23 INC HL -4102+ 1E85 7E LD A,(HL) ; Get MSB of contents -4103+ 1E86 C3 83 13 JP ABPASS ; Return integer AB -4104+ 1E89 -4105+ 1E89 CD C8 0F DOKE: CALL GETNUM ; Get a number -4106+ 1E8C CD 0D 0C CALL DEINT ; Get integer -32768 to 32767 -4107+ 1E8F D5 PUSH DE ; Save address -4108+ 1E90 CD D1 09 CALL CHKSYN ; Make sure ',' follows -4109+ 1E93 2C .BYTE ',' -4110+ 1E94 CD C8 0F CALL GETNUM ; Get a number -4111+ 1E97 CD 0D 0C CALL DEINT ; Get integer -32768 to 32767 -4112+ 1E9A E3 EX (SP),HL ; Save value,get address -4113+ 1E9B 73 LD (HL),E ; Save LSB of value -4114+ 1E9C 23 INC HL -4115+ 1E9D 72 LD (HL),D ; Save MSB of value -4116+ 1E9E E1 POP HL ; Restore code string address -4117+ 1E9F C9 RET -4118+ 1EA0 -4119+ 1EA0 -4120+ 1EA0 ; HEX$(nn) Convert 16 bit number to Hexadecimal string -4121+ 1EA0 -4122+ 1EA0 CD CB 0F HEX: CALL TSTNUM ; Verify it's a number -4123+ 1EA3 CD 0D 0C CALL DEINT ; Get integer -32768 to 32767 -4124+ 1EA6 C5 PUSH BC ; Save contents of BC -4125+ 1EA7 21 99 31 LD HL,PBUFF -4126+ 1EAA 7A LD A,D ; Get high order into A -4127+ 1EAB FE 00 CP $0 -4128+ 1EAD 28 0C JR Z,HEX2 ; Skip output if both high digits are zero -4129+ 1EAF CD D8 1E CALL BYT2ASC ; Convert D to ASCII -4130+ 1EB2 78 LD A,B -4131+ 1EB3 FE 30 CP '0' -4132+ 1EB5 28 02 JR Z,HEX1 ; Don't store high digit if zero -4133+ 1EB7 70 LD (HL),B ; Store it to PBUFF -4134+ 1EB8 23 INC HL ; Next location -4135+ 1EB9 71 HEX1: LD (HL),C ; Store C to PBUFF+1 -4136+ 1EBA 23 INC HL ; Next location -4137+ 1EBB 7B HEX2: LD A,E ; Get lower byte -4138+ 1EBC CD D8 1E CALL BYT2ASC ; Convert E to ASCII -4139+ 1EBF 7A LD A,D -4140+ 1EC0 FE 00 CP $0 -4141+ 1EC2 20 05 JR NZ,HEX3 ; If upper byte was not zero then always print lower byte -4142+ 1EC4 78 LD A,B -4143+ 1EC5 FE 30 CP '0' ; If high digit of lower byte is zero then don't print -4144+ 1EC7 28 02 JR Z,HEX4 -4145+ 1EC9 70 HEX3: LD (HL),B ; to PBUFF+2 -4146+ 1ECA 23 INC HL ; Next location -4147+ 1ECB 71 HEX4: LD (HL),C ; to PBUFF+3 -4148+ 1ECC 23 INC HL ; PBUFF+4 to zero -4149+ 1ECD AF XOR A ; Terminating character -4150+ 1ECE 77 LD (HL),A ; Store zero to terminate -4151+ 1ECF 23 INC HL ; Make sure PBUFF is terminated -4152+ 1ED0 77 LD (HL),A ; Store the double zero there -4153+ 1ED1 C1 POP BC ; Get BC back -4154+ 1ED2 21 99 31 LD HL,PBUFF ; Reset to start of PBUFF -4155+ 1ED5 C3 31 14 JP STR1 ; Convert the PBUFF to a string and return it -4156+ 1ED8 -4157+ 1ED8 47 BYT2ASC LD B,A ; Save original value -4158+ 1ED9 E6 0F AND $0F ; Strip off upper nybble -4159+ 1EDB FE 0A CP $0A ; 0-9? -4160+ 1EDD 38 02 JR C,ADD30 ; If A-F, add 7 more -4161+ 1EDF C6 07 ADD A,$07 ; Bring value up to ASCII A-F -4162+ 1EE1 C6 30 ADD30 ADD A,$30 ; And make ASCII -4163+ 1EE3 4F LD C,A ; Save converted char to C -4164+ 1EE4 78 LD A,B ; Retrieve original value -4165+ 1EE5 0F RRCA ; and Rotate it right -4166+ 1EE6 0F RRCA -4167+ 1EE7 0F RRCA -4168+ 1EE8 0F RRCA -4169+ 1EE9 E6 0F AND $0F ; Mask off upper nybble -4170+ 1EEB FE 0A CP $0A ; 0-9? < A hex? -4171+ 1EED 38 02 JR C,ADD301 ; Skip Add 7 -4172+ 1EEF C6 07 ADD A,$07 ; Bring it up to ASCII A-F -4173+ 1EF1 C6 30 ADD301 ADD A,$30 ; And make it full ASCII -4174+ 1EF3 47 LD B,A ; Store high order byte -4175+ 1EF4 C9 RET -4176+ 1EF5 -4177+ 1EF5 ; Convert "&Hnnnn" to FPREG -4178+ 1EF5 ; Gets a character from (HL) checks for Hexadecimal ASCII numbers "&Hnnnn" -4179+ 1EF5 ; Char is in A, NC if char is ;<=>?@ A-z, CY is set if 0-9 -4180+ 1EF5 EB HEXTFP EX DE,HL ; Move code string pointer to DE -4181+ 1EF6 21 00 00 LD HL,$0000 ; Zero out the value -4182+ 1EF9 CD 0E 1F CALL GETHEX ; Check the number for valid hex -4183+ 1EFC DA 2E 1F JP C,HXERR ; First value wasn't hex, HX error -4184+ 1EFF 18 05 JR HEXLP1 ; Convert first character -4185+ 1F01 CD 0E 1F HEXLP CALL GETHEX ; Get second and addtional characters -4186+ 1F04 38 1F JR C,HEXIT ; Exit if not a hex character -4187+ 1F06 29 HEXLP1 ADD HL,HL ; Rotate 4 bits to the left -4188+ 1F07 29 ADD HL,HL -4189+ 1F08 29 ADD HL,HL -4190+ 1F09 29 ADD HL,HL -4191+ 1F0A B5 OR L ; Add in D0-D3 into L -4192+ 1F0B 6F LD L,A ; Save new value -4193+ 1F0C 18 F3 JR HEXLP ; And continue until all hex characters are in -4194+ 1F0E -4195+ 1F0E 13 GETHEX INC DE ; Next location -4196+ 1F0F 1A LD A,(DE) ; Load character at pointer -4197+ 1F10 FE 20 CP ' ' -4198+ 1F12 CA 0E 1F JP Z,GETHEX ; Skip spaces -4199+ 1F15 D6 30 SUB $30 ; Get absolute value -4200+ 1F17 D8 RET C ; < "0", error -4201+ 1F18 FE 0A CP $0A -4202+ 1F1A 38 05 JR C,NOSUB7 ; Is already in the range 0-9 -4203+ 1F1C D6 07 SUB $07 ; Reduce to A-F -4204+ 1F1E FE 0A CP $0A ; Value should be $0A-$0F at this point -4205+ 1F20 D8 RET C ; CY set if was : ; < = > ? @ -4206+ 1F21 FE 10 NOSUB7 CP $10 ; > Greater than "F"? -4207+ 1F23 3F CCF -4208+ 1F24 C9 RET ; CY set if it wasn't valid hex -4209+ 1F25 -4210+ 1F25 EB HEXIT EX DE,HL ; Value into DE, Code string into HL -4211+ 1F26 7A LD A,D ; Load DE into AC -4212+ 1F27 4B LD C,E ; For prep to -4213+ 1F28 E5 PUSH HL -4214+ 1F29 CD 82 13 CALL ACPASS ; ACPASS to set AC as integer into FPREG -4215+ 1F2C E1 POP HL -4216+ 1F2D C9 RET -4217+ 1F2E -4218+ 1F2E 1E 26 HXERR: LD E,HX ; ?HEX Error -4219+ 1F30 C3 17 07 JP ERROR -4220+ 1F33 -4221+ 1F33 ; BIN$(NN) Convert integer to a 1-16 char binary string -4222+ 1F33 CD CB 0F BIN: CALL TSTNUM ; Verify it's a number -4223+ 1F36 CD 0D 0C CALL DEINT ; Get integer -32768 to 32767 -4224+ 1F39 C5 BIN2: PUSH BC ; Save contents of BC -4225+ 1F3A 21 99 31 LD HL,PBUFF -4226+ 1F3D 06 11 LD B,17 ; One higher than max char count -4227+ 1F3F ZEROSUP: ; Suppress leading zeros -4228+ 1F3F 05 DEC B ; Max 16 chars -4229+ 1F40 78 LD A,B -4230+ 1F41 FE 01 CP $01 -4231+ 1F43 28 08 JR Z,BITOUT ; Always output at least one character -4232+ 1F45 CB 13 RL E -4233+ 1F47 CB 12 RL D -4234+ 1F49 30 F4 JR NC,ZEROSUP -4235+ 1F4B 18 04 JR BITOUT2 -4236+ 1F4D BITOUT: -4237+ 1F4D CB 13 RL E -4238+ 1F4F CB 12 RL D ; Top bit now in carry -4239+ 1F51 BITOUT2: -4240+ 1F51 3E 30 LD A,'0' ; Char for '0' -4241+ 1F53 CE 00 ADC A,0 ; If carry set then '0' --> '1' -4242+ 1F55 77 LD (HL),A -4243+ 1F56 23 INC HL -4244+ 1F57 05 DEC B -4245+ 1F58 20 F3 JR NZ,BITOUT -4246+ 1F5A AF XOR A ; Terminating character -4247+ 1F5B 77 LD (HL),A ; Store zero to terminate -4248+ 1F5C 23 INC HL ; Make sure PBUFF is terminated -4249+ 1F5D 77 LD (HL),A ; Store the double zero there -4250+ 1F5E C1 POP BC -4251+ 1F5F 21 99 31 LD HL,PBUFF -4252+ 1F62 C3 31 14 JP STR1 -4253+ 1F65 -4254+ 1F65 ; Convert "&Bnnnn" to FPREG -4255+ 1F65 ; Gets a character from (HL) checks for Binary ASCII numbers "&Bnnnn" -4256+ 1F65 EB BINTFP: EX DE,HL ; Move code string pointer to DE -4257+ 1F66 21 00 00 LD HL,$0000 ; Zero out the value -4258+ 1F69 CD 82 1F CALL CHKBIN ; Check the number for valid bin -4259+ 1F6C DA 90 1F JP C,BINERR ; First value wasn't bin, HX error -4260+ 1F6F D6 30 BINIT: SUB '0' -4261+ 1F71 29 ADD HL,HL ; Rotate HL left -4262+ 1F72 B5 OR L -4263+ 1F73 6F LD L,A -4264+ 1F74 CD 82 1F CALL CHKBIN ; Get second and addtional characters -4265+ 1F77 30 F6 JR NC,BINIT ; Process if a bin character -4266+ 1F79 EB EX DE,HL ; Value into DE, Code string into HL -4267+ 1F7A 7A LD A,D ; Load DE into AC -4268+ 1F7B 4B LD C,E ; For prep to -4269+ 1F7C E5 PUSH HL -4270+ 1F7D CD 82 13 CALL ACPASS ; ACPASS to set AC as integer into FPREG -4271+ 1F80 E1 POP HL -4272+ 1F81 C9 RET -4273+ 1F82 -4274+ 1F82 ; Char is in A, NC if char is 0 or 1 -4275+ 1F82 13 CHKBIN: INC DE -4276+ 1F83 1A LD A,(DE) -4277+ 1F84 FE 20 CP ' ' -4278+ 1F86 CA 82 1F JP Z,CHKBIN ; Skip spaces -4279+ 1F89 FE 30 CP '0' ; Set C if < '0' -4280+ 1F8B D8 RET C -4281+ 1F8C FE 32 CP '2' -4282+ 1F8E 3F CCF ; Set C if > '1' -4283+ 1F8F C9 RET -4284+ 1F90 -4285+ 1F90 1E 28 BINERR: LD E,BN ; ?BIN Error -4286+ 1F92 C3 17 07 JP ERROR -4287+ 1F95 -4288+ 1F95 -4289+ 1F95 JJUMP1: -4290+ 1F95 DD 21 FF FF LD IX,-1 ; Flag cold start -4291+ 1F99 C3 67 03 JP CSTART ; Go and initialise -4292+ 1F9C -4293+ 1F9C MONOUT: -4294+ 1F9C C3 08 00 JP $0008 ; output a char -4295+ 1F9F -4296+ 1F9F -4297+ 1F9F MONITR: -4298+ 1F9F C3 00 00 JP $0000 ; Restart (Normally Monitor Start) -4299+ 1FA2 -4300+ 1FA2 -4301+ 1FA2 3E 00 INITST: LD A,0 ; Clear break flag -4302+ 1FA4 32 FD 30 LD (BRKFLG),A -4303+ 1FA7 C3 6E 03 JP INIT -4304+ 1FAA -4305+ 1FAA ED 45 ARETN: RETN ; Return from NMI -4306+ 1FAC -4307+ 1FAC -4308+ 1FAC F5 TSTBIT: PUSH AF ; Save bit mask -4309+ 1FAD A0 AND B ; Get common bits -4310+ 1FAE C1 POP BC ; Restore bit mask -4311+ 1FAF B8 CP B ; Same bit set? -4312+ 1FB0 3E 00 LD A,0 ; Return 0 in A -4313+ 1FB2 C9 RET -4314+ 1FB3 -4315+ 1FB3 CD DC 09 OUTNCR: CALL OUTC ; Output character in A -4316+ 1FB6 C3 03 0E JP PRNTCRLF ; Output CRLF -4317+ 1FB9 -0693 1FB9 .end +0596 0277 DB 89 rdWait1: IN A,(SD_STATUS) +0597 0279 FE 80 CP 128 ; Check for ready status +0598 027B 20 FA JR NZ,rdWait1 +0599 027D +0600 027D ; Add multiple status checks before starting read +0601 027D 06 03 LD B,3 ; Check status 3 times +0602 027F rdCheck1: +0603 027F DB 89 IN A,(SD_STATUS) +0604 0281 FE 80 CP 128 +0605 0283 20 FA JR NZ,rdCheck1 +0606 0285 10 F8 DJNZ rdCheck1 +0607 0287 +0608 0287 CD 64 02 CALL setLBAaddr +0609 028A +0610 028A 3E 00 LD A,$00 ; 00 = Read block +0611 028C D3 89 OUT (SD_CONTROL),A +0612 028E +0613 028E 0E 04 LD c,4 +0614 0290 rd4secs: +0615 0290 06 80 LD b,128 +0616 0292 rdByte: +0617 0292 +0618 0292 DB 89 rdWait2: IN A,(SD_STATUS) +0619 0294 FE E0 CP 224 ; Read byte waiting +0620 0296 20 FA JR NZ,rdWait2 +0621 0298 +0622 0298 ; Add extra validation checks before each read +0623 0298 C5 PUSH BC ; Save main counters +0624 0299 06 02 LD B,2 ; Check status twice +0625 029B rdCheck2: +0626 029B DB 89 IN A,(SD_STATUS) +0627 029D FE E0 CP 224 +0628 029F 20 FA JR NZ,rdCheck2 +0629 02A1 10 F8 DJNZ rdCheck2 +0630 02A3 C1 POP BC ; Restore main counters +0631 02A4 +0632 02A4 DB 88 IN A,(SD_DATA) +0633 02A6 +0634 02A6 ; Add small delay after read before store +0635 02A6 C5 PUSH BC +0636 02A7 06 0A LD B,10 +0637 02A9 rdDelay: +0638 02A9 10 FE DJNZ rdDelay +0639 02AB C1 POP BC +0640 02AC +0641 02AC 77 LD (HL),A +0642 02AD 23 INC HL +0643 02AE 05 dec b +0644 02AF 20 E1 JR NZ, rdByte +0645 02B1 0D dec c +0646 02B2 20 DC JR NZ,rd4secs +0647 02B4 +0648 02B4 ; Add final wait before returning +0649 02B4 06 00 LD B,0 +0650 02B6 rdWaitFinal: +0651 02B6 DB 89 IN A,(SD_STATUS) +0652 02B8 FE 80 CP 128 ; Wait for ready status +0653 02BA 20 FA JR NZ,rdWaitFinal +0654 02BC 10 F8 DJNZ rdWaitFinal +0655 02BE +0656 02BE E1 POP HL +0657 02BF C1 POP BC +0658 02C0 F1 POP AF +0659 02C1 +0660 02C1 C9 RET +0661 02C2 +0662 02C2 ;------------------------------------------------------------------------------ +0663 02C2 ; END OF ROUTINES AS USED IN BIOS +0664 02C2 ;------------------------------------------------------------------------------ +0665 02C2 +0666 02C2 +0667 02C2 43 50 2F 4D M_SIGNON .BYTE "CP/M Boot ROM 2.0" +0667 02C6 20 42 6F 6F +0667 02CA 74 20 52 4F +0667 02CE 4D 20 32 2E +0667 02D2 30 +0668 02D3 ; .BYTE " based on design by G. Searle" +0669 02D3 ; .BYTE $0D,$0A +0670 02D3 0D 0A .BYTE $0D,$0A +0671 02D5 49 2D 53 74 .TEXT "I-Strt Intrp" +0671 02D9 72 74 20 49 +0671 02DD 6E 74 72 70 +0672 02E1 0D 0A .BYTE $0D,$0A +0673 02E3 58 2D 42 6F .TEXT "X-Boot CP/M" +0673 02E7 6F 74 20 43 +0673 02EB 50 2F 4D +0674 02EE 0D 0A .BYTE $0D,$0A +0675 02F0 3A 6E 6E 6E .TEXT ":nnnn-Load I rcrd" +0675 02F4 6E 2D 4C 6F +0675 02F8 61 64 20 49 +0675 02FC 20 72 63 72 +0675 0300 64 +0676 0301 0D 0A .BYTE $0D,$0A +0677 0303 47 6E 6E 6E .TEXT "Gnnnn-R loc" +0677 0307 6E 2D 52 20 +0677 030B 6C 6F 63 +0678 030E 0D 0A .BYTE $0D,$0A +0679 0310 00 .BYTE $00 +0680 0311 +0681 0311 M_BASTXT +0682 0311 0D 0A .BYTE $0D,$0A +0683 0313 43 6F 6C 64 .TEXT "Cold or warm?" +0683 0317 20 6F 72 20 +0683 031B 77 61 72 6D +0683 031F 3F +0684 0320 0D 0A 00 .BYTE $0D,$0A,$00 +0685 0323 +0686 0323 43 68 65 63 CKSUMERR .BYTE "Checksum error" +0686 0327 6B 73 75 6D +0686 032B 20 65 72 72 +0686 032F 6F 72 +0687 0331 0D 0A 00 .BYTE $0D,$0A,$00 +0688 0334 +0689 0334 INITTXT +0690 0334 0C .BYTE $0C +0691 0335 50 72 65 73 .TEXT "Press [space] to activate console." +0691 0339 73 20 5B 73 +0691 033D 70 61 63 65 +0691 0341 5D 20 74 6F +0691 0345 20 61 63 74 +0691 0349 69 76 61 74 +0691 034D 65 20 63 6F +0691 0351 6E 73 6F 6C +0691 0355 65 2E +0692 0357 0D 0A 00 .BYTE $0D,$0A, $00 +0693 035A +0694 035A LDETXT +0695 035A 43 6F 6D 70 .TEXT "Complete" +0695 035E 6C 65 74 65 +0696 0362 0D 0A 00 .BYTE $0D,$0A, $00 +0697 0365 +0698 0365 ; ========================================================================================================================== +0699 0365 ; GENERAL EQUATES +0700 0365 +0701 0365 CTRLC .EQU 03H ; Control "C" +0702 0365 CTRLG .EQU 07H ; Control "G" +0703 0365 BKSP .EQU 08H ; Back space +0704 0365 LF .EQU 0AH ; Line feed +0705 0365 CS .EQU 0CH ; Clear screen +0706 0365 CR .EQU 0DH ; Carriage return +0707 0365 CTRLO .EQU 0FH ; Control "O" +0708 0365 CTRLQ .EQU 11H ; Control "Q" +0709 0365 CTRLR .EQU 12H ; Control "R" +0710 0365 CTRLS .EQU 13H ; Control "S" +0711 0365 CTRLU .EQU 15H ; Control "U" +0712 0365 ESC .EQU 1BH ; Escape +0713 0365 DEL .EQU 7FH ; Delete +0714 0365 +0715 0365 +0716 0365 ;=========================================================================================================================== +0717 0365 +0718 0365 ; NASCOM ROM BASIC Ver 4.7, +0719 0365 ; used to be here, removed to get rid of the '(C) 1978 Microsoft' +0720 0365 +0721 0365 STARTINT: +0722 0365 #INCLUDE "SOURCE\\INTPRT.ASM" +0001+ 0365 ;------------------------------------------------------------------------------ +0002+ 0365 ; Start BASIC command +0003+ 0365 ;------------------------------------------------------------------------------ +0004+ 0365 BASIC +0005+ 0365 21 11 03 LD HL,M_BASTXT +0006+ 0368 CD 37 01 CALL M_PRINT +0007+ 036B CD 45 01 CALL M_GETCHR +0008+ 036E C8 RET Z ; Cancel if CTRL-C +0009+ 036F E6 5F AND $5F ; uppercase +0010+ 0371 FE 43 CP 'C' +0011+ 0373 CA 7C 03 JP Z,COLD +0012+ 0376 FE 57 CP 'W' +0013+ 0378 CA 7F 03 JP Z,WARM +0014+ 037B C9 RET +0015+ 037C +0016+ 037C ; BASIC WORK SPACE LOCATIONS +0017+ 037C +0018+ 037C WRKSPC .EQU 30B0H ; BASIC Work space +0019+ 037C USR .EQU WRKSPC+3H ; "USR (x)" jump +0020+ 037C OUTSUB .EQU WRKSPC+6H ; "OUT p,n" +0021+ 037C OTPORT .EQU WRKSPC+7H ; Port (p) +0022+ 037C DIVSUP .EQU WRKSPC+9H ; Division support routine +0023+ 037C DIV1 .EQU WRKSPC+0AH ; <- Values +0024+ 037C DIV2 .EQU WRKSPC+0EH ; <- to +0025+ 037C DIV3 .EQU WRKSPC+12H ; <- be +0026+ 037C DIV4 .EQU WRKSPC+15H ; <-inserted +0027+ 037C SEED .EQU WRKSPC+17H ; Random number seed +0028+ 037C LSTRND .EQU WRKSPC+3AH ; Last random number +0029+ 037C INPSUB .EQU WRKSPC+3EH ; #INP (x)" Routine +0030+ 037C INPORT .EQU WRKSPC+3FH ; PORT (x) +0031+ 037C NULLS .EQU WRKSPC+41H ; Number of nulls +0032+ 037C LWIDTH .EQU WRKSPC+42H ; Terminal width +0033+ 037C COMMAN .EQU WRKSPC+43H ; Width for commas +0034+ 037C NULFLG .EQU WRKSPC+44H ; Null after input byte flag +0035+ 037C CTLOFG .EQU WRKSPC+45H ; Control "O" flag +0036+ 037C LINESC .EQU WRKSPC+46H ; Lines counter +0037+ 037C LINESN .EQU WRKSPC+48H ; Lines number +0038+ 037C CHKSUM .EQU WRKSPC+4AH ; Array load/save check sum +0039+ 037C NMIFLG .EQU WRKSPC+4CH ; Flag for NMI break routine +0040+ 037C BRKFLG .EQU WRKSPC+4DH ; Break flag +0041+ 037C RINPUT .EQU WRKSPC+4EH ; Input reflection +0042+ 037C POINT .EQU WRKSPC+51H ; "POINT" reflection (unused) +0043+ 037C PSET .EQU WRKSPC+54H ; "SET" reflection +0044+ 037C RESET .EQU WRKSPC+57H ; "RESET" reflection +0045+ 037C STRSPC .EQU WRKSPC+5AH ; Bottom of string space +0046+ 037C LINEAT .EQU WRKSPC+5CH ; Current line number +0047+ 037C BASTXT .EQU WRKSPC+5EH ; Pointer to start of program +0048+ 037C BUFFER .EQU WRKSPC+61H ; Input buffer +0049+ 037C STACK .EQU WRKSPC+66H ; Initial stack +0050+ 037C CURPOS .EQU WRKSPC+0ABH ; Character position on line +0051+ 037C LCRFLG .EQU WRKSPC+0ACH ; Locate/Create flag +0052+ 037C TYPE .EQU WRKSPC+0ADH ; Data type flag +0053+ 037C DATFLG .EQU WRKSPC+0AEH ; Literal statement flag +0054+ 037C LSTRAM .EQU WRKSPC+0AFH ; Last available RAM +0055+ 037C TMSTPT .EQU WRKSPC+0B1H ; Temporary string pointer +0056+ 037C TMSTPL .EQU WRKSPC+0B3H ; Temporary string pool +0057+ 037C TMPSTR .EQU WRKSPC+0BFH ; Temporary string +0058+ 037C STRBOT .EQU WRKSPC+0C3H ; Bottom of string space +0059+ 037C CUROPR .EQU WRKSPC+0C5H ; Current operator in EVAL +0060+ 037C LOOPST .EQU WRKSPC+0C7H ; First statement of loop +0061+ 037C DATLIN .EQU WRKSPC+0C9H ; Line of current DATA item +0062+ 037C FORFLG .EQU WRKSPC+0CBH ; "FOR" loop flag +0063+ 037C LSTBIN .EQU WRKSPC+0CCH ; Last byte entered +0064+ 037C READFG .EQU WRKSPC+0CDH ; Read/Input flag +0065+ 037C BRKLIN .EQU WRKSPC+0CEH ; Line of break +0066+ 037C NXTOPR .EQU WRKSPC+0D0H ; Next operator in EVAL +0067+ 037C ERRLIN .EQU WRKSPC+0D2H ; Line of error +0068+ 037C CONTAD .EQU WRKSPC+0D4H ; Where to CONTinue +0069+ 037C PROGND .EQU WRKSPC+0D6H ; End of program +0070+ 037C VAREND .EQU WRKSPC+0D8H ; End of variables +0071+ 037C ARREND .EQU WRKSPC+0DAH ; End of arrays +0072+ 037C NXTDAT .EQU WRKSPC+0DCH ; Next data item +0073+ 037C FNRGNM .EQU WRKSPC+0DEH ; Name of FN argument +0074+ 037C FNARG .EQU WRKSPC+0E0H ; FN argument value +0075+ 037C FPREG .EQU WRKSPC+0E4H ; Floating point register +0076+ 037C FPEXP .EQU FPREG+3 ; Floating point exponent +0077+ 037C SGNRES .EQU WRKSPC+0E8H ; Sign of result +0078+ 037C PBUFF .EQU WRKSPC+0E9H ; Number print buffer +0079+ 037C MULVAL .EQU WRKSPC+0F6H ; Multiplier +0080+ 037C PROGST .EQU WRKSPC+0F9H ; Start of program text area +0081+ 037C STLOOK .EQU WRKSPC+15DH ; Start of memory test +0082+ 037C +0083+ 037C ; BASIC ERROR CODE VALUES +0084+ 037C +0085+ 037C NF .EQU 00H ; NEXT without FOR +0086+ 037C SN .EQU 02H ; Syntax error +0087+ 037C RG .EQU 04H ; RETURN without GOSUB +0088+ 037C OD .EQU 06H ; Out of DATA +0089+ 037C FC .EQU 08H ; Function call error +0090+ 037C OV .EQU 0AH ; Overflow +0091+ 037C OM .EQU 0CH ; Out of memory +0092+ 037C UL .EQU 0EH ; Undefined line number +0093+ 037C BS .EQU 10H ; Bad subscript +0094+ 037C DD .EQU 12H ; Re-DIMensioned array +0095+ 037C DZ .EQU 14H ; Division by zero (/0) +0096+ 037C ID .EQU 16H ; Illegal direct +0097+ 037C TM .EQU 18H ; Type miss-match +0098+ 037C OS .EQU 1AH ; Out of string space +0099+ 037C LS .EQU 1CH ; String too long +0100+ 037C ST .EQU 1EH ; String formula too complex +0101+ 037C CN .EQU 20H ; Can't CONTinue +0102+ 037C UF .EQU 22H ; UnDEFined FN function +0103+ 037C MO .EQU 24H ; Missing operand +0104+ 037C HX .EQU 26H ; HEX error +0105+ 037C BN .EQU 28H ; BIN error +0106+ 037C +0107+ 037C ; .ORG 00396H +0108+ 037C +0109+ 037C C3 82 03 COLD: JP STARTB ; Jump for cold start +0110+ 037F C3 20 04 WARM: JP WARMST ; Jump for warm start +0111+ 0382 STARTB: +0112+ 0382 DD 21 00 00 LD IX,0 ; Flag cold start +0113+ 0386 C3 8D 03 JP CSTART ; Jump to initialise +0114+ 0389 +0115+ 0389 33 0C .WORD DEINT ; Get integer -32768 to 32767 +0116+ 038B A9 13 .WORD ABPASS ; Return integer in AB +0117+ 038D +0118+ 038D +0119+ 038D 21 B0 30 CSTART: LD HL,WRKSPC ; Start of workspace RAM +0120+ 0390 F9 LD SP,HL ; Set up a temporary stack +0121+ 0391 C3 C8 1F JP INITST ; Go to initialise +0122+ 0394 +0123+ 0394 11 5A 06 INIT: LD DE,INITAB ; Initialise workspace +0124+ 0397 06 63 LD B,INITBE-INITAB+3; Bytes to copy +0125+ 0399 21 B0 30 LD HL,WRKSPC ; Into workspace RAM +0126+ 039C 1A COPY: LD A,(DE) ; Get source +0127+ 039D 77 LD (HL),A ; To destination +0128+ 039E 23 INC HL ; Next destination +0129+ 039F 13 INC DE ; Next source +0130+ 03A0 05 DEC B ; Count bytes +0131+ 03A1 C2 9C 03 JP NZ,COPY ; More to move +0132+ 03A4 F9 LD SP,HL ; Temporary stack +0133+ 03A5 CD 5B 08 CALL CLREG ; Clear registers and stack +0134+ 03A8 CD 29 0E CALL PRNTCRLF ; Output CRLF +0135+ 03AB 32 5A 31 LD (BUFFER+72+1),A ; Mark end of buffer +0136+ 03AE 32 A9 31 LD (PROGST),A ; Initialise program area +0137+ 03B1 21 6F 04 MSIZE: LD HL,MEMMSG ; Point to message +0138+ 03B4 CD C7 14 CALL PRS ; Output "Memory size" +0139+ 03B7 CD 78 08 CALL PROMPT ; Get input with '?' +0140+ 03BA CD 81 0B CALL GETCHR ; Get next character +0141+ 03BD B7 OR A ; Set flags +0142+ 03BE C2 D6 03 JP NZ,TSTMEM ; If number - Test if RAM there +0143+ 03C1 21 0D 32 LD HL,STLOOK ; Point to start of RAM +0144+ 03C4 23 MLOOP: INC HL ; Next byte +0145+ 03C5 7C LD A,H ; Above address FFFF ? +0146+ 03C6 B5 OR L +0147+ 03C7 CA E8 03 JP Z,SETTOP ; Yes - 64K RAM +0148+ 03CA 7E LD A,(HL) ; Get contents +0149+ 03CB 47 LD B,A ; Save it +0150+ 03CC 2F CPL ; Flip all bits +0151+ 03CD 77 LD (HL),A ; Put it back +0152+ 03CE BE CP (HL) ; RAM there if same +0153+ 03CF 70 LD (HL),B ; Restore old contents +0154+ 03D0 CA C4 03 JP Z,MLOOP ; If RAM - test next byte +0155+ 03D3 C3 E8 03 JP SETTOP ; Top of RAM found +0156+ 03D6 +0157+ 03D6 CD 4D 0C TSTMEM: CALL ATOH ; Get high memory into DE +0158+ 03D9 B7 OR A ; Set flags on last byte +0159+ 03DA C2 29 07 JP NZ,SNERR ; ?SN Error if bad character +0160+ 03DD EB EX DE,HL ; Address into HL +0161+ 03DE 2B DEC HL ; Back one byte +0162+ 03DF 3E D9 LD A,11011001B ; Test byte +0163+ 03E1 46 LD B,(HL) ; Get old contents +0164+ 03E2 77 LD (HL),A ; Load test byte +0165+ 03E3 BE CP (HL) ; RAM there if same +0166+ 03E4 70 LD (HL),B ; Restore old contents +0167+ 03E5 C2 B1 03 JP NZ,MSIZE ; Ask again if no RAM +0168+ 03E8 +0169+ 03E8 2B SETTOP: DEC HL ; Back one byte +0170+ 03E9 11 0C 32 LD DE,STLOOK-1 ; See if enough RAM +0171+ 03EC CD F1 09 CALL CPDEHL ; Compare DE with HL +0172+ 03EF DA B1 03 JP C,MSIZE ; Ask again if not enough RAM +0173+ 03F2 11 CE FF LD DE,0-50 ; 50 Bytes string space +0174+ 03F5 22 5F 31 LD (LSTRAM),HL ; Save last available RAM +0175+ 03F8 19 ADD HL,DE ; Allocate string space +0176+ 03F9 22 0A 31 LD (STRSPC),HL ; Save string space +0177+ 03FC CD 36 08 CALL CLRPTR ; Clear program area +0178+ 03FF 2A 0A 31 LD HL,(STRSPC) ; Get end of memory +0179+ 0402 11 EF FF LD DE,0-17 ; Offset for free bytes +0180+ 0405 19 ADD HL,DE ; Adjust HL +0181+ 0406 11 A9 31 LD DE,PROGST ; Start of program text +0182+ 0409 7D LD A,L ; Get LSB +0183+ 040A 93 SUB E ; Adjust it +0184+ 040B 6F LD L,A ; Re-save +0185+ 040C 7C LD A,H ; Get MSB +0186+ 040D 9A SBC A,D ; Adjust it +0187+ 040E 67 LD H,A ; Re-save +0188+ 040F E5 PUSH HL ; Save bytes free +0189+ 0410 21 38 04 LD HL,SIGNON ; Sign-on message +0190+ 0413 CD C7 14 CALL PRS ; Output string +0191+ 0416 E1 POP HL ; Get bytes free back +0192+ 0417 CD 6A 1B CALL PRNTHL ; Output amount of free memory +0193+ 041A 21 29 04 LD HL,BFREE ; " Bytes free" message +0194+ 041D CD C7 14 CALL PRS ; Output string +0195+ 0420 +0196+ 0420 31 16 31 WARMST: LD SP,STACK ; Temporary stack +0197+ 0423 CD 5B 08 BRKRET: CALL CLREG ; Clear registers and stack +0198+ 0426 C3 74 07 JP PRNTOK ; Go to get command line +0199+ 0429 +0200+ 0429 20 42 79 74 BFREE: .BYTE " Bytes free",CR,LF,0,0 +0200+ 042D 65 73 20 66 +0200+ 0431 72 65 65 0D +0200+ 0435 0A 00 00 +0201+ 0438 +0202+ 0438 5A 38 30 20 SIGNON: .BYTE "Z80 BASIC Ver 4.7b",CR,LF +0202+ 043C 42 41 53 49 +0202+ 0440 43 20 56 65 +0202+ 0444 72 20 34 2E +0202+ 0448 37 62 0D 0A +0203+ 044C 43 6F 70 79 .BYTE "Copyright ",40,"C",41 +0203+ 0450 72 69 67 68 +0203+ 0454 74 20 28 43 +0203+ 0458 29 +0204+ 0459 20 31 39 37 .BYTE " 1978 by Microsoft",CR,LF,0,0 +0204+ 045D 38 20 62 79 +0204+ 0461 20 4D 69 63 +0204+ 0465 72 6F 73 6F +0204+ 0469 66 74 0D 0A +0204+ 046D 00 00 +0205+ 046F +0206+ 046F 4D 65 6D 6F MEMMSG: .BYTE "Memory top",0 +0206+ 0473 72 79 20 74 +0206+ 0477 6F 70 00 +0207+ 047A +0208+ 047A ; FUNCTION ADDRESS TABLE +0209+ 047A +0210+ 047A DF 19 FNCTAB: .WORD SGN +0211+ 047C A3 1A .WORD INT +0212+ 047E F5 19 .WORD ABS +0213+ 0480 B3 30 .WORD USR +0214+ 0482 87 13 .WORD FRE +0215+ 0484 0C 17 .WORD INP +0216+ 0486 B5 13 .WORD POS +0217+ 0488 69 1C .WORD SQR +0218+ 048A 48 1D .WORD RND +0219+ 048C 84 18 .WORD LOG +0220+ 048E B7 1C .WORD EXP +0221+ 0490 BD 1D .WORD COS +0222+ 0492 C3 1D .WORD SIN +0223+ 0494 24 1E .WORD TAN +0224+ 0496 39 1E .WORD ATN +0225+ 0498 60 17 .WORD PEEK +0226+ 049A A4 1E .WORD DEEK +0227+ 049C 01 31 .WORD POINT +0228+ 049E 39 16 .WORD LEN +0229+ 04A0 51 14 .WORD STR +0230+ 04A2 D3 16 .WORD VAL +0231+ 04A4 48 16 .WORD ASC +0232+ 04A6 59 16 .WORD CHR +0233+ 04A8 C6 1E .WORD HEX +0234+ 04AA 59 1F .WORD BIN +0235+ 04AC 69 16 .WORD LEFT +0236+ 04AE 99 16 .WORD RIGHT +0237+ 04B0 A3 16 .WORD MID +0238+ 04B2 +0239+ 04B2 ; RESERVED WORD LIST +0240+ 04B2 +0241+ 04B2 C5 4E 44 WORDS: .BYTE 'E'+80H,"ND" +0242+ 04B5 C6 4F 52 .BYTE 'F'+80H,"OR" +0243+ 04B8 CE 45 58 54 .BYTE 'N'+80H,"EXT" +0244+ 04BC C4 41 54 41 .BYTE 'D'+80H,"ATA" +0245+ 04C0 C9 4E 50 55 .BYTE 'I'+80H,"NPUT" +0245+ 04C4 54 +0246+ 04C5 C4 49 4D .BYTE 'D'+80H,"IM" +0247+ 04C8 D2 45 41 44 .BYTE 'R'+80H,"EAD" +0248+ 04CC CC 45 54 .BYTE 'L'+80H,"ET" +0249+ 04CF C7 4F 54 4F .BYTE 'G'+80H,"OTO" +0250+ 04D3 D2 55 4E .BYTE 'R'+80H,"UN" +0251+ 04D6 C9 46 .BYTE 'I'+80H,"F" +0252+ 04D8 D2 45 53 54 .BYTE 'R'+80H,"ESTORE" +0252+ 04DC 4F 52 45 +0253+ 04DF C7 4F 53 55 .BYTE 'G'+80H,"OSUB" +0253+ 04E3 42 +0254+ 04E4 D2 45 54 55 .BYTE 'R'+80H,"ETURN" +0254+ 04E8 52 4E +0255+ 04EA D2 45 4D .BYTE 'R'+80H,"EM" +0256+ 04ED D3 54 4F 50 .BYTE 'S'+80H,"TOP" +0257+ 04F1 CF 55 54 .BYTE 'O'+80H,"UT" +0258+ 04F4 CF 4E .BYTE 'O'+80H,"N" +0259+ 04F6 CE 55 4C 4C .BYTE 'N'+80H,"ULL" +0260+ 04FA D7 41 49 54 .BYTE 'W'+80H,"AIT" +0261+ 04FE C4 45 46 .BYTE 'D'+80H,"EF" +0262+ 0501 D0 4F 4B 45 .BYTE 'P'+80H,"OKE" +0263+ 0505 C4 4F 4B 45 .BYTE 'D'+80H,"OKE" +0264+ 0509 D3 43 52 45 .BYTE 'S'+80H,"CREEN" +0264+ 050D 45 4E +0265+ 050F CC 49 4E 45 .BYTE 'L'+80H,"INES" +0265+ 0513 53 +0266+ 0514 C3 4C 53 .BYTE 'C'+80H,"LS" +0267+ 0517 D7 49 44 54 .BYTE 'W'+80H,"IDTH" +0267+ 051B 48 +0268+ 051C CD 4F 4E 49 .BYTE 'M'+80H,"ONITOR" +0268+ 0520 54 4F 52 +0269+ 0523 D3 45 54 .BYTE 'S'+80H,"ET" +0270+ 0526 D2 45 53 45 .BYTE 'R'+80H,"ESET" +0270+ 052A 54 +0271+ 052B D0 52 49 4E .BYTE 'P'+80H,"RINT" +0271+ 052F 54 +0272+ 0530 C3 4F 4E 54 .BYTE 'C'+80H,"ONT" +0273+ 0534 CC 49 53 54 .BYTE 'L'+80H,"IST" +0274+ 0538 C3 4C 45 41 .BYTE 'C'+80H,"LEAR" +0274+ 053C 52 +0275+ 053D C3 4C 4F 41 .BYTE 'C'+80H,"LOAD" +0275+ 0541 44 +0276+ 0542 C3 53 41 56 .BYTE 'C'+80H,"SAVE" +0276+ 0546 45 +0277+ 0547 CE 45 57 .BYTE 'N'+80H,"EW" +0278+ 054A +0279+ 054A D4 41 42 28 .BYTE 'T'+80H,"AB(" +0280+ 054E D4 4F .BYTE 'T'+80H,"O" +0281+ 0550 C6 4E .BYTE 'F'+80H,"N" +0282+ 0552 D3 50 43 28 .BYTE 'S'+80H,"PC(" +0283+ 0556 D4 48 45 4E .BYTE 'T'+80H,"HEN" +0284+ 055A CE 4F 54 .BYTE 'N'+80H,"OT" +0285+ 055D D3 54 45 50 .BYTE 'S'+80H,"TEP" +0286+ 0561 +0287+ 0561 AB .BYTE '+'+80H +0288+ 0562 AD .BYTE '-'+80H +0289+ 0563 AA .BYTE '*'+80H +0290+ 0564 AF .BYTE '/'+80H +0291+ 0565 DE .BYTE '^'+80H +0292+ 0566 C1 4E 44 .BYTE 'A'+80H,"ND" +0293+ 0569 CF 52 .BYTE 'O'+80H,"R" +0294+ 056B BE .BYTE '>'+80H +0295+ 056C BD .BYTE '='+80H +0296+ 056D BC .BYTE '<'+80H +0297+ 056E +0298+ 056E D3 47 4E .BYTE 'S'+80H,"GN" +0299+ 0571 C9 4E 54 .BYTE 'I'+80H,"NT" +0300+ 0574 C1 42 53 .BYTE 'A'+80H,"BS" +0301+ 0577 D5 53 52 .BYTE 'U'+80H,"SR" +0302+ 057A C6 52 45 .BYTE 'F'+80H,"RE" +0303+ 057D C9 4E 50 .BYTE 'I'+80H,"NP" +0304+ 0580 D0 4F 53 .BYTE 'P'+80H,"OS" +0305+ 0583 D3 51 52 .BYTE 'S'+80H,"QR" +0306+ 0586 D2 4E 44 .BYTE 'R'+80H,"ND" +0307+ 0589 CC 4F 47 .BYTE 'L'+80H,"OG" +0308+ 058C C5 58 50 .BYTE 'E'+80H,"XP" +0309+ 058F C3 4F 53 .BYTE 'C'+80H,"OS" +0310+ 0592 D3 49 4E .BYTE 'S'+80H,"IN" +0311+ 0595 D4 41 4E .BYTE 'T'+80H,"AN" +0312+ 0598 C1 54 4E .BYTE 'A'+80H,"TN" +0313+ 059B D0 45 45 4B .BYTE 'P'+80H,"EEK" +0314+ 059F C4 45 45 4B .BYTE 'D'+80H,"EEK" +0315+ 05A3 D0 4F 49 4E .BYTE 'P'+80H,"OINT" +0315+ 05A7 54 +0316+ 05A8 CC 45 4E .BYTE 'L'+80H,"EN" +0317+ 05AB D3 54 52 24 .BYTE 'S'+80H,"TR$" +0318+ 05AF D6 41 4C .BYTE 'V'+80H,"AL" +0319+ 05B2 C1 53 43 .BYTE 'A'+80H,"SC" +0320+ 05B5 C3 48 52 24 .BYTE 'C'+80H,"HR$" +0321+ 05B9 C8 45 58 24 .BYTE 'H'+80H,"EX$" +0322+ 05BD C2 49 4E 24 .BYTE 'B'+80H,"IN$" +0323+ 05C1 CC 45 46 54 .BYTE 'L'+80H,"EFT$" +0323+ 05C5 24 +0324+ 05C6 D2 49 47 48 .BYTE 'R'+80H,"IGHT$" +0324+ 05CA 54 24 +0325+ 05CC CD 49 44 24 .BYTE 'M'+80H,"ID$" +0326+ 05D0 80 .BYTE 80H ; End of list marker +0327+ 05D1 +0328+ 05D1 ; KEYWORD ADDRESS TABLE +0329+ 05D1 +0330+ 05D1 CB 0B WORDTB: .WORD PEND +0331+ 05D3 C8 0A .WORD FOR +0332+ 05D5 A3 0F .WORD NEXT +0333+ 05D7 18 0D .WORD DATA +0334+ 05D9 AA 0E .WORD INPUT +0335+ 05DB DF 11 .WORD DIM +0336+ 05DD D9 0E .WORD READ +0337+ 05DF 2F 0D .WORD LET +0338+ 05E1 D5 0C .WORD GOTO +0339+ 05E3 B8 0C .WORD RUN +0340+ 05E5 A7 0D .WORD IF +0341+ 05E7 91 0B .WORD RESTOR +0342+ 05E9 C4 0C .WORD GOSUB +0343+ 05EB F3 0C .WORD RETURN +0344+ 05ED 1A 0D .WORD REM +0345+ 05EF C9 0B .WORD STOP +0346+ 05F1 18 17 .WORD POUT +0347+ 05F3 89 0D .WORD ON +0348+ 05F5 0A 0C .WORD NULL +0349+ 05F7 1E 17 .WORD WAIT +0350+ 05F9 BD 13 .WORD DEF +0351+ 05FB 67 17 .WORD POKE +0352+ 05FD AF 1E .WORD DOKE +0353+ 05FF 1A 0D .WORD REM +0354+ 0601 95 1E .WORD LINES +0355+ 0603 88 1E .WORD CLS +0356+ 0605 8D 1E .WORD WIDTH +0357+ 0607 C5 1F .WORD MONITR +0358+ 0609 04 31 .WORD PSET +0359+ 060B 07 31 .WORD RESET +0360+ 060D CB 0D .WORD PRINT +0361+ 060F F7 0B .WORD CONT +0362+ 0611 3D 0A .WORD LIST +0363+ 0613 72 0C .WORD CLEAR +0364+ 0615 1A 0D .WORD REM +0365+ 0617 1A 0D .WORD REM +0366+ 0619 35 08 .WORD NEW +0367+ 061B +0368+ 061B ; RESERVED WORD TOKEN VALUES +0369+ 061B +0370+ 061B ZEND .EQU 080H ; END +0371+ 061B ZFOR .EQU 081H ; FOR +0372+ 061B ZDATA .EQU 083H ; DATA +0373+ 061B ZGOTO .EQU 088H ; GOTO +0374+ 061B ZGOSUB .EQU 08CH ; GOSUB +0375+ 061B ZREM .EQU 08EH ; REM +0376+ 061B ZPRINT .EQU 09EH ; PRINT +0377+ 061B ZNEW .EQU 0A4H ; NEW +0378+ 061B +0379+ 061B ZTAB .EQU 0A5H ; TAB +0380+ 061B ZTO .EQU 0A6H ; TO +0381+ 061B ZFN .EQU 0A7H ; FN +0382+ 061B ZSPC .EQU 0A8H ; SPC +0383+ 061B ZTHEN .EQU 0A9H ; THEN +0384+ 061B ZNOT .EQU 0AAH ; NOT +0385+ 061B ZSTEP .EQU 0ABH ; STEP +0386+ 061B +0387+ 061B ZPLUS .EQU 0ACH ; + +0388+ 061B ZMINUS .EQU 0ADH ; - +0389+ 061B ZTIMES .EQU 0AEH ; * +0390+ 061B ZDIV .EQU 0AFH ; / +0391+ 061B ZOR .EQU 0B2H ; OR +0392+ 061B ZGTR .EQU 0B3H ; > +0393+ 061B ZEQUAL .EQU 0B4H ; M +0394+ 061B ZLTH .EQU 0B5H ; < +0395+ 061B ZSGN .EQU 0B6H ; SGN +0396+ 061B ZPOINT .EQU 0C7H ; POINT +0397+ 061B ZLEFT .EQU 0CDH +2 ; LEFT$ +0398+ 061B +0399+ 061B ; ARITHMETIC PRECEDENCE TABLE +0400+ 061B +0401+ 061B 79 PRITAB: .BYTE 79H ; Precedence value +0402+ 061C 51 1B .WORD PADD ; FPREG = + FPREG +0403+ 061E +0404+ 061E 79 .BYTE 79H ; Precedence value +0405+ 061F 85 17 .WORD PSUB ; FPREG = - FPREG +0406+ 0621 +0407+ 0621 7C .BYTE 7CH ; Precedence value +0408+ 0622 C3 18 .WORD MULT ; PPREG = * FPREG +0409+ 0624 +0410+ 0624 7C .BYTE 7CH ; Precedence value +0411+ 0625 24 19 .WORD DIV ; FPREG = / FPREG +0412+ 0627 +0413+ 0627 7F .BYTE 7FH ; Precedence value +0414+ 0628 72 1C .WORD POWER ; FPREG = ^ FPREG +0415+ 062A +0416+ 062A 50 .BYTE 50H ; Precedence value +0417+ 062B 38 11 .WORD PAND ; FPREG = AND FPREG +0418+ 062D +0419+ 062D 46 .BYTE 46H ; Precedence value +0420+ 062E 37 11 .WORD POR ; FPREG = OR FPREG +0421+ 0630 +0422+ 0630 ; BASIC ERROR CODE LIST +0423+ 0630 +0424+ 0630 4E 46 ERRORS: .BYTE "NF" ; NEXT without FOR +0425+ 0632 53 4E .BYTE "SN" ; Syntax error +0426+ 0634 52 47 .BYTE "RG" ; RETURN without GOSUB +0427+ 0636 4F 44 .BYTE "OD" ; Out of DATA +0428+ 0638 46 43 .BYTE "FC" ; Illegal function call +0429+ 063A 4F 56 .BYTE "OV" ; Overflow error +0430+ 063C 4F 4D .BYTE "OM" ; Out of memory +0431+ 063E 55 4C .BYTE "UL" ; Undefined line +0432+ 0640 42 53 .BYTE "BS" ; Bad subscript +0433+ 0642 44 44 .BYTE "DD" ; Re-DIMensioned array +0434+ 0644 2F 30 .BYTE "/0" ; Division by zero +0435+ 0646 49 44 .BYTE "ID" ; Illegal direct +0436+ 0648 54 4D .BYTE "TM" ; Type mis-match +0437+ 064A 4F 53 .BYTE "OS" ; Out of string space +0438+ 064C 4C 53 .BYTE "LS" ; String too long +0439+ 064E 53 54 .BYTE "ST" ; String formula too complex +0440+ 0650 43 4E .BYTE "CN" ; Can't CONTinue +0441+ 0652 55 46 .BYTE "UF" ; Undefined FN function +0442+ 0654 4D 4F .BYTE "MO" ; Missing operand +0443+ 0656 48 58 .BYTE "HX" ; HEX error +0444+ 0658 42 4E .BYTE "BN" ; BIN error +0445+ 065A +0446+ 065A ; INITIALISATION TABLE ------------------------------------------------------- +0447+ 065A +0448+ 065A C3 20 04 INITAB: JP WARMST ; Warm start jump +0449+ 065D C3 48 0C JP FCERR ; "USR (X)" jump (Set to Error) +0450+ 0660 D3 00 OUT (0),A ; "OUT p,n" skeleton +0451+ 0662 C9 RET +0452+ 0663 D6 00 SUB 0 ; Division support routine +0453+ 0665 6F LD L,A +0454+ 0666 7C LD A,H +0455+ 0667 DE 00 SBC A,0 +0456+ 0669 67 LD H,A +0457+ 066A 78 LD A,B +0458+ 066B DE 00 SBC A,0 +0459+ 066D 47 LD B,A +0460+ 066E 3E 00 LD A,0 +0461+ 0670 C9 RET +0462+ 0671 00 00 00 .BYTE 0,0,0 ; Random number seed table used by RND +0463+ 0674 35 4A CA 99 .BYTE 035H,04AH,0CAH,099H ;-2.65145E+07 +0464+ 0678 39 1C 76 98 .BYTE 039H,01CH,076H,098H ; 1.61291E+07 +0465+ 067C 22 95 B3 98 .BYTE 022H,095H,0B3H,098H ;-1.17691E+07 +0466+ 0680 0A DD 47 98 .BYTE 00AH,0DDH,047H,098H ; 1.30983E+07 +0467+ 0684 53 D1 99 99 .BYTE 053H,0D1H,099H,099H ;-2-01612E+07 +0468+ 0688 0A 1A 9F 98 .BYTE 00AH,01AH,09FH,098H ;-1.04269E+07 +0469+ 068C 65 BC CD 98 .BYTE 065H,0BCH,0CDH,098H ;-1.34831E+07 +0470+ 0690 D6 77 3E 98 .BYTE 0D6H,077H,03EH,098H ; 1.24825E+07 +0471+ 0694 52 C7 4F 80 .BYTE 052H,0C7H,04FH,080H ; Last random number +0472+ 0698 DB 00 IN A,(0) ; INP (x) skeleton +0473+ 069A C9 RET +0474+ 069B 01 .BYTE 1 ; POS (x) number (1) +0475+ 069C FF .BYTE 255 ; Terminal width (255 = no auto CRLF) +0476+ 069D 1C .BYTE 28 ; Width for commas (3 columns) +0477+ 069E 00 .BYTE 0 ; No nulls after input bytes +0478+ 069F 00 .BYTE 0 ; Output enabled (^O off) +0479+ 06A0 14 00 .WORD 20 ; Initial lines counter +0480+ 06A2 14 00 .WORD 20 ; Initial lines number +0481+ 06A4 00 00 .WORD 0 ; Array load/save check sum +0482+ 06A6 00 .BYTE 0 ; Break not by NMI +0483+ 06A7 00 .BYTE 0 ; Break flag +0484+ 06A8 C3 6E 09 JP TTYLIN ; Input reflection (set to TTY) +0485+ 06AB C3 00 00 JP $0000 ; POINT reflection unused +0486+ 06AE C3 00 00 JP $0000 ; SET reflection +0487+ 06B1 C3 00 00 JP $0000 ; RESET reflection +0488+ 06B4 0D 32 .WORD STLOOK ; Temp string space +0489+ 06B6 FE FF .WORD -2 ; Current line number (cold) +0490+ 06B8 AA 31 .WORD PROGST+1 ; Start of program text +0491+ 06BA INITBE: +0492+ 06BA +0493+ 06BA ; END OF INITIALISATION TABLE --------------------------------------------------- +0494+ 06BA +0495+ 06BA 20 45 72 72 ERRMSG: .BYTE " Error",0 +0495+ 06BE 6F 72 00 +0496+ 06C1 20 69 6E 20 INMSG: .BYTE " in ",0 +0496+ 06C5 00 +0497+ 06C6 ZERBYT .EQU $-1 ; A zero byte +0498+ 06C6 4F 6B 0D 0A OKMSG: .BYTE "Ok",CR,LF,0,0 +0498+ 06CA 00 00 +0499+ 06CC 42 72 65 61 BRKMSG: .BYTE "Break",0 +0499+ 06D0 6B 00 +0500+ 06D2 +0501+ 06D2 21 04 00 BAKSTK: LD HL,4 ; Look for "FOR" block with +0502+ 06D5 39 ADD HL,SP ; same index as specified +0503+ 06D6 7E LOKFOR: LD A,(HL) ; Get block ID +0504+ 06D7 23 INC HL ; Point to index address +0505+ 06D8 FE 81 CP ZFOR ; Is it a "FOR" token +0506+ 06DA C0 RET NZ ; No - exit +0507+ 06DB 4E LD C,(HL) ; BC = Address of "FOR" index +0508+ 06DC 23 INC HL +0509+ 06DD 46 LD B,(HL) +0510+ 06DE 23 INC HL ; Point to sign of STEP +0511+ 06DF E5 PUSH HL ; Save pointer to sign +0512+ 06E0 69 LD L,C ; HL = address of "FOR" index +0513+ 06E1 60 LD H,B +0514+ 06E2 7A LD A,D ; See if an index was specified +0515+ 06E3 B3 OR E ; DE = 0 if no index specified +0516+ 06E4 EB EX DE,HL ; Specified index into HL +0517+ 06E5 CA EC 06 JP Z,INDFND ; Skip if no index given +0518+ 06E8 EB EX DE,HL ; Index back into DE +0519+ 06E9 CD F1 09 CALL CPDEHL ; Compare index with one given +0520+ 06EC 01 0D 00 INDFND: LD BC,16-3 ; Offset to next block +0521+ 06EF E1 POP HL ; Restore pointer to sign +0522+ 06F0 C8 RET Z ; Return if block found +0523+ 06F1 09 ADD HL,BC ; Point to next block +0524+ 06F2 C3 D6 06 JP LOKFOR ; Keep on looking +0525+ 06F5 +0526+ 06F5 CD 0F 07 MOVUP: CALL ENFMEM ; See if enough memory +0527+ 06F8 C5 MOVSTR: PUSH BC ; Save end of source +0528+ 06F9 E3 EX (SP),HL ; Swap source and dest" end +0529+ 06FA C1 POP BC ; Get end of destination +0530+ 06FB CD F1 09 MOVLP: CALL CPDEHL ; See if list moved +0531+ 06FE 7E LD A,(HL) ; Get byte +0532+ 06FF 02 LD (BC),A ; Move it +0533+ 0700 C8 RET Z ; Exit if all done +0534+ 0701 0B DEC BC ; Next byte to move to +0535+ 0702 2B DEC HL ; Next byte to move +0536+ 0703 C3 FB 06 JP MOVLP ; Loop until all bytes moved +0537+ 0706 +0538+ 0706 E5 CHKSTK: PUSH HL ; Save code string address +0539+ 0707 2A 8A 31 LD HL,(ARREND) ; Lowest free memory +0540+ 070A 06 00 LD B,0 ; BC = Number of levels to test +0541+ 070C 09 ADD HL,BC ; 2 Bytes for each level +0542+ 070D 09 ADD HL,BC +0543+ 070E 3E .BYTE 3EH ; Skip "PUSH HL" +0544+ 070F E5 ENFMEM: PUSH HL ; Save code string address +0545+ 0710 3E D0 LD A,0D0H ;LOW -48 ; 48 Bytes minimum RAM +0546+ 0712 95 SUB L +0547+ 0713 6F LD L,A +0548+ 0714 3E FF LD A,0FFH; HIGH (-48) ; 48 Bytes minimum RAM +0549+ 0716 9C SBC A,H +0550+ 0717 DA 1E 07 JP C,OMERR ; Not enough - ?OM Error +0551+ 071A 67 LD H,A +0552+ 071B 39 ADD HL,SP ; Test if stack is overflowed +0553+ 071C E1 POP HL ; Restore code string address +0554+ 071D D8 RET C ; Return if enough mmory +0555+ 071E 1E 0C OMERR: LD E,OM ; ?OM Error +0556+ 0720 C3 3D 07 JP ERROR +0557+ 0723 +0558+ 0723 2A 79 31 DATSNR: LD HL,(DATLIN) ; Get line of current DATA item +0559+ 0726 22 0C 31 LD (LINEAT),HL ; Save as current line +0560+ 0729 1E 02 SNERR: LD E,SN ; ?SN Error +0561+ 072B 01 .BYTE 01H ; Skip "LD E,DZ" +0562+ 072C 1E 14 DZERR: LD E,DZ ; ?/0 Error +0563+ 072E 01 .BYTE 01H ; Skip "LD E,NF" +0564+ 072F 1E 00 NFERR: LD E,NF ; ?NF Error +0565+ 0731 01 .BYTE 01H ; Skip "LD E,DD" +0566+ 0732 1E 12 DDERR: LD E,DD ; ?DD Error +0567+ 0734 01 .BYTE 01H ; Skip "LD E,UF" +0568+ 0735 1E 22 UFERR: LD E,UF ; ?UF Error +0569+ 0737 01 .BYTE 01H ; Skip "LD E,OV +0570+ 0738 1E 0A OVERR: LD E,OV ; ?OV Error +0571+ 073A 01 .BYTE 01H ; Skip "LD E,TM" +0572+ 073B 1E 18 TMERR: LD E,TM ; ?TM Error +0573+ 073D +0574+ 073D CD 5B 08 ERROR: CALL CLREG ; Clear registers and stack +0575+ 0740 32 F5 30 LD (CTLOFG),A ; Enable output (A is 0) +0576+ 0743 CD 1C 0E CALL STTLIN ; Start new line +0577+ 0746 21 30 06 LD HL,ERRORS ; Point to error codes +0578+ 0749 57 LD D,A ; D = 0 (A is 0) +0579+ 074A 3E 3F LD A,'?' +0580+ 074C CD 02 0A CALL OUTC ; Output '?' +0581+ 074F 19 ADD HL,DE ; Offset to correct error code +0582+ 0750 7E LD A,(HL) ; First character +0583+ 0751 CD 02 0A CALL OUTC ; Output it +0584+ 0754 CD 81 0B CALL GETCHR ; Get next character +0585+ 0757 CD 02 0A CALL OUTC ; Output it +0586+ 075A 21 BA 06 LD HL,ERRMSG ; "Error" message +0587+ 075D CD C7 14 ERRIN: CALL PRS ; Output message +0588+ 0760 2A 0C 31 LD HL,(LINEAT) ; Get line of error +0589+ 0763 11 FE FF LD DE,-2 ; Cold start error if -2 +0590+ 0766 CD F1 09 CALL CPDEHL ; See if cold start error +0591+ 0769 CA 8D 03 JP Z,CSTART ; Cold start error - Restart +0592+ 076C 7C LD A,H ; Was it a direct error? +0593+ 076D A5 AND L ; Line = -1 if direct error +0594+ 076E 3C INC A +0595+ 076F C4 62 1B CALL NZ,LINEIN ; No - output line of error +0596+ 0772 3E .BYTE 3EH ; Skip "POP BC" +0597+ 0773 C1 POPNOK: POP BC ; Drop address in input buffer +0598+ 0774 +0599+ 0774 AF PRNTOK: XOR A ; Output "Ok" and get command +0600+ 0775 32 F5 30 LD (CTLOFG),A ; Enable output +0601+ 0778 CD 1C 0E CALL STTLIN ; Start new line +0602+ 077B 21 C6 06 LD HL,OKMSG ; "Ok" message +0603+ 077E CD C7 14 CALL PRS ; Output "Ok" +0604+ 0781 21 FF FF GETCMD: LD HL,-1 ; Flag direct mode +0605+ 0784 22 0C 31 LD (LINEAT),HL ; Save as current line +0606+ 0787 CD 6E 09 CALL GETLIN ; Get an input line +0607+ 078A DA 81 07 JP C,GETCMD ; Get line again if break +0608+ 078D CD 81 0B CALL GETCHR ; Get first character +0609+ 0790 3C INC A ; Test if end of line +0610+ 0791 3D DEC A ; Without affecting Carry +0611+ 0792 CA 81 07 JP Z,GETCMD ; Nothing entered - Get another +0612+ 0795 F5 PUSH AF ; Save Carry status +0613+ 0796 CD 4D 0C CALL ATOH ; Get line number into DE +0614+ 0799 D5 PUSH DE ; Save line number +0615+ 079A CD 85 08 CALL CRUNCH ; Tokenise rest of line +0616+ 079D 47 LD B,A ; Length of tokenised line +0617+ 079E D1 POP DE ; Restore line number +0618+ 079F F1 POP AF ; Restore Carry +0619+ 07A0 D2 61 0B JP NC,EXCUTE ; No line number - Direct mode +0620+ 07A3 D5 PUSH DE ; Save line number +0621+ 07A4 C5 PUSH BC ; Save length of tokenised line +0622+ 07A5 AF XOR A +0623+ 07A6 32 7C 31 LD (LSTBIN),A ; Clear last byte input +0624+ 07A9 CD 81 0B CALL GETCHR ; Get next character +0625+ 07AC B7 OR A ; Set flags +0626+ 07AD F5 PUSH AF ; And save them +0627+ 07AE CD 15 08 CALL SRCHLN ; Search for line number in DE +0628+ 07B1 DA BA 07 JP C,LINFND ; Jump if line found +0629+ 07B4 F1 POP AF ; Get status +0630+ 07B5 F5 PUSH AF ; And re-save +0631+ 07B6 CA EE 0C JP Z,ULERR ; Nothing after number - Error +0632+ 07B9 B7 OR A ; Clear Carry +0633+ 07BA C5 LINFND: PUSH BC ; Save address of line in prog +0634+ 07BB D2 D1 07 JP NC,INEWLN ; Line not found - Insert new +0635+ 07BE EB EX DE,HL ; Next line address in DE +0636+ 07BF 2A 86 31 LD HL,(PROGND) ; End of program +0637+ 07C2 1A SFTPRG: LD A,(DE) ; Shift rest of program down +0638+ 07C3 02 LD (BC),A +0639+ 07C4 03 INC BC ; Next destination +0640+ 07C5 13 INC DE ; Next source +0641+ 07C6 CD F1 09 CALL CPDEHL ; All done? +0642+ 07C9 C2 C2 07 JP NZ,SFTPRG ; More to do +0643+ 07CC 60 LD H,B ; HL - New end of program +0644+ 07CD 69 LD L,C +0645+ 07CE 22 86 31 LD (PROGND),HL ; Update end of program +0646+ 07D1 +0647+ 07D1 D1 INEWLN: POP DE ; Get address of line, +0648+ 07D2 F1 POP AF ; Get status +0649+ 07D3 CA F8 07 JP Z,SETPTR ; No text - Set up pointers +0650+ 07D6 2A 86 31 LD HL,(PROGND) ; Get end of program +0651+ 07D9 E3 EX (SP),HL ; Get length of input line +0652+ 07DA C1 POP BC ; End of program to BC +0653+ 07DB 09 ADD HL,BC ; Find new end +0654+ 07DC E5 PUSH HL ; Save new end +0655+ 07DD CD F5 06 CALL MOVUP ; Make space for line +0656+ 07E0 E1 POP HL ; Restore new end +0657+ 07E1 22 86 31 LD (PROGND),HL ; Update end of program pointer +0658+ 07E4 EB EX DE,HL ; Get line to move up in HL +0659+ 07E5 74 LD (HL),H ; Save MSB +0660+ 07E6 D1 POP DE ; Get new line number +0661+ 07E7 23 INC HL ; Skip pointer +0662+ 07E8 23 INC HL +0663+ 07E9 73 LD (HL),E ; Save LSB of line number +0664+ 07EA 23 INC HL +0665+ 07EB 72 LD (HL),D ; Save MSB of line number +0666+ 07EC 23 INC HL ; To first byte in line +0667+ 07ED 11 11 31 LD DE,BUFFER ; Copy buffer to program +0668+ 07F0 1A MOVBUF: LD A,(DE) ; Get source +0669+ 07F1 77 LD (HL),A ; Save destinations +0670+ 07F2 23 INC HL ; Next source +0671+ 07F3 13 INC DE ; Next destination +0672+ 07F4 B7 OR A ; Done? +0673+ 07F5 C2 F0 07 JP NZ,MOVBUF ; No - Repeat +0674+ 07F8 CD 41 08 SETPTR: CALL RUNFST ; Set line pointers +0675+ 07FB 23 INC HL ; To LSB of pointer +0676+ 07FC EB EX DE,HL ; Address to DE +0677+ 07FD 62 PTRLP: LD H,D ; Address to HL +0678+ 07FE 6B LD L,E +0679+ 07FF 7E LD A,(HL) ; Get LSB of pointer +0680+ 0800 23 INC HL ; To MSB of pointer +0681+ 0801 B6 OR (HL) ; Compare with MSB pointer +0682+ 0802 CA 81 07 JP Z,GETCMD ; Get command line if end +0683+ 0805 23 INC HL ; To LSB of line number +0684+ 0806 23 INC HL ; Skip line number +0685+ 0807 23 INC HL ; Point to first byte in line +0686+ 0808 AF XOR A ; Looking for 00 byte +0687+ 0809 BE FNDEND: CP (HL) ; Found end of line? +0688+ 080A 23 INC HL ; Move to next byte +0689+ 080B C2 09 08 JP NZ,FNDEND ; No - Keep looking +0690+ 080E EB EX DE,HL ; Next line address to HL +0691+ 080F 73 LD (HL),E ; Save LSB of pointer +0692+ 0810 23 INC HL +0693+ 0811 72 LD (HL),D ; Save MSB of pointer +0694+ 0812 C3 FD 07 JP PTRLP ; Do next line +0695+ 0815 +0696+ 0815 2A 0E 31 SRCHLN: LD HL,(BASTXT) ; Start of program text +0697+ 0818 44 SRCHLP: LD B,H ; BC = Address to look at +0698+ 0819 4D LD C,L +0699+ 081A 7E LD A,(HL) ; Get address of next line +0700+ 081B 23 INC HL +0701+ 081C B6 OR (HL) ; End of program found? +0702+ 081D 2B DEC HL +0703+ 081E C8 RET Z ; Yes - Line not found +0704+ 081F 23 INC HL +0705+ 0820 23 INC HL +0706+ 0821 7E LD A,(HL) ; Get LSB of line number +0707+ 0822 23 INC HL +0708+ 0823 66 LD H,(HL) ; Get MSB of line number +0709+ 0824 6F LD L,A +0710+ 0825 CD F1 09 CALL CPDEHL ; Compare with line in DE +0711+ 0828 60 LD H,B ; HL = Start of this line +0712+ 0829 69 LD L,C +0713+ 082A 7E LD A,(HL) ; Get LSB of next line address +0714+ 082B 23 INC HL +0715+ 082C 66 LD H,(HL) ; Get MSB of next line address +0716+ 082D 6F LD L,A ; Next line to HL +0717+ 082E 3F CCF +0718+ 082F C8 RET Z ; Lines found - Exit +0719+ 0830 3F CCF +0720+ 0831 D0 RET NC ; Line not found,at line after +0721+ 0832 C3 18 08 JP SRCHLP ; Keep looking +0722+ 0835 +0723+ 0835 C0 NEW: RET NZ ; Return if any more on line +0724+ 0836 2A 0E 31 CLRPTR: LD HL,(BASTXT) ; Point to start of program +0725+ 0839 AF XOR A ; Set program area to empty +0726+ 083A 77 LD (HL),A ; Save LSB = 00 +0727+ 083B 23 INC HL +0728+ 083C 77 LD (HL),A ; Save MSB = 00 +0729+ 083D 23 INC HL +0730+ 083E 22 86 31 LD (PROGND),HL ; Set program end +0731+ 0841 +0732+ 0841 2A 0E 31 RUNFST: LD HL,(BASTXT) ; Clear all variables +0733+ 0844 2B DEC HL +0734+ 0845 +0735+ 0845 22 7E 31 INTVAR: LD (BRKLIN),HL ; Initialise RUN variables +0736+ 0848 2A 5F 31 LD HL,(LSTRAM) ; Get end of RAM +0737+ 084B 22 73 31 LD (STRBOT),HL ; Clear string space +0738+ 084E AF XOR A +0739+ 084F CD 91 0B CALL RESTOR ; Reset DATA pointers +0740+ 0852 2A 86 31 LD HL,(PROGND) ; Get end of program +0741+ 0855 22 88 31 LD (VAREND),HL ; Clear variables +0742+ 0858 22 8A 31 LD (ARREND),HL ; Clear arrays +0743+ 085B +0744+ 085B C1 CLREG: POP BC ; Save return address +0745+ 085C 2A 0A 31 LD HL,(STRSPC) ; Get end of working RAN +0746+ 085F F9 LD SP,HL ; Set stack +0747+ 0860 21 63 31 LD HL,TMSTPL ; Temporary string pool +0748+ 0863 22 61 31 LD (TMSTPT),HL ; Reset temporary string ptr +0749+ 0866 AF XOR A ; A = 00 +0750+ 0867 6F LD L,A ; HL = 0000 +0751+ 0868 67 LD H,A +0752+ 0869 22 84 31 LD (CONTAD),HL ; No CONTinue +0753+ 086C 32 7B 31 LD (FORFLG),A ; Clear FOR flag +0754+ 086F 22 8E 31 LD (FNRGNM),HL ; Clear FN argument +0755+ 0872 E5 PUSH HL ; HL = 0000 +0756+ 0873 C5 PUSH BC ; Put back return +0757+ 0874 2A 7E 31 DOAGN: LD HL,(BRKLIN) ; Get address of code to RUN +0758+ 0877 C9 RET ; Return to execution driver +0759+ 0878 +0760+ 0878 3E 3F PROMPT: LD A,'?' ; '?' +0761+ 087A CD 02 0A CALL OUTC ; Output character +0762+ 087D 3E 20 LD A,' ' ; Space +0763+ 087F CD 02 0A CALL OUTC ; Output character +0764+ 0882 C3 FE 30 JP RINPUT ; Get input line +0765+ 0885 +0766+ 0885 AF CRUNCH: XOR A ; Tokenise line @ HL to BUFFER +0767+ 0886 32 5E 31 LD (DATFLG),A ; Reset literal flag +0768+ 0889 0E 05 LD C,2+3 ; 2 byte number and 3 nulls +0769+ 088B 11 11 31 LD DE,BUFFER ; Start of input buffer +0770+ 088E 7E CRNCLP: LD A,(HL) ; Get byte +0771+ 088F FE 20 CP ' ' ; Is it a space? +0772+ 0891 CA 0D 09 JP Z,MOVDIR ; Yes - Copy direct +0773+ 0894 47 LD B,A ; Save character +0774+ 0895 FE 22 CP '"' ; Is it a quote? +0775+ 0897 CA 2D 09 JP Z,CPYLIT ; Yes - Copy literal string +0776+ 089A B7 OR A ; Is it end of buffer? +0777+ 089B CA 34 09 JP Z,ENDBUF ; Yes - End buffer +0778+ 089E 3A 5E 31 LD A,(DATFLG) ; Get data type +0779+ 08A1 B7 OR A ; Literal? +0780+ 08A2 7E LD A,(HL) ; Get byte to copy +0781+ 08A3 C2 0D 09 JP NZ,MOVDIR ; Literal - Copy direct +0782+ 08A6 FE 3F CP '?' ; Is it '?' short for PRINT +0783+ 08A8 3E 9E LD A,ZPRINT ; "PRINT" token +0784+ 08AA CA 0D 09 JP Z,MOVDIR ; Yes - replace it +0785+ 08AD 7E LD A,(HL) ; Get byte again +0786+ 08AE FE 30 CP '0' ; Is it less than '0' +0787+ 08B0 DA B8 08 JP C,FNDWRD ; Yes - Look for reserved words +0788+ 08B3 FE 3C CP 60; ";"+1 ; Is it "0123456789:;" ? +0789+ 08B5 DA 0D 09 JP C,MOVDIR ; Yes - copy it direct +0790+ 08B8 D5 FNDWRD: PUSH DE ; Look for reserved words +0791+ 08B9 11 B1 04 LD DE,WORDS-1 ; Point to table +0792+ 08BC C5 PUSH BC ; Save count +0793+ 08BD 01 09 09 LD BC,RETNAD ; Where to return to +0794+ 08C0 C5 PUSH BC ; Save return address +0795+ 08C1 06 7F LD B,ZEND-1 ; First token value -1 +0796+ 08C3 7E LD A,(HL) ; Get byte +0797+ 08C4 FE 61 CP 'a' ; Less than 'a' ? +0798+ 08C6 DA D1 08 JP C,SEARCH ; Yes - search for words +0799+ 08C9 FE 7B CP 'z'+1 ; Greater than 'z' ? +0800+ 08CB D2 D1 08 JP NC,SEARCH ; Yes - search for words +0801+ 08CE E6 5F AND 01011111B ; Force upper case +0802+ 08D0 77 LD (HL),A ; Replace byte +0803+ 08D1 4E SEARCH: LD C,(HL) ; Search for a word +0804+ 08D2 EB EX DE,HL +0805+ 08D3 23 GETNXT: INC HL ; Get next reserved word +0806+ 08D4 B6 OR (HL) ; Start of word? +0807+ 08D5 F2 D3 08 JP P,GETNXT ; No - move on +0808+ 08D8 04 INC B ; Increment token value +0809+ 08D9 7E LD A, (HL) ; Get byte from table +0810+ 08DA E6 7F AND 01111111B ; Strip bit 7 +0811+ 08DC C8 RET Z ; Return if end of list +0812+ 08DD B9 CP C ; Same character as in buffer? +0813+ 08DE C2 D3 08 JP NZ,GETNXT ; No - get next word +0814+ 08E1 EB EX DE,HL +0815+ 08E2 E5 PUSH HL ; Save start of word +0816+ 08E3 +0817+ 08E3 13 NXTBYT: INC DE ; Look through rest of word +0818+ 08E4 1A LD A,(DE) ; Get byte from table +0819+ 08E5 B7 OR A ; End of word ? +0820+ 08E6 FA 05 09 JP M,MATCH ; Yes - Match found +0821+ 08E9 4F LD C,A ; Save it +0822+ 08EA 78 LD A,B ; Get token value +0823+ 08EB FE 88 CP ZGOTO ; Is it "GOTO" token ? +0824+ 08ED C2 F4 08 JP NZ,NOSPC ; No - Don't allow spaces +0825+ 08F0 CD 81 0B CALL GETCHR ; Get next character +0826+ 08F3 2B DEC HL ; Cancel increment from GETCHR +0827+ 08F4 23 NOSPC: INC HL ; Next byte +0828+ 08F5 7E LD A,(HL) ; Get byte +0829+ 08F6 FE 61 CP 'a' ; Less than 'a' ? +0830+ 08F8 DA FD 08 JP C,NOCHNG ; Yes - don't change +0831+ 08FB E6 5F AND 01011111B ; Make upper case +0832+ 08FD B9 NOCHNG: CP C ; Same as in buffer ? +0833+ 08FE CA E3 08 JP Z,NXTBYT ; Yes - keep testing +0834+ 0901 E1 POP HL ; Get back start of word +0835+ 0902 C3 D1 08 JP SEARCH ; Look at next word +0836+ 0905 +0837+ 0905 48 MATCH: LD C,B ; Word found - Save token value +0838+ 0906 F1 POP AF ; Throw away return +0839+ 0907 EB EX DE,HL +0840+ 0908 C9 RET ; Return to "RETNAD" +0841+ 0909 EB RETNAD: EX DE,HL ; Get address in string +0842+ 090A 79 LD A,C ; Get token value +0843+ 090B C1 POP BC ; Restore buffer length +0844+ 090C D1 POP DE ; Get destination address +0845+ 090D 23 MOVDIR: INC HL ; Next source in buffer +0846+ 090E 12 LD (DE),A ; Put byte in buffer +0847+ 090F 13 INC DE ; Move up buffer +0848+ 0910 0C INC C ; Increment length of buffer +0849+ 0911 D6 3A SUB ':' ; End of statement? +0850+ 0913 CA 1B 09 JP Z,SETLIT ; Jump if multi-statement line +0851+ 0916 FE 49 CP ZDATA-3AH ; Is it DATA statement ? +0852+ 0918 C2 1E 09 JP NZ,TSTREM ; No - see if REM +0853+ 091B 32 5E 31 SETLIT: LD (DATFLG),A ; Set literal flag +0854+ 091E D6 54 TSTREM: SUB ZREM-3AH ; Is it REM? +0855+ 0920 C2 8E 08 JP NZ,CRNCLP ; No - Leave flag +0856+ 0923 47 LD B,A ; Copy rest of buffer +0857+ 0924 7E NXTCHR: LD A,(HL) ; Get byte +0858+ 0925 B7 OR A ; End of line ? +0859+ 0926 CA 34 09 JP Z,ENDBUF ; Yes - Terminate buffer +0860+ 0929 B8 CP B ; End of statement ? +0861+ 092A CA 0D 09 JP Z,MOVDIR ; Yes - Get next one +0862+ 092D 23 CPYLIT: INC HL ; Move up source string +0863+ 092E 12 LD (DE),A ; Save in destination +0864+ 092F 0C INC C ; Increment length +0865+ 0930 13 INC DE ; Move up destination +0866+ 0931 C3 24 09 JP NXTCHR ; Repeat +0867+ 0934 +0868+ 0934 21 10 31 ENDBUF: LD HL,BUFFER-1 ; Point to start of buffer +0869+ 0937 12 LD (DE),A ; Mark end of buffer (A = 00) +0870+ 0938 13 INC DE +0871+ 0939 12 LD (DE),A ; A = 00 +0872+ 093A 13 INC DE +0873+ 093B 12 LD (DE),A ; A = 00 +0874+ 093C C9 RET +0875+ 093D +0876+ 093D 3A F4 30 DODEL: LD A,(NULFLG) ; Get null flag status +0877+ 0940 B7 OR A ; Is it zero? +0878+ 0941 3E 00 LD A,0 ; Zero A - Leave flags +0879+ 0943 32 F4 30 LD (NULFLG),A ; Zero null flag +0880+ 0946 C2 51 09 JP NZ,ECHDEL ; Set - Echo it +0881+ 0949 05 DEC B ; Decrement length +0882+ 094A CA 6E 09 JP Z,GETLIN ; Get line again if empty +0883+ 094D CD 02 0A CALL OUTC ; Output null character +0884+ 0950 3E .BYTE 3EH ; Skip "DEC B" +0885+ 0951 05 ECHDEL: DEC B ; Count bytes in buffer +0886+ 0952 2B DEC HL ; Back space buffer +0887+ 0953 CA 65 09 JP Z,OTKLN ; No buffer - Try again +0888+ 0956 7E LD A,(HL) ; Get deleted byte +0889+ 0957 CD 02 0A CALL OUTC ; Echo it +0890+ 095A C3 77 09 JP MORINP ; Get more input +0891+ 095D +0892+ 095D 05 DELCHR: DEC B ; Count bytes in buffer +0893+ 095E 2B DEC HL ; Back space buffer +0894+ 095F CD 02 0A CALL OUTC ; Output character in A +0895+ 0962 C2 77 09 JP NZ,MORINP ; Not end - Get more +0896+ 0965 CD 02 0A OTKLN: CALL OUTC ; Output character in A +0897+ 0968 CD 29 0E KILIN: CALL PRNTCRLF ; Output CRLF +0898+ 096B C3 6E 09 JP TTYLIN ; Get line again +0899+ 096E +0900+ 096E GETLIN: +0901+ 096E 21 11 31 TTYLIN: LD HL,BUFFER ; Get a line by character +0902+ 0971 06 01 LD B,1 ; Set buffer as empty +0903+ 0973 AF XOR A +0904+ 0974 32 F4 30 LD (NULFLG),A ; Clear null flag +0905+ 0977 CD 2C 0A MORINP: CALL CLOTST ; Get character and test ^O +0906+ 097A 4F LD C,A ; Save character in C +0907+ 097B FE 7F CP DEL ; Delete character? +0908+ 097D CA 3D 09 JP Z,DODEL ; Yes - Process it +0909+ 0980 3A F4 30 LD A,(NULFLG) ; Get null flag +0910+ 0983 B7 OR A ; Test null flag status +0911+ 0984 CA 90 09 JP Z,PROCES ; Reset - Process character +0912+ 0987 3E 00 LD A,0 ; Set a null +0913+ 0989 CD 02 0A CALL OUTC ; Output null +0914+ 098C AF XOR A ; Clear A +0915+ 098D 32 F4 30 LD (NULFLG),A ; Reset null flag +0916+ 0990 79 PROCES: LD A,C ; Get character +0917+ 0991 FE 07 CP CTRLG ; Bell? +0918+ 0993 CA D4 09 JP Z,PUTCTL ; Yes - Save it +0919+ 0996 FE 03 CP CTRLC ; Is it control "C"? +0920+ 0998 CC 29 0E CALL Z,PRNTCRLF ; Yes - Output CRLF +0921+ 099B 37 SCF ; Flag break +0922+ 099C C8 RET Z ; Return if control "C" +0923+ 099D FE 0D CP CR ; Is it enter? +0924+ 099F CA 24 0E JP Z,ENDINP ; Yes - Terminate input +0925+ 09A2 FE 15 CP CTRLU ; Is it control "U"? +0926+ 09A4 CA 68 09 JP Z,KILIN ; Yes - Get another line +0927+ 09A7 FE 40 CP '@' ; Is it "kill line"? +0928+ 09A9 CA 65 09 JP Z,OTKLN ; Yes - Kill line +0929+ 09AC FE 5F CP '_' ; Is it delete? +0930+ 09AE CA 5D 09 JP Z,DELCHR ; Yes - Delete character +0931+ 09B1 FE 08 CP BKSP ; Is it backspace? +0932+ 09B3 CA 5D 09 JP Z,DELCHR ; Yes - Delete character +0933+ 09B6 FE 12 CP CTRLR ; Is it control "R"? +0934+ 09B8 C2 CF 09 JP NZ,PUTBUF ; No - Put in buffer +0935+ 09BB C5 PUSH BC ; Save buffer length +0936+ 09BC D5 PUSH DE ; Save DE +0937+ 09BD E5 PUSH HL ; Save buffer address +0938+ 09BE 36 00 LD (HL),0 ; Mark end of buffer +0939+ 09C0 CD D9 1F CALL OUTNCR ; Output and do CRLF +0940+ 09C3 21 11 31 LD HL,BUFFER ; Point to buffer start +0941+ 09C6 CD C7 14 CALL PRS ; Output buffer +0942+ 09C9 E1 POP HL ; Restore buffer address +0943+ 09CA D1 POP DE ; Restore DE +0944+ 09CB C1 POP BC ; Restore buffer length +0945+ 09CC C3 77 09 JP MORINP ; Get another character +0946+ 09CF +0947+ 09CF FE 20 PUTBUF: CP ' ' ; Is it a control code? +0948+ 09D1 DA 77 09 JP C,MORINP ; Yes - Ignore +0949+ 09D4 78 PUTCTL: LD A,B ; Get number of bytes in buffer +0950+ 09D5 FE 49 CP 72+1 ; Test for line overflow +0951+ 09D7 3E 07 LD A,CTRLG ; Set a bell +0952+ 09D9 D2 E9 09 JP NC,OUTNBS ; Ring bell if buffer full +0953+ 09DC 79 LD A,C ; Get character +0954+ 09DD 71 LD (HL),C ; Save in buffer +0955+ 09DE 32 7C 31 LD (LSTBIN),A ; Save last input byte +0956+ 09E1 23 INC HL ; Move up buffer +0957+ 09E2 04 INC B ; Increment length +0958+ 09E3 CD 02 0A OUTIT: CALL OUTC ; Output the character entered +0959+ 09E6 C3 77 09 JP MORINP ; Get another character +0960+ 09E9 +0961+ 09E9 CD 02 0A OUTNBS: CALL OUTC ; Output bell and back over it +0962+ 09EC 3E 08 LD A,BKSP ; Set back space +0963+ 09EE C3 E3 09 JP OUTIT ; Output it and get more +0964+ 09F1 +0965+ 09F1 7C CPDEHL: LD A,H ; Get H +0966+ 09F2 92 SUB D ; Compare with D +0967+ 09F3 C0 RET NZ ; Different - Exit +0968+ 09F4 7D LD A,L ; Get L +0969+ 09F5 93 SUB E ; Compare with E +0970+ 09F6 C9 RET ; Return status +0971+ 09F7 +0972+ 09F7 7E CHKSYN: LD A,(HL) ; Check syntax of character +0973+ 09F8 E3 EX (SP),HL ; Address of test byte +0974+ 09F9 BE CP (HL) ; Same as in code string? +0975+ 09FA 23 INC HL ; Return address +0976+ 09FB E3 EX (SP),HL ; Put it back +0977+ 09FC CA 81 0B JP Z,GETCHR ; Yes - Get next character +0978+ 09FF C3 29 07 JP SNERR ; Different - ?SN Error +0979+ 0A02 +0980+ 0A02 F5 OUTC: PUSH AF ; Save character +0981+ 0A03 3A F5 30 LD A,(CTLOFG) ; Get control "O" flag +0982+ 0A06 B7 OR A ; Is it set? +0983+ 0A07 C2 FC 14 JP NZ,POPAF ; Yes - don't output +0984+ 0A0A F1 POP AF ; Restore character +0985+ 0A0B C5 PUSH BC ; Save buffer length +0986+ 0A0C F5 PUSH AF ; Save character +0987+ 0A0D FE 20 CP ' ' ; Is it a control code? +0988+ 0A0F DA 26 0A JP C,DINPOS ; Yes - Don't INC POS(X) +0989+ 0A12 3A F2 30 LD A,(LWIDTH) ; Get line width +0990+ 0A15 47 LD B,A ; To B +0991+ 0A16 3A 5B 31 LD A,(CURPOS) ; Get cursor position +0992+ 0A19 04 INC B ; Width 255? +0993+ 0A1A CA 22 0A JP Z,INCLEN ; Yes - No width limit +0994+ 0A1D 05 DEC B ; Restore width +0995+ 0A1E B8 CP B ; At end of line? +0996+ 0A1F CC 29 0E CALL Z,PRNTCRLF ; Yes - output CRLF +0997+ 0A22 3C INCLEN: INC A ; Move on one character +0998+ 0A23 32 5B 31 LD (CURPOS),A ; Save new position +0999+ 0A26 F1 DINPOS: POP AF ; Restore character +1000+ 0A27 C1 POP BC ; Restore buffer length +1001+ 0A28 CD C2 1F CALL MONOUT ; Send it +1002+ 0A2B C9 RET +1003+ 0A2C +1004+ 0A2C CD 86 1E CLOTST: CALL GETINP ; Get input character +1005+ 0A2F E6 7F AND 01111111B ; Strip bit 7 +1006+ 0A31 FE 0F CP CTRLO ; Is it control "O"? +1007+ 0A33 C0 RET NZ ; No don't flip flag +1008+ 0A34 3A F5 30 LD A,(CTLOFG) ; Get flag +1009+ 0A37 2F CPL ; Flip it +1010+ 0A38 32 F5 30 LD (CTLOFG),A ; Put it back +1011+ 0A3B AF XOR A ; Null character +1012+ 0A3C C9 RET +1013+ 0A3D +1014+ 0A3D CD 4D 0C LIST: CALL ATOH ; ASCII number to DE +1015+ 0A40 C0 RET NZ ; Return if anything extra +1016+ 0A41 C1 POP BC ; Rubbish - Not needed +1017+ 0A42 CD 15 08 CALL SRCHLN ; Search for line number in DE +1018+ 0A45 C5 PUSH BC ; Save address of line +1019+ 0A46 CD 93 0A CALL SETLIN ; Set up lines counter +1020+ 0A49 E1 LISTLP: POP HL ; Restore address of line +1021+ 0A4A 4E LD C,(HL) ; Get LSB of next line +1022+ 0A4B 23 INC HL +1023+ 0A4C 46 LD B,(HL) ; Get MSB of next line +1024+ 0A4D 23 INC HL +1025+ 0A4E 78 LD A,B ; BC = 0 (End of program)? +1026+ 0A4F B1 OR C +1027+ 0A50 CA 74 07 JP Z,PRNTOK ; Yes - Go to command mode +1028+ 0A53 CD 9C 0A CALL COUNT ; Count lines +1029+ 0A56 CD AC 0B CALL TSTBRK ; Test for break key +1030+ 0A59 C5 PUSH BC ; Save address of next line +1031+ 0A5A CD 29 0E CALL PRNTCRLF ; Output CRLF +1032+ 0A5D 5E LD E,(HL) ; Get LSB of line number +1033+ 0A5E 23 INC HL +1034+ 0A5F 56 LD D,(HL) ; Get MSB of line number +1035+ 0A60 23 INC HL +1036+ 0A61 E5 PUSH HL ; Save address of line start +1037+ 0A62 EB EX DE,HL ; Line number to HL +1038+ 0A63 CD 6A 1B CALL PRNTHL ; Output line number in decimal +1039+ 0A66 3E 20 LD A,' ' ; Space after line number +1040+ 0A68 E1 POP HL ; Restore start of line address +1041+ 0A69 CD 02 0A LSTLP2: CALL OUTC ; Output character in A +1042+ 0A6C 7E LSTLP3: LD A,(HL) ; Get next byte in line +1043+ 0A6D B7 OR A ; End of line? +1044+ 0A6E 23 INC HL ; To next byte in line +1045+ 0A6F CA 49 0A JP Z,LISTLP ; Yes - get next line +1046+ 0A72 F2 69 0A JP P,LSTLP2 ; No token - output it +1047+ 0A75 D6 7F SUB ZEND-1 ; Find and output word +1048+ 0A77 4F LD C,A ; Token offset+1 to C +1049+ 0A78 11 B2 04 LD DE,WORDS ; Reserved word list +1050+ 0A7B 1A FNDTOK: LD A,(DE) ; Get character in list +1051+ 0A7C 13 INC DE ; Move on to next +1052+ 0A7D B7 OR A ; Is it start of word? +1053+ 0A7E F2 7B 0A JP P,FNDTOK ; No - Keep looking for word +1054+ 0A81 0D DEC C ; Count words +1055+ 0A82 C2 7B 0A JP NZ,FNDTOK ; Not there - keep looking +1056+ 0A85 E6 7F OUTWRD: AND 01111111B ; Strip bit 7 +1057+ 0A87 CD 02 0A CALL OUTC ; Output first character +1058+ 0A8A 1A LD A,(DE) ; Get next character +1059+ 0A8B 13 INC DE ; Move on to next +1060+ 0A8C B7 OR A ; Is it end of word? +1061+ 0A8D F2 85 0A JP P,OUTWRD ; No - output the rest +1062+ 0A90 C3 6C 0A JP LSTLP3 ; Next byte in line +1063+ 0A93 +1064+ 0A93 E5 SETLIN: PUSH HL ; Set up LINES counter +1065+ 0A94 2A F8 30 LD HL,(LINESN) ; Get LINES number +1066+ 0A97 22 F6 30 LD (LINESC),HL ; Save in LINES counter +1067+ 0A9A E1 POP HL +1068+ 0A9B C9 RET +1069+ 0A9C +1070+ 0A9C E5 COUNT: PUSH HL ; Save code string address +1071+ 0A9D D5 PUSH DE +1072+ 0A9E 2A F6 30 LD HL,(LINESC) ; Get LINES counter +1073+ 0AA1 11 FF FF LD DE,-1 +1074+ 0AA4 ED 5A ADC HL,DE ; Decrement +1075+ 0AA6 22 F6 30 LD (LINESC),HL ; Put it back +1076+ 0AA9 D1 POP DE +1077+ 0AAA E1 POP HL ; Restore code string address +1078+ 0AAB F0 RET P ; Return if more lines to go +1079+ 0AAC E5 PUSH HL ; Save code string address +1080+ 0AAD 2A F8 30 LD HL,(LINESN) ; Get LINES number +1081+ 0AB0 22 F6 30 LD (LINESC),HL ; Reset LINES counter +1082+ 0AB3 CD 86 1E CALL GETINP ; Get input character +1083+ 0AB6 FE 03 CP CTRLC ; Is it control "C"? +1084+ 0AB8 CA BF 0A JP Z,RSLNBK ; Yes - Reset LINES and break +1085+ 0ABB E1 POP HL ; Restore code string address +1086+ 0ABC C3 9C 0A JP COUNT ; Keep on counting +1087+ 0ABF +1088+ 0ABF 2A F8 30 RSLNBK: LD HL,(LINESN) ; Get LINES number +1089+ 0AC2 22 F6 30 LD (LINESC),HL ; Reset LINES counter +1090+ 0AC5 C3 23 04 JP BRKRET ; Go and output "Break" +1091+ 0AC8 +1092+ 0AC8 3E 64 FOR: LD A,64H ; Flag "FOR" assignment +1093+ 0ACA 32 7B 31 LD (FORFLG),A ; Save "FOR" flag +1094+ 0ACD CD 2F 0D CALL LET ; Set up initial index +1095+ 0AD0 C1 POP BC ; Drop RETurn address +1096+ 0AD1 E5 PUSH HL ; Save code string address +1097+ 0AD2 CD 18 0D CALL DATA ; Get next statement address +1098+ 0AD5 22 77 31 LD (LOOPST),HL ; Save it for start of loop +1099+ 0AD8 21 02 00 LD HL,2 ; Offset for "FOR" block +1100+ 0ADB 39 ADD HL,SP ; Point to it +1101+ 0ADC CD D6 06 FORSLP: CALL LOKFOR ; Look for existing "FOR" block +1102+ 0ADF D1 POP DE ; Get code string address +1103+ 0AE0 C2 F8 0A JP NZ,FORFND ; No nesting found +1104+ 0AE3 09 ADD HL,BC ; Move into "FOR" block +1105+ 0AE4 D5 PUSH DE ; Save code string address +1106+ 0AE5 2B DEC HL +1107+ 0AE6 56 LD D,(HL) ; Get MSB of loop statement +1108+ 0AE7 2B DEC HL +1109+ 0AE8 5E LD E,(HL) ; Get LSB of loop statement +1110+ 0AE9 23 INC HL +1111+ 0AEA 23 INC HL +1112+ 0AEB E5 PUSH HL ; Save block address +1113+ 0AEC 2A 77 31 LD HL,(LOOPST) ; Get address of loop statement +1114+ 0AEF CD F1 09 CALL CPDEHL ; Compare the FOR loops +1115+ 0AF2 E1 POP HL ; Restore block address +1116+ 0AF3 C2 DC 0A JP NZ,FORSLP ; Different FORs - Find another +1117+ 0AF6 D1 POP DE ; Restore code string address +1118+ 0AF7 F9 LD SP,HL ; Remove all nested loops +1119+ 0AF8 +1120+ 0AF8 EB FORFND: EX DE,HL ; Code string address to HL +1121+ 0AF9 0E 08 LD C,8 +1122+ 0AFB CD 06 07 CALL CHKSTK ; Check for 8 levels of stack +1123+ 0AFE E5 PUSH HL ; Save code string address +1124+ 0AFF 2A 77 31 LD HL,(LOOPST) ; Get first statement of loop +1125+ 0B02 E3 EX (SP),HL ; Save and restore code string +1126+ 0B03 E5 PUSH HL ; Re-save code string address +1127+ 0B04 2A 0C 31 LD HL,(LINEAT) ; Get current line number +1128+ 0B07 E3 EX (SP),HL ; Save and restore code string +1129+ 0B08 CD F1 0F CALL TSTNUM ; Make sure it's a number +1130+ 0B0B CD F7 09 CALL CHKSYN ; Make sure "TO" is next +1131+ 0B0E A6 .BYTE ZTO ; "TO" token +1132+ 0B0F CD EE 0F CALL GETNUM ; Get "TO" expression value +1133+ 0B12 E5 PUSH HL ; Save code string address +1134+ 0B13 CD 1C 1A CALL BCDEFP ; Move "TO" value to BCDE +1135+ 0B16 E1 POP HL ; Restore code string address +1136+ 0B17 C5 PUSH BC ; Save "TO" value in block +1137+ 0B18 D5 PUSH DE +1138+ 0B19 01 00 81 LD BC,8100H ; BCDE - 1 (default STEP) +1139+ 0B1C 51 LD D,C ; C=0 +1140+ 0B1D 5A LD E,D ; D=0 +1141+ 0B1E 7E LD A,(HL) ; Get next byte in code string +1142+ 0B1F FE AB CP ZSTEP ; See if "STEP" is stated +1143+ 0B21 3E 01 LD A,1 ; Sign of step = 1 +1144+ 0B23 C2 34 0B JP NZ,SAVSTP ; No STEP given - Default to 1 +1145+ 0B26 CD 81 0B CALL GETCHR ; Jump over "STEP" token +1146+ 0B29 CD EE 0F CALL GETNUM ; Get step value +1147+ 0B2C E5 PUSH HL ; Save code string address +1148+ 0B2D CD 1C 1A CALL BCDEFP ; Move STEP to BCDE +1149+ 0B30 CD D0 19 CALL TSTSGN ; Test sign of FPREG +1150+ 0B33 E1 POP HL ; Restore code string address +1151+ 0B34 C5 SAVSTP: PUSH BC ; Save the STEP value in block +1152+ 0B35 D5 PUSH DE +1153+ 0B36 F5 PUSH AF ; Save sign of STEP +1154+ 0B37 33 INC SP ; Don't save flags +1155+ 0B38 E5 PUSH HL ; Save code string address +1156+ 0B39 2A 7E 31 LD HL,(BRKLIN) ; Get address of index variable +1157+ 0B3C E3 EX (SP),HL ; Save and restore code string +1158+ 0B3D 06 81 PUTFID: LD B,ZFOR ; "FOR" block marker +1159+ 0B3F C5 PUSH BC ; Save it +1160+ 0B40 33 INC SP ; Don't save C +1161+ 0B41 +1162+ 0B41 CD AC 0B RUNCNT: CALL TSTBRK ; Execution driver - Test break +1163+ 0B44 22 7E 31 LD (BRKLIN),HL ; Save code address for break +1164+ 0B47 7E LD A,(HL) ; Get next byte in code string +1165+ 0B48 FE 3A CP ':' ; Multi statement line? +1166+ 0B4A CA 61 0B JP Z,EXCUTE ; Yes - Execute it +1167+ 0B4D B7 OR A ; End of line? +1168+ 0B4E C2 29 07 JP NZ,SNERR ; No - Syntax error +1169+ 0B51 23 INC HL ; Point to address of next line +1170+ 0B52 7E LD A,(HL) ; Get LSB of line pointer +1171+ 0B53 23 INC HL +1172+ 0B54 B6 OR (HL) ; Is it zero (End of prog)? +1173+ 0B55 CA D3 0B JP Z,ENDPRG ; Yes - Terminate execution +1174+ 0B58 23 INC HL ; Point to line number +1175+ 0B59 5E LD E,(HL) ; Get LSB of line number +1176+ 0B5A 23 INC HL +1177+ 0B5B 56 LD D,(HL) ; Get MSB of line number +1178+ 0B5C EB EX DE,HL ; Line number to HL +1179+ 0B5D 22 0C 31 LD (LINEAT),HL ; Save as current line number +1180+ 0B60 EB EX DE,HL ; Line number back to DE +1181+ 0B61 CD 81 0B EXCUTE: CALL GETCHR ; Get key word +1182+ 0B64 11 41 0B LD DE,RUNCNT ; Where to RETurn to +1183+ 0B67 D5 PUSH DE ; Save for RETurn +1184+ 0B68 C8 IFJMP: RET Z ; Go to RUNCNT if end of STMT +1185+ 0B69 D6 80 ONJMP: SUB ZEND ; Is it a token? +1186+ 0B6B DA 2F 0D JP C,LET ; No - try to assign it +1187+ 0B6E FE 25 CP ZNEW+1-ZEND ; END to NEW ? +1188+ 0B70 D2 29 07 JP NC,SNERR ; Not a key word - ?SN Error +1189+ 0B73 07 RLCA ; Double it +1190+ 0B74 4F LD C,A ; BC = Offset into table +1191+ 0B75 06 00 LD B,0 +1192+ 0B77 EB EX DE,HL ; Save code string address +1193+ 0B78 21 D1 05 LD HL,WORDTB ; Keyword address table +1194+ 0B7B 09 ADD HL,BC ; Point to routine address +1195+ 0B7C 4E LD C,(HL) ; Get LSB of routine address +1196+ 0B7D 23 INC HL +1197+ 0B7E 46 LD B,(HL) ; Get MSB of routine address +1198+ 0B7F C5 PUSH BC ; Save routine address +1199+ 0B80 EB EX DE,HL ; Restore code string address +1200+ 0B81 +1201+ 0B81 23 GETCHR: INC HL ; Point to next character +1202+ 0B82 7E LD A,(HL) ; Get next code string byte +1203+ 0B83 FE 3A CP ':' ; Z if ':' +1204+ 0B85 D0 RET NC ; NC if > "9" +1205+ 0B86 FE 20 CP ' ' +1206+ 0B88 CA 81 0B JP Z,GETCHR ; Skip over spaces +1207+ 0B8B FE 30 CP '0' +1208+ 0B8D 3F CCF ; NC if < '0' +1209+ 0B8E 3C INC A ; Test for zero - Leave carry +1210+ 0B8F 3D DEC A ; Z if Null +1211+ 0B90 C9 RET +1212+ 0B91 +1213+ 0B91 EB RESTOR: EX DE,HL ; Save code string address +1214+ 0B92 2A 0E 31 LD HL,(BASTXT) ; Point to start of program +1215+ 0B95 CA A6 0B JP Z,RESTNL ; Just RESTORE - reset pointer +1216+ 0B98 EB EX DE,HL ; Restore code string address +1217+ 0B99 CD 4D 0C CALL ATOH ; Get line number to DE +1218+ 0B9C E5 PUSH HL ; Save code string address +1219+ 0B9D CD 15 08 CALL SRCHLN ; Search for line number in DE +1220+ 0BA0 60 LD H,B ; HL = Address of line +1221+ 0BA1 69 LD L,C +1222+ 0BA2 D1 POP DE ; Restore code string address +1223+ 0BA3 D2 EE 0C JP NC,ULERR ; ?UL Error if not found +1224+ 0BA6 2B RESTNL: DEC HL ; Byte before DATA statement +1225+ 0BA7 22 8C 31 UPDATA: LD (NXTDAT),HL ; Update DATA pointer +1226+ 0BAA EB EX DE,HL ; Restore code string address +1227+ 0BAB C9 RET +1228+ 0BAC +1229+ 0BAC +1230+ 0BAC DF TSTBRK: RST 18H ; Check input status +1231+ 0BAD C8 RET Z ; No key, go back +1232+ 0BAE D7 RST 10H ; Get the key into A +1233+ 0BAF FE 1B CP ESC ; Escape key? +1234+ 0BB1 28 11 JR Z,BRK ; Yes, break +1235+ 0BB3 FE 03 CP CTRLC ; +1236+ 0BB5 28 0D JR Z,BRK ; Yes, break +1237+ 0BB7 FE 13 CP CTRLS ; Stop scrolling? +1238+ 0BB9 C0 RET NZ ; Other key, ignore +1239+ 0BBA +1240+ 0BBA +1241+ 0BBA D7 STALL: RST 10H ; Wait for key +1242+ 0BBB FE 11 CP CTRLQ ; Resume scrolling? +1243+ 0BBD C8 RET Z ; Release the chokehold +1244+ 0BBE FE 03 CP CTRLC ; Second break? +1245+ 0BC0 28 07 JR Z,STOP ; Break during hold exits prog +1246+ 0BC2 18 F6 JR STALL ; Loop until or +1247+ 0BC4 +1248+ 0BC4 3E FF BRK LD A,$FF ; Set BRKFLG +1249+ 0BC6 32 FD 30 LD (BRKFLG),A ; Store it +1250+ 0BC9 +1251+ 0BC9 +1252+ 0BC9 C0 STOP: RET NZ ; Exit if anything else +1253+ 0BCA F6 .BYTE 0F6H ; Flag "STOP" +1254+ 0BCB C0 PEND: RET NZ ; Exit if anything else +1255+ 0BCC 22 7E 31 LD (BRKLIN),HL ; Save point of break +1256+ 0BCF 21 .BYTE 21H ; Skip "OR 11111111B" +1257+ 0BD0 F6 FF INPBRK: OR 11111111B ; Flag "Break" wanted +1258+ 0BD2 C1 POP BC ; Return not needed and more +1259+ 0BD3 2A 0C 31 ENDPRG: LD HL,(LINEAT) ; Get current line number +1260+ 0BD6 F5 PUSH AF ; Save STOP / END status +1261+ 0BD7 7D LD A,L ; Is it direct break? +1262+ 0BD8 A4 AND H +1263+ 0BD9 3C INC A ; Line is -1 if direct break +1264+ 0BDA CA E6 0B JP Z,NOLIN ; Yes - No line number +1265+ 0BDD 22 82 31 LD (ERRLIN),HL ; Save line of break +1266+ 0BE0 2A 7E 31 LD HL,(BRKLIN) ; Get point of break +1267+ 0BE3 22 84 31 LD (CONTAD),HL ; Save point to CONTinue +1268+ 0BE6 AF NOLIN: XOR A +1269+ 0BE7 32 F5 30 LD (CTLOFG),A ; Enable output +1270+ 0BEA CD 1C 0E CALL STTLIN ; Start a new line +1271+ 0BED F1 POP AF ; Restore STOP / END status +1272+ 0BEE 21 CC 06 LD HL,BRKMSG ; "Break" message +1273+ 0BF1 C2 5D 07 JP NZ,ERRIN ; "in line" wanted? +1274+ 0BF4 C3 74 07 JP PRNTOK ; Go to command mode +1275+ 0BF7 +1276+ 0BF7 2A 84 31 CONT: LD HL,(CONTAD) ; Get CONTinue address +1277+ 0BFA 7C LD A,H ; Is it zero? +1278+ 0BFB B5 OR L +1279+ 0BFC 1E 20 LD E,CN ; ?CN Error +1280+ 0BFE CA 3D 07 JP Z,ERROR ; Yes - output "?CN Error" +1281+ 0C01 EB EX DE,HL ; Save code string address +1282+ 0C02 2A 82 31 LD HL,(ERRLIN) ; Get line of last break +1283+ 0C05 22 0C 31 LD (LINEAT),HL ; Set up current line number +1284+ 0C08 EB EX DE,HL ; Restore code string address +1285+ 0C09 C9 RET ; CONTinue where left off +1286+ 0C0A +1287+ 0C0A CD 4F 17 NULL: CALL GETINT ; Get integer 0-255 +1288+ 0C0D C0 RET NZ ; Return if bad value +1289+ 0C0E 32 F1 30 LD (NULLS),A ; Set nulls number +1290+ 0C11 C9 RET +1291+ 0C12 +1292+ 0C12 +1293+ 0C12 E5 ACCSUM: PUSH HL ; Save address in array +1294+ 0C13 2A FA 30 LD HL,(CHKSUM) ; Get check sum +1295+ 0C16 06 00 LD B,0 ; BC - Value of byte +1296+ 0C18 4F LD C,A +1297+ 0C19 09 ADD HL,BC ; Add byte to check sum +1298+ 0C1A 22 FA 30 LD (CHKSUM),HL ; Re-save check sum +1299+ 0C1D E1 POP HL ; Restore address in array +1300+ 0C1E C9 RET +1301+ 0C1F +1302+ 0C1F 7E CHKLTR: LD A,(HL) ; Get byte +1303+ 0C20 FE 41 CP 'A' ; < 'a' ? +1304+ 0C22 D8 RET C ; Carry set if not letter +1305+ 0C23 FE 5B CP 'Z'+1 ; > 'z' ? +1306+ 0C25 3F CCF +1307+ 0C26 C9 RET ; Carry set if not letter +1308+ 0C27 +1309+ 0C27 CD 81 0B FPSINT: CALL GETCHR ; Get next character +1310+ 0C2A CD EE 0F POSINT: CALL GETNUM ; Get integer 0 to 32767 +1311+ 0C2D CD D0 19 DEPINT: CALL TSTSGN ; Test sign of FPREG +1312+ 0C30 FA 48 0C JP M,FCERR ; Negative - ?FC Error +1313+ 0C33 3A 97 31 DEINT: LD A,(FPEXP) ; Get integer value to DE +1314+ 0C36 FE 90 CP 80H+16 ; Exponent in range (16 bits)? +1315+ 0C38 DA 78 1A JP C,FPINT ; Yes - convert it +1316+ 0C3B 01 80 90 LD BC,9080H ; BCDE = -32768 +1317+ 0C3E 11 00 00 LD DE,0000 +1318+ 0C41 E5 PUSH HL ; Save code string address +1319+ 0C42 CD 4B 1A CALL CMPNUM ; Compare FPREG with BCDE +1320+ 0C45 E1 POP HL ; Restore code string address +1321+ 0C46 51 LD D,C ; MSB to D +1322+ 0C47 C8 RET Z ; Return if in range +1323+ 0C48 1E 08 FCERR: LD E,FC ; ?FC Error +1324+ 0C4A C3 3D 07 JP ERROR ; Output error- +1325+ 0C4D +1326+ 0C4D 2B ATOH: DEC HL ; ASCII number to DE binary +1327+ 0C4E 11 00 00 GETLN: LD DE,0 ; Get number to DE +1328+ 0C51 CD 81 0B GTLNLP: CALL GETCHR ; Get next character +1329+ 0C54 D0 RET NC ; Exit if not a digit +1330+ 0C55 E5 PUSH HL ; Save code string address +1331+ 0C56 F5 PUSH AF ; Save digit +1332+ 0C57 21 98 19 LD HL,65529/10 ; Largest number 65529 +1333+ 0C5A CD F1 09 CALL CPDEHL ; Number in range? +1334+ 0C5D DA 29 07 JP C,SNERR ; No - ?SN Error +1335+ 0C60 62 LD H,D ; HL = Number +1336+ 0C61 6B LD L,E +1337+ 0C62 19 ADD HL,DE ; Times 2 +1338+ 0C63 29 ADD HL,HL ; Times 4 +1339+ 0C64 19 ADD HL,DE ; Times 5 +1340+ 0C65 29 ADD HL,HL ; Times 10 +1341+ 0C66 F1 POP AF ; Restore digit +1342+ 0C67 D6 30 SUB '0' ; Make it 0 to 9 +1343+ 0C69 5F LD E,A ; DE = Value of digit +1344+ 0C6A 16 00 LD D,0 +1345+ 0C6C 19 ADD HL,DE ; Add to number +1346+ 0C6D EB EX DE,HL ; Number to DE +1347+ 0C6E E1 POP HL ; Restore code string address +1348+ 0C6F C3 51 0C JP GTLNLP ; Go to next character +1349+ 0C72 +1350+ 0C72 CA 45 08 CLEAR: JP Z,INTVAR ; Just "CLEAR" Keep parameters +1351+ 0C75 CD 2A 0C CALL POSINT ; Get integer 0 to 32767 to DE +1352+ 0C78 2B DEC HL ; Cancel increment +1353+ 0C79 CD 81 0B CALL GETCHR ; Get next character +1354+ 0C7C E5 PUSH HL ; Save code string address +1355+ 0C7D 2A 5F 31 LD HL,(LSTRAM) ; Get end of RAM +1356+ 0C80 CA 95 0C JP Z,STORED ; No value given - Use stored +1357+ 0C83 E1 POP HL ; Restore code string address +1358+ 0C84 CD F7 09 CALL CHKSYN ; Check for comma +1359+ 0C87 2C .BYTE ',' +1360+ 0C88 D5 PUSH DE ; Save number +1361+ 0C89 CD 2A 0C CALL POSINT ; Get integer 0 to 32767 +1362+ 0C8C 2B DEC HL ; Cancel increment +1363+ 0C8D CD 81 0B CALL GETCHR ; Get next character +1364+ 0C90 C2 29 07 JP NZ,SNERR ; ?SN Error if more on line +1365+ 0C93 E3 EX (SP),HL ; Save code string address +1366+ 0C94 EB EX DE,HL ; Number to DE +1367+ 0C95 7D STORED: LD A,L ; Get LSB of new RAM top +1368+ 0C96 93 SUB E ; Subtract LSB of string space +1369+ 0C97 5F LD E,A ; Save LSB +1370+ 0C98 7C LD A,H ; Get MSB of new RAM top +1371+ 0C99 9A SBC A,D ; Subtract MSB of string space +1372+ 0C9A 57 LD D,A ; Save MSB +1373+ 0C9B DA 1E 07 JP C,OMERR ; ?OM Error if not enough mem +1374+ 0C9E E5 PUSH HL ; Save RAM top +1375+ 0C9F 2A 86 31 LD HL,(PROGND) ; Get program end +1376+ 0CA2 01 28 00 LD BC,40 ; 40 Bytes minimum working RAM +1377+ 0CA5 09 ADD HL,BC ; Get lowest address +1378+ 0CA6 CD F1 09 CALL CPDEHL ; Enough memory? +1379+ 0CA9 D2 1E 07 JP NC,OMERR ; No - ?OM Error +1380+ 0CAC EB EX DE,HL ; RAM top to HL +1381+ 0CAD 22 0A 31 LD (STRSPC),HL ; Set new string space +1382+ 0CB0 E1 POP HL ; End of memory to use +1383+ 0CB1 22 5F 31 LD (LSTRAM),HL ; Set new top of RAM +1384+ 0CB4 E1 POP HL ; Restore code string address +1385+ 0CB5 C3 45 08 JP INTVAR ; Initialise variables +1386+ 0CB8 +1387+ 0CB8 CA 41 08 RUN: JP Z,RUNFST ; RUN from start if just RUN +1388+ 0CBB CD 45 08 CALL INTVAR ; Initialise variables +1389+ 0CBE 01 41 0B LD BC,RUNCNT ; Execution driver loop +1390+ 0CC1 C3 D4 0C JP RUNLIN ; RUN from line number +1391+ 0CC4 +1392+ 0CC4 0E 03 GOSUB: LD C,3 ; 3 Levels of stack needed +1393+ 0CC6 CD 06 07 CALL CHKSTK ; Check for 3 levels of stack +1394+ 0CC9 C1 POP BC ; Get return address +1395+ 0CCA E5 PUSH HL ; Save code string for RETURN +1396+ 0CCB E5 PUSH HL ; And for GOSUB routine +1397+ 0CCC 2A 0C 31 LD HL,(LINEAT) ; Get current line +1398+ 0CCF E3 EX (SP),HL ; Into stack - Code string out +1399+ 0CD0 3E 8C LD A,ZGOSUB ; "GOSUB" token +1400+ 0CD2 F5 PUSH AF ; Save token +1401+ 0CD3 33 INC SP ; Don't save flags +1402+ 0CD4 +1403+ 0CD4 C5 RUNLIN: PUSH BC ; Save return address +1404+ 0CD5 CD 4D 0C GOTO: CALL ATOH ; ASCII number to DE binary +1405+ 0CD8 CD 1A 0D CALL REM ; Get end of line +1406+ 0CDB E5 PUSH HL ; Save end of line +1407+ 0CDC 2A 0C 31 LD HL,(LINEAT) ; Get current line +1408+ 0CDF CD F1 09 CALL CPDEHL ; Line after current? +1409+ 0CE2 E1 POP HL ; Restore end of line +1410+ 0CE3 23 INC HL ; Start of next line +1411+ 0CE4 DC 18 08 CALL C,SRCHLP ; Line is after current line +1412+ 0CE7 D4 15 08 CALL NC,SRCHLN ; Line is before current line +1413+ 0CEA 60 LD H,B ; Set up code string address +1414+ 0CEB 69 LD L,C +1415+ 0CEC 2B DEC HL ; Incremented after +1416+ 0CED D8 RET C ; Line found +1417+ 0CEE 1E 0E ULERR: LD E,UL ; ?UL Error +1418+ 0CF0 C3 3D 07 JP ERROR ; Output error message +1419+ 0CF3 +1420+ 0CF3 C0 RETURN: RET NZ ; Return if not just RETURN +1421+ 0CF4 16 FF LD D,-1 ; Flag "GOSUB" search +1422+ 0CF6 CD D2 06 CALL BAKSTK ; Look "GOSUB" block +1423+ 0CF9 F9 LD SP,HL ; Kill all FORs in subroutine +1424+ 0CFA FE 8C CP ZGOSUB ; Test for "GOSUB" token +1425+ 0CFC 1E 04 LD E,RG ; ?RG Error +1426+ 0CFE C2 3D 07 JP NZ,ERROR ; Error if no "GOSUB" found +1427+ 0D01 E1 POP HL ; Get RETURN line number +1428+ 0D02 22 0C 31 LD (LINEAT),HL ; Save as current +1429+ 0D05 23 INC HL ; Was it from direct statement? +1430+ 0D06 7C LD A,H +1431+ 0D07 B5 OR L ; Return to line +1432+ 0D08 C2 12 0D JP NZ,RETLIN ; No - Return to line +1433+ 0D0B 3A 7C 31 LD A,(LSTBIN) ; Any INPUT in subroutine? +1434+ 0D0E B7 OR A ; If so buffer is corrupted +1435+ 0D0F C2 73 07 JP NZ,POPNOK ; Yes - Go to command mode +1436+ 0D12 21 41 0B RETLIN: LD HL,RUNCNT ; Execution driver loop +1437+ 0D15 E3 EX (SP),HL ; Into stack - Code string out +1438+ 0D16 3E .BYTE 3EH ; Skip "POP HL" +1439+ 0D17 E1 NXTDTA: POP HL ; Restore code string address +1440+ 0D18 +1441+ 0D18 01 3A DATA: .BYTE 01H,3AH ; ':' End of statement +1442+ 0D1A 0E 00 REM: LD C,0 ; 00 End of statement +1443+ 0D1C 06 00 LD B,0 +1444+ 0D1E 79 NXTSTL: LD A,C ; Statement and byte +1445+ 0D1F 48 LD C,B +1446+ 0D20 47 LD B,A ; Statement end byte +1447+ 0D21 7E NXTSTT: LD A,(HL) ; Get byte +1448+ 0D22 B7 OR A ; End of line? +1449+ 0D23 C8 RET Z ; Yes - Exit +1450+ 0D24 B8 CP B ; End of statement? +1451+ 0D25 C8 RET Z ; Yes - Exit +1452+ 0D26 23 INC HL ; Next byte +1453+ 0D27 FE 22 CP '"' ; Literal string? +1454+ 0D29 CA 1E 0D JP Z,NXTSTL ; Yes - Look for another '"' +1455+ 0D2C C3 21 0D JP NXTSTT ; Keep looking +1456+ 0D2F +1457+ 0D2F CD E4 11 LET: CALL GETVAR ; Get variable name +1458+ 0D32 CD F7 09 CALL CHKSYN ; Make sure "=" follows +1459+ 0D35 B4 .BYTE ZEQUAL ; "=" token +1460+ 0D36 D5 PUSH DE ; Save address of variable +1461+ 0D37 3A 5D 31 LD A,(TYPE) ; Get data type +1462+ 0D3A F5 PUSH AF ; Save type +1463+ 0D3B CD 00 10 CALL EVAL ; Evaluate expression +1464+ 0D3E F1 POP AF ; Restore type +1465+ 0D3F E3 EX (SP),HL ; Save code - Get var addr +1466+ 0D40 22 7E 31 LD (BRKLIN),HL ; Save address of variable +1467+ 0D43 1F RRA ; Adjust type +1468+ 0D44 CD F3 0F CALL CHKTYP ; Check types are the same +1469+ 0D47 CA 82 0D JP Z,LETNUM ; Numeric - Move value +1470+ 0D4A E5 LETSTR: PUSH HL ; Save address of string var +1471+ 0D4B 2A 94 31 LD HL,(FPREG) ; Pointer to string entry +1472+ 0D4E E5 PUSH HL ; Save it on stack +1473+ 0D4F 23 INC HL ; Skip over length +1474+ 0D50 23 INC HL +1475+ 0D51 5E LD E,(HL) ; LSB of string address +1476+ 0D52 23 INC HL +1477+ 0D53 56 LD D,(HL) ; MSB of string address +1478+ 0D54 2A 0E 31 LD HL,(BASTXT) ; Point to start of program +1479+ 0D57 CD F1 09 CALL CPDEHL ; Is string before program? +1480+ 0D5A D2 71 0D JP NC,CRESTR ; Yes - Create string entry +1481+ 0D5D 2A 0A 31 LD HL,(STRSPC) ; Point to string space +1482+ 0D60 CD F1 09 CALL CPDEHL ; Is string literal in program? +1483+ 0D63 D1 POP DE ; Restore address of string +1484+ 0D64 D2 79 0D JP NC,MVSTPT ; Yes - Set up pointer +1485+ 0D67 21 6F 31 LD HL,TMPSTR ; Temporary string pool +1486+ 0D6A CD F1 09 CALL CPDEHL ; Is string in temporary pool? +1487+ 0D6D D2 79 0D JP NC,MVSTPT ; No - Set up pointer +1488+ 0D70 3E .BYTE 3EH ; Skip "POP DE" +1489+ 0D71 D1 CRESTR: POP DE ; Restore address of string +1490+ 0D72 CD 28 16 CALL BAKTMP ; Back to last tmp-str entry +1491+ 0D75 EB EX DE,HL ; Address of string entry +1492+ 0D76 CD 61 14 CALL SAVSTR ; Save string in string area +1493+ 0D79 CD 28 16 MVSTPT: CALL BAKTMP ; Back to last tmp-str entry +1494+ 0D7C E1 POP HL ; Get string pointer +1495+ 0D7D CD 2B 1A CALL DETHL4 ; Move string pointer to var +1496+ 0D80 E1 POP HL ; Restore code string address +1497+ 0D81 C9 RET +1498+ 0D82 +1499+ 0D82 E5 LETNUM: PUSH HL ; Save address of variable +1500+ 0D83 CD 28 1A CALL FPTHL ; Move value to variable +1501+ 0D86 D1 POP DE ; Restore address of variable +1502+ 0D87 E1 POP HL ; Restore code string address +1503+ 0D88 C9 RET +1504+ 0D89 +1505+ 0D89 CD 4F 17 ON: CALL GETINT ; Get integer 0-255 +1506+ 0D8C 7E LD A,(HL) ; Get "GOTO" or "GOSUB" token +1507+ 0D8D 47 LD B,A ; Save in B +1508+ 0D8E FE 8C CP ZGOSUB ; "GOSUB" token? +1509+ 0D90 CA 98 0D JP Z,ONGO ; Yes - Find line number +1510+ 0D93 CD F7 09 CALL CHKSYN ; Make sure it's "GOTO" +1511+ 0D96 88 .BYTE ZGOTO ; "GOTO" token +1512+ 0D97 2B DEC HL ; Cancel increment +1513+ 0D98 4B ONGO: LD C,E ; Integer of branch value +1514+ 0D99 0D ONGOLP: DEC C ; Count branches +1515+ 0D9A 78 LD A,B ; Get "GOTO" or "GOSUB" token +1516+ 0D9B CA 69 0B JP Z,ONJMP ; Go to that line if right one +1517+ 0D9E CD 4E 0C CALL GETLN ; Get line number to DE +1518+ 0DA1 FE 2C CP ',' ; Another line number? +1519+ 0DA3 C0 RET NZ ; No - Drop through +1520+ 0DA4 C3 99 0D JP ONGOLP ; Yes - loop +1521+ 0DA7 +1522+ 0DA7 CD 00 10 IF: CALL EVAL ; Evaluate expression +1523+ 0DAA 7E LD A,(HL) ; Get token +1524+ 0DAB FE 88 CP ZGOTO ; "GOTO" token? +1525+ 0DAD CA B5 0D JP Z,IFGO ; Yes - Get line +1526+ 0DB0 CD F7 09 CALL CHKSYN ; Make sure it's "THEN" +1527+ 0DB3 A9 .BYTE ZTHEN ; "THEN" token +1528+ 0DB4 2B DEC HL ; Cancel increment +1529+ 0DB5 CD F1 0F IFGO: CALL TSTNUM ; Make sure it's numeric +1530+ 0DB8 CD D0 19 CALL TSTSGN ; Test state of expression +1531+ 0DBB CA 1A 0D JP Z,REM ; False - Drop through +1532+ 0DBE CD 81 0B CALL GETCHR ; Get next character +1533+ 0DC1 DA D5 0C JP C,GOTO ; Number - GOTO that line +1534+ 0DC4 C3 68 0B JP IFJMP ; Otherwise do statement +1535+ 0DC7 +1536+ 0DC7 2B MRPRNT: DEC HL ; DEC 'cos GETCHR INCs +1537+ 0DC8 CD 81 0B CALL GETCHR ; Get next character +1538+ 0DCB CA 29 0E PRINT: JP Z,PRNTCRLF ; CRLF if just PRINT +1539+ 0DCE C8 PRNTLP: RET Z ; End of list - Exit +1540+ 0DCF FE A5 CP ZTAB ; "TAB(" token? +1541+ 0DD1 CA 5C 0E JP Z,DOTAB ; Yes - Do TAB routine +1542+ 0DD4 FE A8 CP ZSPC ; "SPC(" token? +1543+ 0DD6 CA 5C 0E JP Z,DOTAB ; Yes - Do SPC routine +1544+ 0DD9 E5 PUSH HL ; Save code string address +1545+ 0DDA FE 2C CP ',' ; Comma? +1546+ 0DDC CA 45 0E JP Z,DOCOM ; Yes - Move to next zone +1547+ 0DDF FE 3B CP 59 ;";" ; Semi-colon? +1548+ 0DE1 CA 7F 0E JP Z,NEXITM ; Do semi-colon routine +1549+ 0DE4 C1 POP BC ; Code string address to BC +1550+ 0DE5 CD 00 10 CALL EVAL ; Evaluate expression +1551+ 0DE8 E5 PUSH HL ; Save code string address +1552+ 0DE9 3A 5D 31 LD A,(TYPE) ; Get variable type +1553+ 0DEC B7 OR A ; Is it a string variable? +1554+ 0DED C2 15 0E JP NZ,PRNTST ; Yes - Output string contents +1555+ 0DF0 CD 75 1B CALL NUMASC ; Convert number to text +1556+ 0DF3 CD 85 14 CALL CRTST ; Create temporary string +1557+ 0DF6 36 20 LD (HL),' ' ; Followed by a space +1558+ 0DF8 2A 94 31 LD HL,(FPREG) ; Get length of output +1559+ 0DFB 34 INC (HL) ; Plus 1 for the space +1560+ 0DFC 2A 94 31 LD HL,(FPREG) ; < Not needed > +1561+ 0DFF 3A F2 30 LD A,(LWIDTH) ; Get width of line +1562+ 0E02 47 LD B,A ; To B +1563+ 0E03 04 INC B ; Width 255 (No limit)? +1564+ 0E04 CA 11 0E JP Z,PRNTNB ; Yes - Output number string +1565+ 0E07 04 INC B ; Adjust it +1566+ 0E08 3A 5B 31 LD A,(CURPOS) ; Get cursor position +1567+ 0E0B 86 ADD A,(HL) ; Add length of string +1568+ 0E0C 3D DEC A ; Adjust it +1569+ 0E0D B8 CP B ; Will output fit on this line? +1570+ 0E0E D4 29 0E CALL NC,PRNTCRLF ; No - CRLF first +1571+ 0E11 CD CA 14 PRNTNB: CALL PRS1 ; Output string at (HL) +1572+ 0E14 AF XOR A ; Skip CALL by setting 'z' flag +1573+ 0E15 C4 CA 14 PRNTST: CALL NZ,PRS1 ; Output string at (HL) +1574+ 0E18 E1 POP HL ; Restore code string address +1575+ 0E19 C3 C7 0D JP MRPRNT ; See if more to PRINT +1576+ 0E1C +1577+ 0E1C 3A 5B 31 STTLIN: LD A,(CURPOS) ; Make sure on new line +1578+ 0E1F B7 OR A ; Already at start? +1579+ 0E20 C8 RET Z ; Yes - Do nothing +1580+ 0E21 C3 29 0E JP PRNTCRLF ; Start a new line +1581+ 0E24 +1582+ 0E24 36 00 ENDINP: LD (HL),0 ; Mark end of buffer +1583+ 0E26 21 10 31 LD HL,BUFFER-1 ; Point to buffer +1584+ 0E29 3E 0D PRNTCRLF: LD A,CR ; Load a CR +1585+ 0E2B CD 02 0A CALL OUTC ; Output character +1586+ 0E2E 3E 0A LD A,LF ; Load a LF +1587+ 0E30 CD 02 0A CALL OUTC ; Output character +1588+ 0E33 AF DONULL: XOR A ; Set to position 0 +1589+ 0E34 32 5B 31 LD (CURPOS),A ; Store it +1590+ 0E37 3A F1 30 LD A,(NULLS) ; Get number of nulls +1591+ 0E3A 3D NULLP: DEC A ; Count them +1592+ 0E3B C8 RET Z ; Return if done +1593+ 0E3C F5 PUSH AF ; Save count +1594+ 0E3D AF XOR A ; Load a null +1595+ 0E3E CD 02 0A CALL OUTC ; Output it +1596+ 0E41 F1 POP AF ; Restore count +1597+ 0E42 C3 3A 0E JP NULLP ; Keep counting +1598+ 0E45 +1599+ 0E45 3A F3 30 DOCOM: LD A,(COMMAN) ; Get comma width +1600+ 0E48 47 LD B,A ; Save in B +1601+ 0E49 3A 5B 31 LD A,(CURPOS) ; Get current position +1602+ 0E4C B8 CP B ; Within the limit? +1603+ 0E4D D4 29 0E CALL NC,PRNTCRLF ; No - output CRLF +1604+ 0E50 D2 7F 0E JP NC,NEXITM ; Get next item +1605+ 0E53 D6 0E ZONELP: SUB 14 ; Next zone of 14 characters +1606+ 0E55 D2 53 0E JP NC,ZONELP ; Repeat if more zones +1607+ 0E58 2F CPL ; Number of spaces to output +1608+ 0E59 C3 74 0E JP ASPCS ; Output them +1609+ 0E5C +1610+ 0E5C F5 DOTAB: PUSH AF ; Save token +1611+ 0E5D CD 4C 17 CALL FNDNUM ; Evaluate expression +1612+ 0E60 CD F7 09 CALL CHKSYN ; Make sure ")" follows +1613+ 0E63 29 .BYTE ")" +1614+ 0E64 2B DEC HL ; Back space on to ")" +1615+ 0E65 F1 POP AF ; Restore token +1616+ 0E66 D6 A8 SUB ZSPC ; Was it "SPC(" ? +1617+ 0E68 E5 PUSH HL ; Save code string address +1618+ 0E69 CA 6F 0E JP Z,DOSPC ; Yes - Do 'E' spaces +1619+ 0E6C 3A 5B 31 LD A,(CURPOS) ; Get current position +1620+ 0E6F 2F DOSPC: CPL ; Number of spaces to print to +1621+ 0E70 83 ADD A,E ; Total number to print +1622+ 0E71 D2 7F 0E JP NC,NEXITM ; TAB < Current POS(X) +1623+ 0E74 3C ASPCS: INC A ; Output A spaces +1624+ 0E75 47 LD B,A ; Save number to print +1625+ 0E76 3E 20 LD A,' ' ; Space +1626+ 0E78 CD 02 0A SPCLP: CALL OUTC ; Output character in A +1627+ 0E7B 05 DEC B ; Count them +1628+ 0E7C C2 78 0E JP NZ,SPCLP ; Repeat if more +1629+ 0E7F E1 NEXITM: POP HL ; Restore code string address +1630+ 0E80 CD 81 0B CALL GETCHR ; Get next character +1631+ 0E83 C3 CE 0D JP PRNTLP ; More to print +1632+ 0E86 +1633+ 0E86 3F 52 65 64 REDO: .BYTE "?Redo from start",CR,LF,0 +1633+ 0E8A 6F 20 66 72 +1633+ 0E8E 6F 6D 20 73 +1633+ 0E92 74 61 72 74 +1633+ 0E96 0D 0A 00 +1634+ 0E99 +1635+ 0E99 3A 7D 31 BADINP: LD A,(READFG) ; READ or INPUT? +1636+ 0E9C B7 OR A +1637+ 0E9D C2 23 07 JP NZ,DATSNR ; READ - ?SN Error +1638+ 0EA0 C1 POP BC ; Throw away code string addr +1639+ 0EA1 21 86 0E LD HL,REDO ; "Redo from start" message +1640+ 0EA4 CD C7 14 CALL PRS ; Output string +1641+ 0EA7 C3 74 08 JP DOAGN ; Do last INPUT again +1642+ 0EAA +1643+ 0EAA CD 32 14 INPUT: CALL IDTEST ; Test for illegal direct +1644+ 0EAD 7E LD A,(HL) ; Get character after "INPUT" +1645+ 0EAE FE 22 CP '"' ; Is there a prompt string? +1646+ 0EB0 3E 00 LD A,0 ; Clear A and leave flags +1647+ 0EB2 32 F5 30 LD (CTLOFG),A ; Enable output +1648+ 0EB5 C2 C4 0E JP NZ,NOPMPT ; No prompt - get input +1649+ 0EB8 CD 86 14 CALL QTSTR ; Get string terminated by '"' +1650+ 0EBB CD F7 09 CALL CHKSYN ; Check for ';' after prompt +1651+ 0EBE 3B .BYTE ';' +1652+ 0EBF E5 PUSH HL ; Save code string address +1653+ 0EC0 CD CA 14 CALL PRS1 ; Output prompt string +1654+ 0EC3 3E .BYTE 3EH ; Skip "PUSH HL" +1655+ 0EC4 E5 NOPMPT: PUSH HL ; Save code string address +1656+ 0EC5 CD 78 08 CALL PROMPT ; Get input with "? " prompt +1657+ 0EC8 C1 POP BC ; Restore code string address +1658+ 0EC9 DA D0 0B JP C,INPBRK ; Break pressed - Exit +1659+ 0ECC 23 INC HL ; Next byte +1660+ 0ECD 7E LD A,(HL) ; Get it +1661+ 0ECE B7 OR A ; End of line? +1662+ 0ECF 2B DEC HL ; Back again +1663+ 0ED0 C5 PUSH BC ; Re-save code string address +1664+ 0ED1 CA 17 0D JP Z,NXTDTA ; Yes - Find next DATA stmt +1665+ 0ED4 36 2C LD (HL),',' ; Store comma as separator +1666+ 0ED6 C3 DE 0E JP NXTITM ; Get next item +1667+ 0ED9 +1668+ 0ED9 E5 READ: PUSH HL ; Save code string address +1669+ 0EDA 2A 8C 31 LD HL,(NXTDAT) ; Next DATA statement +1670+ 0EDD F6 .BYTE 0F6H ; Flag "READ" +1671+ 0EDE AF NXTITM: XOR A ; Flag "INPUT" +1672+ 0EDF 32 7D 31 LD (READFG),A ; Save "READ"/"INPUT" flag +1673+ 0EE2 E3 EX (SP),HL ; Get code str' , Save pointer +1674+ 0EE3 C3 EA 0E JP GTVLUS ; Get values +1675+ 0EE6 +1676+ 0EE6 CD F7 09 NEDMOR: CALL CHKSYN ; Check for comma between items +1677+ 0EE9 2C .BYTE ',' +1678+ 0EEA CD E4 11 GTVLUS: CALL GETVAR ; Get variable name +1679+ 0EED E3 EX (SP),HL ; Save code str" , Get pointer +1680+ 0EEE D5 PUSH DE ; Save variable address +1681+ 0EEF 7E LD A,(HL) ; Get next "INPUT"/"DATA" byte +1682+ 0EF0 FE 2C CP ',' ; Comma? +1683+ 0EF2 CA 12 0F JP Z,ANTVLU ; Yes - Get another value +1684+ 0EF5 3A 7D 31 LD A,(READFG) ; Is it READ? +1685+ 0EF8 B7 OR A +1686+ 0EF9 C2 7F 0F JP NZ,FDTLP ; Yes - Find next DATA stmt +1687+ 0EFC 3E 3F LD A,'?' ; More INPUT needed +1688+ 0EFE CD 02 0A CALL OUTC ; Output character +1689+ 0F01 CD 78 08 CALL PROMPT ; Get INPUT with prompt +1690+ 0F04 D1 POP DE ; Variable address +1691+ 0F05 C1 POP BC ; Code string address +1692+ 0F06 DA D0 0B JP C,INPBRK ; Break pressed +1693+ 0F09 23 INC HL ; Point to next DATA byte +1694+ 0F0A 7E LD A,(HL) ; Get byte +1695+ 0F0B B7 OR A ; Is it zero (No input) ? +1696+ 0F0C 2B DEC HL ; Back space INPUT pointer +1697+ 0F0D C5 PUSH BC ; Save code string address +1698+ 0F0E CA 17 0D JP Z,NXTDTA ; Find end of buffer +1699+ 0F11 D5 PUSH DE ; Save variable address +1700+ 0F12 3A 5D 31 ANTVLU: LD A,(TYPE) ; Check data type +1701+ 0F15 B7 OR A ; Is it numeric? +1702+ 0F16 CA 3C 0F JP Z,INPBIN ; Yes - Convert to binary +1703+ 0F19 CD 81 0B CALL GETCHR ; Get next character +1704+ 0F1C 57 LD D,A ; Save input character +1705+ 0F1D 47 LD B,A ; Again +1706+ 0F1E FE 22 CP '"' ; Start of literal sting? +1707+ 0F20 CA 30 0F JP Z,STRENT ; Yes - Create string entry +1708+ 0F23 3A 7D 31 LD A,(READFG) ; "READ" or "INPUT" ? +1709+ 0F26 B7 OR A +1710+ 0F27 57 LD D,A ; Save 00 if "INPUT" +1711+ 0F28 CA 2D 0F JP Z,ITMSEP ; "INPUT" - End with 00 +1712+ 0F2B 16 3A LD D,':' ; "DATA" - End with 00 or ':' +1713+ 0F2D 06 2C ITMSEP: LD B,',' ; Item separator +1714+ 0F2F 2B DEC HL ; Back space for DTSTR +1715+ 0F30 CD 89 14 STRENT: CALL DTSTR ; Get string terminated by D +1716+ 0F33 EB EX DE,HL ; String address to DE +1717+ 0F34 21 47 0F LD HL,LTSTND ; Where to go after LETSTR +1718+ 0F37 E3 EX (SP),HL ; Save HL , get input pointer +1719+ 0F38 D5 PUSH DE ; Save address of string +1720+ 0F39 C3 4A 0D JP LETSTR ; Assign string to variable +1721+ 0F3C +1722+ 0F3C CD 81 0B INPBIN: CALL GETCHR ; Get next character +1723+ 0F3F CD D7 1A CALL ASCTFP ; Convert ASCII to FP number +1724+ 0F42 E3 EX (SP),HL ; Save input ptr, Get var addr +1725+ 0F43 CD 28 1A CALL FPTHL ; Move FPREG to variable +1726+ 0F46 E1 POP HL ; Restore input pointer +1727+ 0F47 2B LTSTND: DEC HL ; DEC 'cos GETCHR INCs +1728+ 0F48 CD 81 0B CALL GETCHR ; Get next character +1729+ 0F4B CA 53 0F JP Z,MORDT ; End of line - More needed? +1730+ 0F4E FE 2C CP ',' ; Another value? +1731+ 0F50 C2 99 0E JP NZ,BADINP ; No - Bad input +1732+ 0F53 E3 MORDT: EX (SP),HL ; Get code string address +1733+ 0F54 2B DEC HL ; DEC 'cos GETCHR INCs +1734+ 0F55 CD 81 0B CALL GETCHR ; Get next character +1735+ 0F58 C2 E6 0E JP NZ,NEDMOR ; More needed - Get it +1736+ 0F5B D1 POP DE ; Restore DATA pointer +1737+ 0F5C 3A 7D 31 LD A,(READFG) ; "READ" or "INPUT" ? +1738+ 0F5F B7 OR A +1739+ 0F60 EB EX DE,HL ; DATA pointer to HL +1740+ 0F61 C2 A7 0B JP NZ,UPDATA ; Update DATA pointer if "READ" +1741+ 0F64 D5 PUSH DE ; Save code string address +1742+ 0F65 B6 OR (HL) ; More input given? +1743+ 0F66 21 6E 0F LD HL,EXTIG ; "?Extra ignored" message +1744+ 0F69 C4 C7 14 CALL NZ,PRS ; Output string if extra given +1745+ 0F6C E1 POP HL ; Restore code string address +1746+ 0F6D C9 RET +1747+ 0F6E +1748+ 0F6E 3F 45 78 74 EXTIG: .BYTE "?Extra ignored",CR,LF,0 +1748+ 0F72 72 61 20 69 +1748+ 0F76 67 6E 6F 72 +1748+ 0F7A 65 64 0D 0A +1748+ 0F7E 00 +1749+ 0F7F +1750+ 0F7F CD 18 0D FDTLP: CALL DATA ; Get next statement +1751+ 0F82 B7 OR A ; End of line? +1752+ 0F83 C2 98 0F JP NZ,FANDT ; No - See if DATA statement +1753+ 0F86 23 INC HL +1754+ 0F87 7E LD A,(HL) ; End of program? +1755+ 0F88 23 INC HL +1756+ 0F89 B6 OR (HL) ; 00 00 Ends program +1757+ 0F8A 1E 06 LD E,OD ; ?OD Error +1758+ 0F8C CA 3D 07 JP Z,ERROR ; Yes - Out of DATA +1759+ 0F8F 23 INC HL +1760+ 0F90 5E LD E,(HL) ; LSB of line number +1761+ 0F91 23 INC HL +1762+ 0F92 56 LD D,(HL) ; MSB of line number +1763+ 0F93 EB EX DE,HL +1764+ 0F94 22 79 31 LD (DATLIN),HL ; Set line of current DATA item +1765+ 0F97 EB EX DE,HL +1766+ 0F98 CD 81 0B FANDT: CALL GETCHR ; Get next character +1767+ 0F9B FE 83 CP ZDATA ; "DATA" token +1768+ 0F9D C2 7F 0F JP NZ,FDTLP ; No "DATA" - Keep looking +1769+ 0FA0 C3 12 0F JP ANTVLU ; Found - Convert input +1770+ 0FA3 +1771+ 0FA3 11 00 00 NEXT: LD DE,0 ; In case no index given +1772+ 0FA6 C4 E4 11 NEXT1: CALL NZ,GETVAR ; Get index address +1773+ 0FA9 22 7E 31 LD (BRKLIN),HL ; Save code string address +1774+ 0FAC CD D2 06 CALL BAKSTK ; Look for "FOR" block +1775+ 0FAF C2 2F 07 JP NZ,NFERR ; No "FOR" - ?NF Error +1776+ 0FB2 F9 LD SP,HL ; Clear nested loops +1777+ 0FB3 D5 PUSH DE ; Save index address +1778+ 0FB4 7E LD A,(HL) ; Get sign of STEP +1779+ 0FB5 23 INC HL +1780+ 0FB6 F5 PUSH AF ; Save sign of STEP +1781+ 0FB7 D5 PUSH DE ; Save index address +1782+ 0FB8 CD 0E 1A CALL PHLTFP ; Move index value to FPREG +1783+ 0FBB E3 EX (SP),HL ; Save address of TO value +1784+ 0FBC E5 PUSH HL ; Save address of index +1785+ 0FBD CD 7B 17 CALL ADDPHL ; Add STEP to index value +1786+ 0FC0 E1 POP HL ; Restore address of index +1787+ 0FC1 CD 28 1A CALL FPTHL ; Move value to index variable +1788+ 0FC4 E1 POP HL ; Restore address of TO value +1789+ 0FC5 CD 1F 1A CALL LOADFP ; Move TO value to BCDE +1790+ 0FC8 E5 PUSH HL ; Save address of line of FOR +1791+ 0FC9 CD 4B 1A CALL CMPNUM ; Compare index with TO value +1792+ 0FCC E1 POP HL ; Restore address of line num +1793+ 0FCD C1 POP BC ; Address of sign of STEP +1794+ 0FCE 90 SUB B ; Compare with expected sign +1795+ 0FCF CD 1F 1A CALL LOADFP ; BC = Loop stmt,DE = Line num +1796+ 0FD2 CA DE 0F JP Z,KILFOR ; Loop finished - Terminate it +1797+ 0FD5 EB EX DE,HL ; Loop statement line number +1798+ 0FD6 22 0C 31 LD (LINEAT),HL ; Set loop line number +1799+ 0FD9 69 LD L,C ; Set code string to loop +1800+ 0FDA 60 LD H,B +1801+ 0FDB C3 3D 0B JP PUTFID ; Put back "FOR" and continue +1802+ 0FDE +1803+ 0FDE F9 KILFOR: LD SP,HL ; Remove "FOR" block +1804+ 0FDF 2A 7E 31 LD HL,(BRKLIN) ; Code string after "NEXT" +1805+ 0FE2 7E LD A,(HL) ; Get next byte in code string +1806+ 0FE3 FE 2C CP ',' ; More NEXTs ? +1807+ 0FE5 C2 41 0B JP NZ,RUNCNT ; No - Do next statement +1808+ 0FE8 CD 81 0B CALL GETCHR ; Position to index name +1809+ 0FEB CD A6 0F CALL NEXT1 ; Re-enter NEXT routine +1810+ 0FEE ; < will not RETurn to here , Exit to RUNCNT or Loop > +1811+ 0FEE +1812+ 0FEE CD 00 10 GETNUM: CALL EVAL ; Get a numeric expression +1813+ 0FF1 F6 TSTNUM: .BYTE 0F6H ; Clear carry (numeric) +1814+ 0FF2 37 TSTSTR: SCF ; Set carry (string) +1815+ 0FF3 3A 5D 31 CHKTYP: LD A,(TYPE) ; Check types match +1816+ 0FF6 8F ADC A,A ; Expected + actual +1817+ 0FF7 B7 OR A ; Clear carry , set parity +1818+ 0FF8 E8 RET PE ; Even parity - Types match +1819+ 0FF9 C3 3B 07 JP TMERR ; Different types - Error +1820+ 0FFC +1821+ 0FFC CD F7 09 OPNPAR: CALL CHKSYN ; Make sure "(" follows +1822+ 0FFF 28 .BYTE "(" +1823+ 1000 2B EVAL: DEC HL ; Evaluate expression & save +1824+ 1001 16 00 LD D,0 ; Precedence value +1825+ 1003 D5 EVAL1: PUSH DE ; Save precedence +1826+ 1004 0E 01 LD C,1 +1827+ 1006 CD 06 07 CALL CHKSTK ; Check for 1 level of stack +1828+ 1009 CD 77 10 CALL OPRND ; Get next expression value +1829+ 100C 22 80 31 EVAL2: LD (NXTOPR),HL ; Save address of next operator +1830+ 100F 2A 80 31 EVAL3: LD HL,(NXTOPR) ; Restore address of next opr +1831+ 1012 C1 POP BC ; Precedence value and operator +1832+ 1013 78 LD A,B ; Get precedence value +1833+ 1014 FE 78 CP 78H ; "AND" or "OR" ? +1834+ 1016 D4 F1 0F CALL NC,TSTNUM ; No - Make sure it's a number +1835+ 1019 7E LD A,(HL) ; Get next operator / function +1836+ 101A 16 00 LD D,0 ; Clear Last relation +1837+ 101C D6 B3 RLTLP: SUB ZGTR ; ">" Token +1838+ 101E DA 38 10 JP C,FOPRND ; + - * / ^ AND OR - Test it +1839+ 1021 FE 03 CP ZLTH+1-ZGTR ; < = > +1840+ 1023 D2 38 10 JP NC,FOPRND ; Function - Call it +1841+ 1026 FE 01 CP ZEQUAL-ZGTR ; "=" +1842+ 1028 17 RLA ; <- Test for legal +1843+ 1029 AA XOR D ; <- combinations of < = > +1844+ 102A BA CP D ; <- by combining last token +1845+ 102B 57 LD D,A ; <- with current one +1846+ 102C DA 29 07 JP C,SNERR ; Error if "<<' '==" or ">>" +1847+ 102F 22 75 31 LD (CUROPR),HL ; Save address of current token +1848+ 1032 CD 81 0B CALL GETCHR ; Get next character +1849+ 1035 C3 1C 10 JP RLTLP ; Treat the two as one +1850+ 1038 +1851+ 1038 7A FOPRND: LD A,D ; < = > found ? +1852+ 1039 B7 OR A +1853+ 103A C2 5F 11 JP NZ,TSTRED ; Yes - Test for reduction +1854+ 103D 7E LD A,(HL) ; Get operator token +1855+ 103E 22 75 31 LD (CUROPR),HL ; Save operator address +1856+ 1041 D6 AC SUB ZPLUS ; Operator or function? +1857+ 1043 D8 RET C ; Neither - Exit +1858+ 1044 FE 07 CP ZOR+1-ZPLUS ; Is it + - * / ^ AND OR ? +1859+ 1046 D0 RET NC ; No - Exit +1860+ 1047 5F LD E,A ; Coded operator +1861+ 1048 3A 5D 31 LD A,(TYPE) ; Get data type +1862+ 104B 3D DEC A ; FF = numeric , 00 = string +1863+ 104C B3 OR E ; Combine with coded operator +1864+ 104D 7B LD A,E ; Get coded operator +1865+ 104E CA BD 15 JP Z,CONCAT ; String concatenation +1866+ 1051 07 RLCA ; Times 2 +1867+ 1052 83 ADD A,E ; Times 3 +1868+ 1053 5F LD E,A ; To DE (D is 0) +1869+ 1054 21 1B 06 LD HL,PRITAB ; Precedence table +1870+ 1057 19 ADD HL,DE ; To the operator concerned +1871+ 1058 78 LD A,B ; Last operator precedence +1872+ 1059 56 LD D,(HL) ; Get evaluation precedence +1873+ 105A BA CP D ; Compare with eval precedence +1874+ 105B D0 RET NC ; Exit if higher precedence +1875+ 105C 23 INC HL ; Point to routine address +1876+ 105D CD F1 0F CALL TSTNUM ; Make sure it's a number +1877+ 1060 +1878+ 1060 C5 STKTHS: PUSH BC ; Save last precedence & token +1879+ 1061 01 0F 10 LD BC,EVAL3 ; Where to go on prec' break +1880+ 1064 C5 PUSH BC ; Save on stack for return +1881+ 1065 43 LD B,E ; Save operator +1882+ 1066 4A LD C,D ; Save precedence +1883+ 1067 CD 01 1A CALL STAKFP ; Move value to stack +1884+ 106A 58 LD E,B ; Restore operator +1885+ 106B 51 LD D,C ; Restore precedence +1886+ 106C 4E LD C,(HL) ; Get LSB of routine address +1887+ 106D 23 INC HL +1888+ 106E 46 LD B,(HL) ; Get MSB of routine address +1889+ 106F 23 INC HL +1890+ 1070 C5 PUSH BC ; Save routine address +1891+ 1071 2A 75 31 LD HL,(CUROPR) ; Address of current operator +1892+ 1074 C3 03 10 JP EVAL1 ; Loop until prec' break +1893+ 1077 +1894+ 1077 AF OPRND: XOR A ; Get operand routine +1895+ 1078 32 5D 31 LD (TYPE),A ; Set numeric expected +1896+ 107B CD 81 0B CALL GETCHR ; Get next character +1897+ 107E 1E 24 LD E,MO ; ?MO Error +1898+ 1080 CA 3D 07 JP Z,ERROR ; No operand - Error +1899+ 1083 DA D7 1A JP C,ASCTFP ; Number - Get value +1900+ 1086 CD 1F 0C CALL CHKLTR ; See if a letter +1901+ 1089 D2 DE 10 JP NC,CONVAR ; Letter - Find variable +1902+ 108C FE 26 CP '&' ; &H = HEX, &B = BINARY +1903+ 108E 20 12 JR NZ, NOTAMP +1904+ 1090 CD 81 0B CALL GETCHR ; Get next character +1905+ 1093 FE 48 CP 'H' ; Hex number indicated? [function added] +1906+ 1095 CA 1B 1F JP Z,HEXTFP ; Convert Hex to FPREG +1907+ 1098 FE 42 CP 'B' ; Binary number indicated? [function added] +1908+ 109A CA 8B 1F JP Z,BINTFP ; Convert Bin to FPREG +1909+ 109D 1E 02 LD E,SN ; If neither then a ?SN Error +1910+ 109F CA 3D 07 JP Z,ERROR ; +1911+ 10A2 FE AC NOTAMP: CP ZPLUS ; '+' Token ? +1912+ 10A4 CA 77 10 JP Z,OPRND ; Yes - Look for operand +1913+ 10A7 FE 2E CP '.' ; '.' ? +1914+ 10A9 CA D7 1A JP Z,ASCTFP ; Yes - Create FP number +1915+ 10AC FE AD CP ZMINUS ; '-' Token ? +1916+ 10AE CA CD 10 JP Z,MINUS ; Yes - Do minus +1917+ 10B1 FE 22 CP '"' ; Literal string ? +1918+ 10B3 CA 86 14 JP Z,QTSTR ; Get string terminated by '"' +1919+ 10B6 FE AA CP ZNOT ; "NOT" Token ? +1920+ 10B8 CA BF 11 JP Z,EVNOT ; Yes - Eval NOT expression +1921+ 10BB FE A7 CP ZFN ; "FN" Token ? +1922+ 10BD CA EA 13 JP Z,DOFN ; Yes - Do FN routine +1923+ 10C0 D6 B6 SUB ZSGN ; Is it a function? +1924+ 10C2 D2 EF 10 JP NC,FNOFST ; Yes - Evaluate function +1925+ 10C5 CD FC 0F EVLPAR: CALL OPNPAR ; Evaluate expression in "()" +1926+ 10C8 CD F7 09 CALL CHKSYN ; Make sure ")" follows +1927+ 10CB 29 .BYTE ")" +1928+ 10CC C9 RET +1929+ 10CD +1930+ 10CD 16 7D MINUS: LD D,7DH ; '-' precedence +1931+ 10CF CD 03 10 CALL EVAL1 ; Evaluate until prec' break +1932+ 10D2 2A 80 31 LD HL,(NXTOPR) ; Get next operator address +1933+ 10D5 E5 PUSH HL ; Save next operator address +1934+ 10D6 CD F9 19 CALL INVSGN ; Negate value +1935+ 10D9 CD F1 0F RETNUM: CALL TSTNUM ; Make sure it's a number +1936+ 10DC E1 POP HL ; Restore next operator address +1937+ 10DD C9 RET +1938+ 10DE +1939+ 10DE CD E4 11 CONVAR: CALL GETVAR ; Get variable address to DE +1940+ 10E1 E5 FRMEVL: PUSH HL ; Save code string address +1941+ 10E2 EB EX DE,HL ; Variable address to HL +1942+ 10E3 22 94 31 LD (FPREG),HL ; Save address of variable +1943+ 10E6 3A 5D 31 LD A,(TYPE) ; Get type +1944+ 10E9 B7 OR A ; Numeric? +1945+ 10EA CC 0E 1A CALL Z,PHLTFP ; Yes - Move contents to FPREG +1946+ 10ED E1 POP HL ; Restore code string address +1947+ 10EE C9 RET +1948+ 10EF +1949+ 10EF 06 00 FNOFST: LD B,0 ; Get address of function +1950+ 10F1 07 RLCA ; Double function offset +1951+ 10F2 4F LD C,A ; BC = Offset in function table +1952+ 10F3 C5 PUSH BC ; Save adjusted token value +1953+ 10F4 CD 81 0B CALL GETCHR ; Get next character +1954+ 10F7 79 LD A,C ; Get adjusted token value +1955+ 10F8 FE 31 CP 2*(ZLEFT-ZSGN)-1; Adj' LEFT$,RIGHT$ or MID$ ? +1956+ 10FA DA 16 11 JP C,FNVAL ; No - Do function +1957+ 10FD CD FC 0F CALL OPNPAR ; Evaluate expression (X,... +1958+ 1100 CD F7 09 CALL CHKSYN ; Make sure ',' follows +1959+ 1103 2C .BYTE ',' +1960+ 1104 CD F2 0F CALL TSTSTR ; Make sure it's a string +1961+ 1107 EB EX DE,HL ; Save code string address +1962+ 1108 2A 94 31 LD HL,(FPREG) ; Get address of string +1963+ 110B E3 EX (SP),HL ; Save address of string +1964+ 110C E5 PUSH HL ; Save adjusted token value +1965+ 110D EB EX DE,HL ; Restore code string address +1966+ 110E CD 4F 17 CALL GETINT ; Get integer 0-255 +1967+ 1111 EB EX DE,HL ; Save code string address +1968+ 1112 E3 EX (SP),HL ; Save integer,HL = adj' token +1969+ 1113 C3 1E 11 JP GOFUNC ; Jump to string function +1970+ 1116 +1971+ 1116 CD C5 10 FNVAL: CALL EVLPAR ; Evaluate expression +1972+ 1119 E3 EX (SP),HL ; HL = Adjusted token value +1973+ 111A 11 D9 10 LD DE,RETNUM ; Return number from function +1974+ 111D D5 PUSH DE ; Save on stack +1975+ 111E 01 7A 04 GOFUNC: LD BC,FNCTAB ; Function routine addresses +1976+ 1121 09 ADD HL,BC ; Point to right address +1977+ 1122 4E LD C,(HL) ; Get LSB of address +1978+ 1123 23 INC HL ; +1979+ 1124 66 LD H,(HL) ; Get MSB of address +1980+ 1125 69 LD L,C ; Address to HL +1981+ 1126 E9 JP (HL) ; Jump to function +1982+ 1127 +1983+ 1127 15 SGNEXP: DEC D ; Dee to flag negative exponent +1984+ 1128 FE AD CP ZMINUS ; '-' token ? +1985+ 112A C8 RET Z ; Yes - Return +1986+ 112B FE 2D CP '-' ; '-' ASCII ? +1987+ 112D C8 RET Z ; Yes - Return +1988+ 112E 14 INC D ; Inc to flag positive exponent +1989+ 112F FE 2B CP '+' ; '+' ASCII ? +1990+ 1131 C8 RET Z ; Yes - Return +1991+ 1132 FE AC CP ZPLUS ; '+' token ? +1992+ 1134 C8 RET Z ; Yes - Return +1993+ 1135 2B DEC HL ; DEC 'cos GETCHR INCs +1994+ 1136 C9 RET ; Return "NZ" +1995+ 1137 +1996+ 1137 F6 POR: .BYTE 0F6H ; Flag "OR" +1997+ 1138 AF PAND: XOR A ; Flag "AND" +1998+ 1139 F5 PUSH AF ; Save "AND" / "OR" flag +1999+ 113A CD F1 0F CALL TSTNUM ; Make sure it's a number +2000+ 113D CD 33 0C CALL DEINT ; Get integer -32768 to 32767 +2001+ 1140 F1 POP AF ; Restore "AND" / "OR" flag +2002+ 1141 EB EX DE,HL ; <- Get last +2003+ 1142 C1 POP BC ; <- value +2004+ 1143 E3 EX (SP),HL ; <- from +2005+ 1144 EB EX DE,HL ; <- stack +2006+ 1145 CD 11 1A CALL FPBCDE ; Move last value to FPREG +2007+ 1148 F5 PUSH AF ; Save "AND" / "OR" flag +2008+ 1149 CD 33 0C CALL DEINT ; Get integer -32768 to 32767 +2009+ 114C F1 POP AF ; Restore "AND" / "OR" flag +2010+ 114D C1 POP BC ; Get value +2011+ 114E 79 LD A,C ; Get LSB +2012+ 114F 21 A8 13 LD HL,ACPASS ; Address of save AC as current +2013+ 1152 C2 5A 11 JP NZ,POR1 ; Jump if OR +2014+ 1155 A3 AND E ; "AND" LSBs +2015+ 1156 4F LD C,A ; Save LSB +2016+ 1157 78 LD A,B ; Get MBS +2017+ 1158 A2 AND D ; "AND" MSBs +2018+ 1159 E9 JP (HL) ; Save AC as current (ACPASS) +2019+ 115A +2020+ 115A B3 POR1: OR E ; "OR" LSBs +2021+ 115B 4F LD C,A ; Save LSB +2022+ 115C 78 LD A,B ; Get MSB +2023+ 115D B2 OR D ; "OR" MSBs +2024+ 115E E9 JP (HL) ; Save AC as current (ACPASS) +2025+ 115F +2026+ 115F 21 71 11 TSTRED: LD HL,CMPLOG ; Logical compare routine +2027+ 1162 3A 5D 31 LD A,(TYPE) ; Get data type +2028+ 1165 1F RRA ; Carry set = string +2029+ 1166 7A LD A,D ; Get last precedence value +2030+ 1167 17 RLA ; Times 2 plus carry +2031+ 1168 5F LD E,A ; To E +2032+ 1169 16 64 LD D,64H ; Relational precedence +2033+ 116B 78 LD A,B ; Get current precedence +2034+ 116C BA CP D ; Compare with last +2035+ 116D D0 RET NC ; Eval if last was rel' or log' +2036+ 116E C3 60 10 JP STKTHS ; Stack this one and get next +2037+ 1171 +2038+ 1171 73 11 CMPLOG: .WORD CMPLG1 ; Compare two values / strings +2039+ 1173 79 CMPLG1: LD A,C ; Get data type +2040+ 1174 B7 OR A +2041+ 1175 1F RRA +2042+ 1176 C1 POP BC ; Get last expression to BCDE +2043+ 1177 D1 POP DE +2044+ 1178 F5 PUSH AF ; Save status +2045+ 1179 CD F3 0F CALL CHKTYP ; Check that types match +2046+ 117C 21 B5 11 LD HL,CMPRES ; Result to comparison +2047+ 117F E5 PUSH HL ; Save for RETurn +2048+ 1180 CA 4B 1A JP Z,CMPNUM ; Compare values if numeric +2049+ 1183 AF XOR A ; Compare two strings +2050+ 1184 32 5D 31 LD (TYPE),A ; Set type to numeric +2051+ 1187 D5 PUSH DE ; Save string name +2052+ 1188 CD 0A 16 CALL GSTRCU ; Get current string +2053+ 118B 7E LD A,(HL) ; Get length of string +2054+ 118C 23 INC HL +2055+ 118D 23 INC HL +2056+ 118E 4E LD C,(HL) ; Get LSB of address +2057+ 118F 23 INC HL +2058+ 1190 46 LD B,(HL) ; Get MSB of address +2059+ 1191 D1 POP DE ; Restore string name +2060+ 1192 C5 PUSH BC ; Save address of string +2061+ 1193 F5 PUSH AF ; Save length of string +2062+ 1194 CD 0E 16 CALL GSTRDE ; Get second string +2063+ 1197 CD 1F 1A CALL LOADFP ; Get address of second string +2064+ 119A F1 POP AF ; Restore length of string 1 +2065+ 119B 57 LD D,A ; Length to D +2066+ 119C E1 POP HL ; Restore address of string 1 +2067+ 119D 7B CMPSTR: LD A,E ; Bytes of string 2 to do +2068+ 119E B2 OR D ; Bytes of string 1 to do +2069+ 119F C8 RET Z ; Exit if all bytes compared +2070+ 11A0 7A LD A,D ; Get bytes of string 1 to do +2071+ 11A1 D6 01 SUB 1 +2072+ 11A3 D8 RET C ; Exit if end of string 1 +2073+ 11A4 AF XOR A +2074+ 11A5 BB CP E ; Bytes of string 2 to do +2075+ 11A6 3C INC A +2076+ 11A7 D0 RET NC ; Exit if end of string 2 +2077+ 11A8 15 DEC D ; Count bytes in string 1 +2078+ 11A9 1D DEC E ; Count bytes in string 2 +2079+ 11AA 0A LD A,(BC) ; Byte in string 2 +2080+ 11AB BE CP (HL) ; Compare to byte in string 1 +2081+ 11AC 23 INC HL ; Move up string 1 +2082+ 11AD 03 INC BC ; Move up string 2 +2083+ 11AE CA 9D 11 JP Z,CMPSTR ; Same - Try next bytes +2084+ 11B1 3F CCF ; Flag difference (">" or "<") +2085+ 11B2 C3 DB 19 JP FLGDIF ; "<" gives -1 , ">" gives +1 +2086+ 11B5 +2087+ 11B5 3C CMPRES: INC A ; Increment current value +2088+ 11B6 8F ADC A,A ; Double plus carry +2089+ 11B7 C1 POP BC ; Get other value +2090+ 11B8 A0 AND B ; Combine them +2091+ 11B9 C6 FF ADD A,-1 ; Carry set if different +2092+ 11BB 9F SBC A,A ; 00 - Equal , FF - Different +2093+ 11BC C3 E2 19 JP FLGREL ; Set current value & continue +2094+ 11BF +2095+ 11BF 16 5A EVNOT: LD D,5AH ; Precedence value for "NOT" +2096+ 11C1 CD 03 10 CALL EVAL1 ; Eval until precedence break +2097+ 11C4 CD F1 0F CALL TSTNUM ; Make sure it's a number +2098+ 11C7 CD 33 0C CALL DEINT ; Get integer -32768 - 32767 +2099+ 11CA 7B LD A,E ; Get LSB +2100+ 11CB 2F CPL ; Invert LSB +2101+ 11CC 4F LD C,A ; Save "NOT" of LSB +2102+ 11CD 7A LD A,D ; Get MSB +2103+ 11CE 2F CPL ; Invert MSB +2104+ 11CF CD A8 13 CALL ACPASS ; Save AC as current +2105+ 11D2 C1 POP BC ; Clean up stack +2106+ 11D3 C3 0F 10 JP EVAL3 ; Continue evaluation +2107+ 11D6 +2108+ 11D6 2B DIMRET: DEC HL ; DEC 'cos GETCHR INCs +2109+ 11D7 CD 81 0B CALL GETCHR ; Get next character +2110+ 11DA C8 RET Z ; End of DIM statement +2111+ 11DB CD F7 09 CALL CHKSYN ; Make sure ',' follows +2112+ 11DE 2C .BYTE ',' +2113+ 11DF 01 D6 11 DIM: LD BC,DIMRET ; Return to "DIMRET" +2114+ 11E2 C5 PUSH BC ; Save on stack +2115+ 11E3 F6 .BYTE 0F6H ; Flag "Create" variable +2116+ 11E4 AF GETVAR: XOR A ; Find variable address,to DE +2117+ 11E5 32 5C 31 LD (LCRFLG),A ; Set locate / create flag +2118+ 11E8 46 LD B,(HL) ; Get First byte of name +2119+ 11E9 CD 1F 0C GTFNAM: CALL CHKLTR ; See if a letter +2120+ 11EC DA 29 07 JP C,SNERR ; ?SN Error if not a letter +2121+ 11EF AF XOR A +2122+ 11F0 4F LD C,A ; Clear second byte of name +2123+ 11F1 32 5D 31 LD (TYPE),A ; Set type to numeric +2124+ 11F4 CD 81 0B CALL GETCHR ; Get next character +2125+ 11F7 DA 00 12 JP C,SVNAM2 ; Numeric - Save in name +2126+ 11FA CD 1F 0C CALL CHKLTR ; See if a letter +2127+ 11FD DA 0D 12 JP C,CHARTY ; Not a letter - Check type +2128+ 1200 4F SVNAM2: LD C,A ; Save second byte of name +2129+ 1201 CD 81 0B ENDNAM: CALL GETCHR ; Get next character +2130+ 1204 DA 01 12 JP C,ENDNAM ; Numeric - Get another +2131+ 1207 CD 1F 0C CALL CHKLTR ; See if a letter +2132+ 120A D2 01 12 JP NC,ENDNAM ; Letter - Get another +2133+ 120D D6 24 CHARTY: SUB '$' ; String variable? +2134+ 120F C2 1C 12 JP NZ,NOTSTR ; No - Numeric variable +2135+ 1212 3C INC A ; A = 1 (string type) +2136+ 1213 32 5D 31 LD (TYPE),A ; Set type to string +2137+ 1216 0F RRCA ; A = 80H , Flag for string +2138+ 1217 81 ADD A,C ; 2nd byte of name has bit 7 on +2139+ 1218 4F LD C,A ; Resave second byte on name +2140+ 1219 CD 81 0B CALL GETCHR ; Get next character +2141+ 121C 3A 7B 31 NOTSTR: LD A,(FORFLG) ; Array name needed ? +2142+ 121F 3D DEC A +2143+ 1220 CA C9 12 JP Z,ARLDSV ; Yes - Get array name +2144+ 1223 F2 2C 12 JP P,NSCFOR ; No array with "FOR" or "FN" +2145+ 1226 7E LD A,(HL) ; Get byte again +2146+ 1227 D6 28 SUB '(' ; Subscripted variable? +2147+ 1229 CA A1 12 JP Z,SBSCPT ; Yes - Sort out subscript +2148+ 122C +2149+ 122C AF NSCFOR: XOR A ; Simple variable +2150+ 122D 32 7B 31 LD (FORFLG),A ; Clear "FOR" flag +2151+ 1230 E5 PUSH HL ; Save code string address +2152+ 1231 50 LD D,B ; DE = Variable name to find +2153+ 1232 59 LD E,C +2154+ 1233 2A 8E 31 LD HL,(FNRGNM) ; FN argument name +2155+ 1236 CD F1 09 CALL CPDEHL ; Is it the FN argument? +2156+ 1239 11 90 31 LD DE,FNARG ; Point to argument value +2157+ 123C CA 11 19 JP Z,POPHRT ; Yes - Return FN argument value +2158+ 123F 2A 88 31 LD HL,(VAREND) ; End of variables +2159+ 1242 EB EX DE,HL ; Address of end of search +2160+ 1243 2A 86 31 LD HL,(PROGND) ; Start of variables address +2161+ 1246 CD F1 09 FNDVAR: CALL CPDEHL ; End of variable list table? +2162+ 1249 CA 5F 12 JP Z,CFEVAL ; Yes - Called from EVAL? +2163+ 124C 79 LD A,C ; Get second byte of name +2164+ 124D 96 SUB (HL) ; Compare with name in list +2165+ 124E 23 INC HL ; Move on to first byte +2166+ 124F C2 54 12 JP NZ,FNTHR ; Different - Find another +2167+ 1252 78 LD A,B ; Get first byte of name +2168+ 1253 96 SUB (HL) ; Compare with name in list +2169+ 1254 23 FNTHR: INC HL ; Move on to LSB of value +2170+ 1255 CA 93 12 JP Z,RETADR ; Found - Return address +2171+ 1258 23 INC HL ; <- Skip +2172+ 1259 23 INC HL ; <- over +2173+ 125A 23 INC HL ; <- F.P. +2174+ 125B 23 INC HL ; <- value +2175+ 125C C3 46 12 JP FNDVAR ; Keep looking +2176+ 125F +2177+ 125F E1 CFEVAL: POP HL ; Restore code string address +2178+ 1260 E3 EX (SP),HL ; Get return address +2179+ 1261 D5 PUSH DE ; Save address of variable +2180+ 1262 11 E1 10 LD DE,FRMEVL ; Return address in EVAL +2181+ 1265 CD F1 09 CALL CPDEHL ; Called from EVAL ? +2182+ 1268 D1 POP DE ; Restore address of variable +2183+ 1269 CA 96 12 JP Z,RETNUL ; Yes - Return null variable +2184+ 126C E3 EX (SP),HL ; Put back return +2185+ 126D E5 PUSH HL ; Save code string address +2186+ 126E C5 PUSH BC ; Save variable name +2187+ 126F 01 06 00 LD BC,6 ; 2 byte name plus 4 byte data +2188+ 1272 2A 8A 31 LD HL,(ARREND) ; End of arrays +2189+ 1275 E5 PUSH HL ; Save end of arrays +2190+ 1276 09 ADD HL,BC ; Move up 6 bytes +2191+ 1277 C1 POP BC ; Source address in BC +2192+ 1278 E5 PUSH HL ; Save new end address +2193+ 1279 CD F5 06 CALL MOVUP ; Move arrays up +2194+ 127C E1 POP HL ; Restore new end address +2195+ 127D 22 8A 31 LD (ARREND),HL ; Set new end address +2196+ 1280 60 LD H,B ; End of variables to HL +2197+ 1281 69 LD L,C +2198+ 1282 22 88 31 LD (VAREND),HL ; Set new end address +2199+ 1285 +2200+ 1285 2B ZEROLP: DEC HL ; Back through to zero variable +2201+ 1286 36 00 LD (HL),0 ; Zero byte in variable +2202+ 1288 CD F1 09 CALL CPDEHL ; Done them all? +2203+ 128B C2 85 12 JP NZ,ZEROLP ; No - Keep on going +2204+ 128E D1 POP DE ; Get variable name +2205+ 128F 73 LD (HL),E ; Store second character +2206+ 1290 23 INC HL +2207+ 1291 72 LD (HL),D ; Store first character +2208+ 1292 23 INC HL +2209+ 1293 EB RETADR: EX DE,HL ; Address of variable in DE +2210+ 1294 E1 POP HL ; Restore code string address +2211+ 1295 C9 RET +2212+ 1296 +2213+ 1296 32 97 31 RETNUL: LD (FPEXP),A ; Set result to zero +2214+ 1299 21 C5 06 LD HL,ZERBYT ; Also set a null string +2215+ 129C 22 94 31 LD (FPREG),HL ; Save for EVAL +2216+ 129F E1 POP HL ; Restore code string address +2217+ 12A0 C9 RET +2218+ 12A1 +2219+ 12A1 E5 SBSCPT: PUSH HL ; Save code string address +2220+ 12A2 2A 5C 31 LD HL,(LCRFLG) ; Locate/Create and Type +2221+ 12A5 E3 EX (SP),HL ; Save and get code string +2222+ 12A6 57 LD D,A ; Zero number of dimensions +2223+ 12A7 D5 SCPTLP: PUSH DE ; Save number of dimensions +2224+ 12A8 C5 PUSH BC ; Save array name +2225+ 12A9 CD 27 0C CALL FPSINT ; Get subscript (0-32767) +2226+ 12AC C1 POP BC ; Restore array name +2227+ 12AD F1 POP AF ; Get number of dimensions +2228+ 12AE EB EX DE,HL +2229+ 12AF E3 EX (SP),HL ; Save subscript value +2230+ 12B0 E5 PUSH HL ; Save LCRFLG and TYPE +2231+ 12B1 EB EX DE,HL +2232+ 12B2 3C INC A ; Count dimensions +2233+ 12B3 57 LD D,A ; Save in D +2234+ 12B4 7E LD A,(HL) ; Get next byte in code string +2235+ 12B5 FE 2C CP ',' ; Comma (more to come)? +2236+ 12B7 CA A7 12 JP Z,SCPTLP ; Yes - More subscripts +2237+ 12BA CD F7 09 CALL CHKSYN ; Make sure ")" follows +2238+ 12BD 29 .BYTE ")" +2239+ 12BE 22 80 31 LD (NXTOPR),HL ; Save code string address +2240+ 12C1 E1 POP HL ; Get LCRFLG and TYPE +2241+ 12C2 22 5C 31 LD (LCRFLG),HL ; Restore Locate/create & type +2242+ 12C5 1E 00 LD E,0 ; Flag not CSAVE* or CLOAD* +2243+ 12C7 D5 PUSH DE ; Save number of dimensions (D) +2244+ 12C8 11 .BYTE 11H ; Skip "PUSH HL" and "PUSH AF' +2245+ 12C9 +2246+ 12C9 E5 ARLDSV: PUSH HL ; Save code string address +2247+ 12CA F5 PUSH AF ; A = 00 , Flags set = Z,N +2248+ 12CB 2A 88 31 LD HL,(VAREND) ; Start of arrays +2249+ 12CE 3E .BYTE 3EH ; Skip "ADD HL,DE" +2250+ 12CF 19 FNDARY: ADD HL,DE ; Move to next array start +2251+ 12D0 EB EX DE,HL +2252+ 12D1 2A 8A 31 LD HL,(ARREND) ; End of arrays +2253+ 12D4 EB EX DE,HL ; Current array pointer +2254+ 12D5 CD F1 09 CALL CPDEHL ; End of arrays found? +2255+ 12D8 CA 01 13 JP Z,CREARY ; Yes - Create array +2256+ 12DB 7E LD A,(HL) ; Get second byte of name +2257+ 12DC B9 CP C ; Compare with name given +2258+ 12DD 23 INC HL ; Move on +2259+ 12DE C2 E3 12 JP NZ,NXTARY ; Different - Find next array +2260+ 12E1 7E LD A,(HL) ; Get first byte of name +2261+ 12E2 B8 CP B ; Compare with name given +2262+ 12E3 23 NXTARY: INC HL ; Move on +2263+ 12E4 5E LD E,(HL) ; Get LSB of next array address +2264+ 12E5 23 INC HL +2265+ 12E6 56 LD D,(HL) ; Get MSB of next array address +2266+ 12E7 23 INC HL +2267+ 12E8 C2 CF 12 JP NZ,FNDARY ; Not found - Keep looking +2268+ 12EB 3A 5C 31 LD A,(LCRFLG) ; Found Locate or Create it? +2269+ 12EE B7 OR A +2270+ 12EF C2 32 07 JP NZ,DDERR ; Create - ?DD Error +2271+ 12F2 F1 POP AF ; Locate - Get number of dim'ns +2272+ 12F3 44 LD B,H ; BC Points to array dim'ns +2273+ 12F4 4D LD C,L +2274+ 12F5 CA 11 19 JP Z,POPHRT ; Jump if array load/save +2275+ 12F8 96 SUB (HL) ; Same number of dimensions? +2276+ 12F9 CA 5F 13 JP Z,FINDEL ; Yes - Find element +2277+ 12FC 1E 10 BSERR: LD E,BS ; ?BS Error +2278+ 12FE C3 3D 07 JP ERROR ; Output error +2279+ 1301 +2280+ 1301 11 04 00 CREARY: LD DE,4 ; 4 Bytes per entry +2281+ 1304 F1 POP AF ; Array to save or 0 dim'ns? +2282+ 1305 CA 48 0C JP Z,FCERR ; Yes - ?FC Error +2283+ 1308 71 LD (HL),C ; Save second byte of name +2284+ 1309 23 INC HL +2285+ 130A 70 LD (HL),B ; Save first byte of name +2286+ 130B 23 INC HL +2287+ 130C 4F LD C,A ; Number of dimensions to C +2288+ 130D CD 06 07 CALL CHKSTK ; Check if enough memory +2289+ 1310 23 INC HL ; Point to number of dimensions +2290+ 1311 23 INC HL +2291+ 1312 22 75 31 LD (CUROPR),HL ; Save address of pointer +2292+ 1315 71 LD (HL),C ; Set number of dimensions +2293+ 1316 23 INC HL +2294+ 1317 3A 5C 31 LD A,(LCRFLG) ; Locate of Create? +2295+ 131A 17 RLA ; Carry set = Create +2296+ 131B 79 LD A,C ; Get number of dimensions +2297+ 131C 01 0B 00 CRARLP: LD BC,10+1 ; Default dimension size 10 +2298+ 131F D2 24 13 JP NC,DEFSIZ ; Locate - Set default size +2299+ 1322 C1 POP BC ; Get specified dimension size +2300+ 1323 03 INC BC ; Include zero element +2301+ 1324 71 DEFSIZ: LD (HL),C ; Save LSB of dimension size +2302+ 1325 23 INC HL +2303+ 1326 70 LD (HL),B ; Save MSB of dimension size +2304+ 1327 23 INC HL +2305+ 1328 F5 PUSH AF ; Save num' of dim'ns an status +2306+ 1329 E5 PUSH HL ; Save address of dim'n size +2307+ 132A CD BC 1A CALL MLDEBC ; Multiply DE by BC to find +2308+ 132D EB EX DE,HL ; amount of mem needed (to DE) +2309+ 132E E1 POP HL ; Restore address of dimension +2310+ 132F F1 POP AF ; Restore number of dimensions +2311+ 1330 3D DEC A ; Count them +2312+ 1331 C2 1C 13 JP NZ,CRARLP ; Do next dimension if more +2313+ 1334 F5 PUSH AF ; Save locate/create flag +2314+ 1335 42 LD B,D ; MSB of memory needed +2315+ 1336 4B LD C,E ; LSB of memory needed +2316+ 1337 EB EX DE,HL +2317+ 1338 19 ADD HL,DE ; Add bytes to array start +2318+ 1339 DA 1E 07 JP C,OMERR ; Too big - Error +2319+ 133C CD 0F 07 CALL ENFMEM ; See if enough memory +2320+ 133F 22 8A 31 LD (ARREND),HL ; Save new end of array +2321+ 1342 +2322+ 1342 2B ZERARY: DEC HL ; Back through array data +2323+ 1343 36 00 LD (HL),0 ; Set array element to zero +2324+ 1345 CD F1 09 CALL CPDEHL ; All elements zeroed? +2325+ 1348 C2 42 13 JP NZ,ZERARY ; No - Keep on going +2326+ 134B 03 INC BC ; Number of bytes + 1 +2327+ 134C 57 LD D,A ; A=0 +2328+ 134D 2A 75 31 LD HL,(CUROPR) ; Get address of array +2329+ 1350 5E LD E,(HL) ; Number of dimensions +2330+ 1351 EB EX DE,HL ; To HL +2331+ 1352 29 ADD HL,HL ; Two bytes per dimension size +2332+ 1353 09 ADD HL,BC ; Add number of bytes +2333+ 1354 EB EX DE,HL ; Bytes needed to DE +2334+ 1355 2B DEC HL +2335+ 1356 2B DEC HL +2336+ 1357 73 LD (HL),E ; Save LSB of bytes needed +2337+ 1358 23 INC HL +2338+ 1359 72 LD (HL),D ; Save MSB of bytes needed +2339+ 135A 23 INC HL +2340+ 135B F1 POP AF ; Locate / Create? +2341+ 135C DA 83 13 JP C,ENDDIM ; A is 0 , End if create +2342+ 135F 47 FINDEL: LD B,A ; Find array element +2343+ 1360 4F LD C,A +2344+ 1361 7E LD A,(HL) ; Number of dimensions +2345+ 1362 23 INC HL +2346+ 1363 16 .BYTE 16H ; Skip "POP HL" +2347+ 1364 E1 FNDELP: POP HL ; Address of next dim' size +2348+ 1365 5E LD E,(HL) ; Get LSB of dim'n size +2349+ 1366 23 INC HL +2350+ 1367 56 LD D,(HL) ; Get MSB of dim'n size +2351+ 1368 23 INC HL +2352+ 1369 E3 EX (SP),HL ; Save address - Get index +2353+ 136A F5 PUSH AF ; Save number of dim'ns +2354+ 136B CD F1 09 CALL CPDEHL ; Dimension too large? +2355+ 136E D2 FC 12 JP NC,BSERR ; Yes - ?BS Error +2356+ 1371 E5 PUSH HL ; Save index +2357+ 1372 CD BC 1A CALL MLDEBC ; Multiply previous by size +2358+ 1375 D1 POP DE ; Index supplied to DE +2359+ 1376 19 ADD HL,DE ; Add index to pointer +2360+ 1377 F1 POP AF ; Number of dimensions +2361+ 1378 3D DEC A ; Count them +2362+ 1379 44 LD B,H ; MSB of pointer +2363+ 137A 4D LD C,L ; LSB of pointer +2364+ 137B C2 64 13 JP NZ,FNDELP ; More - Keep going +2365+ 137E 29 ADD HL,HL ; 4 Bytes per element +2366+ 137F 29 ADD HL,HL +2367+ 1380 C1 POP BC ; Start of array +2368+ 1381 09 ADD HL,BC ; Point to element +2369+ 1382 EB EX DE,HL ; Address of element to DE +2370+ 1383 2A 80 31 ENDDIM: LD HL,(NXTOPR) ; Got code string address +2371+ 1386 C9 RET +2372+ 1387 +2373+ 1387 2A 8A 31 FRE: LD HL,(ARREND) ; Start of free memory +2374+ 138A EB EX DE,HL ; To DE +2375+ 138B 21 00 00 LD HL,0 ; End of free memory +2376+ 138E 39 ADD HL,SP ; Current stack value +2377+ 138F 3A 5D 31 LD A,(TYPE) ; Dummy argument type +2378+ 1392 B7 OR A +2379+ 1393 CA A3 13 JP Z,FRENUM ; Numeric - Free variable space +2380+ 1396 CD 0A 16 CALL GSTRCU ; Current string to pool +2381+ 1399 CD 0A 15 CALL GARBGE ; Garbage collection +2382+ 139C 2A 0A 31 LD HL,(STRSPC) ; Bottom of string space in use +2383+ 139F EB EX DE,HL ; To DE +2384+ 13A0 2A 73 31 LD HL,(STRBOT) ; Bottom of string space +2385+ 13A3 7D FRENUM: LD A,L ; Get LSB of end +2386+ 13A4 93 SUB E ; Subtract LSB of beginning +2387+ 13A5 4F LD C,A ; Save difference if C +2388+ 13A6 7C LD A,H ; Get MSB of end +2389+ 13A7 9A SBC A,D ; Subtract MSB of beginning +2390+ 13A8 41 ACPASS: LD B,C ; Return integer AC +2391+ 13A9 50 ABPASS: LD D,B ; Return integer AB +2392+ 13AA 1E 00 LD E,0 +2393+ 13AC 21 5D 31 LD HL,TYPE ; Point to type +2394+ 13AF 73 LD (HL),E ; Set type to numeric +2395+ 13B0 06 90 LD B,80H+16 ; 16 bit integer +2396+ 13B2 C3 E7 19 JP RETINT ; Return the integr +2397+ 13B5 +2398+ 13B5 3A 5B 31 POS: LD A,(CURPOS) ; Get cursor position +2399+ 13B8 47 PASSA: LD B,A ; Put A into AB +2400+ 13B9 AF XOR A ; Zero A +2401+ 13BA C3 A9 13 JP ABPASS ; Return integer AB +2402+ 13BD +2403+ 13BD CD 40 14 DEF: CALL CHEKFN ; Get "FN" and name +2404+ 13C0 CD 32 14 CALL IDTEST ; Test for illegal direct +2405+ 13C3 01 18 0D LD BC,DATA ; To get next statement +2406+ 13C6 C5 PUSH BC ; Save address for RETurn +2407+ 13C7 D5 PUSH DE ; Save address of function ptr +2408+ 13C8 CD F7 09 CALL CHKSYN ; Make sure "(" follows +2409+ 13CB 28 .BYTE "(" +2410+ 13CC CD E4 11 CALL GETVAR ; Get argument variable name +2411+ 13CF E5 PUSH HL ; Save code string address +2412+ 13D0 EB EX DE,HL ; Argument address to HL +2413+ 13D1 2B DEC HL +2414+ 13D2 56 LD D,(HL) ; Get first byte of arg name +2415+ 13D3 2B DEC HL +2416+ 13D4 5E LD E,(HL) ; Get second byte of arg name +2417+ 13D5 E1 POP HL ; Restore code string address +2418+ 13D6 CD F1 0F CALL TSTNUM ; Make sure numeric argument +2419+ 13D9 CD F7 09 CALL CHKSYN ; Make sure ")" follows +2420+ 13DC 29 .BYTE ")" +2421+ 13DD CD F7 09 CALL CHKSYN ; Make sure "=" follows +2422+ 13E0 B4 .BYTE ZEQUAL ; "=" token +2423+ 13E1 44 LD B,H ; Code string address to BC +2424+ 13E2 4D LD C,L +2425+ 13E3 E3 EX (SP),HL ; Save code str , Get FN ptr +2426+ 13E4 71 LD (HL),C ; Save LSB of FN code string +2427+ 13E5 23 INC HL +2428+ 13E6 70 LD (HL),B ; Save MSB of FN code string +2429+ 13E7 C3 7F 14 JP SVSTAD ; Save address and do function +2430+ 13EA +2431+ 13EA CD 40 14 DOFN: CALL CHEKFN ; Make sure FN follows +2432+ 13ED D5 PUSH DE ; Save function pointer address +2433+ 13EE CD C5 10 CALL EVLPAR ; Evaluate expression in "()" +2434+ 13F1 CD F1 0F CALL TSTNUM ; Make sure numeric result +2435+ 13F4 E3 EX (SP),HL ; Save code str , Get FN ptr +2436+ 13F5 5E LD E,(HL) ; Get LSB of FN code string +2437+ 13F6 23 INC HL +2438+ 13F7 56 LD D,(HL) ; Get MSB of FN code string +2439+ 13F8 23 INC HL +2440+ 13F9 7A LD A,D ; And function DEFined? +2441+ 13FA B3 OR E +2442+ 13FB CA 35 07 JP Z,UFERR ; No - ?UF Error +2443+ 13FE 7E LD A,(HL) ; Get LSB of argument address +2444+ 13FF 23 INC HL +2445+ 1400 66 LD H,(HL) ; Get MSB of argument address +2446+ 1401 6F LD L,A ; HL = Arg variable address +2447+ 1402 E5 PUSH HL ; Save it +2448+ 1403 2A 8E 31 LD HL,(FNRGNM) ; Get old argument name +2449+ 1406 E3 EX (SP),HL ; ; Save old , Get new +2450+ 1407 22 8E 31 LD (FNRGNM),HL ; Set new argument name +2451+ 140A 2A 92 31 LD HL,(FNARG+2) ; Get LSB,NLSB of old arg value +2452+ 140D E5 PUSH HL ; Save it +2453+ 140E 2A 90 31 LD HL,(FNARG) ; Get MSB,EXP of old arg value +2454+ 1411 E5 PUSH HL ; Save it +2455+ 1412 21 90 31 LD HL,FNARG ; HL = Value of argument +2456+ 1415 D5 PUSH DE ; Save FN code string address +2457+ 1416 CD 28 1A CALL FPTHL ; Move FPREG to argument +2458+ 1419 E1 POP HL ; Get FN code string address +2459+ 141A CD EE 0F CALL GETNUM ; Get value from function +2460+ 141D 2B DEC HL ; DEC 'cos GETCHR INCs +2461+ 141E CD 81 0B CALL GETCHR ; Get next character +2462+ 1421 C2 29 07 JP NZ,SNERR ; Bad character in FN - Error +2463+ 1424 E1 POP HL ; Get MSB,EXP of old arg +2464+ 1425 22 90 31 LD (FNARG),HL ; Restore it +2465+ 1428 E1 POP HL ; Get LSB,NLSB of old arg +2466+ 1429 22 92 31 LD (FNARG+2),HL ; Restore it +2467+ 142C E1 POP HL ; Get name of old arg +2468+ 142D 22 8E 31 LD (FNRGNM),HL ; Restore it +2469+ 1430 E1 POP HL ; Restore code string address +2470+ 1431 C9 RET +2471+ 1432 +2472+ 1432 E5 IDTEST: PUSH HL ; Save code string address +2473+ 1433 2A 0C 31 LD HL,(LINEAT) ; Get current line number +2474+ 1436 23 INC HL ; -1 means direct statement +2475+ 1437 7C LD A,H +2476+ 1438 B5 OR L +2477+ 1439 E1 POP HL ; Restore code string address +2478+ 143A C0 RET NZ ; Return if in program +2479+ 143B 1E 16 LD E,ID ; ?ID Error +2480+ 143D C3 3D 07 JP ERROR +2481+ 1440 +2482+ 1440 CD F7 09 CHEKFN: CALL CHKSYN ; Make sure FN follows +2483+ 1443 A7 .BYTE ZFN ; "FN" token +2484+ 1444 3E 80 LD A,80H +2485+ 1446 32 7B 31 LD (FORFLG),A ; Flag FN name to find +2486+ 1449 B6 OR (HL) ; FN name has bit 7 set +2487+ 144A 47 LD B,A ; in first byte of name +2488+ 144B CD E9 11 CALL GTFNAM ; Get FN name +2489+ 144E C3 F1 0F JP TSTNUM ; Make sure numeric function +2490+ 1451 +2491+ 1451 CD F1 0F STR: CALL TSTNUM ; Make sure it's a number +2492+ 1454 CD 75 1B CALL NUMASC ; Turn number into text +2493+ 1457 CD 85 14 STR1: CALL CRTST ; Create string entry for it +2494+ 145A CD 0A 16 CALL GSTRCU ; Current string to pool +2495+ 145D 01 65 16 LD BC,TOPOOL ; Save in string pool +2496+ 1460 C5 PUSH BC ; Save address on stack +2497+ 1461 +2498+ 1461 7E SAVSTR: LD A,(HL) ; Get string length +2499+ 1462 23 INC HL +2500+ 1463 23 INC HL +2501+ 1464 E5 PUSH HL ; Save pointer to string +2502+ 1465 CD E0 14 CALL TESTR ; See if enough string space +2503+ 1468 E1 POP HL ; Restore pointer to string +2504+ 1469 4E LD C,(HL) ; Get LSB of address +2505+ 146A 23 INC HL +2506+ 146B 46 LD B,(HL) ; Get MSB of address +2507+ 146C CD 79 14 CALL CRTMST ; Create string entry +2508+ 146F E5 PUSH HL ; Save pointer to MSB of addr +2509+ 1470 6F LD L,A ; Length of string +2510+ 1471 CD FD 15 CALL TOSTRA ; Move to string area +2511+ 1474 D1 POP DE ; Restore pointer to MSB +2512+ 1475 C9 RET +2513+ 1476 +2514+ 1476 CD E0 14 MKTMST: CALL TESTR ; See if enough string space +2515+ 1479 21 6F 31 CRTMST: LD HL,TMPSTR ; Temporary string +2516+ 147C E5 PUSH HL ; Save it +2517+ 147D 77 LD (HL),A ; Save length of string +2518+ 147E 23 INC HL +2519+ 147F 23 SVSTAD: INC HL +2520+ 1480 73 LD (HL),E ; Save LSB of address +2521+ 1481 23 INC HL +2522+ 1482 72 LD (HL),D ; Save MSB of address +2523+ 1483 E1 POP HL ; Restore pointer +2524+ 1484 C9 RET +2525+ 1485 +2526+ 1485 2B CRTST: DEC HL ; DEC - INCed after +2527+ 1486 06 22 QTSTR: LD B,'"' ; Terminating quote +2528+ 1488 50 LD D,B ; Quote to D +2529+ 1489 E5 DTSTR: PUSH HL ; Save start +2530+ 148A 0E FF LD C,-1 ; Set counter to -1 +2531+ 148C 23 QTSTLP: INC HL ; Move on +2532+ 148D 7E LD A,(HL) ; Get byte +2533+ 148E 0C INC C ; Count bytes +2534+ 148F B7 OR A ; End of line? +2535+ 1490 CA 9B 14 JP Z,CRTSTE ; Yes - Create string entry +2536+ 1493 BA CP D ; Terminator D found? +2537+ 1494 CA 9B 14 JP Z,CRTSTE ; Yes - Create string entry +2538+ 1497 B8 CP B ; Terminator B found? +2539+ 1498 C2 8C 14 JP NZ,QTSTLP ; No - Keep looking +2540+ 149B FE 22 CRTSTE: CP '"' ; End with '"'? +2541+ 149D CC 81 0B CALL Z,GETCHR ; Yes - Get next character +2542+ 14A0 E3 EX (SP),HL ; Starting quote +2543+ 14A1 23 INC HL ; First byte of string +2544+ 14A2 EB EX DE,HL ; To DE +2545+ 14A3 79 LD A,C ; Get length +2546+ 14A4 CD 79 14 CALL CRTMST ; Create string entry +2547+ 14A7 11 6F 31 TSTOPL: LD DE,TMPSTR ; Temporary string +2548+ 14AA 2A 61 31 LD HL,(TMSTPT) ; Temporary string pool pointer +2549+ 14AD 22 94 31 LD (FPREG),HL ; Save address of string ptr +2550+ 14B0 3E 01 LD A,1 +2551+ 14B2 32 5D 31 LD (TYPE),A ; Set type to string +2552+ 14B5 CD 2B 1A CALL DETHL4 ; Move string to pool +2553+ 14B8 CD F1 09 CALL CPDEHL ; Out of string pool? +2554+ 14BB 22 61 31 LD (TMSTPT),HL ; Save new pointer +2555+ 14BE E1 POP HL ; Restore code string address +2556+ 14BF 7E LD A,(HL) ; Get next code byte +2557+ 14C0 C0 RET NZ ; Return if pool OK +2558+ 14C1 1E 1E LD E,ST ; ?ST Error +2559+ 14C3 C3 3D 07 JP ERROR ; String pool overflow +2560+ 14C6 +2561+ 14C6 23 PRNUMS: INC HL ; Skip leading space +2562+ 14C7 CD 85 14 PRS: CALL CRTST ; Create string entry for it +2563+ 14CA CD 0A 16 PRS1: CALL GSTRCU ; Current string to pool +2564+ 14CD CD 1F 1A CALL LOADFP ; Move string block to BCDE +2565+ 14D0 1C INC E ; Length + 1 +2566+ 14D1 1D PRSLP: DEC E ; Count characters +2567+ 14D2 C8 RET Z ; End of string +2568+ 14D3 0A LD A,(BC) ; Get byte to output +2569+ 14D4 CD 02 0A CALL OUTC ; Output character in A +2570+ 14D7 FE 0D CP CR ; Return? +2571+ 14D9 CC 33 0E CALL Z,DONULL ; Yes - Do nulls +2572+ 14DC 03 INC BC ; Next byte in string +2573+ 14DD C3 D1 14 JP PRSLP ; More characters to output +2574+ 14E0 +2575+ 14E0 B7 TESTR: OR A ; Test if enough room +2576+ 14E1 0E .BYTE 0EH ; No garbage collection done +2577+ 14E2 F1 GRBDON: POP AF ; Garbage collection done +2578+ 14E3 F5 PUSH AF ; Save status +2579+ 14E4 2A 0A 31 LD HL,(STRSPC) ; Bottom of string space in use +2580+ 14E7 EB EX DE,HL ; To DE +2581+ 14E8 2A 73 31 LD HL,(STRBOT) ; Bottom of string area +2582+ 14EB 2F CPL ; Negate length (Top down) +2583+ 14EC 4F LD C,A ; -Length to BC +2584+ 14ED 06 FF LD B,-1 ; BC = -ve length of string +2585+ 14EF 09 ADD HL,BC ; Add to bottom of space in use +2586+ 14F0 23 INC HL ; Plus one for 2's complement +2587+ 14F1 CD F1 09 CALL CPDEHL ; Below string RAM area? +2588+ 14F4 DA FE 14 JP C,TESTOS ; Tidy up if not done else err +2589+ 14F7 22 73 31 LD (STRBOT),HL ; Save new bottom of area +2590+ 14FA 23 INC HL ; Point to first byte of string +2591+ 14FB EB EX DE,HL ; Address to DE +2592+ 14FC F1 POPAF: POP AF ; Throw away status push +2593+ 14FD C9 RET +2594+ 14FE +2595+ 14FE F1 TESTOS: POP AF ; Garbage collect been done? +2596+ 14FF 1E 1A LD E,OS ; ?OS Error +2597+ 1501 CA 3D 07 JP Z,ERROR ; Yes - Not enough string apace +2598+ 1504 BF CP A ; Flag garbage collect done +2599+ 1505 F5 PUSH AF ; Save status +2600+ 1506 01 E2 14 LD BC,GRBDON ; Garbage collection done +2601+ 1509 C5 PUSH BC ; Save for RETurn +2602+ 150A 2A 5F 31 GARBGE: LD HL,(LSTRAM) ; Get end of RAM pointer +2603+ 150D 22 73 31 GARBLP: LD (STRBOT),HL ; Reset string pointer +2604+ 1510 21 00 00 LD HL,0 +2605+ 1513 E5 PUSH HL ; Flag no string found +2606+ 1514 2A 0A 31 LD HL,(STRSPC) ; Get bottom of string space +2607+ 1517 E5 PUSH HL ; Save bottom of string space +2608+ 1518 21 63 31 LD HL,TMSTPL ; Temporary string pool +2609+ 151B EB GRBLP: EX DE,HL +2610+ 151C 2A 61 31 LD HL,(TMSTPT) ; Temporary string pool pointer +2611+ 151F EB EX DE,HL +2612+ 1520 CD F1 09 CALL CPDEHL ; Temporary string pool done? +2613+ 1523 01 1B 15 LD BC,GRBLP ; Loop until string pool done +2614+ 1526 C2 6F 15 JP NZ,STPOOL ; No - See if in string area +2615+ 1529 2A 86 31 LD HL,(PROGND) ; Start of simple variables +2616+ 152C EB SMPVAR: EX DE,HL +2617+ 152D 2A 88 31 LD HL,(VAREND) ; End of simple variables +2618+ 1530 EB EX DE,HL +2619+ 1531 CD F1 09 CALL CPDEHL ; All simple strings done? +2620+ 1534 CA 42 15 JP Z,ARRLP ; Yes - Do string arrays +2621+ 1537 7E LD A,(HL) ; Get type of variable +2622+ 1538 23 INC HL +2623+ 1539 23 INC HL +2624+ 153A B7 OR A ; "S" flag set if string +2625+ 153B CD 72 15 CALL STRADD ; See if string in string area +2626+ 153E C3 2C 15 JP SMPVAR ; Loop until simple ones done +2627+ 1541 +2628+ 1541 C1 GNXARY: POP BC ; Scrap address of this array +2629+ 1542 EB ARRLP: EX DE,HL +2630+ 1543 2A 8A 31 LD HL,(ARREND) ; End of string arrays +2631+ 1546 EB EX DE,HL +2632+ 1547 CD F1 09 CALL CPDEHL ; All string arrays done? +2633+ 154A CA 98 15 JP Z,SCNEND ; Yes - Move string if found +2634+ 154D CD 1F 1A CALL LOADFP ; Get array name to BCDE +2635+ 1550 7B LD A,E ; Get type of array +2636+ 1551 E5 PUSH HL ; Save address of num of dim'ns +2637+ 1552 09 ADD HL,BC ; Start of next array +2638+ 1553 B7 OR A ; Test type of array +2639+ 1554 F2 41 15 JP P,GNXARY ; Numeric array - Ignore it +2640+ 1557 22 75 31 LD (CUROPR),HL ; Save address of next array +2641+ 155A E1 POP HL ; Get address of num of dim'ns +2642+ 155B 4E LD C,(HL) ; BC = Number of dimensions +2643+ 155C 06 00 LD B,0 +2644+ 155E 09 ADD HL,BC ; Two bytes per dimension size +2645+ 155F 09 ADD HL,BC +2646+ 1560 23 INC HL ; Plus one for number of dim'ns +2647+ 1561 EB GRBARY: EX DE,HL +2648+ 1562 2A 75 31 LD HL,(CUROPR) ; Get address of next array +2649+ 1565 EB EX DE,HL +2650+ 1566 CD F1 09 CALL CPDEHL ; Is this array finished? +2651+ 1569 CA 42 15 JP Z,ARRLP ; Yes - Get next one +2652+ 156C 01 61 15 LD BC,GRBARY ; Loop until array all done +2653+ 156F C5 STPOOL: PUSH BC ; Save return address +2654+ 1570 F6 80 OR 80H ; Flag string type +2655+ 1572 7E STRADD: LD A,(HL) ; Get string length +2656+ 1573 23 INC HL +2657+ 1574 23 INC HL +2658+ 1575 5E LD E,(HL) ; Get LSB of string address +2659+ 1576 23 INC HL +2660+ 1577 56 LD D,(HL) ; Get MSB of string address +2661+ 1578 23 INC HL +2662+ 1579 F0 RET P ; Not a string - Return +2663+ 157A B7 OR A ; Set flags on string length +2664+ 157B C8 RET Z ; Null string - Return +2665+ 157C 44 LD B,H ; Save variable pointer +2666+ 157D 4D LD C,L +2667+ 157E 2A 73 31 LD HL,(STRBOT) ; Bottom of new area +2668+ 1581 CD F1 09 CALL CPDEHL ; String been done? +2669+ 1584 60 LD H,B ; Restore variable pointer +2670+ 1585 69 LD L,C +2671+ 1586 D8 RET C ; String done - Ignore +2672+ 1587 E1 POP HL ; Return address +2673+ 1588 E3 EX (SP),HL ; Lowest available string area +2674+ 1589 CD F1 09 CALL CPDEHL ; String within string area? +2675+ 158C E3 EX (SP),HL ; Lowest available string area +2676+ 158D E5 PUSH HL ; Re-save return address +2677+ 158E 60 LD H,B ; Restore variable pointer +2678+ 158F 69 LD L,C +2679+ 1590 D0 RET NC ; Outside string area - Ignore +2680+ 1591 C1 POP BC ; Get return , Throw 2 away +2681+ 1592 F1 POP AF ; +2682+ 1593 F1 POP AF ; +2683+ 1594 E5 PUSH HL ; Save variable pointer +2684+ 1595 D5 PUSH DE ; Save address of current +2685+ 1596 C5 PUSH BC ; Put back return address +2686+ 1597 C9 RET ; Go to it +2687+ 1598 +2688+ 1598 D1 SCNEND: POP DE ; Addresses of strings +2689+ 1599 E1 POP HL ; +2690+ 159A 7D LD A,L ; HL = 0 if no more to do +2691+ 159B B4 OR H +2692+ 159C C8 RET Z ; No more to do - Return +2693+ 159D 2B DEC HL +2694+ 159E 46 LD B,(HL) ; MSB of address of string +2695+ 159F 2B DEC HL +2696+ 15A0 4E LD C,(HL) ; LSB of address of string +2697+ 15A1 E5 PUSH HL ; Save variable address +2698+ 15A2 2B DEC HL +2699+ 15A3 2B DEC HL +2700+ 15A4 6E LD L,(HL) ; HL = Length of string +2701+ 15A5 26 00 LD H,0 +2702+ 15A7 09 ADD HL,BC ; Address of end of string+1 +2703+ 15A8 50 LD D,B ; String address to DE +2704+ 15A9 59 LD E,C +2705+ 15AA 2B DEC HL ; Last byte in string +2706+ 15AB 44 LD B,H ; Address to BC +2707+ 15AC 4D LD C,L +2708+ 15AD 2A 73 31 LD HL,(STRBOT) ; Current bottom of string area +2709+ 15B0 CD F8 06 CALL MOVSTR ; Move string to new address +2710+ 15B3 E1 POP HL ; Restore variable address +2711+ 15B4 71 LD (HL),C ; Save new LSB of address +2712+ 15B5 23 INC HL +2713+ 15B6 70 LD (HL),B ; Save new MSB of address +2714+ 15B7 69 LD L,C ; Next string area+1 to HL +2715+ 15B8 60 LD H,B +2716+ 15B9 2B DEC HL ; Next string area address +2717+ 15BA C3 0D 15 JP GARBLP ; Look for more strings +2718+ 15BD +2719+ 15BD C5 CONCAT: PUSH BC ; Save prec' opr & code string +2720+ 15BE E5 PUSH HL ; +2721+ 15BF 2A 94 31 LD HL,(FPREG) ; Get first string +2722+ 15C2 E3 EX (SP),HL ; Save first string +2723+ 15C3 CD 77 10 CALL OPRND ; Get second string +2724+ 15C6 E3 EX (SP),HL ; Restore first string +2725+ 15C7 CD F2 0F CALL TSTSTR ; Make sure it's a string +2726+ 15CA 7E LD A,(HL) ; Get length of second string +2727+ 15CB E5 PUSH HL ; Save first string +2728+ 15CC 2A 94 31 LD HL,(FPREG) ; Get second string +2729+ 15CF E5 PUSH HL ; Save second string +2730+ 15D0 86 ADD A,(HL) ; Add length of second string +2731+ 15D1 1E 1C LD E,LS ; ?LS Error +2732+ 15D3 DA 3D 07 JP C,ERROR ; String too long - Error +2733+ 15D6 CD 76 14 CALL MKTMST ; Make temporary string +2734+ 15D9 D1 POP DE ; Get second string to DE +2735+ 15DA CD 0E 16 CALL GSTRDE ; Move to string pool if needed +2736+ 15DD E3 EX (SP),HL ; Get first string +2737+ 15DE CD 0D 16 CALL GSTRHL ; Move to string pool if needed +2738+ 15E1 E5 PUSH HL ; Save first string +2739+ 15E2 2A 71 31 LD HL,(TMPSTR+2) ; Temporary string address +2740+ 15E5 EB EX DE,HL ; To DE +2741+ 15E6 CD F4 15 CALL SSTSA ; First string to string area +2742+ 15E9 CD F4 15 CALL SSTSA ; Second string to string area +2743+ 15EC 21 0C 10 LD HL,EVAL2 ; Return to evaluation loop +2744+ 15EF E3 EX (SP),HL ; Save return,get code string +2745+ 15F0 E5 PUSH HL ; Save code string address +2746+ 15F1 C3 A7 14 JP TSTOPL ; To temporary string to pool +2747+ 15F4 +2748+ 15F4 E1 SSTSA: POP HL ; Return address +2749+ 15F5 E3 EX (SP),HL ; Get string block,save return +2750+ 15F6 7E LD A,(HL) ; Get length of string +2751+ 15F7 23 INC HL +2752+ 15F8 23 INC HL +2753+ 15F9 4E LD C,(HL) ; Get LSB of string address +2754+ 15FA 23 INC HL +2755+ 15FB 46 LD B,(HL) ; Get MSB of string address +2756+ 15FC 6F LD L,A ; Length to L +2757+ 15FD 2C TOSTRA: INC L ; INC - DECed after +2758+ 15FE 2D TSALP: DEC L ; Count bytes moved +2759+ 15FF C8 RET Z ; End of string - Return +2760+ 1600 0A LD A,(BC) ; Get source +2761+ 1601 12 LD (DE),A ; Save destination +2762+ 1602 03 INC BC ; Next source +2763+ 1603 13 INC DE ; Next destination +2764+ 1604 C3 FE 15 JP TSALP ; Loop until string moved +2765+ 1607 +2766+ 1607 CD F2 0F GETSTR: CALL TSTSTR ; Make sure it's a string +2767+ 160A 2A 94 31 GSTRCU: LD HL,(FPREG) ; Get current string +2768+ 160D EB GSTRHL: EX DE,HL ; Save DE +2769+ 160E CD 28 16 GSTRDE: CALL BAKTMP ; Was it last tmp-str? +2770+ 1611 EB EX DE,HL ; Restore DE +2771+ 1612 C0 RET NZ ; No - Return +2772+ 1613 D5 PUSH DE ; Save string +2773+ 1614 50 LD D,B ; String block address to DE +2774+ 1615 59 LD E,C +2775+ 1616 1B DEC DE ; Point to length +2776+ 1617 4E LD C,(HL) ; Get string length +2777+ 1618 2A 73 31 LD HL,(STRBOT) ; Current bottom of string area +2778+ 161B CD F1 09 CALL CPDEHL ; Last one in string area? +2779+ 161E C2 26 16 JP NZ,POPHL ; No - Return +2780+ 1621 47 LD B,A ; Clear B (A=0) +2781+ 1622 09 ADD HL,BC ; Remove string from str' area +2782+ 1623 22 73 31 LD (STRBOT),HL ; Save new bottom of str' area +2783+ 1626 E1 POPHL: POP HL ; Restore string +2784+ 1627 C9 RET +2785+ 1628 +2786+ 1628 2A 61 31 BAKTMP: LD HL,(TMSTPT) ; Get temporary string pool top +2787+ 162B 2B DEC HL ; Back +2788+ 162C 46 LD B,(HL) ; Get MSB of address +2789+ 162D 2B DEC HL ; Back +2790+ 162E 4E LD C,(HL) ; Get LSB of address +2791+ 162F 2B DEC HL ; Back +2792+ 1630 2B DEC HL ; Back +2793+ 1631 CD F1 09 CALL CPDEHL ; String last in string pool? +2794+ 1634 C0 RET NZ ; Yes - Leave it +2795+ 1635 22 61 31 LD (TMSTPT),HL ; Save new string pool top +2796+ 1638 C9 RET +2797+ 1639 +2798+ 1639 01 B8 13 LEN: LD BC,PASSA ; To return integer A +2799+ 163C C5 PUSH BC ; Save address +2800+ 163D CD 07 16 GETLEN: CALL GETSTR ; Get string and its length +2801+ 1640 AF XOR A +2802+ 1641 57 LD D,A ; Clear D +2803+ 1642 32 5D 31 LD (TYPE),A ; Set type to numeric +2804+ 1645 7E LD A,(HL) ; Get length of string +2805+ 1646 B7 OR A ; Set status flags +2806+ 1647 C9 RET +2807+ 1648 +2808+ 1648 01 B8 13 ASC: LD BC,PASSA ; To return integer A +2809+ 164B C5 PUSH BC ; Save address +2810+ 164C CD 3D 16 GTFLNM: CALL GETLEN ; Get length of string +2811+ 164F CA 48 0C JP Z,FCERR ; Null string - Error +2812+ 1652 23 INC HL +2813+ 1653 23 INC HL +2814+ 1654 5E LD E,(HL) ; Get LSB of address +2815+ 1655 23 INC HL +2816+ 1656 56 LD D,(HL) ; Get MSB of address +2817+ 1657 1A LD A,(DE) ; Get first byte of string +2818+ 1658 C9 RET +2819+ 1659 +2820+ 1659 3E 01 CHR: LD A,1 ; One character string +2821+ 165B CD 76 14 CALL MKTMST ; Make a temporary string +2822+ 165E CD 52 17 CALL MAKINT ; Make it integer A +2823+ 1661 2A 71 31 LD HL,(TMPSTR+2) ; Get address of string +2824+ 1664 73 LD (HL),E ; Save character +2825+ 1665 C1 TOPOOL: POP BC ; Clean up stack +2826+ 1666 C3 A7 14 JP TSTOPL ; Temporary string to pool +2827+ 1669 +2828+ 1669 CD 02 17 LEFT: CALL LFRGNM ; Get number and ending ")" +2829+ 166C AF XOR A ; Start at first byte in string +2830+ 166D E3 RIGHT1: EX (SP),HL ; Save code string,Get string +2831+ 166E 4F LD C,A ; Starting position in string +2832+ 166F E5 MID1: PUSH HL ; Save string block address +2833+ 1670 7E LD A,(HL) ; Get length of string +2834+ 1671 B8 CP B ; Compare with number given +2835+ 1672 DA 77 16 JP C,ALLFOL ; All following bytes required +2836+ 1675 78 LD A,B ; Get new length +2837+ 1676 11 .BYTE 11H ; Skip "LD C,0" +2838+ 1677 0E 00 ALLFOL: LD C,0 ; First byte of string +2839+ 1679 C5 PUSH BC ; Save position in string +2840+ 167A CD E0 14 CALL TESTR ; See if enough string space +2841+ 167D C1 POP BC ; Get position in string +2842+ 167E E1 POP HL ; Restore string block address +2843+ 167F E5 PUSH HL ; And re-save it +2844+ 1680 23 INC HL +2845+ 1681 23 INC HL +2846+ 1682 46 LD B,(HL) ; Get LSB of address +2847+ 1683 23 INC HL +2848+ 1684 66 LD H,(HL) ; Get MSB of address +2849+ 1685 68 LD L,B ; HL = address of string +2850+ 1686 06 00 LD B,0 ; BC = starting address +2851+ 1688 09 ADD HL,BC ; Point to that byte +2852+ 1689 44 LD B,H ; BC = source string +2853+ 168A 4D LD C,L +2854+ 168B CD 79 14 CALL CRTMST ; Create a string entry +2855+ 168E 6F LD L,A ; Length of new string +2856+ 168F CD FD 15 CALL TOSTRA ; Move string to string area +2857+ 1692 D1 POP DE ; Clear stack +2858+ 1693 CD 0E 16 CALL GSTRDE ; Move to string pool if needed +2859+ 1696 C3 A7 14 JP TSTOPL ; Temporary string to pool +2860+ 1699 +2861+ 1699 CD 02 17 RIGHT: CALL LFRGNM ; Get number and ending ")" +2862+ 169C D1 POP DE ; Get string length +2863+ 169D D5 PUSH DE ; And re-save +2864+ 169E 1A LD A,(DE) ; Get length +2865+ 169F 90 SUB B ; Move back N bytes +2866+ 16A0 C3 6D 16 JP RIGHT1 ; Go and get sub-string +2867+ 16A3 +2868+ 16A3 EB MID: EX DE,HL ; Get code string address +2869+ 16A4 7E LD A,(HL) ; Get next byte ',' or ")" +2870+ 16A5 CD 07 17 CALL MIDNUM ; Get number supplied +2871+ 16A8 04 INC B ; Is it character zero? +2872+ 16A9 05 DEC B +2873+ 16AA CA 48 0C JP Z,FCERR ; Yes - Error +2874+ 16AD C5 PUSH BC ; Save starting position +2875+ 16AE 1E FF LD E,255 ; All of string +2876+ 16B0 FE 29 CP ')' ; Any length given? +2877+ 16B2 CA BC 16 JP Z,RSTSTR ; No - Rest of string +2878+ 16B5 CD F7 09 CALL CHKSYN ; Make sure ',' follows +2879+ 16B8 2C .BYTE ',' +2880+ 16B9 CD 4F 17 CALL GETINT ; Get integer 0-255 +2881+ 16BC CD F7 09 RSTSTR: CALL CHKSYN ; Make sure ")" follows +2882+ 16BF 29 .BYTE ")" +2883+ 16C0 F1 POP AF ; Restore starting position +2884+ 16C1 E3 EX (SP),HL ; Get string,8ave code string +2885+ 16C2 01 6F 16 LD BC,MID1 ; Continuation of MID$ routine +2886+ 16C5 C5 PUSH BC ; Save for return +2887+ 16C6 3D DEC A ; Starting position-1 +2888+ 16C7 BE CP (HL) ; Compare with length +2889+ 16C8 06 00 LD B,0 ; Zero bytes length +2890+ 16CA D0 RET NC ; Null string if start past end +2891+ 16CB 4F LD C,A ; Save starting position-1 +2892+ 16CC 7E LD A,(HL) ; Get length of string +2893+ 16CD 91 SUB C ; Subtract start +2894+ 16CE BB CP E ; Enough string for it? +2895+ 16CF 47 LD B,A ; Save maximum length available +2896+ 16D0 D8 RET C ; Truncate string if needed +2897+ 16D1 43 LD B,E ; Set specified length +2898+ 16D2 C9 RET ; Go and create string +2899+ 16D3 +2900+ 16D3 CD 3D 16 VAL: CALL GETLEN ; Get length of string +2901+ 16D6 CA F0 17 JP Z,RESZER ; Result zero +2902+ 16D9 5F LD E,A ; Save length +2903+ 16DA 23 INC HL +2904+ 16DB 23 INC HL +2905+ 16DC 7E LD A,(HL) ; Get LSB of address +2906+ 16DD 23 INC HL +2907+ 16DE 66 LD H,(HL) ; Get MSB of address +2908+ 16DF 6F LD L,A ; HL = String address +2909+ 16E0 E5 PUSH HL ; Save string address +2910+ 16E1 19 ADD HL,DE +2911+ 16E2 46 LD B,(HL) ; Get end of string+1 byte +2912+ 16E3 72 LD (HL),D ; Zero it to terminate +2913+ 16E4 E3 EX (SP),HL ; Save string end,get start +2914+ 16E5 C5 PUSH BC ; Save end+1 byte +2915+ 16E6 7E LD A,(HL) ; Get starting byte +2916+ 16E7 FE 24 CP '$' ; Hex number indicated? [function added] +2917+ 16E9 C2 F1 16 JP NZ,VAL1 +2918+ 16EC CD 1B 1F CALL HEXTFP ; Convert Hex to FPREG +2919+ 16EF 18 0D JR VAL3 +2920+ 16F1 FE 25 VAL1: CP '%' ; Binary number indicated? [function added] +2921+ 16F3 C2 FB 16 JP NZ,VAL2 +2922+ 16F6 CD 8B 1F CALL BINTFP ; Convert Bin to FPREG +2923+ 16F9 18 03 JR VAL3 +2924+ 16FB CD D7 1A VAL2: CALL ASCTFP ; Convert ASCII string to FP +2925+ 16FE C1 VAL3: POP BC ; Restore end+1 byte +2926+ 16FF E1 POP HL ; Restore end+1 address +2927+ 1700 70 LD (HL),B ; Put back original byte +2928+ 1701 C9 RET +2929+ 1702 +2930+ 1702 EB LFRGNM: EX DE,HL ; Code string address to HL +2931+ 1703 CD F7 09 CALL CHKSYN ; Make sure ")" follows +2932+ 1706 29 .BYTE ")" +2933+ 1707 C1 MIDNUM: POP BC ; Get return address +2934+ 1708 D1 POP DE ; Get number supplied +2935+ 1709 C5 PUSH BC ; Re-save return address +2936+ 170A 43 LD B,E ; Number to B +2937+ 170B C9 RET +2938+ 170C +2939+ 170C CD 52 17 INP: CALL MAKINT ; Make it integer A +2940+ 170F 32 EF 30 LD (INPORT),A ; Set input port +2941+ 1712 CD EE 30 CALL INPSUB ; Get input from port +2942+ 1715 C3 B8 13 JP PASSA ; Return integer A +2943+ 1718 +2944+ 1718 CD 3C 17 POUT: CALL SETIO ; Set up port number +2945+ 171B C3 B6 30 JP OUTSUB ; Output data and return +2946+ 171E +2947+ 171E CD 3C 17 WAIT: CALL SETIO ; Set up port number +2948+ 1721 F5 PUSH AF ; Save AND mask +2949+ 1722 1E 00 LD E,0 ; Assume zero if none given +2950+ 1724 2B DEC HL ; DEC 'cos GETCHR INCs +2951+ 1725 CD 81 0B CALL GETCHR ; Get next character +2952+ 1728 CA 32 17 JP Z,NOXOR ; No XOR byte given +2953+ 172B CD F7 09 CALL CHKSYN ; Make sure ',' follows +2954+ 172E 2C .BYTE ',' +2955+ 172F CD 4F 17 CALL GETINT ; Get integer 0-255 to XOR with +2956+ 1732 C1 NOXOR: POP BC ; Restore AND mask +2957+ 1733 CD EE 30 WAITLP: CALL INPSUB ; Get input +2958+ 1736 AB XOR E ; Flip selected bits +2959+ 1737 A0 AND B ; Result non-zero? +2960+ 1738 CA 33 17 JP Z,WAITLP ; No = keep waiting +2961+ 173B C9 RET +2962+ 173C +2963+ 173C CD 4F 17 SETIO: CALL GETINT ; Get integer 0-255 +2964+ 173F 32 EF 30 LD (INPORT),A ; Set input port +2965+ 1742 32 B7 30 LD (OTPORT),A ; Set output port +2966+ 1745 CD F7 09 CALL CHKSYN ; Make sure ',' follows +2967+ 1748 2C .BYTE ',' +2968+ 1749 C3 4F 17 JP GETINT ; Get integer 0-255 and return +2969+ 174C +2970+ 174C CD 81 0B FNDNUM: CALL GETCHR ; Get next character +2971+ 174F CD EE 0F GETINT: CALL GETNUM ; Get a number from 0 to 255 +2972+ 1752 CD 2D 0C MAKINT: CALL DEPINT ; Make sure value 0 - 255 +2973+ 1755 7A LD A,D ; Get MSB of number +2974+ 1756 B7 OR A ; Zero? +2975+ 1757 C2 48 0C JP NZ,FCERR ; No - Error +2976+ 175A 2B DEC HL ; DEC 'cos GETCHR INCs +2977+ 175B CD 81 0B CALL GETCHR ; Get next character +2978+ 175E 7B LD A,E ; Get number to A +2979+ 175F C9 RET +2980+ 1760 +2981+ 1760 CD 33 0C PEEK: CALL DEINT ; Get memory address +2982+ 1763 1A LD A,(DE) ; Get byte in memory +2983+ 1764 C3 B8 13 JP PASSA ; Return integer A +2984+ 1767 +2985+ 1767 CD EE 0F POKE: CALL GETNUM ; Get memory address +2986+ 176A CD 33 0C CALL DEINT ; Get integer -32768 to 3276 +2987+ 176D D5 PUSH DE ; Save memory address +2988+ 176E CD F7 09 CALL CHKSYN ; Make sure ',' follows +2989+ 1771 2C .BYTE ',' +2990+ 1772 CD 4F 17 CALL GETINT ; Get integer 0-255 +2991+ 1775 D1 POP DE ; Restore memory address +2992+ 1776 12 LD (DE),A ; Load it into memory +2993+ 1777 C9 RET +2994+ 1778 +2995+ 1778 21 4E 1C ROUND: LD HL,HALF ; Add 0.5 to FPREG +2996+ 177B CD 1F 1A ADDPHL: CALL LOADFP ; Load FP at (HL) to BCDE +2997+ 177E C3 8A 17 JP FPADD ; Add BCDE to FPREG +2998+ 1781 +2999+ 1781 CD 1F 1A SUBPHL: CALL LOADFP ; FPREG = -FPREG + number at HL +3000+ 1784 21 .BYTE 21H ; Skip "POP BC" and "POP DE" +3001+ 1785 C1 PSUB: POP BC ; Get FP number from stack +3002+ 1786 D1 POP DE +3003+ 1787 CD F9 19 SUBCDE: CALL INVSGN ; Negate FPREG +3004+ 178A 78 FPADD: LD A,B ; Get FP exponent +3005+ 178B B7 OR A ; Is number zero? +3006+ 178C C8 RET Z ; Yes - Nothing to add +3007+ 178D 3A 97 31 LD A,(FPEXP) ; Get FPREG exponent +3008+ 1790 B7 OR A ; Is this number zero? +3009+ 1791 CA 11 1A JP Z,FPBCDE ; Yes - Move BCDE to FPREG +3010+ 1794 90 SUB B ; BCDE number larger? +3011+ 1795 D2 A4 17 JP NC,NOSWAP ; No - Don't swap them +3012+ 1798 2F CPL ; Two's complement +3013+ 1799 3C INC A ; FP exponent +3014+ 179A EB EX DE,HL +3015+ 179B CD 01 1A CALL STAKFP ; Put FPREG on stack +3016+ 179E EB EX DE,HL +3017+ 179F CD 11 1A CALL FPBCDE ; Move BCDE to FPREG +3018+ 17A2 C1 POP BC ; Restore number from stack +3019+ 17A3 D1 POP DE +3020+ 17A4 FE 19 NOSWAP: CP 24+1 ; Second number insignificant? +3021+ 17A6 D0 RET NC ; Yes - First number is result +3022+ 17A7 F5 PUSH AF ; Save number of bits to scale +3023+ 17A8 CD 36 1A CALL SIGNS ; Set MSBs & sign of result +3024+ 17AB 67 LD H,A ; Save sign of result +3025+ 17AC F1 POP AF ; Restore scaling factor +3026+ 17AD CD 4F 18 CALL SCALE ; Scale BCDE to same exponent +3027+ 17B0 B4 OR H ; Result to be positive? +3028+ 17B1 21 94 31 LD HL,FPREG ; Point to FPREG +3029+ 17B4 F2 CA 17 JP P,MINCDE ; No - Subtract FPREG from CDE +3030+ 17B7 CD 2F 18 CALL PLUCDE ; Add FPREG to CDE +3031+ 17BA D2 10 18 JP NC,RONDUP ; No overflow - Round it up +3032+ 17BD 23 INC HL ; Point to exponent +3033+ 17BE 34 INC (HL) ; Increment it +3034+ 17BF CA 38 07 JP Z,OVERR ; Number overflowed - Error +3035+ 17C2 2E 01 LD L,1 ; 1 bit to shift right +3036+ 17C4 CD 65 18 CALL SHRT1 ; Shift result right +3037+ 17C7 C3 10 18 JP RONDUP ; Round it up +3038+ 17CA +3039+ 17CA AF MINCDE: XOR A ; Clear A and carry +3040+ 17CB 90 SUB B ; Negate exponent +3041+ 17CC 47 LD B,A ; Re-save exponent +3042+ 17CD 7E LD A,(HL) ; Get LSB of FPREG +3043+ 17CE 9B SBC A, E ; Subtract LSB of BCDE +3044+ 17CF 5F LD E,A ; Save LSB of BCDE +3045+ 17D0 23 INC HL +3046+ 17D1 7E LD A,(HL) ; Get NMSB of FPREG +3047+ 17D2 9A SBC A,D ; Subtract NMSB of BCDE +3048+ 17D3 57 LD D,A ; Save NMSB of BCDE +3049+ 17D4 23 INC HL +3050+ 17D5 7E LD A,(HL) ; Get MSB of FPREG +3051+ 17D6 99 SBC A,C ; Subtract MSB of BCDE +3052+ 17D7 4F LD C,A ; Save MSB of BCDE +3053+ 17D8 DC 3B 18 CONPOS: CALL C,COMPL ; Overflow - Make it positive +3054+ 17DB +3055+ 17DB 68 BNORM: LD L,B ; L = Exponent +3056+ 17DC 63 LD H,E ; H = LSB +3057+ 17DD AF XOR A +3058+ 17DE 47 BNRMLP: LD B,A ; Save bit count +3059+ 17DF 79 LD A,C ; Get MSB +3060+ 17E0 B7 OR A ; Is it zero? +3061+ 17E1 C2 FD 17 JP NZ,PNORM ; No - Do it bit at a time +3062+ 17E4 4A LD C,D ; MSB = NMSB +3063+ 17E5 54 LD D,H ; NMSB= LSB +3064+ 17E6 65 LD H,L ; LSB = VLSB +3065+ 17E7 6F LD L,A ; VLSB= 0 +3066+ 17E8 78 LD A,B ; Get exponent +3067+ 17E9 D6 08 SUB 8 ; Count 8 bits +3068+ 17EB FE E0 CP -24-8 ; Was number zero? +3069+ 17ED C2 DE 17 JP NZ,BNRMLP ; No - Keep normalising +3070+ 17F0 AF RESZER: XOR A ; Result is zero +3071+ 17F1 32 97 31 SAVEXP: LD (FPEXP),A ; Save result as zero +3072+ 17F4 C9 RET +3073+ 17F5 +3074+ 17F5 05 NORMAL: DEC B ; Count bits +3075+ 17F6 29 ADD HL,HL ; Shift HL left +3076+ 17F7 7A LD A,D ; Get NMSB +3077+ 17F8 17 RLA ; Shift left with last bit +3078+ 17F9 57 LD D,A ; Save NMSB +3079+ 17FA 79 LD A,C ; Get MSB +3080+ 17FB 8F ADC A,A ; Shift left with last bit +3081+ 17FC 4F LD C,A ; Save MSB +3082+ 17FD F2 F5 17 PNORM: JP P,NORMAL ; Not done - Keep going +3083+ 1800 78 LD A,B ; Number of bits shifted +3084+ 1801 5C LD E,H ; Save HL in EB +3085+ 1802 45 LD B,L +3086+ 1803 B7 OR A ; Any shifting done? +3087+ 1804 CA 10 18 JP Z,RONDUP ; No - Round it up +3088+ 1807 21 97 31 LD HL,FPEXP ; Point to exponent +3089+ 180A 86 ADD A,(HL) ; Add shifted bits +3090+ 180B 77 LD (HL),A ; Re-save exponent +3091+ 180C D2 F0 17 JP NC,RESZER ; Underflow - Result is zero +3092+ 180F C8 RET Z ; Result is zero +3093+ 1810 78 RONDUP: LD A,B ; Get VLSB of number +3094+ 1811 21 97 31 RONDB: LD HL,FPEXP ; Point to exponent +3095+ 1814 B7 OR A ; Any rounding? +3096+ 1815 FC 22 18 CALL M,FPROND ; Yes - Round number up +3097+ 1818 46 LD B,(HL) ; B = Exponent +3098+ 1819 23 INC HL +3099+ 181A 7E LD A,(HL) ; Get sign of result +3100+ 181B E6 80 AND 10000000B ; Only bit 7 needed +3101+ 181D A9 XOR C ; Set correct sign +3102+ 181E 4F LD C,A ; Save correct sign in number +3103+ 181F C3 11 1A JP FPBCDE ; Move BCDE to FPREG +3104+ 1822 +3105+ 1822 1C FPROND: INC E ; Round LSB +3106+ 1823 C0 RET NZ ; Return if ok +3107+ 1824 14 INC D ; Round NMSB +3108+ 1825 C0 RET NZ ; Return if ok +3109+ 1826 0C INC C ; Round MSB +3110+ 1827 C0 RET NZ ; Return if ok +3111+ 1828 0E 80 LD C,80H ; Set normal value +3112+ 182A 34 INC (HL) ; Increment exponent +3113+ 182B C0 RET NZ ; Return if ok +3114+ 182C C3 38 07 JP OVERR ; Overflow error +3115+ 182F +3116+ 182F 7E PLUCDE: LD A,(HL) ; Get LSB of FPREG +3117+ 1830 83 ADD A,E ; Add LSB of BCDE +3118+ 1831 5F LD E,A ; Save LSB of BCDE +3119+ 1832 23 INC HL +3120+ 1833 7E LD A,(HL) ; Get NMSB of FPREG +3121+ 1834 8A ADC A,D ; Add NMSB of BCDE +3122+ 1835 57 LD D,A ; Save NMSB of BCDE +3123+ 1836 23 INC HL +3124+ 1837 7E LD A,(HL) ; Get MSB of FPREG +3125+ 1838 89 ADC A,C ; Add MSB of BCDE +3126+ 1839 4F LD C,A ; Save MSB of BCDE +3127+ 183A C9 RET +3128+ 183B +3129+ 183B 21 98 31 COMPL: LD HL,SGNRES ; Sign of result +3130+ 183E 7E LD A,(HL) ; Get sign of result +3131+ 183F 2F CPL ; Negate it +3132+ 1840 77 LD (HL),A ; Put it back +3133+ 1841 AF XOR A +3134+ 1842 6F LD L,A ; Set L to zero +3135+ 1843 90 SUB B ; Negate exponent,set carry +3136+ 1844 47 LD B,A ; Re-save exponent +3137+ 1845 7D LD A,L ; Load zero +3138+ 1846 9B SBC A,E ; Negate LSB +3139+ 1847 5F LD E,A ; Re-save LSB +3140+ 1848 7D LD A,L ; Load zero +3141+ 1849 9A SBC A,D ; Negate NMSB +3142+ 184A 57 LD D,A ; Re-save NMSB +3143+ 184B 7D LD A,L ; Load zero +3144+ 184C 99 SBC A,C ; Negate MSB +3145+ 184D 4F LD C,A ; Re-save MSB +3146+ 184E C9 RET +3147+ 184F +3148+ 184F 06 00 SCALE: LD B,0 ; Clear underflow +3149+ 1851 D6 08 SCALLP: SUB 8 ; 8 bits (a whole byte)? +3150+ 1853 DA 5E 18 JP C,SHRITE ; No - Shift right A bits +3151+ 1856 43 LD B,E ; <- Shift +3152+ 1857 5A LD E,D ; <- right +3153+ 1858 51 LD D,C ; <- eight +3154+ 1859 0E 00 LD C,0 ; <- bits +3155+ 185B C3 51 18 JP SCALLP ; More bits to shift +3156+ 185E +3157+ 185E C6 09 SHRITE: ADD A,8+1 ; Adjust count +3158+ 1860 6F LD L,A ; Save bits to shift +3159+ 1861 AF SHRLP: XOR A ; Flag for all done +3160+ 1862 2D DEC L ; All shifting done? +3161+ 1863 C8 RET Z ; Yes - Return +3162+ 1864 79 LD A,C ; Get MSB +3163+ 1865 1F SHRT1: RRA ; Shift it right +3164+ 1866 4F LD C,A ; Re-save +3165+ 1867 7A LD A,D ; Get NMSB +3166+ 1868 1F RRA ; Shift right with last bit +3167+ 1869 57 LD D,A ; Re-save it +3168+ 186A 7B LD A,E ; Get LSB +3169+ 186B 1F RRA ; Shift right with last bit +3170+ 186C 5F LD E,A ; Re-save it +3171+ 186D 78 LD A,B ; Get underflow +3172+ 186E 1F RRA ; Shift right with last bit +3173+ 186F 47 LD B,A ; Re-save underflow +3174+ 1870 C3 61 18 JP SHRLP ; More bits to do +3175+ 1873 +3176+ 1873 00 00 00 81 UNITY: .BYTE 000H,000H,000H,081H ; 1.00000 +3177+ 1877 +3178+ 1877 03 LOGTAB: .BYTE 3 ; Table used by LOG +3179+ 1878 AA 56 19 80 .BYTE 0AAH,056H,019H,080H ; 0.59898 +3180+ 187C F1 22 76 80 .BYTE 0F1H,022H,076H,080H ; 0.96147 +3181+ 1880 45 AA 38 82 .BYTE 045H,0AAH,038H,082H ; 2.88539 +3182+ 1884 +3183+ 1884 CD D0 19 LOG: CALL TSTSGN ; Test sign of value +3184+ 1887 B7 OR A +3185+ 1888 EA 48 0C JP PE,FCERR ; ?FC Error if <= zero +3186+ 188B 21 97 31 LD HL,FPEXP ; Point to exponent +3187+ 188E 7E LD A,(HL) ; Get exponent +3188+ 188F 01 35 80 LD BC,8035H ; BCDE = SQR(1/2) +3189+ 1892 11 F3 04 LD DE,04F3H +3190+ 1895 90 SUB B ; Scale value to be < 1 +3191+ 1896 F5 PUSH AF ; Save scale factor +3192+ 1897 70 LD (HL),B ; Save new exponent +3193+ 1898 D5 PUSH DE ; Save SQR(1/2) +3194+ 1899 C5 PUSH BC +3195+ 189A CD 8A 17 CALL FPADD ; Add SQR(1/2) to value +3196+ 189D C1 POP BC ; Restore SQR(1/2) +3197+ 189E D1 POP DE +3198+ 189F 04 INC B ; Make it SQR(2) +3199+ 18A0 CD 26 19 CALL DVBCDE ; Divide by SQR(2) +3200+ 18A3 21 73 18 LD HL,UNITY ; Point to 1. +3201+ 18A6 CD 81 17 CALL SUBPHL ; Subtract FPREG from 1 +3202+ 18A9 21 77 18 LD HL,LOGTAB ; Coefficient table +3203+ 18AC CD 18 1D CALL SUMSER ; Evaluate sum of series +3204+ 18AF 01 80 80 LD BC,8080H ; BCDE = -0.5 +3205+ 18B2 11 00 00 LD DE,0000H +3206+ 18B5 CD 8A 17 CALL FPADD ; Subtract 0.5 from FPREG +3207+ 18B8 F1 POP AF ; Restore scale factor +3208+ 18B9 CD 4B 1B CALL RSCALE ; Re-scale number +3209+ 18BC 01 31 80 MULLN2: LD BC,8031H ; BCDE = Ln(2) +3210+ 18BF 11 18 72 LD DE,7218H +3211+ 18C2 21 .BYTE 21H ; Skip "POP BC" and "POP DE" +3212+ 18C3 +3213+ 18C3 C1 MULT: POP BC ; Get number from stack +3214+ 18C4 D1 POP DE +3215+ 18C5 CD D0 19 FPMULT: CALL TSTSGN ; Test sign of FPREG +3216+ 18C8 C8 RET Z ; Return zero if zero +3217+ 18C9 2E 00 LD L,0 ; Flag add exponents +3218+ 18CB CD 8E 19 CALL ADDEXP ; Add exponents +3219+ 18CE 79 LD A,C ; Get MSB of multiplier +3220+ 18CF 32 A6 31 LD (MULVAL),A ; Save MSB of multiplier +3221+ 18D2 EB EX DE,HL +3222+ 18D3 22 A7 31 LD (MULVAL+1),HL ; Save rest of multiplier +3223+ 18D6 01 00 00 LD BC,0 ; Partial product (BCDE) = zero +3224+ 18D9 50 LD D,B +3225+ 18DA 58 LD E,B +3226+ 18DB 21 DB 17 LD HL,BNORM ; Address of normalise +3227+ 18DE E5 PUSH HL ; Save for return +3228+ 18DF 21 E7 18 LD HL,MULT8 ; Address of 8 bit multiply +3229+ 18E2 E5 PUSH HL ; Save for NMSB,MSB +3230+ 18E3 E5 PUSH HL ; +3231+ 18E4 21 94 31 LD HL,FPREG ; Point to number +3232+ 18E7 7E MULT8: LD A,(HL) ; Get LSB of number +3233+ 18E8 23 INC HL ; Point to NMSB +3234+ 18E9 B7 OR A ; Test LSB +3235+ 18EA CA 13 19 JP Z,BYTSFT ; Zero - shift to next byte +3236+ 18ED E5 PUSH HL ; Save address of number +3237+ 18EE 2E 08 LD L,8 ; 8 bits to multiply by +3238+ 18F0 1F MUL8LP: RRA ; Shift LSB right +3239+ 18F1 67 LD H,A ; Save LSB +3240+ 18F2 79 LD A,C ; Get MSB +3241+ 18F3 D2 01 19 JP NC,NOMADD ; Bit was zero - Don't add +3242+ 18F6 E5 PUSH HL ; Save LSB and count +3243+ 18F7 2A A7 31 LD HL,(MULVAL+1) ; Get LSB and NMSB +3244+ 18FA 19 ADD HL,DE ; Add NMSB and LSB +3245+ 18FB EB EX DE,HL ; Leave sum in DE +3246+ 18FC E1 POP HL ; Restore MSB and count +3247+ 18FD 3A A6 31 LD A,(MULVAL) ; Get MSB of multiplier +3248+ 1900 89 ADC A,C ; Add MSB +3249+ 1901 1F NOMADD: RRA ; Shift MSB right +3250+ 1902 4F LD C,A ; Re-save MSB +3251+ 1903 7A LD A,D ; Get NMSB +3252+ 1904 1F RRA ; Shift NMSB right +3253+ 1905 57 LD D,A ; Re-save NMSB +3254+ 1906 7B LD A,E ; Get LSB +3255+ 1907 1F RRA ; Shift LSB right +3256+ 1908 5F LD E,A ; Re-save LSB +3257+ 1909 78 LD A,B ; Get VLSB +3258+ 190A 1F RRA ; Shift VLSB right +3259+ 190B 47 LD B,A ; Re-save VLSB +3260+ 190C 2D DEC L ; Count bits multiplied +3261+ 190D 7C LD A,H ; Get LSB of multiplier +3262+ 190E C2 F0 18 JP NZ,MUL8LP ; More - Do it +3263+ 1911 E1 POPHRT: POP HL ; Restore address of number +3264+ 1912 C9 RET +3265+ 1913 +3266+ 1913 43 BYTSFT: LD B,E ; Shift partial product left +3267+ 1914 5A LD E,D +3268+ 1915 51 LD D,C +3269+ 1916 4F LD C,A +3270+ 1917 C9 RET +3271+ 1918 +3272+ 1918 CD 01 1A DIV10: CALL STAKFP ; Save FPREG on stack +3273+ 191B 01 20 84 LD BC,8420H ; BCDE = 10. +3274+ 191E 11 00 00 LD DE,0000H +3275+ 1921 CD 11 1A CALL FPBCDE ; Move 10 to FPREG +3276+ 1924 +3277+ 1924 C1 DIV: POP BC ; Get number from stack +3278+ 1925 D1 POP DE +3279+ 1926 CD D0 19 DVBCDE: CALL TSTSGN ; Test sign of FPREG +3280+ 1929 CA 2C 07 JP Z,DZERR ; Error if division by zero +3281+ 192C 2E FF LD L,-1 ; Flag subtract exponents +3282+ 192E CD 8E 19 CALL ADDEXP ; Subtract exponents +3283+ 1931 34 INC (HL) ; Add 2 to exponent to adjust +3284+ 1932 34 INC (HL) +3285+ 1933 2B DEC HL ; Point to MSB +3286+ 1934 7E LD A,(HL) ; Get MSB of dividend +3287+ 1935 32 C2 30 LD (DIV3),A ; Save for subtraction +3288+ 1938 2B DEC HL +3289+ 1939 7E LD A,(HL) ; Get NMSB of dividend +3290+ 193A 32 BE 30 LD (DIV2),A ; Save for subtraction +3291+ 193D 2B DEC HL +3292+ 193E 7E LD A,(HL) ; Get MSB of dividend +3293+ 193F 32 BA 30 LD (DIV1),A ; Save for subtraction +3294+ 1942 41 LD B,C ; Get MSB +3295+ 1943 EB EX DE,HL ; NMSB,LSB to HL +3296+ 1944 AF XOR A +3297+ 1945 4F LD C,A ; Clear MSB of quotient +3298+ 1946 57 LD D,A ; Clear NMSB of quotient +3299+ 1947 5F LD E,A ; Clear LSB of quotient +3300+ 1948 32 C5 30 LD (DIV4),A ; Clear overflow count +3301+ 194B E5 DIVLP: PUSH HL ; Save divisor +3302+ 194C C5 PUSH BC +3303+ 194D 7D LD A,L ; Get LSB of number +3304+ 194E CD B9 30 CALL DIVSUP ; Subt' divisor from dividend +3305+ 1951 DE 00 SBC A,0 ; Count for overflows +3306+ 1953 3F CCF +3307+ 1954 D2 5E 19 JP NC,RESDIV ; Restore divisor if borrow +3308+ 1957 32 C5 30 LD (DIV4),A ; Re-save overflow count +3309+ 195A F1 POP AF ; Scrap divisor +3310+ 195B F1 POP AF +3311+ 195C 37 SCF ; Set carry to +3312+ 195D D2 .BYTE 0D2H ; Skip "POP BC" and "POP HL" +3313+ 195E +3314+ 195E C1 RESDIV: POP BC ; Restore divisor +3315+ 195F E1 POP HL +3316+ 1960 79 LD A,C ; Get MSB of quotient +3317+ 1961 3C INC A +3318+ 1962 3D DEC A +3319+ 1963 1F RRA ; Bit 0 to bit 7 +3320+ 1964 FA 11 18 JP M,RONDB ; Done - Normalise result +3321+ 1967 17 RLA ; Restore carry +3322+ 1968 7B LD A,E ; Get LSB of quotient +3323+ 1969 17 RLA ; Double it +3324+ 196A 5F LD E,A ; Put it back +3325+ 196B 7A LD A,D ; Get NMSB of quotient +3326+ 196C 17 RLA ; Double it +3327+ 196D 57 LD D,A ; Put it back +3328+ 196E 79 LD A,C ; Get MSB of quotient +3329+ 196F 17 RLA ; Double it +3330+ 1970 4F LD C,A ; Put it back +3331+ 1971 29 ADD HL,HL ; Double NMSB,LSB of divisor +3332+ 1972 78 LD A,B ; Get MSB of divisor +3333+ 1973 17 RLA ; Double it +3334+ 1974 47 LD B,A ; Put it back +3335+ 1975 3A C5 30 LD A,(DIV4) ; Get VLSB of quotient +3336+ 1978 17 RLA ; Double it +3337+ 1979 32 C5 30 LD (DIV4),A ; Put it back +3338+ 197C 79 LD A,C ; Get MSB of quotient +3339+ 197D B2 OR D ; Merge NMSB +3340+ 197E B3 OR E ; Merge LSB +3341+ 197F C2 4B 19 JP NZ,DIVLP ; Not done - Keep dividing +3342+ 1982 E5 PUSH HL ; Save divisor +3343+ 1983 21 97 31 LD HL,FPEXP ; Point to exponent +3344+ 1986 35 DEC (HL) ; Divide by 2 +3345+ 1987 E1 POP HL ; Restore divisor +3346+ 1988 C2 4B 19 JP NZ,DIVLP ; Ok - Keep going +3347+ 198B C3 38 07 JP OVERR ; Overflow error +3348+ 198E +3349+ 198E 78 ADDEXP: LD A,B ; Get exponent of dividend +3350+ 198F B7 OR A ; Test it +3351+ 1990 CA B2 19 JP Z,OVTST3 ; Zero - Result zero +3352+ 1993 7D LD A,L ; Get add/subtract flag +3353+ 1994 21 97 31 LD HL,FPEXP ; Point to exponent +3354+ 1997 AE XOR (HL) ; Add or subtract it +3355+ 1998 80 ADD A,B ; Add the other exponent +3356+ 1999 47 LD B,A ; Save new exponent +3357+ 199A 1F RRA ; Test exponent for overflow +3358+ 199B A8 XOR B +3359+ 199C 78 LD A,B ; Get exponent +3360+ 199D F2 B1 19 JP P,OVTST2 ; Positive - Test for overflow +3361+ 19A0 C6 80 ADD A,80H ; Add excess 128 +3362+ 19A2 77 LD (HL),A ; Save new exponent +3363+ 19A3 CA 11 19 JP Z,POPHRT ; Zero - Result zero +3364+ 19A6 CD 36 1A CALL SIGNS ; Set MSBs and sign of result +3365+ 19A9 77 LD (HL),A ; Save new exponent +3366+ 19AA 2B DEC HL ; Point to MSB +3367+ 19AB C9 RET +3368+ 19AC +3369+ 19AC CD D0 19 OVTST1: CALL TSTSGN ; Test sign of FPREG +3370+ 19AF 2F CPL ; Invert sign +3371+ 19B0 E1 POP HL ; Clean up stack +3372+ 19B1 B7 OVTST2: OR A ; Test if new exponent zero +3373+ 19B2 E1 OVTST3: POP HL ; Clear off return address +3374+ 19B3 F2 F0 17 JP P,RESZER ; Result zero +3375+ 19B6 C3 38 07 JP OVERR ; Overflow error +3376+ 19B9 +3377+ 19B9 CD 1C 1A MLSP10: CALL BCDEFP ; Move FPREG to BCDE +3378+ 19BC 78 LD A,B ; Get exponent +3379+ 19BD B7 OR A ; Is it zero? +3380+ 19BE C8 RET Z ; Yes - Result is zero +3381+ 19BF C6 02 ADD A,2 ; Multiply by 4 +3382+ 19C1 DA 38 07 JP C,OVERR ; Overflow - ?OV Error +3383+ 19C4 47 LD B,A ; Re-save exponent +3384+ 19C5 CD 8A 17 CALL FPADD ; Add BCDE to FPREG (Times 5) +3385+ 19C8 21 97 31 LD HL,FPEXP ; Point to exponent +3386+ 19CB 34 INC (HL) ; Double number (Times 10) +3387+ 19CC C0 RET NZ ; Ok - Return +3388+ 19CD C3 38 07 JP OVERR ; Overflow error +3389+ 19D0 +3390+ 19D0 3A 97 31 TSTSGN: LD A,(FPEXP) ; Get sign of FPREG +3391+ 19D3 B7 OR A +3392+ 19D4 C8 RET Z ; RETurn if number is zero +3393+ 19D5 3A 96 31 LD A,(FPREG+2) ; Get MSB of FPREG +3394+ 19D8 FE .BYTE 0FEH ; Test sign +3395+ 19D9 2F RETREL: CPL ; Invert sign +3396+ 19DA 17 RLA ; Sign bit to carry +3397+ 19DB 9F FLGDIF: SBC A,A ; Carry to all bits of A +3398+ 19DC C0 RET NZ ; Return -1 if negative +3399+ 19DD 3C INC A ; Bump to +1 +3400+ 19DE C9 RET ; Positive - Return +1 +3401+ 19DF +3402+ 19DF CD D0 19 SGN: CALL TSTSGN ; Test sign of FPREG +3403+ 19E2 06 88 FLGREL: LD B,80H+8 ; 8 bit integer in exponent +3404+ 19E4 11 00 00 LD DE,0 ; Zero NMSB and LSB +3405+ 19E7 21 97 31 RETINT: LD HL,FPEXP ; Point to exponent +3406+ 19EA 4F LD C,A ; CDE = MSB,NMSB and LSB +3407+ 19EB 70 LD (HL),B ; Save exponent +3408+ 19EC 06 00 LD B,0 ; CDE = integer to normalise +3409+ 19EE 23 INC HL ; Point to sign of result +3410+ 19EF 36 80 LD (HL),80H ; Set sign of result +3411+ 19F1 17 RLA ; Carry = sign of integer +3412+ 19F2 C3 D8 17 JP CONPOS ; Set sign of result +3413+ 19F5 +3414+ 19F5 CD D0 19 ABS: CALL TSTSGN ; Test sign of FPREG +3415+ 19F8 F0 RET P ; Return if positive +3416+ 19F9 21 96 31 INVSGN: LD HL,FPREG+2 ; Point to MSB +3417+ 19FC 7E LD A,(HL) ; Get sign of mantissa +3418+ 19FD EE 80 XOR 80H ; Invert sign of mantissa +3419+ 19FF 77 LD (HL),A ; Re-save sign of mantissa +3420+ 1A00 C9 RET +3421+ 1A01 +3422+ 1A01 EB STAKFP: EX DE,HL ; Save code string address +3423+ 1A02 2A 94 31 LD HL,(FPREG) ; LSB,NLSB of FPREG +3424+ 1A05 E3 EX (SP),HL ; Stack them,get return +3425+ 1A06 E5 PUSH HL ; Re-save return +3426+ 1A07 2A 96 31 LD HL,(FPREG+2) ; MSB and exponent of FPREG +3427+ 1A0A E3 EX (SP),HL ; Stack them,get return +3428+ 1A0B E5 PUSH HL ; Re-save return +3429+ 1A0C EB EX DE,HL ; Restore code string address +3430+ 1A0D C9 RET +3431+ 1A0E +3432+ 1A0E CD 1F 1A PHLTFP: CALL LOADFP ; Number at HL to BCDE +3433+ 1A11 EB FPBCDE: EX DE,HL ; Save code string address +3434+ 1A12 22 94 31 LD (FPREG),HL ; Save LSB,NLSB of number +3435+ 1A15 60 LD H,B ; Exponent of number +3436+ 1A16 69 LD L,C ; MSB of number +3437+ 1A17 22 96 31 LD (FPREG+2),HL ; Save MSB and exponent +3438+ 1A1A EB EX DE,HL ; Restore code string address +3439+ 1A1B C9 RET +3440+ 1A1C +3441+ 1A1C 21 94 31 BCDEFP: LD HL,FPREG ; Point to FPREG +3442+ 1A1F 5E LOADFP: LD E,(HL) ; Get LSB of number +3443+ 1A20 23 INC HL +3444+ 1A21 56 LD D,(HL) ; Get NMSB of number +3445+ 1A22 23 INC HL +3446+ 1A23 4E LD C,(HL) ; Get MSB of number +3447+ 1A24 23 INC HL +3448+ 1A25 46 LD B,(HL) ; Get exponent of number +3449+ 1A26 23 INCHL: INC HL ; Used for conditional "INC HL" +3450+ 1A27 C9 RET +3451+ 1A28 +3452+ 1A28 11 94 31 FPTHL: LD DE,FPREG ; Point to FPREG +3453+ 1A2B 06 04 DETHL4: LD B,4 ; 4 bytes to move +3454+ 1A2D 1A DETHLB: LD A,(DE) ; Get source +3455+ 1A2E 77 LD (HL),A ; Save destination +3456+ 1A2F 13 INC DE ; Next source +3457+ 1A30 23 INC HL ; Next destination +3458+ 1A31 05 DEC B ; Count bytes +3459+ 1A32 C2 2D 1A JP NZ,DETHLB ; Loop if more +3460+ 1A35 C9 RET +3461+ 1A36 +3462+ 1A36 21 96 31 SIGNS: LD HL,FPREG+2 ; Point to MSB of FPREG +3463+ 1A39 7E LD A,(HL) ; Get MSB +3464+ 1A3A 07 RLCA ; Old sign to carry +3465+ 1A3B 37 SCF ; Set MSBit +3466+ 1A3C 1F RRA ; Set MSBit of MSB +3467+ 1A3D 77 LD (HL),A ; Save new MSB +3468+ 1A3E 3F CCF ; Complement sign +3469+ 1A3F 1F RRA ; Old sign to carry +3470+ 1A40 23 INC HL +3471+ 1A41 23 INC HL +3472+ 1A42 77 LD (HL),A ; Set sign of result +3473+ 1A43 79 LD A,C ; Get MSB +3474+ 1A44 07 RLCA ; Old sign to carry +3475+ 1A45 37 SCF ; Set MSBit +3476+ 1A46 1F RRA ; Set MSBit of MSB +3477+ 1A47 4F LD C,A ; Save MSB +3478+ 1A48 1F RRA +3479+ 1A49 AE XOR (HL) ; New sign of result +3480+ 1A4A C9 RET +3481+ 1A4B +3482+ 1A4B 78 CMPNUM: LD A,B ; Get exponent of number +3483+ 1A4C B7 OR A +3484+ 1A4D CA D0 19 JP Z,TSTSGN ; Zero - Test sign of FPREG +3485+ 1A50 21 D9 19 LD HL,RETREL ; Return relation routine +3486+ 1A53 E5 PUSH HL ; Save for return +3487+ 1A54 CD D0 19 CALL TSTSGN ; Test sign of FPREG +3488+ 1A57 79 LD A,C ; Get MSB of number +3489+ 1A58 C8 RET Z ; FPREG zero - Number's MSB +3490+ 1A59 21 96 31 LD HL,FPREG+2 ; MSB of FPREG +3491+ 1A5C AE XOR (HL) ; Combine signs +3492+ 1A5D 79 LD A,C ; Get MSB of number +3493+ 1A5E F8 RET M ; Exit if signs different +3494+ 1A5F CD 65 1A CALL CMPFP ; Compare FP numbers +3495+ 1A62 1F RRA ; Get carry to sign +3496+ 1A63 A9 XOR C ; Combine with MSB of number +3497+ 1A64 C9 RET +3498+ 1A65 +3499+ 1A65 23 CMPFP: INC HL ; Point to exponent +3500+ 1A66 78 LD A,B ; Get exponent +3501+ 1A67 BE CP (HL) ; Compare exponents +3502+ 1A68 C0 RET NZ ; Different +3503+ 1A69 2B DEC HL ; Point to MBS +3504+ 1A6A 79 LD A,C ; Get MSB +3505+ 1A6B BE CP (HL) ; Compare MSBs +3506+ 1A6C C0 RET NZ ; Different +3507+ 1A6D 2B DEC HL ; Point to NMSB +3508+ 1A6E 7A LD A,D ; Get NMSB +3509+ 1A6F BE CP (HL) ; Compare NMSBs +3510+ 1A70 C0 RET NZ ; Different +3511+ 1A71 2B DEC HL ; Point to LSB +3512+ 1A72 7B LD A,E ; Get LSB +3513+ 1A73 96 SUB (HL) ; Compare LSBs +3514+ 1A74 C0 RET NZ ; Different +3515+ 1A75 E1 POP HL ; Drop RETurn +3516+ 1A76 E1 POP HL ; Drop another RETurn +3517+ 1A77 C9 RET +3518+ 1A78 +3519+ 1A78 47 FPINT: LD B,A ; <- Move +3520+ 1A79 4F LD C,A ; <- exponent +3521+ 1A7A 57 LD D,A ; <- to all +3522+ 1A7B 5F LD E,A ; <- bits +3523+ 1A7C B7 OR A ; Test exponent +3524+ 1A7D C8 RET Z ; Zero - Return zero +3525+ 1A7E E5 PUSH HL ; Save pointer to number +3526+ 1A7F CD 1C 1A CALL BCDEFP ; Move FPREG to BCDE +3527+ 1A82 CD 36 1A CALL SIGNS ; Set MSBs & sign of result +3528+ 1A85 AE XOR (HL) ; Combine with sign of FPREG +3529+ 1A86 67 LD H,A ; Save combined signs +3530+ 1A87 FC 9C 1A CALL M,DCBCDE ; Negative - Decrement BCDE +3531+ 1A8A 3E 98 LD A,80H+24 ; 24 bits +3532+ 1A8C 90 SUB B ; Bits to shift +3533+ 1A8D CD 4F 18 CALL SCALE ; Shift BCDE +3534+ 1A90 7C LD A,H ; Get combined sign +3535+ 1A91 17 RLA ; Sign to carry +3536+ 1A92 DC 22 18 CALL C,FPROND ; Negative - Round number up +3537+ 1A95 06 00 LD B,0 ; Zero exponent +3538+ 1A97 DC 3B 18 CALL C,COMPL ; If negative make positive +3539+ 1A9A E1 POP HL ; Restore pointer to number +3540+ 1A9B C9 RET +3541+ 1A9C +3542+ 1A9C 1B DCBCDE: DEC DE ; Decrement BCDE +3543+ 1A9D 7A LD A,D ; Test LSBs +3544+ 1A9E A3 AND E +3545+ 1A9F 3C INC A +3546+ 1AA0 C0 RET NZ ; Exit if LSBs not FFFF +3547+ 1AA1 0B DEC BC ; Decrement MSBs +3548+ 1AA2 C9 RET +3549+ 1AA3 +3550+ 1AA3 21 97 31 INT: LD HL,FPEXP ; Point to exponent +3551+ 1AA6 7E LD A,(HL) ; Get exponent +3552+ 1AA7 FE 98 CP 80H+24 ; Integer accuracy only? +3553+ 1AA9 3A 94 31 LD A,(FPREG) ; Get LSB +3554+ 1AAC D0 RET NC ; Yes - Already integer +3555+ 1AAD 7E LD A,(HL) ; Get exponent +3556+ 1AAE CD 78 1A CALL FPINT ; F.P to integer +3557+ 1AB1 36 98 LD (HL),80H+24 ; Save 24 bit integer +3558+ 1AB3 7B LD A,E ; Get LSB of number +3559+ 1AB4 F5 PUSH AF ; Save LSB +3560+ 1AB5 79 LD A,C ; Get MSB of number +3561+ 1AB6 17 RLA ; Sign to carry +3562+ 1AB7 CD D8 17 CALL CONPOS ; Set sign of result +3563+ 1ABA F1 POP AF ; Restore LSB of number +3564+ 1ABB C9 RET +3565+ 1ABC +3566+ 1ABC 21 00 00 MLDEBC: LD HL,0 ; Clear partial product +3567+ 1ABF 78 LD A,B ; Test multiplier +3568+ 1AC0 B1 OR C +3569+ 1AC1 C8 RET Z ; Return zero if zero +3570+ 1AC2 3E 10 LD A,16 ; 16 bits +3571+ 1AC4 29 MLDBLP: ADD HL,HL ; Shift P.P left +3572+ 1AC5 DA FC 12 JP C,BSERR ; ?BS Error if overflow +3573+ 1AC8 EB EX DE,HL +3574+ 1AC9 29 ADD HL,HL ; Shift multiplier left +3575+ 1ACA EB EX DE,HL +3576+ 1ACB D2 D2 1A JP NC,NOMLAD ; Bit was zero - No add +3577+ 1ACE 09 ADD HL,BC ; Add multiplicand +3578+ 1ACF DA FC 12 JP C,BSERR ; ?BS Error if overflow +3579+ 1AD2 3D NOMLAD: DEC A ; Count bits +3580+ 1AD3 C2 C4 1A JP NZ,MLDBLP ; More +3581+ 1AD6 C9 RET +3582+ 1AD7 +3583+ 1AD7 FE 2D ASCTFP: CP '-' ; Negative? +3584+ 1AD9 F5 PUSH AF ; Save it and flags +3585+ 1ADA CA E3 1A JP Z,CNVNUM ; Yes - Convert number +3586+ 1ADD FE 2B CP '+' ; Positive? +3587+ 1ADF CA E3 1A JP Z,CNVNUM ; Yes - Convert number +3588+ 1AE2 2B DEC HL ; DEC 'cos GETCHR INCs +3589+ 1AE3 CD F0 17 CNVNUM: CALL RESZER ; Set result to zero +3590+ 1AE6 47 LD B,A ; Digits after point counter +3591+ 1AE7 57 LD D,A ; Sign of exponent +3592+ 1AE8 5F LD E,A ; Exponent of ten +3593+ 1AE9 2F CPL +3594+ 1AEA 4F LD C,A ; Before or after point flag +3595+ 1AEB CD 81 0B MANLP: CALL GETCHR ; Get next character +3596+ 1AEE DA 34 1B JP C,ADDIG ; Digit - Add to number +3597+ 1AF1 FE 2E CP '.' +3598+ 1AF3 CA 0F 1B JP Z,DPOINT ; '.' - Flag point +3599+ 1AF6 FE 45 CP 'E' +3600+ 1AF8 C2 13 1B JP NZ,CONEXP ; Not 'E' - Scale number +3601+ 1AFB CD 81 0B CALL GETCHR ; Get next character +3602+ 1AFE CD 27 11 CALL SGNEXP ; Get sign of exponent +3603+ 1B01 CD 81 0B EXPLP: CALL GETCHR ; Get next character +3604+ 1B04 DA 56 1B JP C,EDIGIT ; Digit - Add to exponent +3605+ 1B07 14 INC D ; Is sign negative? +3606+ 1B08 C2 13 1B JP NZ,CONEXP ; No - Scale number +3607+ 1B0B AF XOR A +3608+ 1B0C 93 SUB E ; Negate exponent +3609+ 1B0D 5F LD E,A ; And re-save it +3610+ 1B0E 0C INC C ; Flag end of number +3611+ 1B0F 0C DPOINT: INC C ; Flag point passed +3612+ 1B10 CA EB 1A JP Z,MANLP ; Zero - Get another digit +3613+ 1B13 E5 CONEXP: PUSH HL ; Save code string address +3614+ 1B14 7B LD A,E ; Get exponent +3615+ 1B15 90 SUB B ; Subtract digits after point +3616+ 1B16 F4 2C 1B SCALMI: CALL P,SCALPL ; Positive - Multiply number +3617+ 1B19 F2 22 1B JP P,ENDCON ; Positive - All done +3618+ 1B1C F5 PUSH AF ; Save number of times to /10 +3619+ 1B1D CD 18 19 CALL DIV10 ; Divide by 10 +3620+ 1B20 F1 POP AF ; Restore count +3621+ 1B21 3C INC A ; Count divides +3622+ 1B22 +3623+ 1B22 C2 16 1B ENDCON: JP NZ,SCALMI ; More to do +3624+ 1B25 D1 POP DE ; Restore code string address +3625+ 1B26 F1 POP AF ; Restore sign of number +3626+ 1B27 CC F9 19 CALL Z,INVSGN ; Negative - Negate number +3627+ 1B2A EB EX DE,HL ; Code string address to HL +3628+ 1B2B C9 RET +3629+ 1B2C +3630+ 1B2C C8 SCALPL: RET Z ; Exit if no scaling needed +3631+ 1B2D F5 MULTEN: PUSH AF ; Save count +3632+ 1B2E CD B9 19 CALL MLSP10 ; Multiply number by 10 +3633+ 1B31 F1 POP AF ; Restore count +3634+ 1B32 3D DEC A ; Count multiplies +3635+ 1B33 C9 RET +3636+ 1B34 +3637+ 1B34 D5 ADDIG: PUSH DE ; Save sign of exponent +3638+ 1B35 57 LD D,A ; Save digit +3639+ 1B36 78 LD A,B ; Get digits after point +3640+ 1B37 89 ADC A,C ; Add one if after point +3641+ 1B38 47 LD B,A ; Re-save counter +3642+ 1B39 C5 PUSH BC ; Save point flags +3643+ 1B3A E5 PUSH HL ; Save code string address +3644+ 1B3B D5 PUSH DE ; Save digit +3645+ 1B3C CD B9 19 CALL MLSP10 ; Multiply number by 10 +3646+ 1B3F F1 POP AF ; Restore digit +3647+ 1B40 D6 30 SUB '0' ; Make it absolute +3648+ 1B42 CD 4B 1B CALL RSCALE ; Re-scale number +3649+ 1B45 E1 POP HL ; Restore code string address +3650+ 1B46 C1 POP BC ; Restore point flags +3651+ 1B47 D1 POP DE ; Restore sign of exponent +3652+ 1B48 C3 EB 1A JP MANLP ; Get another digit +3653+ 1B4B +3654+ 1B4B CD 01 1A RSCALE: CALL STAKFP ; Put number on stack +3655+ 1B4E CD E2 19 CALL FLGREL ; Digit to add to FPREG +3656+ 1B51 C1 PADD: POP BC ; Restore number +3657+ 1B52 D1 POP DE +3658+ 1B53 C3 8A 17 JP FPADD ; Add BCDE to FPREG and return +3659+ 1B56 +3660+ 1B56 7B EDIGIT: LD A,E ; Get digit +3661+ 1B57 07 RLCA ; Times 2 +3662+ 1B58 07 RLCA ; Times 4 +3663+ 1B59 83 ADD A,E ; Times 5 +3664+ 1B5A 07 RLCA ; Times 10 +3665+ 1B5B 86 ADD A,(HL) ; Add next digit +3666+ 1B5C D6 30 SUB '0' ; Make it absolute +3667+ 1B5E 5F LD E,A ; Save new digit +3668+ 1B5F C3 01 1B JP EXPLP ; Look for another digit +3669+ 1B62 +3670+ 1B62 E5 LINEIN: PUSH HL ; Save code string address +3671+ 1B63 21 C1 06 LD HL,INMSG ; Output " in " +3672+ 1B66 CD C7 14 CALL PRS ; Output string at HL +3673+ 1B69 E1 POP HL ; Restore code string address +3674+ 1B6A EB PRNTHL: EX DE,HL ; Code string address to DE +3675+ 1B6B AF XOR A +3676+ 1B6C 06 98 LD B,80H+24 ; 24 bits +3677+ 1B6E CD E7 19 CALL RETINT ; Return the integer +3678+ 1B71 21 C6 14 LD HL,PRNUMS ; Print number string +3679+ 1B74 E5 PUSH HL ; Save for return +3680+ 1B75 21 99 31 NUMASC: LD HL,PBUFF ; Convert number to ASCII +3681+ 1B78 E5 PUSH HL ; Save for return +3682+ 1B79 CD D0 19 CALL TSTSGN ; Test sign of FPREG +3683+ 1B7C 36 20 LD (HL),' ' ; Space at start +3684+ 1B7E F2 83 1B JP P,SPCFST ; Positive - Space to start +3685+ 1B81 36 2D LD (HL),'-' ; '-' sign at start +3686+ 1B83 23 SPCFST: INC HL ; First byte of number +3687+ 1B84 36 30 LD (HL),'0' ; '0' if zero +3688+ 1B86 CA 39 1C JP Z,JSTZER ; Return '0' if zero +3689+ 1B89 E5 PUSH HL ; Save buffer address +3690+ 1B8A FC F9 19 CALL M,INVSGN ; Negate FPREG if negative +3691+ 1B8D AF XOR A ; Zero A +3692+ 1B8E F5 PUSH AF ; Save it +3693+ 1B8F CD 3F 1C CALL RNGTST ; Test number is in range +3694+ 1B92 01 43 91 SIXDIG: LD BC,9143H ; BCDE - 99999.9 +3695+ 1B95 11 F8 4F LD DE,4FF8H +3696+ 1B98 CD 4B 1A CALL CMPNUM ; Compare numbers +3697+ 1B9B B7 OR A +3698+ 1B9C E2 B0 1B JP PO,INRNG ; > 99999.9 - Sort it out +3699+ 1B9F F1 POP AF ; Restore count +3700+ 1BA0 CD 2D 1B CALL MULTEN ; Multiply by ten +3701+ 1BA3 F5 PUSH AF ; Re-save count +3702+ 1BA4 C3 92 1B JP SIXDIG ; Test it again +3703+ 1BA7 +3704+ 1BA7 CD 18 19 GTSIXD: CALL DIV10 ; Divide by 10 +3705+ 1BAA F1 POP AF ; Get count +3706+ 1BAB 3C INC A ; Count divides +3707+ 1BAC F5 PUSH AF ; Re-save count +3708+ 1BAD CD 3F 1C CALL RNGTST ; Test number is in range +3709+ 1BB0 CD 78 17 INRNG: CALL ROUND ; Add 0.5 to FPREG +3710+ 1BB3 3C INC A +3711+ 1BB4 CD 78 1A CALL FPINT ; F.P to integer +3712+ 1BB7 CD 11 1A CALL FPBCDE ; Move BCDE to FPREG +3713+ 1BBA 01 06 03 LD BC,0306H ; 1E+06 to 1E-03 range +3714+ 1BBD F1 POP AF ; Restore count +3715+ 1BBE 81 ADD A,C ; 6 digits before point +3716+ 1BBF 3C INC A ; Add one +3717+ 1BC0 FA CC 1B JP M,MAKNUM ; Do it in 'E' form if < 1E-02 +3718+ 1BC3 FE 08 CP 6+1+1 ; More than 999999 ? +3719+ 1BC5 D2 CC 1B JP NC,MAKNUM ; Yes - Do it in 'E' form +3720+ 1BC8 3C INC A ; Adjust for exponent +3721+ 1BC9 47 LD B,A ; Exponent of number +3722+ 1BCA 3E 02 LD A,2 ; Make it zero after +3723+ 1BCC +3724+ 1BCC 3D MAKNUM: DEC A ; Adjust for digits to do +3725+ 1BCD 3D DEC A +3726+ 1BCE E1 POP HL ; Restore buffer address +3727+ 1BCF F5 PUSH AF ; Save count +3728+ 1BD0 11 52 1C LD DE,POWERS ; Powers of ten +3729+ 1BD3 05 DEC B ; Count digits before point +3730+ 1BD4 C2 DD 1B JP NZ,DIGTXT ; Not zero - Do number +3731+ 1BD7 36 2E LD (HL),'.' ; Save point +3732+ 1BD9 23 INC HL ; Move on +3733+ 1BDA 36 30 LD (HL),'0' ; Save zero +3734+ 1BDC 23 INC HL ; Move on +3735+ 1BDD 05 DIGTXT: DEC B ; Count digits before point +3736+ 1BDE 36 2E LD (HL),'.' ; Save point in case +3737+ 1BE0 CC 26 1A CALL Z,INCHL ; Last digit - move on +3738+ 1BE3 C5 PUSH BC ; Save digits before point +3739+ 1BE4 E5 PUSH HL ; Save buffer address +3740+ 1BE5 D5 PUSH DE ; Save powers of ten +3741+ 1BE6 CD 1C 1A CALL BCDEFP ; Move FPREG to BCDE +3742+ 1BE9 E1 POP HL ; Powers of ten table +3743+ 1BEA 06 2F LD B, '0'-1 ; ASCII '0' - 1 +3744+ 1BEC 04 TRYAGN: INC B ; Count subtractions +3745+ 1BED 7B LD A,E ; Get LSB +3746+ 1BEE 96 SUB (HL) ; Subtract LSB +3747+ 1BEF 5F LD E,A ; Save LSB +3748+ 1BF0 23 INC HL +3749+ 1BF1 7A LD A,D ; Get NMSB +3750+ 1BF2 9E SBC A,(HL) ; Subtract NMSB +3751+ 1BF3 57 LD D,A ; Save NMSB +3752+ 1BF4 23 INC HL +3753+ 1BF5 79 LD A,C ; Get MSB +3754+ 1BF6 9E SBC A,(HL) ; Subtract MSB +3755+ 1BF7 4F LD C,A ; Save MSB +3756+ 1BF8 2B DEC HL ; Point back to start +3757+ 1BF9 2B DEC HL +3758+ 1BFA D2 EC 1B JP NC,TRYAGN ; No overflow - Try again +3759+ 1BFD CD 2F 18 CALL PLUCDE ; Restore number +3760+ 1C00 23 INC HL ; Start of next number +3761+ 1C01 CD 11 1A CALL FPBCDE ; Move BCDE to FPREG +3762+ 1C04 EB EX DE,HL ; Save point in table +3763+ 1C05 E1 POP HL ; Restore buffer address +3764+ 1C06 70 LD (HL),B ; Save digit in buffer +3765+ 1C07 23 INC HL ; And move on +3766+ 1C08 C1 POP BC ; Restore digit count +3767+ 1C09 0D DEC C ; Count digits +3768+ 1C0A C2 DD 1B JP NZ,DIGTXT ; More - Do them +3769+ 1C0D 05 DEC B ; Any decimal part? +3770+ 1C0E CA 1D 1C JP Z,DOEBIT ; No - Do 'E' bit +3771+ 1C11 2B SUPTLZ: DEC HL ; Move back through buffer +3772+ 1C12 7E LD A,(HL) ; Get character +3773+ 1C13 FE 30 CP '0' ; '0' character? +3774+ 1C15 CA 11 1C JP Z,SUPTLZ ; Yes - Look back for more +3775+ 1C18 FE 2E CP '.' ; A decimal point? +3776+ 1C1A C4 26 1A CALL NZ,INCHL ; Move back over digit +3777+ 1C1D +3778+ 1C1D F1 DOEBIT: POP AF ; Get 'E' flag +3779+ 1C1E CA 3C 1C JP Z,NOENED ; No 'E' needed - End buffer +3780+ 1C21 36 45 LD (HL),'E' ; Put 'E' in buffer +3781+ 1C23 23 INC HL ; And move on +3782+ 1C24 36 2B LD (HL),'+' ; Put '+' in buffer +3783+ 1C26 F2 2D 1C JP P,OUTEXP ; Positive - Output exponent +3784+ 1C29 36 2D LD (HL),'-' ; Put '-' in buffer +3785+ 1C2B 2F CPL ; Negate exponent +3786+ 1C2C 3C INC A +3787+ 1C2D 06 2F OUTEXP: LD B,'0'-1 ; ASCII '0' - 1 +3788+ 1C2F 04 EXPTEN: INC B ; Count subtractions +3789+ 1C30 D6 0A SUB 10 ; Tens digit +3790+ 1C32 D2 2F 1C JP NC,EXPTEN ; More to do +3791+ 1C35 C6 3A ADD A,'0'+10 ; Restore and make ASCII +3792+ 1C37 23 INC HL ; Move on +3793+ 1C38 70 LD (HL),B ; Save MSB of exponent +3794+ 1C39 23 JSTZER: INC HL ; +3795+ 1C3A 77 LD (HL),A ; Save LSB of exponent +3796+ 1C3B 23 INC HL +3797+ 1C3C 71 NOENED: LD (HL),C ; Mark end of buffer +3798+ 1C3D E1 POP HL ; Restore code string address +3799+ 1C3E C9 RET +3800+ 1C3F +3801+ 1C3F 01 74 94 RNGTST: LD BC,9474H ; BCDE = 999999. +3802+ 1C42 11 F7 23 LD DE,23F7H +3803+ 1C45 CD 4B 1A CALL CMPNUM ; Compare numbers +3804+ 1C48 B7 OR A +3805+ 1C49 E1 POP HL ; Return address to HL +3806+ 1C4A E2 A7 1B JP PO,GTSIXD ; Too big - Divide by ten +3807+ 1C4D E9 JP (HL) ; Otherwise return to caller +3808+ 1C4E +3809+ 1C4E 00 00 00 80 HALF: .BYTE 00H,00H,00H,80H ; 0.5 +3810+ 1C52 +3811+ 1C52 A0 86 01 POWERS: .BYTE 0A0H,086H,001H ; 100000 +3812+ 1C55 10 27 00 .BYTE 010H,027H,000H ; 10000 +3813+ 1C58 E8 03 00 .BYTE 0E8H,003H,000H ; 1000 +3814+ 1C5B 64 00 00 .BYTE 064H,000H,000H ; 100 +3815+ 1C5E 0A 00 00 .BYTE 00AH,000H,000H ; 10 +3816+ 1C61 01 00 00 .BYTE 001H,000H,000H ; 1 +3817+ 1C64 +3818+ 1C64 21 F9 19 NEGAFT: LD HL,INVSGN ; Negate result +3819+ 1C67 E3 EX (SP),HL ; To be done after caller +3820+ 1C68 E9 JP (HL) ; Return to caller +3821+ 1C69 +3822+ 1C69 CD 01 1A SQR: CALL STAKFP ; Put value on stack +3823+ 1C6C 21 4E 1C LD HL,HALF ; Set power to 1/2 +3824+ 1C6F CD 0E 1A CALL PHLTFP ; Move 1/2 to FPREG +3825+ 1C72 +3826+ 1C72 C1 POWER: POP BC ; Get base +3827+ 1C73 D1 POP DE +3828+ 1C74 CD D0 19 CALL TSTSGN ; Test sign of power +3829+ 1C77 78 LD A,B ; Get exponent of base +3830+ 1C78 CA B7 1C JP Z,EXP ; Make result 1 if zero +3831+ 1C7B F2 82 1C JP P,POWER1 ; Positive base - Ok +3832+ 1C7E B7 OR A ; Zero to negative power? +3833+ 1C7F CA 2C 07 JP Z,DZERR ; Yes - ?/0 Error +3834+ 1C82 B7 POWER1: OR A ; Base zero? +3835+ 1C83 CA F1 17 JP Z,SAVEXP ; Yes - Return zero +3836+ 1C86 D5 PUSH DE ; Save base +3837+ 1C87 C5 PUSH BC +3838+ 1C88 79 LD A,C ; Get MSB of base +3839+ 1C89 F6 7F OR 01111111B ; Get sign status +3840+ 1C8B CD 1C 1A CALL BCDEFP ; Move power to BCDE +3841+ 1C8E F2 9F 1C JP P,POWER2 ; Positive base - Ok +3842+ 1C91 D5 PUSH DE ; Save power +3843+ 1C92 C5 PUSH BC +3844+ 1C93 CD A3 1A CALL INT ; Get integer of power +3845+ 1C96 C1 POP BC ; Restore power +3846+ 1C97 D1 POP DE +3847+ 1C98 F5 PUSH AF ; MSB of base +3848+ 1C99 CD 4B 1A CALL CMPNUM ; Power an integer? +3849+ 1C9C E1 POP HL ; Restore MSB of base +3850+ 1C9D 7C LD A,H ; but don't affect flags +3851+ 1C9E 1F RRA ; Exponent odd or even? +3852+ 1C9F E1 POWER2: POP HL ; Restore MSB and exponent +3853+ 1CA0 22 96 31 LD (FPREG+2),HL ; Save base in FPREG +3854+ 1CA3 E1 POP HL ; LSBs of base +3855+ 1CA4 22 94 31 LD (FPREG),HL ; Save in FPREG +3856+ 1CA7 DC 64 1C CALL C,NEGAFT ; Odd power - Negate result +3857+ 1CAA CC F9 19 CALL Z,INVSGN ; Negative base - Negate it +3858+ 1CAD D5 PUSH DE ; Save power +3859+ 1CAE C5 PUSH BC +3860+ 1CAF CD 84 18 CALL LOG ; Get LOG of base +3861+ 1CB2 C1 POP BC ; Restore power +3862+ 1CB3 D1 POP DE +3863+ 1CB4 CD C5 18 CALL FPMULT ; Multiply LOG by power +3864+ 1CB7 +3865+ 1CB7 CD 01 1A EXP: CALL STAKFP ; Put value on stack +3866+ 1CBA 01 38 81 LD BC,08138H ; BCDE = 1/Ln(2) +3867+ 1CBD 11 3B AA LD DE,0AA3BH +3868+ 1CC0 CD C5 18 CALL FPMULT ; Multiply value by 1/LN(2) +3869+ 1CC3 3A 97 31 LD A,(FPEXP) ; Get exponent +3870+ 1CC6 FE 88 CP 80H+8 ; Is it in range? +3871+ 1CC8 D2 AC 19 JP NC,OVTST1 ; No - Test for overflow +3872+ 1CCB CD A3 1A CALL INT ; Get INT of FPREG +3873+ 1CCE C6 80 ADD A,80H ; For excess 128 +3874+ 1CD0 C6 02 ADD A,2 ; Exponent > 126? +3875+ 1CD2 DA AC 19 JP C,OVTST1 ; Yes - Test for overflow +3876+ 1CD5 F5 PUSH AF ; Save scaling factor +3877+ 1CD6 21 73 18 LD HL,UNITY ; Point to 1. +3878+ 1CD9 CD 7B 17 CALL ADDPHL ; Add 1 to FPREG +3879+ 1CDC CD BC 18 CALL MULLN2 ; Multiply by LN(2) +3880+ 1CDF F1 POP AF ; Restore scaling factor +3881+ 1CE0 C1 POP BC ; Restore exponent +3882+ 1CE1 D1 POP DE +3883+ 1CE2 F5 PUSH AF ; Save scaling factor +3884+ 1CE3 CD 87 17 CALL SUBCDE ; Subtract exponent from FPREG +3885+ 1CE6 CD F9 19 CALL INVSGN ; Negate result +3886+ 1CE9 21 F7 1C LD HL,EXPTAB ; Coefficient table +3887+ 1CEC CD 27 1D CALL SMSER1 ; Sum the series +3888+ 1CEF 11 00 00 LD DE,0 ; Zero LSBs +3889+ 1CF2 C1 POP BC ; Scaling factor +3890+ 1CF3 4A LD C,D ; Zero MSB +3891+ 1CF4 C3 C5 18 JP FPMULT ; Scale result to correct value +3892+ 1CF7 +3893+ 1CF7 08 EXPTAB: .BYTE 8 ; Table used by EXP +3894+ 1CF8 40 2E 94 74 .BYTE 040H,02EH,094H,074H ; -1/7! (-1/5040) +3895+ 1CFC 70 4F 2E 77 .BYTE 070H,04FH,02EH,077H ; 1/6! ( 1/720) +3896+ 1D00 6E 02 88 7A .BYTE 06EH,002H,088H,07AH ; -1/5! (-1/120) +3897+ 1D04 E6 A0 2A 7C .BYTE 0E6H,0A0H,02AH,07CH ; 1/4! ( 1/24) +3898+ 1D08 50 AA AA 7E .BYTE 050H,0AAH,0AAH,07EH ; -1/3! (-1/6) +3899+ 1D0C FF FF 7F 7F .BYTE 0FFH,0FFH,07FH,07FH ; 1/2! ( 1/2) +3900+ 1D10 00 00 80 81 .BYTE 000H,000H,080H,081H ; -1/1! (-1/1) +3901+ 1D14 00 00 00 81 .BYTE 000H,000H,000H,081H ; 1/0! ( 1/1) +3902+ 1D18 +3903+ 1D18 CD 01 1A SUMSER: CALL STAKFP ; Put FPREG on stack +3904+ 1D1B 11 C3 18 LD DE,MULT ; Multiply by "X" +3905+ 1D1E D5 PUSH DE ; To be done after +3906+ 1D1F E5 PUSH HL ; Save address of table +3907+ 1D20 CD 1C 1A CALL BCDEFP ; Move FPREG to BCDE +3908+ 1D23 CD C5 18 CALL FPMULT ; Square the value +3909+ 1D26 E1 POP HL ; Restore address of table +3910+ 1D27 CD 01 1A SMSER1: CALL STAKFP ; Put value on stack +3911+ 1D2A 7E LD A,(HL) ; Get number of coefficients +3912+ 1D2B 23 INC HL ; Point to start of table +3913+ 1D2C CD 0E 1A CALL PHLTFP ; Move coefficient to FPREG +3914+ 1D2F 06 .BYTE 06H ; Skip "POP AF" +3915+ 1D30 F1 SUMLP: POP AF ; Restore count +3916+ 1D31 C1 POP BC ; Restore number +3917+ 1D32 D1 POP DE +3918+ 1D33 3D DEC A ; Cont coefficients +3919+ 1D34 C8 RET Z ; All done +3920+ 1D35 D5 PUSH DE ; Save number +3921+ 1D36 C5 PUSH BC +3922+ 1D37 F5 PUSH AF ; Save count +3923+ 1D38 E5 PUSH HL ; Save address in table +3924+ 1D39 CD C5 18 CALL FPMULT ; Multiply FPREG by BCDE +3925+ 1D3C E1 POP HL ; Restore address in table +3926+ 1D3D CD 1F 1A CALL LOADFP ; Number at HL to BCDE +3927+ 1D40 E5 PUSH HL ; Save address in table +3928+ 1D41 CD 8A 17 CALL FPADD ; Add coefficient to FPREG +3929+ 1D44 E1 POP HL ; Restore address in table +3930+ 1D45 C3 30 1D JP SUMLP ; More coefficients +3931+ 1D48 +3932+ 1D48 CD D0 19 RND: CALL TSTSGN ; Test sign of FPREG +3933+ 1D4B 21 C9 30 LD HL,SEED+2 ; Random number seed +3934+ 1D4E FA A9 1D JP M,RESEED ; Negative - Re-seed +3935+ 1D51 21 EA 30 LD HL,LSTRND ; Last random number +3936+ 1D54 CD 0E 1A CALL PHLTFP ; Move last RND to FPREG +3937+ 1D57 21 C9 30 LD HL,SEED+2 ; Random number seed +3938+ 1D5A C8 RET Z ; Return if RND(0) +3939+ 1D5B 86 ADD A,(HL) ; Add (SEED)+2) +3940+ 1D5C E6 07 AND 00000111B ; 0 to 7 +3941+ 1D5E 06 00 LD B,0 +3942+ 1D60 77 LD (HL),A ; Re-save seed +3943+ 1D61 23 INC HL ; Move to coefficient table +3944+ 1D62 87 ADD A,A ; 4 bytes +3945+ 1D63 87 ADD A,A ; per entry +3946+ 1D64 4F LD C,A ; BC = Offset into table +3947+ 1D65 09 ADD HL,BC ; Point to coefficient +3948+ 1D66 CD 1F 1A CALL LOADFP ; Coefficient to BCDE +3949+ 1D69 CD C5 18 CALL FPMULT ; ; Multiply FPREG by coefficient +3950+ 1D6C 3A C8 30 LD A,(SEED+1) ; Get (SEED+1) +3951+ 1D6F 3C INC A ; Add 1 +3952+ 1D70 E6 03 AND 00000011B ; 0 to 3 +3953+ 1D72 06 00 LD B,0 +3954+ 1D74 FE 01 CP 1 ; Is it zero? +3955+ 1D76 88 ADC A,B ; Yes - Make it 1 +3956+ 1D77 32 C8 30 LD (SEED+1),A ; Re-save seed +3957+ 1D7A 21 AD 1D LD HL,RNDTAB-4 ; Addition table +3958+ 1D7D 87 ADD A,A ; 4 bytes +3959+ 1D7E 87 ADD A,A ; per entry +3960+ 1D7F 4F LD C,A ; BC = Offset into table +3961+ 1D80 09 ADD HL,BC ; Point to value +3962+ 1D81 CD 7B 17 CALL ADDPHL ; Add value to FPREG +3963+ 1D84 CD 1C 1A RND1: CALL BCDEFP ; Move FPREG to BCDE +3964+ 1D87 7B LD A,E ; Get LSB +3965+ 1D88 59 LD E,C ; LSB = MSB +3966+ 1D89 EE 4F XOR 01001111B ; Fiddle around +3967+ 1D8B 4F LD C,A ; New MSB +3968+ 1D8C 36 80 LD (HL),80H ; Set exponent +3969+ 1D8E 2B DEC HL ; Point to MSB +3970+ 1D8F 46 LD B,(HL) ; Get MSB +3971+ 1D90 36 80 LD (HL),80H ; Make value -0.5 +3972+ 1D92 21 C7 30 LD HL,SEED ; Random number seed +3973+ 1D95 34 INC (HL) ; Count seed +3974+ 1D96 7E LD A,(HL) ; Get seed +3975+ 1D97 D6 AB SUB 171 ; Do it modulo 171 +3976+ 1D99 C2 A0 1D JP NZ,RND2 ; Non-zero - Ok +3977+ 1D9C 77 LD (HL),A ; Zero seed +3978+ 1D9D 0C INC C ; Fillde about +3979+ 1D9E 15 DEC D ; with the +3980+ 1D9F 1C INC E ; number +3981+ 1DA0 CD DB 17 RND2: CALL BNORM ; Normalise number +3982+ 1DA3 21 EA 30 LD HL,LSTRND ; Save random number +3983+ 1DA6 C3 28 1A JP FPTHL ; Move FPREG to last and return +3984+ 1DA9 +3985+ 1DA9 77 RESEED: LD (HL),A ; Re-seed random numbers +3986+ 1DAA 2B DEC HL +3987+ 1DAB 77 LD (HL),A +3988+ 1DAC 2B DEC HL +3989+ 1DAD 77 LD (HL),A +3990+ 1DAE C3 84 1D JP RND1 ; Return RND seed +3991+ 1DB1 +3992+ 1DB1 68 B1 46 68 RNDTAB: .BYTE 068H,0B1H,046H,068H ; Table used by RND +3993+ 1DB5 99 E9 92 69 .BYTE 099H,0E9H,092H,069H +3994+ 1DB9 10 D1 75 68 .BYTE 010H,0D1H,075H,068H +3995+ 1DBD +3996+ 1DBD 21 07 1E COS: LD HL,HALFPI ; Point to PI/2 +3997+ 1DC0 CD 7B 17 CALL ADDPHL ; Add it to PPREG +3998+ 1DC3 CD 01 1A SIN: CALL STAKFP ; Put angle on stack +3999+ 1DC6 01 49 83 LD BC,8349H ; BCDE = 2 PI +4000+ 1DC9 11 DB 0F LD DE,0FDBH +4001+ 1DCC CD 11 1A CALL FPBCDE ; Move 2 PI to FPREG +4002+ 1DCF C1 POP BC ; Restore angle +4003+ 1DD0 D1 POP DE +4004+ 1DD1 CD 26 19 CALL DVBCDE ; Divide angle by 2 PI +4005+ 1DD4 CD 01 1A CALL STAKFP ; Put it on stack +4006+ 1DD7 CD A3 1A CALL INT ; Get INT of result +4007+ 1DDA C1 POP BC ; Restore number +4008+ 1DDB D1 POP DE +4009+ 1DDC CD 87 17 CALL SUBCDE ; Make it 0 <= value < 1 +4010+ 1DDF 21 0B 1E LD HL,QUARTR ; Point to 0.25 +4011+ 1DE2 CD 81 17 CALL SUBPHL ; Subtract value from 0.25 +4012+ 1DE5 CD D0 19 CALL TSTSGN ; Test sign of value +4013+ 1DE8 37 SCF ; Flag positive +4014+ 1DE9 F2 F3 1D JP P,SIN1 ; Positive - Ok +4015+ 1DEC CD 78 17 CALL ROUND ; Add 0.5 to value +4016+ 1DEF CD D0 19 CALL TSTSGN ; Test sign of value +4017+ 1DF2 B7 OR A ; Flag negative +4018+ 1DF3 F5 SIN1: PUSH AF ; Save sign +4019+ 1DF4 F4 F9 19 CALL P,INVSGN ; Negate value if positive +4020+ 1DF7 21 0B 1E LD HL,QUARTR ; Point to 0.25 +4021+ 1DFA CD 7B 17 CALL ADDPHL ; Add 0.25 to value +4022+ 1DFD F1 POP AF ; Restore sign +4023+ 1DFE D4 F9 19 CALL NC,INVSGN ; Negative - Make positive +4024+ 1E01 21 0F 1E LD HL,SINTAB ; Coefficient table +4025+ 1E04 C3 18 1D JP SUMSER ; Evaluate sum of series +4026+ 1E07 +4027+ 1E07 DB 0F 49 81 HALFPI: .BYTE 0DBH,00FH,049H,081H ; 1.5708 (PI/2) +4028+ 1E0B +4029+ 1E0B 00 00 00 7F QUARTR: .BYTE 000H,000H,000H,07FH ; 0.25 +4030+ 1E0F +4031+ 1E0F 05 SINTAB: .BYTE 5 ; Table used by SIN +4032+ 1E10 BA D7 1E 86 .BYTE 0BAH,0D7H,01EH,086H ; 39.711 +4033+ 1E14 64 26 99 87 .BYTE 064H,026H,099H,087H ;-76.575 +4034+ 1E18 58 34 23 87 .BYTE 058H,034H,023H,087H ; 81.602 +4035+ 1E1C E0 5D A5 86 .BYTE 0E0H,05DH,0A5H,086H ;-41.342 +4036+ 1E20 DA 0F 49 83 .BYTE 0DAH,00FH,049H,083H ; 6.2832 +4037+ 1E24 +4038+ 1E24 CD 01 1A TAN: CALL STAKFP ; Put angle on stack +4039+ 1E27 CD C3 1D CALL SIN ; Get SIN of angle +4040+ 1E2A C1 POP BC ; Restore angle +4041+ 1E2B E1 POP HL +4042+ 1E2C CD 01 1A CALL STAKFP ; Save SIN of angle +4043+ 1E2F EB EX DE,HL ; BCDE = Angle +4044+ 1E30 CD 11 1A CALL FPBCDE ; Angle to FPREG +4045+ 1E33 CD BD 1D CALL COS ; Get COS of angle +4046+ 1E36 C3 24 19 JP DIV ; TAN = SIN / COS +4047+ 1E39 +4048+ 1E39 CD D0 19 ATN: CALL TSTSGN ; Test sign of value +4049+ 1E3C FC 64 1C CALL M,NEGAFT ; Negate result after if -ve +4050+ 1E3F FC F9 19 CALL M,INVSGN ; Negate value if -ve +4051+ 1E42 3A 97 31 LD A,(FPEXP) ; Get exponent +4052+ 1E45 FE 81 CP 81H ; Number less than 1? +4053+ 1E47 DA 56 1E JP C,ATN1 ; Yes - Get arc tangnt +4054+ 1E4A 01 00 81 LD BC,8100H ; BCDE = 1 +4055+ 1E4D 51 LD D,C +4056+ 1E4E 59 LD E,C +4057+ 1E4F CD 26 19 CALL DVBCDE ; Get reciprocal of number +4058+ 1E52 21 81 17 LD HL,SUBPHL ; Sub angle from PI/2 +4059+ 1E55 E5 PUSH HL ; Save for angle > 1 +4060+ 1E56 21 60 1E ATN1: LD HL,ATNTAB ; Coefficient table +4061+ 1E59 CD 18 1D CALL SUMSER ; Evaluate sum of series +4062+ 1E5C 21 07 1E LD HL,HALFPI ; PI/2 - angle in case > 1 +4063+ 1E5F C9 RET ; Number > 1 - Sub from PI/2 +4064+ 1E60 +4065+ 1E60 09 ATNTAB: .BYTE 9 ; Table used by ATN +4066+ 1E61 4A D7 3B 78 .BYTE 04AH,0D7H,03BH,078H ; 1/17 +4067+ 1E65 02 6E 84 7B .BYTE 002H,06EH,084H,07BH ;-1/15 +4068+ 1E69 FE C1 2F 7C .BYTE 0FEH,0C1H,02FH,07CH ; 1/13 +4069+ 1E6D 74 31 9A 7D .BYTE 074H,031H,09AH,07DH ;-1/11 +4070+ 1E71 84 3D 5A 7D .BYTE 084H,03DH,05AH,07DH ; 1/9 +4071+ 1E75 C8 7F 91 7E .BYTE 0C8H,07FH,091H,07EH ;-1/7 +4072+ 1E79 E4 BB 4C 7E .BYTE 0E4H,0BBH,04CH,07EH ; 1/5 +4073+ 1E7D 6C AA AA 7F .BYTE 06CH,0AAH,0AAH,07FH ;-1/3 +4074+ 1E81 00 00 00 81 .BYTE 000H,000H,000H,081H ; 1/1 +4075+ 1E85 +4076+ 1E85 +4077+ 1E85 C9 ARET: RET ; A RETurn instruction +4078+ 1E86 +4079+ 1E86 D7 GETINP: RST 10H ;input a character +4080+ 1E87 C9 RET +4081+ 1E88 +4082+ 1E88 CLS: +4083+ 1E88 3E 0C LD A,CS ; ASCII Clear screen +4084+ 1E8A C3 C2 1F JP MONOUT ; Output character +4085+ 1E8D +4086+ 1E8D CD 4F 17 WIDTH: CALL GETINT ; Get integer 0-255 +4087+ 1E90 7B LD A,E ; Width to A +4088+ 1E91 32 F2 30 LD (LWIDTH),A ; Set width +4089+ 1E94 C9 RET +4090+ 1E95 +4091+ 1E95 CD EE 0F LINES: CALL GETNUM ; Get a number +4092+ 1E98 CD 33 0C CALL DEINT ; Get integer -32768 to 32767 +4093+ 1E9B ED 53 F6 30 LD (LINESC),DE ; Set lines counter +4094+ 1E9F ED 53 F8 30 LD (LINESN),DE ; Set lines number +4095+ 1EA3 C9 RET +4096+ 1EA4 +4097+ 1EA4 CD 33 0C DEEK: CALL DEINT ; Get integer -32768 to 32767 +4098+ 1EA7 D5 PUSH DE ; Save number +4099+ 1EA8 E1 POP HL ; Number to HL +4100+ 1EA9 46 LD B,(HL) ; Get LSB of contents +4101+ 1EAA 23 INC HL +4102+ 1EAB 7E LD A,(HL) ; Get MSB of contents +4103+ 1EAC C3 A9 13 JP ABPASS ; Return integer AB +4104+ 1EAF +4105+ 1EAF CD EE 0F DOKE: CALL GETNUM ; Get a number +4106+ 1EB2 CD 33 0C CALL DEINT ; Get integer -32768 to 32767 +4107+ 1EB5 D5 PUSH DE ; Save address +4108+ 1EB6 CD F7 09 CALL CHKSYN ; Make sure ',' follows +4109+ 1EB9 2C .BYTE ',' +4110+ 1EBA CD EE 0F CALL GETNUM ; Get a number +4111+ 1EBD CD 33 0C CALL DEINT ; Get integer -32768 to 32767 +4112+ 1EC0 E3 EX (SP),HL ; Save value,get address +4113+ 1EC1 73 LD (HL),E ; Save LSB of value +4114+ 1EC2 23 INC HL +4115+ 1EC3 72 LD (HL),D ; Save MSB of value +4116+ 1EC4 E1 POP HL ; Restore code string address +4117+ 1EC5 C9 RET +4118+ 1EC6 +4119+ 1EC6 +4120+ 1EC6 ; HEX$(nn) Convert 16 bit number to Hexadecimal string +4121+ 1EC6 +4122+ 1EC6 CD F1 0F HEX: CALL TSTNUM ; Verify it's a number +4123+ 1EC9 CD 33 0C CALL DEINT ; Get integer -32768 to 32767 +4124+ 1ECC C5 PUSH BC ; Save contents of BC +4125+ 1ECD 21 99 31 LD HL,PBUFF +4126+ 1ED0 7A LD A,D ; Get high order into A +4127+ 1ED1 FE 00 CP $0 +4128+ 1ED3 28 0C JR Z,HEX2 ; Skip output if both high digits are zero +4129+ 1ED5 CD FE 1E CALL BYT2ASC ; Convert D to ASCII +4130+ 1ED8 78 LD A,B +4131+ 1ED9 FE 30 CP '0' +4132+ 1EDB 28 02 JR Z,HEX1 ; Don't store high digit if zero +4133+ 1EDD 70 LD (HL),B ; Store it to PBUFF +4134+ 1EDE 23 INC HL ; Next location +4135+ 1EDF 71 HEX1: LD (HL),C ; Store C to PBUFF+1 +4136+ 1EE0 23 INC HL ; Next location +4137+ 1EE1 7B HEX2: LD A,E ; Get lower byte +4138+ 1EE2 CD FE 1E CALL BYT2ASC ; Convert E to ASCII +4139+ 1EE5 7A LD A,D +4140+ 1EE6 FE 00 CP $0 +4141+ 1EE8 20 05 JR NZ,HEX3 ; If upper byte was not zero then always print lower byte +4142+ 1EEA 78 LD A,B +4143+ 1EEB FE 30 CP '0' ; If high digit of lower byte is zero then don't print +4144+ 1EED 28 02 JR Z,HEX4 +4145+ 1EEF 70 HEX3: LD (HL),B ; to PBUFF+2 +4146+ 1EF0 23 INC HL ; Next location +4147+ 1EF1 71 HEX4: LD (HL),C ; to PBUFF+3 +4148+ 1EF2 23 INC HL ; PBUFF+4 to zero +4149+ 1EF3 AF XOR A ; Terminating character +4150+ 1EF4 77 LD (HL),A ; Store zero to terminate +4151+ 1EF5 23 INC HL ; Make sure PBUFF is terminated +4152+ 1EF6 77 LD (HL),A ; Store the double zero there +4153+ 1EF7 C1 POP BC ; Get BC back +4154+ 1EF8 21 99 31 LD HL,PBUFF ; Reset to start of PBUFF +4155+ 1EFB C3 57 14 JP STR1 ; Convert the PBUFF to a string and return it +4156+ 1EFE +4157+ 1EFE 47 BYT2ASC LD B,A ; Save original value +4158+ 1EFF E6 0F AND $0F ; Strip off upper nybble +4159+ 1F01 FE 0A CP $0A ; 0-9? +4160+ 1F03 38 02 JR C,ADD30 ; If A-F, add 7 more +4161+ 1F05 C6 07 ADD A,$07 ; Bring value up to ASCII A-F +4162+ 1F07 C6 30 ADD30 ADD A,$30 ; And make ASCII +4163+ 1F09 4F LD C,A ; Save converted char to C +4164+ 1F0A 78 LD A,B ; Retrieve original value +4165+ 1F0B 0F RRCA ; and Rotate it right +4166+ 1F0C 0F RRCA +4167+ 1F0D 0F RRCA +4168+ 1F0E 0F RRCA +4169+ 1F0F E6 0F AND $0F ; Mask off upper nybble +4170+ 1F11 FE 0A CP $0A ; 0-9? < A hex? +4171+ 1F13 38 02 JR C,ADD301 ; Skip Add 7 +4172+ 1F15 C6 07 ADD A,$07 ; Bring it up to ASCII A-F +4173+ 1F17 C6 30 ADD301 ADD A,$30 ; And make it full ASCII +4174+ 1F19 47 LD B,A ; Store high order byte +4175+ 1F1A C9 RET +4176+ 1F1B +4177+ 1F1B ; Convert "&Hnnnn" to FPREG +4178+ 1F1B ; Gets a character from (HL) checks for Hexadecimal ASCII numbers "&Hnnnn" +4179+ 1F1B ; Char is in A, NC if char is ;<=>?@ A-z, CY is set if 0-9 +4180+ 1F1B EB HEXTFP EX DE,HL ; Move code string pointer to DE +4181+ 1F1C 21 00 00 LD HL,$0000 ; Zero out the value +4182+ 1F1F CD 34 1F CALL GETHEX ; Check the number for valid hex +4183+ 1F22 DA 54 1F JP C,HXERR ; First value wasn't hex, HX error +4184+ 1F25 18 05 JR HEXLP1 ; Convert first character +4185+ 1F27 CD 34 1F HEXLP CALL GETHEX ; Get second and addtional characters +4186+ 1F2A 38 1F JR C,HEXIT ; Exit if not a hex character +4187+ 1F2C 29 HEXLP1 ADD HL,HL ; Rotate 4 bits to the left +4188+ 1F2D 29 ADD HL,HL +4189+ 1F2E 29 ADD HL,HL +4190+ 1F2F 29 ADD HL,HL +4191+ 1F30 B5 OR L ; Add in D0-D3 into L +4192+ 1F31 6F LD L,A ; Save new value +4193+ 1F32 18 F3 JR HEXLP ; And continue until all hex characters are in +4194+ 1F34 +4195+ 1F34 13 GETHEX INC DE ; Next location +4196+ 1F35 1A LD A,(DE) ; Load character at pointer +4197+ 1F36 FE 20 CP ' ' +4198+ 1F38 CA 34 1F JP Z,GETHEX ; Skip spaces +4199+ 1F3B D6 30 SUB $30 ; Get absolute value +4200+ 1F3D D8 RET C ; < "0", error +4201+ 1F3E FE 0A CP $0A +4202+ 1F40 38 05 JR C,NOSUB7 ; Is already in the range 0-9 +4203+ 1F42 D6 07 SUB $07 ; Reduce to A-F +4204+ 1F44 FE 0A CP $0A ; Value should be $0A-$0F at this point +4205+ 1F46 D8 RET C ; CY set if was : ; < = > ? @ +4206+ 1F47 FE 10 NOSUB7 CP $10 ; > Greater than "F"? +4207+ 1F49 3F CCF +4208+ 1F4A C9 RET ; CY set if it wasn't valid hex +4209+ 1F4B +4210+ 1F4B EB HEXIT EX DE,HL ; Value into DE, Code string into HL +4211+ 1F4C 7A LD A,D ; Load DE into AC +4212+ 1F4D 4B LD C,E ; For prep to +4213+ 1F4E E5 PUSH HL +4214+ 1F4F CD A8 13 CALL ACPASS ; ACPASS to set AC as integer into FPREG +4215+ 1F52 E1 POP HL +4216+ 1F53 C9 RET +4217+ 1F54 +4218+ 1F54 1E 26 HXERR: LD E,HX ; ?HEX Error +4219+ 1F56 C3 3D 07 JP ERROR +4220+ 1F59 +4221+ 1F59 ; BIN$(NN) Convert integer to a 1-16 char binary string +4222+ 1F59 CD F1 0F BIN: CALL TSTNUM ; Verify it's a number +4223+ 1F5C CD 33 0C CALL DEINT ; Get integer -32768 to 32767 +4224+ 1F5F C5 BIN2: PUSH BC ; Save contents of BC +4225+ 1F60 21 99 31 LD HL,PBUFF +4226+ 1F63 06 11 LD B,17 ; One higher than max char count +4227+ 1F65 ZEROSUP: ; Suppress leading zeros +4228+ 1F65 05 DEC B ; Max 16 chars +4229+ 1F66 78 LD A,B +4230+ 1F67 FE 01 CP $01 +4231+ 1F69 28 08 JR Z,BITOUT ; Always output at least one character +4232+ 1F6B CB 13 RL E +4233+ 1F6D CB 12 RL D +4234+ 1F6F 30 F4 JR NC,ZEROSUP +4235+ 1F71 18 04 JR BITOUT2 +4236+ 1F73 BITOUT: +4237+ 1F73 CB 13 RL E +4238+ 1F75 CB 12 RL D ; Top bit now in carry +4239+ 1F77 BITOUT2: +4240+ 1F77 3E 30 LD A,'0' ; Char for '0' +4241+ 1F79 CE 00 ADC A,0 ; If carry set then '0' --> '1' +4242+ 1F7B 77 LD (HL),A +4243+ 1F7C 23 INC HL +4244+ 1F7D 05 DEC B +4245+ 1F7E 20 F3 JR NZ,BITOUT +4246+ 1F80 AF XOR A ; Terminating character +4247+ 1F81 77 LD (HL),A ; Store zero to terminate +4248+ 1F82 23 INC HL ; Make sure PBUFF is terminated +4249+ 1F83 77 LD (HL),A ; Store the double zero there +4250+ 1F84 C1 POP BC +4251+ 1F85 21 99 31 LD HL,PBUFF +4252+ 1F88 C3 57 14 JP STR1 +4253+ 1F8B +4254+ 1F8B ; Convert "&Bnnnn" to FPREG +4255+ 1F8B ; Gets a character from (HL) checks for Binary ASCII numbers "&Bnnnn" +4256+ 1F8B EB BINTFP: EX DE,HL ; Move code string pointer to DE +4257+ 1F8C 21 00 00 LD HL,$0000 ; Zero out the value +4258+ 1F8F CD A8 1F CALL CHKBIN ; Check the number for valid bin +4259+ 1F92 DA B6 1F JP C,BINERR ; First value wasn't bin, HX error +4260+ 1F95 D6 30 BINIT: SUB '0' +4261+ 1F97 29 ADD HL,HL ; Rotate HL left +4262+ 1F98 B5 OR L +4263+ 1F99 6F LD L,A +4264+ 1F9A CD A8 1F CALL CHKBIN ; Get second and addtional characters +4265+ 1F9D 30 F6 JR NC,BINIT ; Process if a bin character +4266+ 1F9F EB EX DE,HL ; Value into DE, Code string into HL +4267+ 1FA0 7A LD A,D ; Load DE into AC +4268+ 1FA1 4B LD C,E ; For prep to +4269+ 1FA2 E5 PUSH HL +4270+ 1FA3 CD A8 13 CALL ACPASS ; ACPASS to set AC as integer into FPREG +4271+ 1FA6 E1 POP HL +4272+ 1FA7 C9 RET +4273+ 1FA8 +4274+ 1FA8 ; Char is in A, NC if char is 0 or 1 +4275+ 1FA8 13 CHKBIN: INC DE +4276+ 1FA9 1A LD A,(DE) +4277+ 1FAA FE 20 CP ' ' +4278+ 1FAC CA A8 1F JP Z,CHKBIN ; Skip spaces +4279+ 1FAF FE 30 CP '0' ; Set C if < '0' +4280+ 1FB1 D8 RET C +4281+ 1FB2 FE 32 CP '2' +4282+ 1FB4 3F CCF ; Set C if > '1' +4283+ 1FB5 C9 RET +4284+ 1FB6 +4285+ 1FB6 1E 28 BINERR: LD E,BN ; ?BIN Error +4286+ 1FB8 C3 3D 07 JP ERROR +4287+ 1FBB +4288+ 1FBB +4289+ 1FBB JJUMP1: +4290+ 1FBB DD 21 FF FF LD IX,-1 ; Flag cold start +4291+ 1FBF C3 8D 03 JP CSTART ; Go and initialise +4292+ 1FC2 +4293+ 1FC2 MONOUT: +4294+ 1FC2 C3 08 00 JP $0008 ; output a char +4295+ 1FC5 +4296+ 1FC5 +4297+ 1FC5 MONITR: +4298+ 1FC5 C3 00 00 JP $0000 ; Restart (Normally Monitor Start) +4299+ 1FC8 +4300+ 1FC8 +4301+ 1FC8 3E 00 INITST: LD A,0 ; Clear break flag +4302+ 1FCA 32 FD 30 LD (BRKFLG),A +4303+ 1FCD C3 94 03 JP INIT +4304+ 1FD0 +4305+ 1FD0 ED 45 ARETN: RETN ; Return from NMI +4306+ 1FD2 +4307+ 1FD2 +4308+ 1FD2 F5 TSTBIT: PUSH AF ; Save bit mask +4309+ 1FD3 A0 AND B ; Get common bits +4310+ 1FD4 C1 POP BC ; Restore bit mask +4311+ 1FD5 B8 CP B ; Same bit set? +4312+ 1FD6 3E 00 LD A,0 ; Return 0 in A +4313+ 1FD8 C9 RET +4314+ 1FD9 +4315+ 1FD9 CD 02 0A OUTNCR: CALL OUTC ; Output character in A +4316+ 1FDC C3 29 0E JP PRNTCRLF ; Output CRLF +4317+ 1FDF +0723 1FDF .end tasm: Number of errors = 0 diff --git a/build_id.v b/build_id.v index 077f20d..9eddd91 100644 --- a/build_id.v +++ b/build_id.v @@ -1 +1 @@ -`define BUILD_DATE "241216" \ No newline at end of file +`define BUILD_DATE "241217" \ No newline at end of file diff --git a/releases/MultiComp_20241217.rbf b/releases/MultiComp_20241217.rbf new file mode 100644 index 0000000..6b7992a Binary files /dev/null and b/releases/MultiComp_20241217.rbf differ