diff --git a/printm.s b/printm.s index 54ea729..6436235 100644 --- a/printm.s +++ b/printm.s @@ -1,16 +1,19 @@ ; ca65 .feature c_comments -/* Version 17 -printm - a printf replacement for 65C02 +/* Version 18 +printm - a modular micro printf replacement for 65C02 Michael Pohoreski - +Copyleft {c} Feb, 2016 +Special Thanks: Sheldon for his 65C02 printf() source Problem: -Ideally we want to print a single line that includes literal and variables -in MIXED ASCII case -- high bit characters would be output "as is" -and ASCII characters would be interpreted as a variable output. +Ideally we want to print an 1:1 mapping of input:output text that includes +literal and variables. We could do this by using mixed ASCII case: + + - high bit characters would be output "as is" + - ASCII characters would be interpreted as a variable output. __ ___ ____ __ ________ ________ .byte "X=## Y=### $=$$$$:@@ %%%%%%%%~????????" @@ -31,6 +34,8 @@ While originally this gives us a nice 1:1 mapping for input:output ... a) it has to be constructed in pieces b) and it is bloated. +Can we fix (a) ? + Can we use a more compact printf-style format string where we don't waste storing the escape character AND toggle the high bit on characters on/off as needed? @@ -39,7 +44,11 @@ Yes, if we use a macro! PRINTM "X=%# Y=%d $=%x:%@ %%~%?" -This is why printf() on the 6502 sucks: +Can we fix (b) ? + +Yes, by using an unique meta character that has the width associated with it. + +This is why the cannonical printf() on the 6502 sucks: - is bloated by using a meta-character '%' instead of the high bit - doesn't provide a standard way to print binary *facepalm* @@ -47,10 +56,13 @@ This is why printf() on the 6502 sucks: - 2 digit, 3 digit and 5 digit decimals requiring wasting "width" characters e.g. %2d, %3d, %5d When a single character would work instead. +- printf() is notorious for being bloated. If you don't use + features you can't turn them off to reclaim the memory used + by the code (or data) Solution: -Here is a micro replacement, printm() +Here is a *modular* _micro_ replacement: printm() * Literals have the high byte set (APPLE text) * Meta characters have the high bit cleared (ASCII) @@ -69,238 +81,245 @@ Here is a micro replacement, printm() % Bin - Print 8 bits ? Bin - Print 8 bits but 1's in inverse + o Oct - Print 1 Byte in octal (max 3 digits) + O Oct - Print 2 Byte in octal (max 6 digits) + a Str - APPLE text (high bit set), last char is ASCII s Str - C string, zero terminated p Str - Pascal string, first character is string length -Each option can invidivually be enabled / disabled -to control the memory footprint. +Each option can individually be enabled / disabled +to control the memory footprint since you probably +don't need "every" feature. Seriously, when was the last time +you _needed_ octal? :-) -With everything enabled printm() takes up $1D1 = 465 bytes +With everything enabled printm() takes up $205 = 517 bytes (Plus 2 bytes in zero page.) -With all features turned off the core routines use $64 = 100 bytes. +Whoa! I thought you said this was micro!? -With Bin, Dec2, Dec5, Hex2, Hex4, and StrA -the size is $154 = 340 bytes +With all 15 features turned OFF the core routines use $64 = 100 bytes. -To toggle features on / off, change USE_*: +With the common setting (default): + BinAsc, Dec2, Dec3, Dec5, Hex2, Hex4, and StrA +the size is $162 = 354 bytes + +To toggle features on / off change USE_* to 0 or 1: */ ; NOTE: The Size *also* includes the core routines ; so the actual implementation size for each feature ; is actually smaller the size leads you to believe. +; Also, "common functionality" is also included in the count.. + +; core _PrintDec routine. ; -; Feature Size Total Notes -USE_BIN_ASC = 1 ; $81 \ -USE_BIN_INV = 1 ; $87 / $8B -USE_DEC_2 = 1 ; $D7 \ -USE_DEC_3 = 1 ; $D9 $106 -USE_DEC_5 = 1 ; $D9 -USE_DEC_BYTE = 1 ; $F3 / sets ENABLE_DEC -USE_HEX_2 = 1 ; $AE \ -USE_HEX_4 = 1 ; $AE / $B2 -USE_PTR_2 = 1 ; $C0 sets ENABLE_HEX -USE_PTR_4 = 1 ; $C3 sets ENABLE_HEX -USE_STR_A = 1 ; $7A \ -USE_STR_C = 1 ; $7A $A8 -USE_STR_PASCAL = 1 ; $7C / +; Feature Size Bytes Total Notes +USE_BIN_ASC = 1 ; $84 132 \ +USE_BIN_INV = 1 ; $86 134 / $8B (139 bytes) +USE_DEC_2 = 1 ; $D7 215 \ +USE_DEC_3 = 1 ; $D9 217 $106 (262 bytes) +USE_DEC_5 = 1 ; $D9 217 +USE_DEC_BYTE = 1 ; $F3 243 / sets ENABLE_DEC +USE_HEX_2 = 1 ; $AF 175 \ +USE_HEX_4 = 1 ; $B1 177 / $B6 (182 bytes) +USE_OCT_3 = 1 ; $9C 156 \ +USE_OCT_6 = 1 ; $9E 158 / $A3 (163 bytes) +USE_PTR_2 = 1 ; $C0 192 \ sets ENABLE_HEX +USE_PTR_4 = 1 ; $C2 194 / $C7 (199 bytes) +USE_STR_A = 1 ; $7A 122 \ +USE_STR_C = 1 ; $7A 122 $A8 (168 bytes) +USE_STR_PASCAL = 1 ; $7C 124 / /* Demo + Library text dump: 4000:20 58 FC A9 D5 8D 00 20 -4008:A9 AA 8D 01 20 AD 6F 41 +4008:A9 AA 8D 01 20 AD E9 41 4010:A2 00 A0 00 20 11 F4 18 -4018:A5 26 6D 6D 41 85 26 AA -4020:A4 27 8E 71 41 8C 72 41 -4028:8E 73 41 8C 74 41 AD 00 -4030:20 A0 00 91 26 8D 75 41 -4038:9C 76 41 20 0F 41 8D 77 -4040:41 9C 78 41 A0 00 20 1A -4048:41 A2 6B A0 41 20 04 43 -4050:A0 01 20 1A 41 A2 8F A0 -4058:41 20 04 43 A0 02 20 1A -4060:41 A2 93 A0 41 20 04 43 -4068:A0 03 20 1A 41 A2 BE A0 -4070:41 20 04 43 A0 04 20 1A -4078:41 A2 C2 A0 41 20 04 43 -4080:A0 05 20 1A 41 A2 C6 A0 -4088:41 20 04 43 A0 06 20 1A -4090:41 A2 CA A0 41 20 04 43 -4098:A0 07 20 1A 41 A2 FE A0 -40A0:41 20 04 43 A0 08 20 1A -40A8:41 A2 02 A0 42 20 04 43 -40B0:A0 09 20 1A 41 A2 06 A0 -40B8:42 20 04 43 A0 0A 20 1A -40C0:41 A2 0C A0 42 20 04 43 -40C8:A0 0B 20 1A 41 A2 58 A0 -40D0:42 20 04 43 A0 0C 20 1A -40D8:41 A2 5E A0 42 20 04 43 -40E0:A0 0D 20 1A 41 A2 62 A0 -40E8:42 20 04 43 A9 0E 20 5B -40F0:FB A0 00 B9 66 42 F0 06 -40F8:20 ED FD C8 D0 F5 AD 75 -4100:42 20 D3 FD AD 74 42 20 -4108:DA FD A9 8D 4C ED FD A2 -4110:08 85 FF 06 FF 6A CA D0 -4118:FA 60 B9 29 41 8D 89 44 -4120:B9 41 41 09 04 8D 8A 44 -4128:60 00 80 00 80 00 80 00 -4130:80 28 A8 28 A8 28 A8 28 -4138:A8 50 D0 50 D0 50 D0 50 -4140:D0 00 00 01 01 02 02 03 -4148:03 00 00 01 01 02 02 03 -4150:03 00 00 01 01 02 02 03 -4158:03 D8 BD 23 A0 D9 BD 64 -4160:A0 A4 BD 78 BA 40 A0 25 -4168:FE 3F 00 59 41 27 00 BF -4170:00 DE C0 DE C0 1A DA 1A -4178:DA C2 E9 EE A0 C1 D3 C3 -4180:BA A0 25 00 C2 E9 EE A0 -4188:C9 CE D6 BA A0 3F 00 79 -4190:41 75 41 84 41 75 41 C4 -4198:E5 E3 B2 BA A0 23 00 C4 -41A0:E5 E3 B3 BA A0 64 00 C4 -41A8:E5 E3 B5 BA A0 75 00 C2 -41B0:F9 F4 E5 BD 62 A0 62 A0 -41B8:62 A0 62 A0 62 00 97 41 -41C0:63 00 9F 41 E7 03 A7 41 -41C8:69 FF AF 41 80 00 FF 00 -41D0:00 00 01 00 7F 00 C8 E5 -41D8:F8 B2 BA A0 A4 24 00 C8 -41E0:E5 F8 B4 BA A0 A4 78 00 -41E8:D0 F4 F2 B2 BA A0 A4 78 -41F0:BA 40 00 D0 F4 F2 B4 BA -41F8:A0 A4 78 BA 26 00 D6 41 -4200:34 12 DF 41 34 12 E8 41 -4208:00 20 00 20 F3 41 00 20 -4210:00 20 C8 C5 CC CC CF 00 -4218:D7 CF D2 CC C4 00 C8 CF -4220:CD 45 0D D0 E1 F3 E3 E1 -4228:EC A0 CC E5 EE A0 B1 B3 -4230:C3 A0 A0 A0 A0 A0 BA A0 -4238:A7 73 A7 AC A7 73 A7 00 -4240:C1 F0 F0 EC E5 A0 BA A0 -4248:A7 61 A7 00 D0 E1 F3 E3 -4250:E1 EC BA A0 A7 70 A7 00 -4258:30 42 12 42 18 42 40 42 -4260:1E 42 4C 42 22 42 F0 F2 -4268:E9 EE F4 ED A8 A9 AE F3 -4270:E9 FA E5 00 D1 01 00 00 -4278:00 00 00 00 00 00 00 00 -4280:00 00 00 00 00 00 00 00 -4288:00 00 00 00 00 00 00 00 -4290:00 00 00 00 00 00 00 00 -4298:00 00 00 00 00 00 00 00 -42A0:00 00 00 00 00 00 00 00 -42A8:00 00 00 00 00 00 00 00 -42B0:00 00 00 00 00 00 00 00 -42B8:00 00 00 00 00 00 00 00 -42C0:00 00 00 00 00 00 00 00 -42C8:00 00 00 00 00 00 00 00 -42D0:00 00 00 00 00 00 00 00 -42D8:00 00 00 00 00 00 00 00 -42E0:00 00 00 00 00 00 00 00 -42E8:00 00 00 00 00 00 00 00 -42F0:00 00 00 00 00 00 00 00 -42F8:00 00 00 00 00 00 00 00 -4300:A9 04 D0 16 8E 96 44 8C -4308:97 44 9C 94 44 20 8F 44 -4310:8E 98 43 8C 99 43 80 7F -4318:A9 02 8D 52 43 20 8F 44 -4320:8E AC 44 8C AD 44 A2 00 -4328:AD AC 44 29 0F C9 0A 90 -4330:02 69 06 69 B0 9D A6 44 -4338:4E AD 44 6E AC 44 4E AD -4340:44 6E AC 44 4E AD 44 6E -4348:AC 44 4E AD 44 6E AC 44 -4350:E8 E0 04 D0 D3 CA 30 37 -4358:BD A6 44 20 88 44 80 F5 -4360:A9 04 D0 02 A9 02 8D 52 -4368:43 20 8F 44 A0 00 B1 FE -4370:AA C8 B1 FE A8 80 A9 20 -4378:8F 44 A0 00 B1 FE 10 0A -4380:20 88 44 C8 D0 F6 E6 FF -4388:80 F2 09 80 20 88 44 EE -4390:98 43 D0 03 EE 99 43 AD -4398:DE C0 F0 14 30 EE A2 0C -43A0:DD AE 44 F0 05 CA 10 F8 -43A8:30 E5 8A 0A AA 7C BB 44 -43B0:60 A9 05 D0 06 A9 03 D0 -43B8:02 A9 02 8D 1A 44 20 8F -43C0:44 8E AC 44 8C AD 44 9C -43C8:A6 44 9C A7 44 9C A8 44 -43D0:A2 10 F8 0E AC 44 2E AD -43D8:44 AD A6 44 6D A6 44 8D -43E0:A6 44 AD A7 44 6D A7 44 -43E8:8D A7 44 AD A8 44 6D A8 -43F0:44 8D A8 44 CA D0 DC D8 -43F8:A2 02 A0 05 BD A6 44 4A -4400:4A 4A 4A 18 69 B0 99 A6 -4408:44 88 BD A6 44 29 0F 18 -4410:69 B0 99 A6 44 88 CA 10 -4418:E3 A2 00 4C 55 43 A9 81 -4420:D0 02 A9 01 8D 36 44 20 -4428:8F 44 A0 08 8A C9 80 2A -4430:AA 29 01 F0 02 A9 81 49 -4438:B0 20 88 44 88 D0 ED 4C -4440:8F 43 20 8F 44 8A 10 0D -4448:A9 AD 20 88 44 8A 49 FF -4450:29 7F 18 69 01 AA A0 00 -4458:A9 03 8D 1A 44 4C C1 43 -4460:20 8F 44 A0 00 B1 FE F0 -4468:D6 20 88 44 C8 D0 F6 E6 -4470:FF 80 F2 20 8F 44 A0 00 -4478:B1 FE F0 C3 AA C8 B1 FE -4480:20 88 44 CA D0 F7 F0 B7 -4488:8D DE C0 EE 89 44 60 20 -4490:93 44 AA A0 00 B9 DE C0 -4498:EE 94 44 D0 03 EE 97 44 -44A0:A8 86 FE 84 FF 60 00 00 -44A8:00 00 00 00 00 00 3F 25 -44B0:62 75 64 23 78 24 26 40 -44B8:70 73 61 1E 44 22 44 42 -44C0:44 B1 43 B5 43 B9 43 00 -44C8:43 18 43 60 43 64 43 73 -44D0:44 60 44 77 43 +4018:A5 26 6D E7 41 85 26 AA +4020:A4 27 8E EB 41 8C EC 41 +4028:8E ED 41 8C EE 41 AD 00 +4030:20 A0 00 91 26 8D EF 41 +4038:9C F0 41 8D 0B 42 8D 0F +4040:42 20 B4 41 8D F1 41 9C +4048:F2 41 A0 00 20 C4 41 A2 +4050:E5 A0 41 20 27 43 A0 01 +4058:20 C4 41 A2 09 A0 42 20 +4060:27 43 A0 02 20 C4 41 A2 +4068:0D A0 42 20 27 43 A0 03 +4070:20 C4 41 A2 38 A0 42 20 +4078:27 43 A0 04 20 C4 41 A2 +4080:3C A0 42 20 27 43 A0 05 +4088:20 C4 41 A2 40 A0 42 20 +4090:27 43 A0 06 20 C4 41 A2 +4098:44 A0 42 20 27 43 A0 07 +40A0:20 C4 41 A2 74 A0 42 20 +40A8:27 43 A0 08 20 C4 41 A2 +40B0:78 A0 42 20 27 43 A0 09 +40B8:20 C4 41 A2 7C A0 42 20 +40C0:27 43 A0 0A 20 C4 41 A2 +40C8:82 A0 42 20 27 43 A0 0B +40D0:20 C4 41 A2 98 A0 42 20 +40D8:27 43 A0 0C 20 C4 41 A2 +40E0:9C A0 42 20 27 43 A0 0D +40E8:20 C4 41 A2 EC A0 42 20 +40F0:27 43 A0 0E 20 C4 41 A2 +40F8:E6 A0 42 20 27 43 A0 0F +4100:20 C4 41 A2 F0 A0 42 20 +4108:27 43 A9 11 20 5B FB A2 +4110:F4 A0 42 20 A3 41 AD 22 +4118:43 85 FF 20 DA FD AD 21 +4120:43 85 FE 20 DA FD 20 BF +4128:41 20 50 41 A2 06 A0 43 +4130:20 A3 41 AE C2 43 E8 86 +4138:FE 64 FF 8A 20 DA FD 20 +4140:BF 41 20 50 41 A9 8D 4C +4148:ED FD 00 00 00 00 00 00 +4150:A2 4A A0 41 86 FC 84 FD +4158:9C 4A 41 9C 4B 41 9C 4C +4160:41 A0 00 A2 10 F8 06 FE +4168:26 FF B1 FC 71 FC 91 FC +4170:C8 B1 FC 71 FC 91 FC C8 +4178:B1 FC 71 FC 91 FC C8 A0 +4180:00 CA D0 E2 D8 A2 02 BD +4188:4A 41 4A 4A 4A 4A 18 69 +4190:B0 20 ED FD BD 4A 41 29 +4198:0F 18 69 B0 20 ED FD CA +41A0:10 E5 60 86 FC 84 FD A0 +41A8:00 B1 FC F0 06 20 ED FD +41B0:C8 D0 F6 60 A2 08 85 FE +41B8:06 FE 6A CA D0 FA 60 A9 +41C0:A0 4C ED FD 98 20 C1 FB +41C8:A6 28 A4 29 8E DA 44 8C +41D0:DB 44 60 D8 BD 23 A0 D9 +41D8:BD 64 A0 A4 BD 78 BA 40 +41E0:A0 25 FE 3F 00 D3 41 27 +41E8:00 BF 00 DE C0 DE C0 1A +41F0:DA 1A DA C2 E9 EE A0 C1 +41F8:D3 C3 BA A0 25 00 C2 E9 +4200:EE A0 C9 CE D6 BA A0 3F +4208:00 F3 41 1A DA FE 41 1A +4210:DA C4 E5 E3 B2 BA A0 23 +4218:00 C4 E5 E3 B3 BA A0 64 +4220:00 C4 E5 E3 B5 BA A0 75 +4228:00 C2 F9 F4 E5 BD 62 A0 +4230:62 A0 62 A0 62 A0 62 00 +4238:11 42 63 00 19 42 E7 03 +4240:21 42 69 FF 29 42 80 00 +4248:FF 00 00 00 01 00 7F 00 +4250:C8 E5 F8 B2 BA A0 24 00 +4258:C8 E5 F8 B4 BA A0 78 00 +4260:D0 F4 F2 B2 BA A0 78 BA +4268:40 00 D0 F4 F2 B4 BA A0 +4270:78 BA 26 00 50 42 34 12 +4278:58 42 34 12 60 42 00 20 +4280:00 20 6A 42 00 20 00 20 +4288:CF E3 F4 B3 BA A0 6F 00 +4290:CF E3 F4 B6 BA A0 4F 00 +4298:88 42 B6 01 90 42 DF 32 +42A0:C8 C5 CC CC CF 00 D7 CF +42A8:D2 CC C4 00 C8 CF CD 45 +42B0:0D D0 E1 F3 E3 E1 EC A0 +42B8:CC E5 EE A0 B1 B3 C3 A0 +42C0:A0 A0 A0 A0 BA A0 A7 73 +42C8:A7 AC A7 73 A7 00 C1 F0 +42D0:F0 EC E5 A0 BA A0 A7 61 +42D8:A7 00 D0 E1 F3 E3 E1 EC +42E0:BA A0 A7 70 A7 00 BE 42 +42E8:A0 42 A6 42 CE 42 AC 42 +42F0:DA 42 B0 42 F0 F2 E9 EE +42F8:F4 ED A8 A9 AE F3 E9 FA +4300:E5 A0 BD A0 A4 00 A0 E2 +4308:F9 F4 E5 F3 8D A0 A0 A0 +4310:A0 AE E6 E5 E1 F4 F5 F2 +4318:E5 F3 A0 BD A0 A4 A0 A0 +4320:00 09 02 A9 04 D0 16 8E +4328:E7 44 8C E8 44 9C E5 44 +4330:20 E0 44 8E BB 43 8C BC +4338:43 80 7F A9 02 8D 75 43 +4340:20 E0 44 8E FD 44 8C FE +4348:44 A2 00 AD FD 44 29 0F +4350:C9 0A 90 02 69 06 69 B0 +4358:9D F7 44 4E FE 44 6E FD +4360:44 4E FE 44 6E FD 44 4E +4368:FE 44 6E FD 44 4E FE 44 +4370:6E FD 44 E8 E0 04 D0 D3 +4378:CA 30 37 BD F7 44 20 D9 +4380:44 80 F5 A9 04 D0 02 A9 +4388:02 8D 75 43 20 E0 44 A0 +4390:00 B1 FE AA C8 B1 FE A8 +4398:80 A9 20 E0 44 A0 00 B1 +43A0:FE 10 0A 20 D9 44 C8 D0 +43A8:F6 E6 FF 80 F2 09 80 20 +43B0:D9 44 EE BB 43 D0 03 EE +43B8:BC 43 AD DE C0 F0 14 30 +43C0:EE A2 0E DD FF 44 F0 05 +43C8:CA 10 F8 30 E5 8A 0A AA +43D0:7C 0E 45 60 A9 05 D0 06 +43D8:A9 03 D0 02 A9 02 8D 3D +43E0:44 20 E0 44 8E FD 44 8C +43E8:FE 44 9C F7 44 9C F8 44 +43F0:9C F9 44 A2 10 F8 0E FD +43F8:44 2E FE 44 AD F7 44 6D +4400:F7 44 8D F7 44 AD F8 44 +4408:6D F8 44 8D F8 44 AD F9 +4410:44 6D F9 44 8D F9 44 CA +4418:D0 DC D8 A2 02 A0 05 BD +4420:F7 44 4A 4A 4A 4A 18 69 +4428:B0 99 F7 44 88 BD F7 44 +4430:29 0F 18 69 B0 99 F7 44 +4438:88 CA 10 E3 A2 00 4C 78 +4440:43 A9 81 D0 02 A9 01 8D +4448:59 44 20 E0 44 A0 08 8A +4450:C9 80 2A AA 29 01 F0 02 +4458:A9 81 49 B0 20 D9 44 88 +4460:D0 ED 4C B2 43 20 E0 44 +4468:8A 10 0D A9 AD 20 D9 44 +4470:8A 49 FF 29 7F 18 69 01 +4478:AA A0 00 A9 03 8D 3D 44 +4480:4C E4 43 A9 06 D0 02 A9 +4488:03 8D AD 44 20 E0 44 A2 +4490:00 A5 FE 29 07 18 69 B0 +4498:9D F7 44 46 FF 66 FE 46 +44A0:FF 66 FE 46 FF 66 FE E8 +44A8:E0 06 D0 E5 A2 06 4C 78 +44B0:43 20 E0 44 A0 00 B1 FE +44B8:F0 A8 20 D9 44 C8 D0 F6 +44C0:E6 FF 80 F2 20 E0 44 A0 +44C8:00 B1 FE F0 95 AA C8 B1 +44D0:FE 20 D9 44 CA D0 F7 F0 +44D8:89 8D DE C0 EE DA 44 60 +44E0:20 E4 44 AA A0 00 B9 DE +44E8:C0 EE E5 44 D0 03 EE E8 +44F0:44 A8 86 FE 84 FF 60 00 +44F8:00 00 00 00 00 00 00 3F +4500:25 62 75 64 23 78 24 26 +4508:40 4F 6F 70 73 61 41 44 +4510:45 44 65 44 D4 43 D8 43 +4518:DC 43 23 43 3B 43 83 43 +4520:87 43 83 44 87 44 C4 44 +4528:B1 44 9A 43 */ -; Include necessary components based on features requested -ENABLE_BIN = USE_BIN_ASC || USE_BIN_INV -ENABLE_DEC = USE_DEC_2 || USE_DEC_3 || USE_DEC_5 || USE_DEC_BYTE -ENABLE_HEX = USE_HEX_2 || USE_HEX_4 || USE_PTR_2 || USE_PTR_4 -ENABLE_PTR = USE_PTR_2 || USE_PTR_4 -ENABLE_STR = USE_STR_A || USE_STR_C || USE_STR_PASCAL - -; more ca65 +; more ca65 features .linecont + -NumMeta = 0 + \ - USE_BIN_ASC + \ - USE_BIN_INV + \ - USE_DEC_2 + \ - USE_DEC_3 + \ - USE_DEC_5 + \ - USE_DEC_BYTE + \ - USE_HEX_2 + \ - USE_HEX_4 + \ - USE_PTR_2 + \ - USE_PTR_4 + \ - USE_STR_A + \ - USE_STR_C + \ - USE_STR_PASCAL -;.out .sprintf( "Commands: %d", NumMeta ) -.linecont - - .feature labels_without_colons .feature leading_dot_in_identifiers ; 65C02 .PC02 +; Assemble-time diagnostic information +.macro DEBUG text +.if 0 + .out text +.endif +.endmacro + ; This will take a printf-style string and compact it. The '%' is the escape ; character to output the next byte in ASCII (high bit clear) and print a var. ; Otherwise the remaining chars will default to literals having their high bit @@ -381,17 +400,46 @@ NumMeta = 0 + \ .res bytes .endmacro - GBASL = $26 +; Include necessary components based on features requested + ENABLE_BIN = USE_BIN_ASC || USE_BIN_INV + ENABLE_DEC = USE_DEC_2 || USE_DEC_3 || USE_DEC_5 || USE_DEC_BYTE + ENABLE_HEX = USE_HEX_2 || USE_HEX_4 || USE_PTR_2 || USE_PTR_4 + ENABLE_OCT = USE_OCT_3 || USE_OCT_6 + ENABLE_PTR = USE_PTR_2 || USE_PTR_4 + ENABLE_STR = USE_STR_A || USE_STR_C || USE_STR_PASCAL + +NumMeta = 0 + \ + USE_BIN_ASC + \ + USE_BIN_INV + \ + USE_DEC_2 + \ + USE_DEC_3 + \ + USE_DEC_5 + \ + USE_DEC_BYTE + \ + USE_HEX_2 + \ + USE_HEX_4 + \ + USE_OCT_3 + \ + USE_OCT_6 + \ + USE_PTR_2 + \ + USE_PTR_4 + \ + USE_STR_A + \ + USE_STR_C + \ + USE_STR_PASCAL +DEBUG .sprintf( "Features enabled: %d", NumMeta ) + + +; Only used by demo + BASL = $28 ; TXT pointer to cursor + BASH = $29 + GBASL = $26 ; HGR pointer to cursor GBASH = $27 - HPOSN = $F411 ; A= Y, X=lo,Y=hi, sets GBASL, GBASH + HPOSN = $F411 ; A=row, X=col.lo,Y=col.hi, sets GBASL, GBASH + BASCALC = $FBC1 ; A=row, sets BASL, BASH HOME = $FC58 TABV = $FB5B COUT = $FDED - PREQHEX = $FDD3 ; print '=', then A in hex - PRBYTE = $FDDA - -; printm pointer for PrintPtr2, PrintPtr4, PrintStrA, PrintStrC, PrintStrP - _temp = $FE + PRBYTE = $FDDA ; print A in hex + demoptr = $FC + demotmp = $FE __MAIN = $4000 ; DOS3.3 meta -- remove these 2 if running under ProDOS @@ -402,21 +450,25 @@ NumMeta = 0 + \ Output: -X=39 Y=191 $=2345:D5 11010101~10101011 -Bin ASC: 01010111 <- ??? -Bin REV: 01010111 <- FIXME: Bin INV, Bin REV +X=39 Y=191 $=3FF7:D5 11010101~10101011 +Bin ASC: 11010101 +Bin INV: 11010101 Dec2: 99 Dec3: 999 Dec5: 65385 Byte=-128 -001 000 001 127 -Hex2: $34 -Hex4: $1234 -Ptr2: $2000:D5 -Ptr4: $2000:AAD5 -C : 'HELLO','WORLD' +Hex2: 34 +Hex4: 1234 +Ptr2: 2000:D5 +Ptr4: 2000:AAD5 +Oct3: 666 +Oct6: 031337 Apple : 'HOME' +C : 'HELLO','WORLD' Pascal: 'Pascal Len 13' +printm().size = $0209 000521 bytes + .features = $ 0F 000015 */ .org __MAIN ; .org must come after header else offsets are wrong @@ -450,12 +502,13 @@ Pascal: 'Pascal Len 13' STA (GBASL),Y STA ARGS_DEMO+10 ; aArg[5] STZ ARGS_DEMO+11 + STA ARGS_BIN_ASC+2 + STA ARGS_BIN_INV+2 JSR ReverseByte STA ARGS_DEMO+12 ; aArg[6] STZ ARGS_DEMO+13 - STA ARGS_BIN_INV+2 .if ENABLE_BIN && ENABLE_DEC && ENABLE_HEX LDY #0 @@ -466,7 +519,9 @@ Pascal: 'Pascal Len 13' .endif .if ENABLE_BIN +DEBUG "+BIN" .if USE_BIN_ASC +DEBUG "____:ASC" LDY #1 JSR VTABY LDX #ARGS_STR_C + LDX #ARGS_OCT_3 JSR PrintM .endif + .if USE_OCT_6 +DEBUG "____:Oct6" + LDY #12 + JSR VTABY + LDX #ARGS_OCT_6 + JSR PrintM + .endif +.endif + +.if ENABLE_STR +DEBUG "+STR" .if USE_STR_A - LDY #12 +DEBUG "____:StrA" + LDY #13 JSR VTABY LDX #ARGS_STR_A JSR PrintM .endif + .if USE_STR_C +DEBUG "____:StrC" + LDY #14 + JSR VTABY + LDX #ARGS_STR_C + JSR PrintM + .endif + .if USE_STR_PASCAL - LDY #13 +DEBUG "____:StrP" + LDY #15 JSR VTABY LDX #ARGS_STR_PASCAL @@ -570,67 +661,144 @@ Pascal: 'Pascal Len 13' .endif .endif ; ENABLE_STR - LDA #14 + LDA #17 JSR TABV -; old-skool text/hex printing - LDY #0 -@_Text - LDA PRINTM_TEXT,Y - BEQ @_Size - JSR COUT - INY - BNE @_Text -@_Size +; "old-skool" text/hex printing: use ROM funcs + LDX #PRINTM_TEXT + JSR PrintStringZ LDA PRINTM_SIZE+1 + STA demotmp+1 JSR PRBYTE LDA PRINTM_SIZE+0 + STA demotmp+0 JSR PRBYTE + + JSR PrintSpc + JSR PrintDec + + LDX #PRINTM_CMDS + JSR PrintStringZ + + LDX GetNumFeatures+1 + INX + STX demotmp+0 + STZ demotmp+1 + TXA + JSR PRBYTE + + JSR PrintSpc + JSR PrintDec + LDA #$8D JMP COUT +; ====================================================================== + +; ds 256 - <* +_digits ds 6 + +; Print demotmp in Decimal +PrintDec + LDX #<_digits + LDY #>_digits + STX demoptr+0 + STY demoptr+1 + + STZ _digits+0 + STZ _digits+1 + STZ _digits+2 + + LDY #0 + LDX #16 ; 16 bits + SED ; Double Dabble +@Hex2BCD: + ASL demotmp+0 + ROL demotmp+1 + +.if 1 +.repeat 3 + LDA (demoptr),Y + ADC (demoptr),Y + STA (demoptr),Y + INY +.endrep +.else + LDA _digits+0 + ADC _digits+0 + STA _digits+0 + + LDA _digits+1 + ADC _digits+1 + STA _digits+1 + + LDA _digits+2 + ADC _digits+2 + STA _digits+2 +.endif + LDY #0 + DEX + BNE @Hex2BCD + CLD + + LDX #2 +@PrintBCD + LDA _digits, X + LSR + LSR + LSR + LSR + CLC + ADC #'0'+$80 + JSR COUT + LDA _digits, X + AND #$F + CLC + ADC #'0'+$80 + JSR COUT + DEX + BPL @PrintBCD + RTS + +; Can't use printm PrintStr*() as it may not be enabled/available +PrintStringZ + STX demoptr+0 + STY demoptr+1 + LDY #0 +@_Text + LDA (demoptr),Y + BEQ @_Done + JSR COUT + INY + BNE @_Text +@_Done + RTS + ReverseByte LDX #8 - STA $FF ; temp working byte + STA demotmp ; temp working byte ReverseBit - ASL $FF ; temp working byte + ASL demotmp ; temp working byte ROR DEX BNE ReverseBit RTS -VTABY - LDA SCREEN_LO,Y - STA PutChar+1 - LDA SCREEN_HI,Y - ORA #$04 ; TXT page 1 - STA PutChar+2 +PrintSpc + LDA #' '+$80 + JMP COUT + +VTABY TYA + JSR BASCALC + LDX BASL + LDY BASH + STX PutChar+1 + STY PutChar+2 RTS -; Pad until end of page so data starts on new page -; ds 256 - <* - -; Y Lookup Table for 40x24 Text Screen -SCREEN_LO - .byte $00, $80, $00, $80 - .byte $00, $80, $00, $80 - - .byte $28, $A8, $28, $A8 - .byte $28, $A8, $28, $A8 - - .byte $50, $D0, $50, $D0 - .byte $50, $D0, $50, $D0 -SCREEN_HI - .byte $00, $00, $01, $01 - .byte $02, $02, $03, $03 - - .byte $00, $00, $01, $01 - .byte $02, $02, $03, $03 - - .byte $00, $00, $01, $01 - .byte $02, $02, $03, $03 - ; ______________________________________________________________________ TEXT_DEMO @@ -713,6 +881,19 @@ ARGS_PTR_4 ; ______________________________________________________________________ +TEXT_OCT_3 PRINTM "Oct3: %o", 0 +TEXT_OCT_6 PRINTM "Oct6: %O", 0 + +ARGS_OCT_3 + dw TEXT_OCT_3 + dw 438 + +ARGS_OCT_6 + dw TEXT_OCT_6 + dw 13023 + +; ______________________________________________________________________ + TEXT_HELLO APPLE "HELLO" db 0 @@ -753,40 +934,63 @@ ARGS_STR_PASCAL PRINTM_TEXT APPLE "printm().size = $" db 0 -PRINTM_SIZE - dw __END - PrintM +PRINTM_CMDS APPLE " bytes" + db $8D + APPLE " .features = $ " + db 0 + +__LIB_SIZE = __END - __PRINTM + +PRINTM_SIZE + dw __LIB_SIZE ; Pad until end of page so PrintM starts on new page - ds 256 - <* +; ds (256 - <*) & 7 +; ds (256 - <*) & 15 +; ds (256 - <*) +; ---------------------------------------------------------------------- +; ---------------------------------------------------------------------- +; +; printm() library code starts here +; +; ---------------------------------------------------------------------- +; ---------------------------------------------------------------------- +__PRINTM + +; pointer for PrintPtr2, PrintPtr4, PrintStrA, PrintStrC, PrintStrP + _temp = $FE + ; self-modifying variable aliases - _pScreen = PutChar +1 _pFormat = GetFormat +1 _iArg = NxtArgByte+1 _pArg = IncArg +1 .if ENABLE_DEC _nDecWidth = DecWidth +1 -.endif ; ENABLE_DEC +.endif +.if ENABLE_OCT + _nOctWidth = OctWidth +1 +.endif .if ENABLE_HEX _nHexWidth = HexWidth +1 + ; Moved here so NextArg can reach GetFormat .if USE_HEX_4 +DEBUG .sprintf( "PrintHex4() @ %X", * ) PrintHex4: LDA #4 BNE _PrintHex .endif .endif - -; Note: The dummy address $C0DE is to force the assembler -; to generate a 16-bit address instead of optimizing a ZP operand -; +; Entry Point ; ====================================================================== ; printm( format, args, ... ) ; ====================================================================== + PrintM STX _pArg+0 STY _pArg+1 @@ -798,12 +1002,13 @@ NextArg STY _pFormat+1 ; hi BRA GetFormat ; always -.if ENABLE_HEX ; $ Hex 2 Byte ; x Hex 4 Byte ; ====================================================================== +.if ENABLE_HEX .if USE_HEX_2 +DEBUG .sprintf( "PrintHex2() @ %X", * ) PrintHex2: LDA #2 .endif @@ -823,12 +1028,19 @@ NextArg LDA _val+0 AND #$F CMP #$A ; n < 10 ? - BCC _Hex2Asc + BCC @Hex2Asc ADC #6 ; n += 6 $A -> +6 + (C=1) = $11 - _Hex2Asc: + @Hex2Asc: ADC #'0' + $80 ; inverse=remove #$80 STA _bcd, X ; NOTE: Digits are reversed! - +.if 0 + LDY #3 + @HexShr: + LSR _val+1 ; 16-bit SHR nibble + ROR _val+0 + DEY + BNE @HexShr +.else LSR _val+1 ; 16-bit SHR nibble ROR _val+0 @@ -840,7 +1052,7 @@ NextArg LSR _val+1 ROR _val+0 - +.endif INX HexWidth: CPX #4 ; _nHexWidth NOTE: self-modifying! @@ -848,9 +1060,9 @@ NextArg ; Intentional fall into reverse BCD .endif -.if ENABLE_HEX || ENABLE_DEC ; On Entry: X number of chars to print in buffer _bcd ; ====================================================================== +.if ENABLE_HEX || ENABLE_DEC || ENABLE_OCT PrintReverseBCD DEX BMI NextFormat @@ -860,22 +1072,23 @@ PrintReverseBCD .endif -.if ENABLE_HEX ; @ Ptr 2 Byte ; & Ptr 4 Byte ; ====================================================================== +.if ENABLE_PTR .if USE_PTR_4 +DEBUG .sprintf( "PrintPtr4() @ %X", * ) PrintPtr4: LDA #4 BNE _PrintPtr .endif .if USE_PTR_2 +DEBUG .sprintf( "PrintPtr2() @ %X", * ) PrintPtr2: LDA #2 .endif - .if ENABLE_PTR _PrintPtr: STA _nHexWidth JSR NxtArgToTemp @@ -888,15 +1101,15 @@ PrintReverseBCD TAY BRA PrintHexYX ; needs XYtoVal setup - .endif ; ENABLE_PTR -.endif ; ENABLE_HEX +.endif ; ENABLE_PTR -.if ENABLE_STR ; a String (APPLE text, last byte ASCII) ; See: DCI ; ====================================================================== +.if ENABLE_STR .if USE_STR_A +DEBUG .sprintf( "PrintStrA() @ %X", * ) PrintStrA: JSR NxtArgToTemp @@ -913,11 +1126,15 @@ PrintReverseBCD .endif ; USE_STR_A .endif ; ENABLE_STR -; Main loop of printm() ... print literal chars ; ====================================================================== +; Main Read/Eval/Print/Loop of printm() +; ====================================================================== +; Note: The dummy address $C0DE is to force the assembler +; to generate a 16-bit address instead of optimizing a ZP operand + ForceAPPLE ORA #$80 -Print +Print ; print literal chars JSR PutChar NextFormat ; Adjust pointer to next char in format INC _pFormat+0 @@ -934,6 +1151,7 @@ GetFormat ; We can't use this equation since it is not const due to the assembler ; not having defined _MetaCharEnd yet ; Instead we count the number of features enabled +GetNumFeatures .if (NumMeta > 0) LDX #NumMeta-1 ; pos = meta .else @@ -955,30 +1173,34 @@ CallMeta _Done RTS -; === Meta Ops === +; ______________________________________________________________________ -.if ENABLE_DEC ; # Dec 1 Byte (max 2 digits) ; d Dec 2 Byte (max 3 digits) ; u Dec 2 Byte (max 5 digits) ; ====================================================================== +.if ENABLE_DEC .if USE_DEC_5 +DEBUG .sprintf( "PrintDec5() @ %X", * ) PrintDec5: LDA #5 BNE _PrintDec ; always .endif .if USE_DEC_3 +DEBUG .sprintf( "PrintDec3() @ %X", * ) PrintDec3: LDA #3 BNE _PrintDec ; always .endif .if USE_DEC_2 +DEBUG .sprintf( "PrintDec2() @ %X", * ) PrintDec2: LDA #2 ; 2 digits .endif + ; no .if USE_DEC_BYTE here because ENABLE_DEC already covers that _PrintDec: STA _nDecWidth JSR NxtArgYX @@ -992,9 +1214,9 @@ _Done STZ _bcd+2 Dec2BCD: - LDX #16 - SED - _Dec2BCD: + LDX #16 ; 16 bits + SED ; "Double Dabble" + _Dec2BCD: ; https://en.wikipedia.org/wiki/Double_dabble ASL _val+0 ROl _val+1 @@ -1017,7 +1239,7 @@ _Done BCD2Char: LDX #2 LDY #5 - _BCD2Char: + _BCD2Char: ; NOTE: Digits are reversed! LDA _bcd,X ; __c??? _b_?XX a_YYXX LSR LSR @@ -1044,17 +1266,19 @@ _Done ; ______________________________________________________________________ -.if ENABLE_BIN ; % Bin 1 Byte normal ones, normal zeroes ; ? Bin 1 Byte inverse ones, normal zeroes ; ====================================================================== +.if ENABLE_BIN .if USE_BIN_INV +DEBUG .sprintf( "PrintBinI() @ %X", * ) PrintBinInv: LDA #$81 BNE _PrintBin .endif ; USE_BIN_INV .if USE_BIN_ASC +DEBUG .sprintf( "PrintBinA() @ %X", * ) PrintBinAsc: LDA #$01 .endif ; USE_BIN_ASC @@ -1080,6 +1304,7 @@ _Done BNE _Bit2Asc .endif ; ENABLE_BIN +; Left as exercise for the reader to optimize the jump size :-) _JumpNextFormat ; BRA NextFormat ; always JMP NextFormat ; JMP :-( @@ -1088,6 +1313,7 @@ _JumpNextFormat ; ====================================================================== .if ENABLE_DEC .if USE_DEC_BYTE +DEBUG .sprintf( "PrintDecB() @ %X", * ) PrintByte: JSR NxtArgYX ; X = low byte TXA @@ -1111,12 +1337,57 @@ _JumpNextFormat ; ______________________________________________________________________ +; o Print byte in octal (max 3 digits) +; O Print word in octal (max 6 digits) +; ====================================================================== +.if ENABLE_OCT + .if USE_OCT_6 +DEBUG .sprintf( "PrintOct6() @ %X", * ) + PrintOct6: + LDA #6 + BNE _PrintOct + .endif + .if USE_OCT_3 +DEBUG .sprintf( "PrintOct3() @ %X", * ) + PrintOct3: + LDA #3 + .endif + _PrintOct: + STA _nOctWidth + JSR NxtArgYX ; X = low byte -.if ENABLE_STR + LDX #0 + @_Oct2Asc: + LDA _temp + AND #7 + CLC + ADC #'0'+$80 + STA _bcd,x ; NOTE: Digits are reversed! + + LSR _temp+1 + ROR _temp+0 + + LSR _temp+1 + ROR _temp+0 + + LSR _temp+1 + ROR _temp+0 + + INX + CPX #6 + BNE @_Oct2Asc + OctWidth: + LDX #6 ; _nOctDigits NOTE: self-modifying! + JMP PrintReverseBCD +.endif ; ENABLE_OCT + +; ______________________________________________________________________ ; s String (C,ASCIIZ) ; ====================================================================== +.if ENABLE_STR .if USE_STR_C +DEBUG .sprintf( "PrintStrC() @ %X", * ) PrintStrC: JSR NxtArgToTemp @@ -1127,13 +1398,16 @@ _JumpNextFormat JSR PutChar INY BNE @_NextByte - INC _temp+1 + INC _temp+1 ; support strings > 256 chars BRA @_NextByte .endif +.endif ; p String (Pascal) ; ====================================================================== +.if ENABLE_STR .if USE_STR_PASCAL +DEBUG .sprintf( "PrintStrP() @ %X", * ) PrintStrP: JSR NxtArgToTemp @@ -1151,13 +1425,20 @@ _JumpNextFormat .endif .endif ; ENABLE_STR -; __________ Utility __________ +; ---------------------------------------------------------------------- +; Utility +; ---------------------------------------------------------------------- ; ====================================================================== +; PutChar +.if 1 STA $C0DE ; _pScreen NOTE: self-modifying! INC PutChar+1 ; inc lo RTS +.else ; Alternatively use the monitor ROM char output + JMP COUT +.endif ; ====================================================================== ; @return next arg as 16-bit arg value in Y,X @@ -1200,7 +1481,7 @@ MetaChar .if USE_BIN_INV db '?' ; PrintBinInv NOTE: 1's printed in inverse .endif - .if USE_BIN_INV + .if USE_BIN_ASC db '%' ; PrintBinAsc .endif .endif @@ -1232,6 +1513,14 @@ MetaChar db '@' ; PrintPtr2 .endif .endif +.if ENABLE_OCT + .if USE_OCT_6 + db 'O' ; PrintOct6 + .endif + .if USE_OCT_3 + db 'o' ; PrintOct3 + .endif +.endif .if ENABLE_STR .if USE_STR_PASCAL db 'p' ; PrintStrP NOTE: Pascal string; C printf 'p' is pointer! @@ -1284,6 +1573,14 @@ MetaFunc dw PrintPtr2 .endif .endif +.if ENABLE_OCT + .if USE_OCT_6 + dw PrintOct6 + .endif + .if USE_OCT_3 + dw PrintOct3 + .endif +.endif .if ENABLE_STR .if USE_STR_PASCAL dw PrintStrP @@ -1298,3 +1595,6 @@ MetaFunc __END +DEBUG .sprintf( "Lib Size: %X (%d bytes)", __LIB_SIZE , __LIB_SIZE ) +DEBUG .sprintf( "Total Size: %X (%d bytes)", __END-__MAIN, __END-__MAIN) +