Jump to content
IGNORED

Pascal on the 99/4A


apersson850

Recommended Posts

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.

Link to comment
Share on other sites

Posted (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 by apersson850
Link to comment
Share on other sites

  • 2 weeks later...

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...

  • Sad 1
Link to comment
Share on other sites

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.

  • Like 2
Link to comment
Share on other sites

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.
 

 

 

In the right hands much can be created.

  • Like 3
Link to comment
Share on other sites

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.
 

 

 

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.

 

  • Like 3
Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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! 

  • Like 1
Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

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.

  • Like 3
Link to comment
Share on other sites

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 😀

  • Like 1
Link to comment
Share on other sites

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

  • Like 2
Link to comment
Share on other sites

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.

  • Like 2
Link to comment
Share on other sites

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. 

 

  • Like 1
Link to comment
Share on other sites

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

  • Like 3
Link to comment
Share on other sites

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.

  • Haha 1
Link to comment
Share on other sites

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.

  • Like 1
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 by GDMike
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...