+Vorticon Posted June 7 Share Posted June 7 On 6/5/2024 at 4:12 PM, apersson850 said: I've not managed to get the p-system to automatically find more than one disk controller in the system. I can use it with the physical drives and two RAMdisks, but then I inject the PCB for the RAMdisks manually. To avoid changing TOPMEM I put them in the sprite attribute table, since I normally don't use that anyway. With TIPI at >1000, it is able to automatically detect it as a drive controller when DSK1-DSK3 are set up. It does not *seem* detect the TI controller at >1100 in that situation. On 6/5/2024 at 4:12 PM, apersson850 said: All disk units point to the same place, since they use the same controller. But the p-system knows that there will not be more than three disks, so it doesn't populate the entries for units #10, #11 and #12. So for a CorComp controller which has four drives you simply copy the same value as is stored for #4 to the place where you have #10. Since TIPI actually supports DSK4 and DSK5 as well, we should be able to get those working too by adding 2 more PCB's. It should be simpler than RAMDISKS because the DSR is unchanged. Do we know where the PCB's are located in VDP? I looked at the location pointed to by TOPMEM in Classic99 but did not recognize PCB's at first glance. What I still don't understand however is why the Editor is running out of VDP memory with only 3 TIPI disk drives as it should theoretically be a similar situation to when a real TI controller is present with 3 drives attached. Any thoughts on this? The answer probably lies with inspection of the PCB table once I know where it is. Quote Link to comment Share on other sites More sharing options...
apersson850 Posted June 9 Author Share Posted June 9 (edited) The physical drives controlled by the same controller use the same PCB. The call just changes a parameter in the PCB to indicate which drive to use. Since I don't have any TIPI I've not checked this, but perhaps the system by default allocates space for a PCB for the standard disk controller and does then allocate one more when it unexpectedly discovers a disk controller showing up before the standard one during the search? Pure speculation - I don't know why this happens. Edited June 10 by apersson850 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted June 22 Share Posted June 22 I have a main program which uses a custom library of 3 separate units. The units USE several of the TI supplied units (speech, sound, random etc...) and compile just fine. However, unless I also USE these same TI supplied units in the main program which does not need them, I get the error UNIT NOT DECLARED IN PREVIOUS USES. I don't understand why that is the case, and doing so robs precious memory from the main program... Example: Library TESTLIB has: UNIT1 UNIT2 Both UNIT1 and UNIT2 need the TI supplied units SUPPORT and RANDOM which they explicitly USE in their INTERFACE section. Now TEST is a program which USES the TESTLIB library, but does not need SUPPORT or RANDOM to work. However, it seems I still have to USE SUPPORT and RANDOM in the TEST main program regardless, which does not make sense. I must be missing some concept here... 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted June 22 Share Posted June 22 OK I figured it out. I was USING the TI units in the INTERFACE section instead of the IMPLEMENTATION section. Doing the former forced the need to also use them in the main program. Still not completely clear as to why though. 2 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted June 23 Share Posted June 23 I've been exploring the features of the SOUND unit and it's become apparent that it is quite powerful and versatile, albeit somewhat cumbersome to use, and vastly superior to the measly CALL SOUND of TI basic/xb. Some highlights: Each sound and noise channel is controlled completely independently from the others, which allows for extreme flexibility in creating sounds and music it allows for relative jumps, jumping to and returning from "subroutines" within the sound list, jumping to other sound lists, and chaining sound lists. Flags can be set within a sound list which can be checked for by the main program for timing purposes Once a channel is started, it will continue playing its sound list in the background while your program continues to run normally. Here's a little example showing a basic "drum" running in the background later joined by a "melody". Please excuse my non-existent musical abilities blatantly on display here... program drums; uses sound; var dsnd, dsnd1 : sndlstptr; begin {drums track} make_snd_list(dsnd, 40); snd_volume(dsnd, 12); white_noise(dsnd, 0, 1); snd_volume(dsnd, 0); white_noise(dsnd, 0, 1); snd_volume(dsnd, 12); white_noise(dsnd, 0, 1); snd_volume(dsnd, 0); white_noise(dsnd, 0, 1); snd_volume(dsnd, 6); white_noise(dsnd, 1, 1); snd_volume(dsnd, 0); white_noise(dsnd, 0, 3); jump_snd(dsnd, 0); end_snd(dsnd); {melody track} make_snd_list(dsnd1, 100); snd_volume(dsnd1, 10); snd_note(dsnd1, 262, 5); snd_note(dsnd1, 294, 5); snd_note(dsnd1, 330, 5); snd_note(dsnd1, 349, 5); snd_note(dsnd1, 392, 5); snd_note(dsnd1, 440, 5); snd_note(dsnd1, 494, 5); snd_note(dsnd1, 440, 5); snd_note(dsnd1, 392, 5); snd_note(dsnd1, 349, 5); snd_note(dsnd1, 330, 5); snd_note(dsnd1, 294, 5); snd_note(dsnd1, 262, 5); jump_snd(dsnd1, 0); end_snd(dsnd1); set_snd(4, dsnd); set_snd(1, dsnd1); set_snd_tempo(4, 150); set_snd_tempo(1, 100); play_snd(4); repeat until snd_beat(4) >= 32; play_snd(1); readln; kill_all_snd; del_snd_list(dsnd); del_snd_list(dsnd1); end. Classic99 QI399.065 2024-06-23 14-16-27.mp4 In the right hands much can be created. 3 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted June 24 Share Posted June 24 6 hours ago, Vorticon said: I've been exploring the features of the SOUND unit and it's become apparent that it is quite powerful and versatile, albeit somewhat cumbersome to use, and vastly superior to the measly CALL SOUND of TI basic/xb. Some highlights: Each sound and noise channel is controlled completely independently from the others, which allows for extreme flexibility in creating sounds and music it allows for relative jumps, jumping to and returning from "subroutines" within the sound list, jumping to other sound lists, and chaining sound lists. Flags can be set within a sound list which can be checked for by the main program for timing purposes Once a channel is started, it will continue playing its sound list in the background while your program continues to run normally. Here's a little example showing a basic "drum" running in the background later joined by a "melody". Please excuse my non-existent musical abilities blatantly on display here... program drums; uses sound; var dsnd, dsnd1 : sndlstptr; begin {drums track} make_snd_list(dsnd, 40); snd_volume(dsnd, 12); white_noise(dsnd, 0, 1); snd_volume(dsnd, 0); white_noise(dsnd, 0, 1); snd_volume(dsnd, 12); white_noise(dsnd, 0, 1); snd_volume(dsnd, 0); white_noise(dsnd, 0, 1); snd_volume(dsnd, 6); white_noise(dsnd, 1, 1); snd_volume(dsnd, 0); white_noise(dsnd, 0, 3); jump_snd(dsnd, 0); end_snd(dsnd); {melody track} make_snd_list(dsnd1, 100); snd_volume(dsnd1, 10); snd_note(dsnd1, 262, 5); snd_note(dsnd1, 294, 5); snd_note(dsnd1, 330, 5); snd_note(dsnd1, 349, 5); snd_note(dsnd1, 392, 5); snd_note(dsnd1, 440, 5); snd_note(dsnd1, 494, 5); snd_note(dsnd1, 440, 5); snd_note(dsnd1, 392, 5); snd_note(dsnd1, 349, 5); snd_note(dsnd1, 330, 5); snd_note(dsnd1, 294, 5); snd_note(dsnd1, 262, 5); jump_snd(dsnd1, 0); end_snd(dsnd1); set_snd(4, dsnd); set_snd(1, dsnd1); set_snd_tempo(4, 150); set_snd_tempo(1, 100); play_snd(4); repeat until snd_beat(4) >= 32; play_snd(1); readln; kill_all_snd; del_snd_list(dsnd); del_snd_list(dsnd1); end. Classic99 QI399.065 2024-06-23 14-16-27.mp4 14.71 MB · 0 downloads In the right hands much can be created. Very neat. I suspect that type sndlstptr is an address in VDP RAM? Of course the Pascal programmer doesn't need to know that but that is how the system sound player player seems to work best in my exploring. I was never a fan of the SOUND() function in BASIC because it is not factored into smaller building blocks that let you put the music together with some granularity. This Pascal interface gives more control. I took a run at trying to make a sound list "Assembler" that is similar in intent to these functions so it is neat to see someone else's ideas. Making all the channels play in a synchronized way took me a long while to get working. Ended up using the ISR to handle turning off each channel at the right time. Not sure if you ever took music lessons, but something to consider is to make a timebase system that takes a master time for 1 beat of music. Metronome 60 means 60 beats per minute. (bpm) 120 = 120 bpm With a "beat" defined, then you make "notes" functions or constants that are whole note: 4 beats dotted half note: 3 beats half note: 2 beats dotted quarter: 1.5 beats quarter note: 1 beat 1/8th note: 1/2 beat 1/16th not: 1/4 beat. Then name a range of constants for the notes you want: A B C D E F G etc along with sharps and flats. A# ( A sharp) Ab (A flat) etc. Armed with those you can literally type music notation off a page and enter it into your programs with these Pascal functions. Thanks for kicking the Pascal card (quite hard) and publishing your findings. 3 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 1 Author Share Posted July 1 The unit relationship depends on that the interface part is compiled with the main program, but the implementation part is not. Units used in interface parts have to be used by the main program or it will be a surprise to the compiler when the show up in the units. In the implementation part they are private to that unit. Another side of this is that if you have a large program where everybody must rely on some global data, it's usually best to create a unit called globals. Then all other units as well as the main program can refer to it on the same terms. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 1 Share Posted July 1 3 hours ago, apersson850 said: Another side of this is that if you have a large program where everybody must rely on some global data, it's usually best to create a unit called globals. Then all other units as well as the main program can refer to it on the same terms. That's exactly what I ended up doing. Thanks for validating that approach! 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 7 Share Posted July 7 I have not been able to locate the PCB's using Classic99 at the location mentioned in @apersson850's memory map (PCB pointer table at >29DC to >2A1C does not seem to contain valid pointers). Not knowing how the PCB is structured does not help either. Am I looking in the wrong place? Any hints to the PCB format? Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 9 Author Share Posted July 9 My note says the following: 0 Entry address to call 2 Character count (base name) 4 CRU base address of device/card 6 Version number (byte) 7 Link offset (byte) 8 Op code and status (PAB) 10 PAB 12 PAB 14 PAB 16 PAB 18 Device name (physical) So eight bytes of additional PCB data followed by a conventional PAB. 1 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 10 Share Posted July 10 Thanks! This is extremely helpful. Any idea where in VDP RAM the PCB's are located? Quote Link to comment Share on other sites More sharing options...
+mizapf Posted July 10 Share Posted July 10 Interestingly, the question "Any idea where on the PCBs the VDP RAM is located?" makes its own sense. 2 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 11 Author Share Posted July 11 I'll have to check. I've started a task to make all my pencil notes on paper about the content of the ROM on the p-code card to an electronic document. But it takes some time. Eventually I'll publish it, when I'm ready. 3 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 11 Share Posted July 11 9 hours ago, apersson850 said: I'll have to check. I've started a task to make all my pencil notes on paper about the content of the ROM on the p-code card to an electronic document. But it takes some time. Eventually I'll publish it, when I'm ready. In the mean time, I have been documenting all your informative posts in a folder in OneNote for future reference 😀 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 16 Share Posted July 16 Here's a utility disk that includes an assembly routine named CLOCK that returns the date and time of the RTC in the IDE card. It assumes a CRU of >1900 for the card. The CLOCKTEST program demonstrates usage. One obvious use is to amend the SYSTEM.STARTUP file to update the system time automatically on boot. Spoiler ;ide card rtc low-level access routines .proc ctime,3 ;get time ;usage: ctime(intvarsec, intvarmin, intvarhr) .def pcodeon,pcodoff,procret,pmeret,bcd2hex mov r11,@procret bl @pcodoff li r12,1900h ;activate ide card at cru >1900 sbo 0 sbo 1 ;enable mapping of >4000 - >40ff space sbo 3 ;fixed page at >4000 - >40ff mov *r10+,r1 ;get pointer to hours variable mov *r10+,r2 ;get pointer to minutes variable mov *r10,r3 ;get pointer to seconds variable li r4,0800h ;latch rtc registers socb r4,@403ch clr r4 movb @4020h,r4 ;get seconds swpb r4 bl @bcd2hex ;convert to hex mov r6,*r3 clr r4 movb @4024h,r4 ;get minutes swpb r4 bl @bcd2hex ;convert to hex mov r6,*r2 clr r4 movb @4028h,r4 ;get hours swpb r4 bl @bcd2hex mov r6,*r1 li r4,0800h ;unlatch rtc registers szcb r4,@403ch sbz 1 ;inactivate ram mapping sbz 0 ;inactivate ide card bl @pcodeon mov @procret,r11 b *r11 procret .word pmeret .word pcodeon li r12,1f00h ;activate pcode card sbo 0 mov @pmeret,r12 ;retrieve pme pointer b *r11 pcodoff mov r12,@pmeret ;save pme pointer li r12,1f00h ;inactivate pcode card sbz 0 b *r11 bcd2hex mov r4,r5 ;isolate low digit andi r5,000fh mov r4,r6 ;isolate high digit andi r6,00f0h srl r6,4 mov r6,r4 ;save original value sla r6,3 ;multiply by 8 sla r4,1 ;multiply original value by 2 a r4,r6 ;high value has now been multiplied by 10 a r5,r6 ;add low and high numbers. r6 now has hex value b *r11 .proc cdate,4 ;get date ;usage: cdate(intvarday, intvardow, intvarmonth, intvaryear) .ref pcodeon,pcodoff,procret,pmeret,bcd2hex mov r11,@procret bl @pcodoff li r12,1900h ;activate ide card at cru >1900 sbo 0 sbo 1 ;enable mapping of >4000 - >40ff space sbo 3 ;fixed page at >4000 - >40ff mov *r10+,r0 ;get pointer to year variable mov *r10+,r1 ;get pointer to month variable mov *r10+,r2 ;get pointer to day of week var (sunday = 1) mov *r10,r3 ;get pointer to day of month variable clr r4 movb @402ch,r4 ;get day of month swpb r4 bl @bcd2hex ;convert to hex mov r6,*r3 clr r4 movb @4030h,r4 ;get day of week swpb r4 bl @bcd2hex ;convert to hex mov r6,*r2 clr r4 movb @4032h,r4 ;get month swpb r4 bl @bcd2hex ;convert to hex mov r6,*r1 clr r4 movb @4034h,r4 ;get year swpb r4 bl @bcd2hex ;convert to hex mov r6,*r0 sbz 1 ;inactivate ram mapping sbz 0 ;inactivate ide card bl @pcodeon mov @procret,r11 b *r11 .end Spoiler program clocktest; var sec, min, hr, day, dow, month, year : integer; dowstr : array [1..7] of string; procedure ctime(var sec, min, hr : integer); external; procedure cdate(var day, dow, month, year : integer); external; begin dowstr[1] := 'sunday'; dowstr[2] := 'monday'; dowstr[3] := 'tuesday'; dowstr[4] := 'wednesday'; dowstr[5] := 'thursday'; dowstr[6] := 'friday'; dowstr[7] := 'saturday'; cdate(day, dow, month, year); ctime(sec, min, hr); writeln(dowstr[dow],' ',month,'/',day,'/',year); writeln(hr,':',min,':',sec); end. CLOCK.DSK 2 Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 16 Author Share Posted July 16 6 hours ago, Vorticon said: One obvious use is to amend the SYSTEM.STARTUP file to update the system time automatically on boot. That's a good idea. I've used my own clock for the same purpose. I also used an unused part of the system diskette to store not only the date but also the time, so I can report both date and time from the last login. Out of the first four physical sectors on the diskette, the p-system uses them like this: 0: Disk catalog header. 1: Disk sector map. 2: Faked PASCAL file to make the disk possible to copy with the standard disk manager. 3: Unused. So there's plenty of space the p-system will not touch. Physical disk sectors 4 and 5 then make up the first 512 byte p-system disk block. Here the p-system's disk catalog is stored. Normally you can't read any p-system blocks before this logical block 0, but unitread/unitwrite has a physical block access mode bit, so you can override that logical disk block mapping and actually access even the first sectors on the diskette. 2 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 16 Share Posted July 16 Storing the time in addition of the date is a nice touch. I'll be looking into that this week. 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted July 16 Share Posted July 16 18 hours ago, Vorticon said: Here's a utility disk that includes an assembly routine named CLOCK that returns the date and time of the RTC in the IDE card. It assumes a CRU of >1900 for the card. The CLOCKTEST program demonstrates usage. One obvious use is to amend the SYSTEM.STARTUP file to update the system time automatically on boot. Reveal hidden contents ;ide card rtc low-level access routines .proc ctime,3 ;get time ;usage: ctime(intvarsec, intvarmin, intvarhr) .def pcodeon,pcodoff,procret,pmeret,bcd2hex mov r11,@procret bl @pcodoff li r12,1900h ;activate ide card at cru >1900 sbo 0 sbo 1 ;enable mapping of >4000 - >40ff space sbo 3 ;fixed page at >4000 - >40ff mov *r10+,r1 ;get pointer to hours variable mov *r10+,r2 ;get pointer to minutes variable mov *r10,r3 ;get pointer to seconds variable li r4,0800h ;latch rtc registers socb r4,@403ch clr r4 movb @4020h,r4 ;get seconds swpb r4 bl @bcd2hex ;convert to hex mov r6,*r3 clr r4 movb @4024h,r4 ;get minutes swpb r4 bl @bcd2hex ;convert to hex mov r6,*r2 clr r4 movb @4028h,r4 ;get hours swpb r4 bl @bcd2hex mov r6,*r1 li r4,0800h ;unlatch rtc registers szcb r4,@403ch sbz 1 ;inactivate ram mapping sbz 0 ;inactivate ide card bl @pcodeon mov @procret,r11 b *r11 procret .word pmeret .word pcodeon li r12,1f00h ;activate pcode card sbo 0 mov @pmeret,r12 ;retrieve pme pointer b *r11 pcodoff mov r12,@pmeret ;save pme pointer li r12,1f00h ;inactivate pcode card sbz 0 b *r11 bcd2hex mov r4,r5 ;isolate low digit andi r5,000fh mov r4,r6 ;isolate high digit andi r6,00f0h srl r6,4 mov r6,r4 ;save original value sla r6,3 ;multiply by 8 sla r4,1 ;multiply original value by 2 a r4,r6 ;high value has now been multiplied by 10 a r5,r6 ;add low and high numbers. r6 now has hex value b *r11 .proc cdate,4 ;get date ;usage: cdate(intvarday, intvardow, intvarmonth, intvaryear) .ref pcodeon,pcodoff,procret,pmeret,bcd2hex mov r11,@procret bl @pcodoff li r12,1900h ;activate ide card at cru >1900 sbo 0 sbo 1 ;enable mapping of >4000 - >40ff space sbo 3 ;fixed page at >4000 - >40ff mov *r10+,r0 ;get pointer to year variable mov *r10+,r1 ;get pointer to month variable mov *r10+,r2 ;get pointer to day of week var (sunday = 1) mov *r10,r3 ;get pointer to day of month variable clr r4 movb @402ch,r4 ;get day of month swpb r4 bl @bcd2hex ;convert to hex mov r6,*r3 clr r4 movb @4030h,r4 ;get day of week swpb r4 bl @bcd2hex ;convert to hex mov r6,*r2 clr r4 movb @4032h,r4 ;get month swpb r4 bl @bcd2hex ;convert to hex mov r6,*r1 clr r4 movb @4034h,r4 ;get year swpb r4 bl @bcd2hex ;convert to hex mov r6,*r0 sbz 1 ;inactivate ram mapping sbz 0 ;inactivate ide card bl @pcodeon mov @procret,r11 b *r11 .end Reveal hidden contents program clocktest; var sec, min, hr, day, dow, month, year : integer; dowstr : array [1..7] of string; procedure ctime(var sec, min, hr : integer); external; procedure cdate(var day, dow, month, year : integer); external; begin dowstr[1] := 'sunday'; dowstr[2] := 'monday'; dowstr[3] := 'tuesday'; dowstr[4] := 'wednesday'; dowstr[5] := 'thursday'; dowstr[6] := 'friday'; dowstr[7] := 'saturday'; cdate(day, dow, month, year); ctime(sec, min, hr); writeln(dowstr[dow],' ',month,'/',day,'/',year); writeln(hr,':',min,':',sec); end. CLOCK.DSK 180 kB · 4 downloads Minor point for you to ponder. Your BCD2HEX routine is actually converting BCD to a binary integer. So BCD2INT might be a better name. ? "Hexadecimal" is a way to display a binary number in a specific way but the same binary number could be displayed as decimal, octal or binary. So that is why I didn't need a conversion to display time, I just printed HEX and BCD comes out correct. But if I wanted to do math with the BCD numbers I would need a conversion routine. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 16 Share Posted July 16 Good point I'm not trying to display hex numbers here. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 17 Share Posted July 17 On 7/15/2024 at 10:35 PM, Vorticon said: Here's a utility disk that includes an assembly routine named CLOCK that returns the date and time of the RTC in the IDE card. Since your ultimate goal is to display CLOCK information on the screen, why not just convert the BCD directly to ASCII? * Convert BCD in LSB to 2-character ASCII word... * BCD2ASC MOV R4,R5 copy (low BCD digit in LSB) SLA R5,4 high BCD digit to MSB MOVB R5,R4 high BCD digit to MSB of R4 ANDI R4,>0F0F leave only BCD digits in MSB,LSB * The folowing works because we only ever have decimal digits, * which are contiguous ASCII characters: ORI R4,>3030 convert to 2 ASCII digits RT ...lee 3 Quote Link to comment Share on other sites More sharing options...
GDMike Posted July 17 Share Posted July 17 (edited) Pretty it up with am/pm-12 hour time Edited July 17 by GDMike Quote Link to comment Share on other sites More sharing options...
apersson850 Posted July 17 Author Share Posted July 17 13 minutes ago, GDMike said: Pretty it up... You mean dumb it down? You live in an old-fashioned part of the world. Back to BCD to ASCII: Since @Vorticon made sure that R4's upper half is zero when the two BCD digits come into the other half of the register, then ANDI R4,>0F0F makes no difference. 1 Quote Link to comment Share on other sites More sharing options...
+Vorticon Posted July 17 Share Posted July 17 40 minutes ago, Lee Stewart said: Since your ultimate goal is to display CLOCK information on the screen, why not just convert the BCD directly to ASCII? * Convert BCD in LSB to 2-character ASCII word... * BCD2ASC MOV R4,R5 copy (low BCD digit in LSB) SLA R5,4 high BCD digit to MSB MOVB R5,R4 high BCD digit to MSB of R4 ANDI R4,>0F0F leave only BCD digits in MSB,LSB * The folowing works because we only ever have decimal digits, * which are contiguous ASCII characters: ORI R4,>3030 convert to 2 ASCII digits RT ...lee Hah! Pretty nifty! But probably not very useful here because it will require more effort to parse out the ascii code from the returned variables and display it. Much simpler to just display the integers directly. Still a cool trick that might come in handy at some point. 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted July 17 Share Posted July 17 34 minutes ago, apersson850 said: You mean dumb it down? You live in an old-fashioned part of the world. Back to BCD to ASCII: Since @Vorticon made sure that R4's upper half is zero when the two BCD digits come into the other half of the register, then ANDI R4,>0F0F makes no difference. Still need to mask off the upper nybble of the LSB. ...lee Quote Link to comment Share on other sites More sharing options...
GDMike Posted July 17 Share Posted July 17 (edited) 2 hours ago, apersson850 said: You mean dumb it down? You live in an old-fashioned part of the world. Back to BCD to ASCII: Since @Vorticon made sure that R4's upper half is zero when the two BCD digits come into the other half of the register, then ANDI R4,>0F0F makes no difference. It's easy to have both you already have the first half. A default setting would make it usable and a switch setting would make it right. I notice I'm not in the military anymore Edited July 17 by GDMike Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.