Jump to content
IGNORED

Can anyone get this Assembly code to work?


Recommended Posts

As I'm not affluent with the ways and means to even start coding assembly into a TI99, I've no idea if this works?  It's code that's been generated from AI.  It's meant to bounce a ball around the screen.
With my lack of assembly knowledge apparent, I wouldn't know either way if AI got the code right , but the one thing I do notice right away is there's no ORG number to start.  Or the TI equivelant.
Also I've had to set this up how I think it should be as pasting from the website just splurged it all over the screen with no carriage returns whatsoever.


* Set up screen parameters

 

LI R0,>8300 * Set base address of screen memory

LI R1,>0000 * Set initial X position

LI R2,>0000 * Set initial Y position

LI R3,>0001 * Set initial X direction

LI R4,>0001 * Set initial Y direction

* Main loop

LOOP

* Draw ball at current position

MOV R5,R1 * Copy X position to R5

ADDI R5,>83C0 * Add offset to screen memory

MOV *R5,R2 * Store Y position in screen memory

 

* Update X position and direction

ADDI R1,R3 * Add X direction to X position

CMP R1,>00F0 * Check if X position reached screen edge

JEQ CHANGE_X * If yes, change X direction

 

* Update Y position and direction

ADDI R2,R4 * Add Y direction to Y position

CMP R2,>00F0 * Check if Y position reached screen edge

JEQ CHANGE_Y * If yes, change Y direction

 

* Delay loop

LI R5,>FFFF * Set delay counter

DELAY DEC R5 * Decrement delay counter

JNE DELAY * Loop until counter reaches zero

 

* Continue main loop

JMP LOOP

 

* Subroutine to change X direction

CHANGE_X

NEG R3 * Negate X direction

JMP LOOP

* Subroutine to change Y direction

CHANGE_Y

NEG R4 * Negate Y direction

JMP LOOP



The URL for the website that did this is here,  I typed "TI99 ASSEMBLY" and then "WRITE A PROGRAM THAT BOUNCES A BALL AROUND THE SCREEN "

 

https://zzzcode.ai/code-generator

 

 

Link to comment
Share on other sites

The very first line is wrong. 

8300 is not a screen address so I suspect it goes wrong pretty fast. 

 

And all VDP memory must be accessed through port addresses in memory and need some code. 

 

The delay will work! :) 

 

  • Like 2
  • Sad 1
Link to comment
Share on other sites

They can only learn what they have seen, they can't extrapolate information and apply it differently. So reading the manual would allow it to write the manual and maybe even answer questions about the instructions (possibly even accurately from time to time), but would not allow it to generate assembly code (much - the examples might give it some clues).

 

You could feed it all the existing working TI assembly source code, and it would start to infer the order in which instructions come together, but it would be limited to whatever the comments looked like when it came to trying to put something new together. Given the way most assembly software is commented, there's usually a wealth of minute details but less emphasis on the big picture, which could make it difficult to get a full program out of it.

 

And of course it still wouldn't understand what it was generating, so the likelihood of bugs remain high. Only if you were asking for something commonly done would you be likely to get working code.

 

These models work largely on huge datasets to learn from - I honestly don't think there's enough 9900 source code in existence to get good training. But, I'd love to be proven wrong and learn. ;)

 

  • Like 6
Link to comment
Share on other sites

27 minutes ago, Tursi said:

For kicks, I took this challenge to ChatGPT. I teased it into generating a valid and reasonably efficient screen clear - and stopped there. It's rather long, so I threw the writeup over on Blogger:

 

https://tursilion.blogspot.com/2024/02/ai-code-gen.html

 

Chat talks as Skeletor.  Then comes out with "I shall provide a skeletal framework".  I see what it did there.  :)

  • Like 2
Link to comment
Share on other sites

BOUNCING BALL.txt < XB source , needs to be compiled for best results.

 

@Vorticon recently asked me how I do the sound in my programs.  At least I think it was you?  Anyhow, this XB program is fully documented and has an example of how I do the sound.  It's a bouncing ball program that asks the user for the delay value before it starts the ball rolling.  When the ball hits the boundaries of the screen, a nice "ping" type noise is produced, which has a sustained volume until the volume value hits 30 then it switches off the variable for the ping.

 

To note;  The Ping in this program is affected by the delay value because I didn't code it as I normally would.  The program is not what I call "modular".  Normally, I would have a list of GOSUBS that would look like this;

1000 GOSUB 2100   ! Decrease delay val

1005 GOSUB 2150   ! Delay value 0?  update the ball
1010 GOSUB 2200   ! is "ping" active? update ping if so
1020 GOTO 1000

If done that way, the ping would be the same speed no matter what the delay value for the ball was.
If anyone wants to convert my program to Assembly language so I can study it , that would be nice.  This post has nothing to do with AI, I've given up on it.  It's stupid.

 

 

Edited by Retrospect
  • Like 4
Link to comment
Share on other sites

I tried at this. A lot going on...

image.thumb.jpeg.b778293f87cd9788c49afe5bbd439de7.jpeg

@Tursi, Is there a way to make a CALL, from your DEBUGGER, and than RETURN, like with EASYBUG?

Since the .BIN, is ROM only, I thought about mashing them together.:ponder:

 

Spoiler
   6486  06A0  bl   @>6556                
         6556
   648A  06A0  bl   @>6666                
         6666
   648E  06A0  bl   @>678a                
         678A
   6492  06A0  bl   @>6952                
         6952
   6496  06A0  bl   @>6944                
         6944
   649A  06A0  bl   @>6722                
         6722
   649E  0460  b    @>647e                
         647E
   64A2  C30B  mov  R11,R12               
   64A4  06A0  bl   @>6cce                
         6CCE
   64A8  C2CC  mov  R12,R11               
   64AA  04C3  clr  R3                    
   64AC  04C4  clr  R4                    
   64AE  D0E0  movb @>8377,R3             
         8377
   64B2  C103  mov  R3,R4                 
   64B4  0284  ci   R4,>ff00              
         FF00
   64B8  1614  jne  >64e2                 
   64BA  C820  mov  @>8364,@>8364         
         8364
         8364
   64C0  1604  jne  >64ca                 
   64C2  0204  li   R4,>0700              
         0700
   64C6  0604  dec  R4                    
   64C8  16FE  jne  >64c6                 
   64CA  05A0  inc  @>8364                
         8364
   64CE  0204  li   R4,>0700              
         0700
   64D2  0604  dec  R4                    
   64D4  16FE  jne  >64d2                 
   64D6  8820  c    @>8364,@>8396         
         8364
         8396
   64DC  1137  jlt  >654c                 
   64DE  04E0  clr  @>8364                
         8364
   64E2  0204  li   R4,>0200              
         0200
   64E6  0200  li   R0,>0301              
         0301
   64EA  04C1  clr  R1                    
   64EC  C30B  mov  R11,R12               
   64EE  06A0  bl   @>6c24                
         6C24
   64F2  C2CC  mov  R12,R11               
   64F4  06C1  swpb R1                    
   64F6  0205  li   R5,>04fc              
         04FC
   64FA  9143  cb   R3,R5                 
   64FC  1309  jeq  >6510                 
   64FE  06C5  swpb R5                    
   6500  9143  cb   R3,R5                 
   6502  1624  jne  >654c                 
   6504  0281  ci   R1,>001f              
         001F
   6508  1121  jlt  >654c                 
   650A  06C1  swpb R1                    
   650C  7044  sb   R4,R1                 
   650E  1005  jmp  >651a                 
   6510  0281  ci   R1,>00c9              
         00C9
   6514  151B  jgt  >654c                 
   6516  06C1  swpb R1                    
   6518  B044  ab   R4,R1                 
   651A  C30B  mov  R11,R12               
   651C  06A0  bl   @>6c38                
         6C38
   6520  C2CC  mov  R12,R11               
   6522  0220  ai   R0,>0004              
         0004
   6526  B060  ab   @>8346,R1             
         8346
   652A  C30B  mov  R11,R12               
   652C  06A0  bl   @>6c38                
         6C38
   6530  C2CC  mov  R12,R11               
   6532  0220  ai   R0,>0004              
         0004
   6536  B060  ab   @>8346,R1             
         8346
   653A  C30B  mov  R11,R12               
   653C  06A0  bl   @>6c38                
         6C38
   6540  C2CC  mov  R12,R11               
   6542  0204  li   R4,>0384              
         0384
   6546  0604  dec  R4                    
   6548  16FE  jne  >6546                 
   654A  045B  b    *R11                  
   654C  0204  li   R4,>0320              
         0320
   6550  0604  dec  R4                    
   6552  16FE  jne  >6550                 
   6554  045B  b    *R11                  
   6556  04C1  clr  R1                    
   6558  0200  li   R0,>030c              
         030C
   655C  C30B  mov  R11,R12               
   655E  06A0  bl   @>6c24                
         6C24
   6562  C2CC  mov  R12,R11               
   6564  06C1  swpb R1                    
   6566  0281  ci   R1,>00b1              
         00B1
   656A  115B  jlt  >6622                 
   656C  0200  li   R0,>078c              
         078C
   6570  04C1  clr  R1                    
   6572  C30B  mov  R11,R12               
   6574  06A0  bl   @>6c24                
         6C24
   6578  C2CC  mov  R12,R11               
   657A  06C1  swpb R1                    
   657C  0281  ci   R1,>003c              
         003C
   6580  1550  jgt  >6622                 
   6582  04C1  clr  R1                    
   6584  04C3  clr  R3                    
   6586  04C4  clr  R4                    
   6588  0200  li   R0,>030d              
         030D
   658C  C30B  mov  R11,R12               
   658E  06A0  bl   @>6c24                
         6C24
   6592  C2CC  mov  R12,R11               
   6594  D0C1  movb R1,R3                 
   6596  06C3  swpb R3                    
   6598  0200  li   R0,>0301              
         0301
   659C  C30B  mov  R11,R12               
   659E  06A0  bl   @>6c24                
         6C24
   65A2  C2CC  mov  R12,R11               
   65A4  D101  movb R1,R4                 
   65A6  06C4  swpb R4                    
   65A8  8103  c    R3,R4                 
   65AA  1508  jgt  >65bc                 
   65AC  6103  s    R3,R4                 
   65AE  0284  ci   R4,>0006              
         0006
   65B2  1538  jgt  >6624                 
   65B4  0201  li   R1,>8348              
         8348
   65B8  0460  b    @>6600                
         6600
   65BC  60C4  s    R4,R3                 
   65BE  0283  ci   R3,>0004              
         0004
   65C2  1504  jgt  >65cc                 
   65C4  0201  li   R1,>834a              
         834A
   65C8  0460  b    @>6600                
         6600
   65CC  0283  ci   R3,>0008              
         0008
   65D0  1504  jgt  >65da                 
   65D2  0201  li   R1,>834c              
         834C
   65D6  0460  b    @>6600                
         6600
   65DA  0283  ci   R3,>000c              
         000C
   65DE  1504  jgt  >65e8                 
   65E0  0201  li   R1,>834e              
         834E
   65E4  0460  b    @>6600                
         6600
   65E8  0283  ci   R3,>0010              
         0010
   65EC  1504  jgt  >65f6                 
   65EE  0201  li   R1,>8350              
         8350
   65F2  0460  b    @>6600                
         6600
   65F6  0283  ci   R3,>0016              
         0016
   65FA  1514  jgt  >6624                 
   65FC  0201  li   R1,>8352              
         8352
   6600  0200  li   R0,>078c              
         078C
   6604  0202  li   R2,>0002              
         0002
   6608  C30B  mov  R11,R12               
   660A  06A0  bl   @>6ca8                
         6CA8
   660E  C2CC  mov  R12,R11               
   6610  04E0  clr  @>8384                
         8384
   6614  0200  li   R0,>1508              
         1508
   6618  C800  mov  R0,@>83cc             
         83CC
   661C  D820  movb @>8340,@>83ce         
         8340
         83CE
   6622  045B  b    *R11                  
   6624  0200  li   R0,>1510              
         1510
   6628  C800  mov  R0,@>83cc             
         83CC
   662C  D820  movb @>8340,@>83ce         
         8340
         83CE
   6632  0200  li   R0,>078c              
         078C
   6636  0201  li   R1,>83ac              
         83AC
   663A  0202  li   R2,>0002              
         0002
   663E  C30B  mov  R11,R12               
   6640  06A0  bl   @>6ca8                
         6CA8
   6644  C2CC  mov  R12,R11               
   6646  05A0  inc  @>83a8                
         83A8
   664A  C020  mov  @>83a8,R0             
         83A8
   664E  0280  ci   R0,>0005              
         0005
   6652  1502  jgt  >6658                 
   6654  0460  b    @>63dc                
         63DC
   6658  0460  b    @>6a5a                
         6A5A
   665C  0300  limi >0002                 
         0002
   6660  0300  limi >0000                 
         0000
   6664  045B  b    *R11                  
   6666  0200  li   R0,>078c              
         078C
   666A  0201  li   R1,>8362              
         8362
   666E  0202  li   R2,>0002              
         0002
   6672  C30B  mov  R11,R12               
   6674  06A0  bl   @>6c88                
         6C88
   6678  C2CC  mov  R12,R11               
   667A  0200  li   R0,>030d              
         030D
   667E  04C1  clr  R1                    
   6680  C30B  mov  R11,R12               
   6682  06A0  bl   @>6c24                
         6C24
   6686  C2CC  mov  R12,R11               
   6688  06C1  swpb R1                    
   668A  0281  ci   R1,>001f              
         001F
   668E  1104  jlt  >6698                 
   6690  0281  ci   R1,>00d8              
         00D8
   6694  151A  jgt  >66ca                 
   6696  1044  jmp  >6720                 
   6698  0203  li   R3,>8352              
         8352
   669C  0204  li   R4,>8348              
         8348
   66A0  0205  li   R5,>0003              
         0003
   66A4  8834  c    *R4+,@>8362           
         8362
   66A8  1329  jeq  >66fc                 
   66AA  0643  dect R3                    
   66AC  0605  dec  R5                    
   66AE  16FA  jne  >66a4                 
   66B0  0205  li   R5,>0003              
         0003
   66B4  0203  li   R3,>835e              
         835E
   66B8  0204  li   R4,>8354              
         8354
   66BC  8834  c    *R4+,@>8362           
         8362
   66C0  131D  jeq  >66fc                 
   66C2  0643  dect R3                    
   66C4  0605  dec  R5                    
   66C6  16FA  jne  >66bc                 
   66C8  102B  jmp  >6720                 
   66CA  0204  li   R4,>834e              
         834E
   66CE  0203  li   R3,>834c              
         834C
   66D2  0205  li   R5,>0003              
         0003
   66D6  8834  c    *R4+,@>8362           
         8362
   66DA  1310  jeq  >66fc                 
   66DC  0643  dect R3                    
   66DE  0605  dec  R5                    
   66E0  16FA  jne  >66d6                 
   66E2  0205  li   R5,>0003              
         0003
   66E6  0203  li   R3,>8358              
         8358
   66EA  0204  li   R4,>835a              
         835A
   66EE  8834  c    *R4+,@>8362           
         8362
   66F2  1304  jeq  >66fc                 
   66F4  0643  dect R3                    
   66F6  0605  dec  R5                    
   66F8  16FA  jne  >66ee                 
   66FA  1012  jmp  >6720                 
   66FC  0200  li   R0,>078c              
         078C
   6700  C043  mov  R3,R1                 
   6702  0202  li   R2,>0002              
         0002
   6706  C30B  mov  R11,R12               
   6708  06A0  bl   @>6ca8                
         6CA8
   670C  C2CC  mov  R12,R11               
   670E  04E0  clr  @>8384                
         8384
   6712  0200  li   R0,>1508              
         1508
   6716  C800  mov  R0,@>83cc             
         83CC
   671A  D820  movb @>8340,@>83ce         
         8340
         83CE
   6720  045B  b    *R11                  
   6722  0200  li   R0,>030c              
         030C
   6726  04C1  clr  R1                    
   6728  C30B  mov  R11,R12               
   672A  06A0  bl   @>6c24                
         6C24
   672E  C2CC  mov  R12,R11               
   6730  06C1  swpb R1                    
   6732  0281  ci   R1,>0017              
         0017
   6736  15F4  jgt  >6720                 
   6738  04E0  clr  @>8384                
         8384
   673C  0200  li   R0,>078c              
         078C
   6740  0201  li   R1,>8362              
         8362
   6744  0202  li   R2,>0002              
         0002
   6748  C30B  mov  R11,R12               
   674A  06A0  bl   @>6c88                
         6C88
   674E  C2CC  mov  R12,R11               
   6750  0203  li   R3,>8348              
         8348
   6754  0204  li   R4,>8354              
         8354
   6758  0205  li   R5,>0006              
         0006
   675C  8833  c    *R3+,@>8362           
         8362
   6760  1304  jeq  >676a                 
   6762  05C4  inct R4                    
   6764  0605  dec  R5                    
   6766  16FA  jne  >675c                 
   6768  10DB  jmp  >6720                 
   676A  C044  mov  R4,R1                 
   676C  C30B  mov  R11,R12               
   676E  06A0  bl   @>6ca8                
         6CA8
   6772  C2CC  mov  R12,R11               
   6774  0200  li   R0,>1508              
         1508
   6778  C800  mov  R0,@>83cc             
         83CC
   677C  D820  movb @>8340,@>83ce         
         8340
         83CE
   6782  C820  mov  @>8340,@>838e         
         8340
         838E
   6788  10CB  jmp  >6720                 
   678A  0200  li   R0,>030c              
         030C
   678E  0201  li   R1,>8360              
         8360
   6792  0202  li   R2,>0002              
         0002
   6796  C30B  mov  R11,R12               
   6798  06A0  bl   @>6c88                
         6C88
   679C  C2CC  mov  R12,R11               
   679E  04C3  clr  R3                    
   67A0  04C4  clr  R4                    
   67A2  D120  movb @>8360,R4             
         8360
   67A6  06C4  swpb R4                    
   67A8  0224  ai   R4,>0004              
         0004
   67AC  3CE0  div  @>8366,R3             
         8366
   67B0  38E0  mpy  @>8368,R3             
         8368
   67B4  C144  mov  R4,R5                 
   67B6  04C3  clr  R3                    
   67B8  04C4  clr  R4                    
   67BA  D120  movb @>8361,R4             
         8361
   67BE  06C4  swpb R4                    
   67C0  0224  ai   R4,>0004              
         0004
   67C4  3CE0  div  @>8366,R3             
         8366
   67C8  04C1  clr  R1                    
   67CA  0200  li   R0,>078d              
         078D
   67CE  C30B  mov  R11,R12               
   67D0  06A0  bl   @>6c24                
         6C24
   67D4  C2CC  mov  R12,R11               
   67D6  C041  mov  R1,R1                 
   67D8  1106  jlt  >67e6                 
   67DA  1309  jeq  >67ee                 
   67DC  0284  ci   R4,>0005              
         0005
   67E0  1106  jlt  >67ee                 
   67E2  0583  inc  R3                    
   67E4  1004  jmp  >67ee                 
   67E6  0284  ci   R4,>0002              
         0002
   67EA  1501  jgt  >67ee                 
   67EC  0603  dec  R3                    
   67EE  A143  a    R3,R5                 
   67F0  C005  mov  R5,R0                 
   67F2  04C1  clr  R1                    
   67F4  C30B  mov  R11,R12               
   67F6  06A0  bl   @>6c24                
         6C24
   67FA  C2CC  mov  R12,R11               
   67FC  0281  ci   R1,>8800              
         8800
   6800  1607  jne  >6810                 
   6802  A820  a    @>83a4,@>839a         
         83A4
         839A
   6808  C820  mov  @>8340,@>8386         
         8340
         8386
   680E  1012  jmp  >6834                 
   6810  0281  ci   R1,>9000              
         9000
   6814  1607  jne  >6824                 
   6816  A820  a    @>83a2,@>839a         
         83A2
         839A
   681C  C820  mov  @>8340,@>838a         
         8340
         838A
   6822  1008  jmp  >6834                 
   6824  0281  ci   R1,>9800              
         9800
   6828  1604  jne  >6832                 
   682A  A820  a    @>83a0,@>839a         
         83A0
         839A
   6830  1001  jmp  >6834                 
   6832  045B  b    *R11                  
   6834  0201  li   R1,>2000              
         2000
   6838  C30B  mov  R11,R12               
   683A  06A0  bl   @>6c38                
         6C38
   683E  C2CC  mov  R12,R11               
   6840  0200  li   R0,>1500              
         1500
   6844  C800  mov  R0,@>83cc             
         83CC
   6848  D820  movb @>8340,@>83ce         
         8340
         83CE
   684E  020A  li   R10,>8398             
         8398
   6852  C30B  mov  R11,R12               
   6854  06A0  bl   @>68ca                
         68CA
   6858  C2CC  mov  R12,R11               
   685A  0620  dec  @>83aa                
         83AA
   685E  C820  mov  @>8392,@>8392         
         8392
         8392
   6864  13E6  jeq  >6832                 
   6866  C820  mov  @>8384,@>8384         
         8384
         8384
   686C  16E2  jne  >6832                 
   686E  C820  mov  @>8340,@>8384         
         8340
         8384
   6874  0200  li   R0,>078c              
         078C
   6878  0201  li   R1,>8362              
         8362
   687C  0202  li   R2,>0002              
         0002
   6880  C30B  mov  R11,R12               
   6882  06A0  bl   @>6c88                
         6C88
   6886  C2CC  mov  R12,R11               
   6888  0203  li   R3,>8348              
         8348
   688C  0204  li   R4,>8354              
         8354
   6890  0205  li   R5,>0006              
         0006
   6894  8833  c    *R3+,@>8362           
         8362
   6898  130D  jeq  >68b4                 
   689A  05C4  inct R4                    
   689C  0605  dec  R5                    
   689E  16FA  jne  >6894                 
   68A0  0204  li   R4,>8348              
         8348
   68A4  0205  li   R5,>0006              
         0006
   68A8  8833  c    *R3+,@>8362           
         8362
   68AC  1303  jeq  >68b4                 
   68AE  05C4  inct R4                    
   68B0  0605  dec  R5                    
   68B2  16FA  jne  >68a8                 
   68B4  C044  mov  R4,R1                 
   68B6  C30B  mov  R11,R12               
   68B8  06A0  bl   @>6ca8                
         6CA8
   68BC  C2CC  mov  R12,R11               
   68BE  10B9  jmp  >6832                 
   68C0  0000  data >0000                 
   68C2  000A  data >000a                 
   68C4  0064  data >0064                 
   68C6  03E8  lrex                       
   68C8  2710  czc  *R0,R12               
   68CA  C800  mov  R0,@>83be             
         83BE
   68CE  C801  mov  R1,@>83bc             
         83BC
   68D2  C802  mov  R2,@>83ba             
         83BA
   68D6  C803  mov  R3,@>83b8             
         83B8
   68DA  C804  mov  R4,@>83b6             
         83B6
   68DE  C805  mov  R5,@>83b4             
         83B4
   68E2  C34B  mov  R11,R13               
   68E4  C0CA  mov  R10,R3                
   68E6  C013  mov  *R3,R0                
   68E8  C0E3  mov  @>0002(R3),R3         
         0002
   68EC  04C2  clr  R2                    
   68EE  04C5  clr  R5                    
   68F0  0204  li   R4,>0008              
         0008
   68F4  3CA4  div  @>68c0(R4),R2         
         68C0
   68F8  C145  mov  R5,R5                 
   68FA  1605  jne  >6906                 
   68FC  C082  mov  R2,R2                 
   68FE  1603  jne  >6906                 
   6900  0201  li   R1,>2000              
         2000
   6904  1005  jmp  >6910                 
   6906  C042  mov  R2,R1                 
   6908  0221  ai   R1,>0030              
         0030
   690C  06C1  swpb R1                    
   690E  0585  inc  R5                    
   6910  06A0  bl   @>6c38                
         6C38
   6914  0580  inc  R0                    
   6916  04C2  clr  R2                    
   6918  0644  dect R4                    
   691A  16EC  jne  >68f4                 
   691C  C043  mov  R3,R1                 
   691E  0221  ai   R1,>0030              
         0030
   6922  06C1  swpb R1                    
   6924  06A0  bl   @>6c38                
         6C38
   6928  C020  mov  @>83be,R0             
         83BE
   692C  C060  mov  @>83bc,R1             
         83BC
   6930  C0A0  mov  @>83ba,R2             
         83BA
   6934  C0E0  mov  @>83b8,R3             
         83B8
   6938  C120  mov  @>83b6,R4             
         83B6
   693C  C160  mov  @>83b4,R5             
         83B4
   6940  C2CD  mov  R13,R11               
   6942  045B  b    *R11                  
   6944  C820  mov  @>83aa,@>83aa         
         83AA
         83AA
   694A  1602  jne  >6950                 
   694C  0460  b    @>62f8                
         62F8
   6950  045B  b    *R11                  
   6952  C820  mov  @>838e,@>838e         
         838E
         838E
   6958  130A  jeq  >696e                 
   695A  C820  mov  @>8390,@>8390         
         8390
         8390
   6960  1644  jne  >69ea                 
   6962  0205  li   R5,>1048              
         1048
   6966  C820  mov  @>8340,@>8390         
         8340
         8390
   696C  101B  jmp  >69a4                 
   696E  C820  mov  @>8386,@>8386         
         8386
         8386
   6974  130A  jeq  >698a                 
   6976  C820  mov  @>8388,@>8388         
         8388
         8388
   697C  1636  jne  >69ea                 
   697E  0205  li   R5,>1030              
         1030
   6982  C820  mov  @>8340,@>8388         
         8340
         8388
   6988  100D  jmp  >69a4                 
   698A  C820  mov  @>838a,@>838a         
         838A
         838A
   6990  132C  jeq  >69ea                 
   6992  C820  mov  @>838c,@>838c         
         838C
         838C
   6998  1628  jne  >69ea                 
   699A  0205  li   R5,>1018              
         1018
   699E  C820  mov  @>8340,@>838c         
         8340
         838C
   69A4  0200  li   R0,>078c              
         078C
   69A8  0201  li   R1,>8362              
         8362
   69AC  0202  li   R2,>0002              
         0002
   69B0  C30B  mov  R11,R12               
   69B2  06A0  bl   @>6c88                
         6C88
   69B6  C2CC  mov  R12,R11               
   69B8  0204  li   R4,>8348              
         8348
   69BC  8834  c    *R4+,@>8362           
         8362
   69C0  1301  jeq  >69c4                 
   69C2  10FC  jmp  >69bc                 
   69C4  C005  mov  R5,R0                 
   69C6  0201  li   R1,>8348              
         8348
   69CA  0202  li   R2,>0018              
         0018
   69CE  C30B  mov  R11,R12               
   69D0  06A0  bl   @>6c88                
         6C88
   69D4  C2CC  mov  R12,R11               
   69D6  0200  li   R0,>078c              
         078C
   69DA  C044  mov  R4,R1                 
   69DC  0641  dect R1                    
   69DE  0202  li   R2,>0002              
         0002
   69E2  C30B  mov  R11,R12               
   69E4  06A0  bl   @>6ca8                
         6CA8
   69E8  C2CC  mov  R12,R11               
   69EA  045B  b    *R11                  
   69EC  04C4  clr  R4                    
   69EE  0200  li   R0,>1527              
         1527
   69F2  C800  mov  R0,@>83cc             
         83CC
   69F6  D820  movb @>8340,@>83ce         
         8340
         83CE
   69FC  0300  limi >0002                 
         0002
   6A00  D820  movb @>83ce,@>83ce         
         83CE
         83CE
   6A06  16FC  jne  >6a00                 
   6A08  0300  limi >0000                 
         0000
   6A0C  D804  movb R4,@>8374             
         8374
   6A10  C30B  mov  R11,R12               
   6A12  06A0  bl   @>6cce                
         6CCE
   6A16  C2CC  mov  R12,R11               
   6A18  D120  movb @>8375,R4             
         8375
   6A1C  0284  ci   R4,>ff00              
         FF00
   6A20  13F7  jeq  >6a10                 
   6A22  045B  b    *R11                  
   6A24  0200  li   R0,>02ff              
         02FF
   6A28  0201  li   R1,>a800              
         A800
   6A2C  C30B  mov  R11,R12               
   6A2E  06A0  bl   @>6c38                
         6C38
   6A32  C2CC  mov  R12,R11               
   6A34  0600  dec  R0                    
   6A36  16FA  jne  >6a2c                 
   6A38  045B  b    *R11                  
   6A3A  0204  li   R4,>0004              
         0004
   6A3E  0203  li   R3,>2300              
         2300
   6A42  0300  limi >0002                 
         0002
   6A46  0300  limi >0000                 
         0000
   6A4A  0603  dec  R3                    
   6A4C  16FA  jne  >6a42                 
   6A4E  0604  dec  R4                    
   6A50  16F6  jne  >6a3e                 
   6A52  045B  b    *R11                  
   6A54  0204  li   R4,>0002              
         0002
   6A58  10F2  jmp  >6a3e                 
   6A5A  0200  li   R0,>0390              
         0390
   6A5E  0201  li   R1,>6d3a              
         6D3A
   6A62  0202  li   R2,>0006              
         0006
   6A66  06A0  bl   @>6ca8                
         6CA8
   6A6A  06A0  bl   @>6a3a                
         6A3A
   6A6E  0200  li   R0,>0300              
         0300
   6A72  0201  li   R1,>6d28              
         6D28
   6A76  0202  li   R2,>0011              
         0011
   6A7A  06A0  bl   @>6ca8                
         6CA8
   6A7E  8820  c    @>839a,@>839e         
         839A
         839E
   6A84  1109  jlt  >6a98                 
   6A86  C820  mov  @>839a,@>839e         
         839A
         839E
   6A8C  020A  li   R10,>839c             
         839C
   6A90  C30B  mov  R11,R12               
   6A92  06A0  bl   @>68ca                
         68CA
   6A96  C2CC  mov  R12,R11               
   6A98  0200  li   R0,>018b              
         018B
   6A9C  0201  li   R1,>6ebc              
         6EBC
   6AA0  0202  li   R2,>0009              
         0009
   6AA4  06A0  bl   @>6ca8                
         6CA8
   6AA8  06A0  bl   @>6a3a                
         6A3A
   6AAC  0220  ai   R0,>0041              
         0041
   6AB0  0202  li   R2,>0006              
         0006
   6AB4  0201  li   R1,>6ec5              
         6EC5
   6AB8  06A0  bl   @>6ca8                
         6CA8
   6ABC  0220  ai   R0,>003d              
         003D
   6AC0  0201  li   R1,>6ecb              
         6ECB
   6AC4  0202  li   R2,>000d              
         000D
   6AC8  06A0  bl   @>6ca8                
         6CA8
   6ACC  0220  ai   R0,>0040              
         0040
   6AD0  0201  li   R1,>6ed8              
         6ED8
   6AD4  0602  dec  R2                    
   6AD6  06A0  bl   @>6ca8                
         6CA8
   6ADA  0220  ai   R0,>0040              
         0040
   6ADE  0201  li   R1,>6ee4              
         6EE4
   6AE2  0202  li   R2,>0008              
         0008
   6AE6  06A0  bl   @>6ca8                
         6CA8
   6AEA  06A0  bl   @>69ec                
         69EC
   6AEE  0284  ci   R4,>3100              
         3100
   6AF2  1602  jne  >6af8                 
   6AF4  0460  b    @>6232                
         6232
   6AF8  0284  ci   R4,>3200              
         3200
   6AFC  1610  jne  >6b1e                 
   6AFE  0200  li   R0,>0303              
         0303
   6B02  0201  li   R1,>0100              
         0100
   6B06  06A0  bl   @>6c38                
         6C38
   6B0A  0220  ai   R0,>0004              
         0004
   6B0E  06A0  bl   @>6c38                
         6C38
   6B12  0220  ai   R0,>0004              
         0004
   6B16  06A0  bl   @>6c38                
         6C38
   6B1A  0460  b    @>611c                
         611C
   6B1E  0284  ci   R4,>3300              
         3300
   6B22  16E3  jne  >6aea                 
   6B24  0420  blwp @>0000                
         0000
   6B28  C30B  mov  R11,R12               
   6B2A  0200  li   R0,>0000              
         0000
   6B2E  06A0  bl   @>6c52                
         6C52
   6B32  0200  li   R0,>01e0              
         01E0
   6B36  06A0  bl   @>6c52                
         6C52
   6B3A  06C0  swpb R0                    
   6B3C  D800  movb R0,@>83d4             
         83D4
   6B40  0200  li   R0,>0200              
         0200
   6B44  06A0  bl   @>6c52                
         6C52
   6B48  0200  li   R0,>030e              
         030E
   6B4C  06A0  bl   @>6c52                
         6C52
   6B50  0200  li   R0,>0401              
         0401
   6B54  06A0  bl   @>6c52                
         6C52
   6B58  0200  li   R0,>0506              
         0506
   6B5C  06A0  bl   @>6c52                
         6C52
   6B60  0200  li   R0,>0600              
         0600
   6B64  06A0  bl   @>6c52                
         6C52
   6B68  0207  li   R7,>07f5              
         07F5
   6B6C  06A0  bl   @>6c52                
         6C52
   6B70  0200  li   R0,>0300              
         0300
   6B74  0201  li   R1,>d000              
         D000
   6B78  06A0  bl   @>6c38                
         6C38
   6B7C  0203  li   R3,>0018              
         0018
   6B80  D803  movb R3,@>9c02             
         9C02
   6B84  06C3  swpb R3                    
   6B86  D803  movb R3,@>9c02             
         9C02
   6B8A  1000  jmp  >6b8c                 
   6B8C  D0E0  movb @>9800,R3             
         9800
   6B90  06C3  swpb R3                    
   6B92  D0E0  movb @>9800,R3             
         9800
   6B96  06C3  swpb R3                    
   6B98  0243  andi R3,>0fff              
         0FFF
   6B9C  D803  movb R3,@>9c02             
         9C02
   6BA0  06C3  swpb R3                    
   6BA2  D803  movb R3,@>9c02             
         9C02
   6BA6  0200  li   R0,>0004              
         0004
   6BAA  D0E0  movb @>9800,R3             
         9800
   6BAE  0600  dec  R0                    
   6BB0  16FC  jne  >6baa                 
   6BB2  06C3  swpb R3                    
   6BB4  D0E0  movb @>9800,R3             
         9800
   6BB8  06C3  swpb R3                    
   6BBA  D803  movb R3,@>9c02             
         9C02
   6BBE  06C3  swpb R3                    
   6BC0  D803  movb R3,@>9c02             
         9C02
   6BC4  0200  li   R0,>0900              
         0900
   6BC8  0203  li   R3,>0007              
         0007
   6BCC  04C1  clr  R1                    
   6BCE  06A0  bl   @>6c38                
         6C38
   6BD2  0580  inc  R0                    
   6BD4  D060  movb @>9800,R1             
         9800
   6BD8  06A0  bl   @>6c38                
         6C38
   6BDC  0580  inc  R0                    
   6BDE  0603  dec  R3                    
   6BE0  16F9  jne  >6bd4                 
   6BE2  0280  ci   R0,>0bf8              
         0BF8
   6BE6  1AF0  jl   >6bc8                 
   6BE8  04C0  clr  R0                    
   6BEA  0201  li   R1,>2000              
         2000
   6BEE  0202  li   R2,>0300              
         0300
   6BF2  06A0  bl   @>6c38                
         6C38
   6BF6  0580  inc  R0                    
   6BF8  0602  dec  R2                    
   6BFA  16FB  jne  >6bf2                 
   6BFC  0200  li   R0,>8340              
         8340
   6C00  0201  li   R1,>6f0e              
         6F0E
   6C04  0202  li   R2,>0018              
         0018
   6C08  CC31  mov  *R1+,*R0+             
   6C0A  0602  dec  R2                    
   6C0C  16FD  jne  >6c08                 
   6C0E  0200  li   R0,>8384              
         8384
   6C12  0201  li   R1,>6f3e              
         6F3E
   6C16  0202  li   R2,>001a              
         001A
   6C1A  CC31  mov  *R1+,*R0+             
   6C1C  0602  dec  R2                    
   6C1E  16FD  jne  >6c1a                 
   6C20  C2CC  mov  R12,R11               
   6C22  045B  b    *R11                  
   6C24  06C0  swpb R0                    
   6C26  D800  movb R0,@>8c02             
         8C02
   6C2A  06C0  swpb R0                    
   6C2C  D800  movb R0,@>8c02             
         8C02
   6C30  1000  jmp  >6c32                 
   6C32  D060  movb @>8800,R1             
         8800
   6C36  045B  b    *R11                  
   6C38  0260  ori  R0,>4000              
         4000
   6C3C  06C0  swpb R0                    
   6C3E  D800  movb R0,@>8c02             
         8C02
   6C42  06C0  swpb R0                    
   6C44  D800  movb R0,@>8c02             
         8C02
   6C48  0240  andi R0,>3fff              
         3FFF
   6C4C  D801  movb R1,@>8c00             
         8C00
   6C50  045B  b    *R11                  
   6C52  0260  ori  R0,>8000              
         8000
   6C56  06C0  swpb R0                    
   6C58  D800  movb R0,@>8c02             
         8C02
   6C5C  06C0  swpb R0                    
   6C5E  D800  movb R0,@>8c02             
         8C02
   6C62  0240  andi R0,>3fff              
         3FFF
   6C66  045B  b    *R11                  
   6C68  0200  li   R0,>0030              
         0030
   6C6C  0A90  sla  R0,9                  
   6C6E  D010  movb *R0,R0                
   6C70  0240  andi R0,>ff00              
         FF00
   6C74  1001  jmp  >6c78                 
   6C76  2020  coc  @>0280,R0             
         0280
   6C7A  AA00  a    R0,@>1001(R8)         
         1001
   6C7E  2020  coc  @>1301,R0             
         1301
   6C82  10FF  jmp  >6c82                 
   6C84  C020  mov  @>837e,R0             
         837E
   6C88  C381  mov  R1,R14                
   6C8A  C3C2  mov  R2,R15                
   6C8C  06C0  swpb R0                    
   6C8E  D800  movb R0,@>8c02             
         8C02
   6C92  06C0  swpb R0                    
   6C94  D800  movb R0,@>8c02             
         8C02
   6C98  1000  jmp  >6c9a                 
   6C9A  DC60  movb @>8800,*R1+           
         8800
   6C9E  0602  dec  R2                    
   6CA0  16FC  jne  >6c9a                 
   6CA2  C04E  mov  R14,R1                
   6CA4  C08F  mov  R15,R2                
   6CA6  045B  b    *R11                  
   6CA8  C381  mov  R1,R14                
   6CAA  C3C2  mov  R2,R15                
   6CAC  0260  ori  R0,>4000              
         4000
   6CB0  06C0  swpb R0                    
   6CB2  D800  movb R0,@>8c02             
         8C02
   6CB6  06C0  swpb R0                    
   6CB8  D800  movb R0,@>8c02             
         8C02
   6CBC  0240  andi R0,>3fff              
         3FFF
   6CC0  D831  movb *R1+,@>8c00           
         8C00
   6CC4  0602  dec  R2                    
   6CC6  16FC  jne  >6cc0                 
   6CC8  C04E  mov  R14,R1                
   6CCA  C08F  mov  R15,R2                
   6CCC  045B  b    *R11                  
   6CCE  020F  li   R15,>045b             
         045B
   6CD2  02AE  stwp R14                   
   6CD4  020D  li   R13,>02e0             
         02E0
   6CD8  C80D  mov  R13,@>83ba            
         83BA
   6CDC  C80E  mov  R14,@>83bc            
         83BC
   6CE0  C80F  mov  R15,@>83be            
         83BE
   6CE4  02E0  lwpi >83e0                 
         83E0
   6CE8  C80B  mov  R11,@>83b8            
         83B8
   6CEC  06A0  bl   @>000e                
         000E
   6CF0  C2E0  mov  @>83b8,R11            
         83B8
   6CF4  0460  b    @>83ba                
         83BA
   6CF8  0000  data >0000                 
   6CFA  183C  joc  >6d74                 
   6CFC  3C18  div  *R8,R0                
   6CFE  0000  data >0000                 
   6D00  0000  data >0000                 
   6D02  0000  data >0000                 
   6D04  00FF  data >00ff                 
   6D06  FFFF  socb *R15+,*R15+           
   6D08  007F  data >007f                 
   6D0A  7F7F  sb   *R15+,*R13+           
   6D0C  7F7F  sb   *R15+,*R13+           
   6D0E  0000  data >0000                 
   6D10  0000  data >0000                 
   6D12  0000  data >0000                 
   6D14  00FF  data >00ff                 
   6D16  FFFF  socb *R15+,*R15+           
   6D18  0707  seto R7                    
   6D1A  0707  seto R7                    
   6D1C  0707  seto R7                    
   6D1E  0707  seto R7                    
   6D20  E0E0  soc  @>e0e0,R3             
         E0E0
   6D24  E0E0  soc  @>e0e0,R3             
         E0E0
   6D28  B070  ab   *R0+,R1               
   6D2A  810F  c    R15,R4                
   6D2C  B078  ab   *R8+,R1               
   6D2E  810F  c    R15,R4                
   6D30  B080  ab   R0,R2                 
   6D32  810F  c    R15,R4                
   6D34  5AD8  szcb *R8,@>8001(R11)       
         8001
   6D38  D000  movb R0,R0                 
   6D3A  F181  socb R1,R6                 
   6D3C  2141  coc  R1,R5                 
   6D3E  EE11  soc  *R1,*R8+              
   6D40  9121  cb   @>5191(R1),R4         
         5191
   6D44  2151  coc  *R1,R5                
   6D46  9121  cb   @>5191(R1),R4         
         5191
   6D4A  2151  coc  *R1,R5                
   6D4C  F111  socb *R1,R4                
   6D4E  1111  jlt  >6d72                 
   6D50  EE11  soc  *R1,*R8+              
   6D52  A0A0  a    @>a0a0,R2             
         A0A0
   6D56  EAE5  soc  @>e9f2(R5),@>e7f9(R11)
         E9F2
         E7F9
   6D5C  E707  soc  R7,*R12               
   6D5E  E90E  soc  R14,@>ea1b(R4)        
         EA1B
   6D62  16E5  jne  >6d2e                 
   6D64  17F2  jnc  >6d4a                 
   6D66  19F9  jno  >6d5a                 
   6D68  1907  jno  >6d78                 
   6D6A  170E  jnc  >6d88                 
   6D6C  161B  jne  >6da4                 
   6D6E  E5DE  soc  *R14,*R7              
   6D70  E3EE  soc  @>e0f7(R14),R15       
         E0F7
   6D74  E009  soc  R9,R0                 
   6D76  E312  soc  *R2,R12               
   6D78  E522  soc  @>1bde(R2),*R4        
         1BDE
   6D7C  1DEE  sbo  >ffee                 
   6D7E  20F7  coc  *R7+,R3               
   6D80  2009  coc  R9,R0                 
   6D82  1D12  sbo  >0012                 
   6D84  1B22  jh   >6dca                 
   6D86  DFD7  movb *R7,*R15+             
   6D88  DDEB  movb @>d9f5(R11),*R7+      
         D9F5
   6D8C  D90B  movb R11,@>dd15(R4)        
         DD15
   6D90  DF29  movb @>21d7(R9),*R12+      
         21D7
   6D94  23EB  coc  @>27f5(R11),R15       
         27F5
   6D98  270B  czc  R11,R12               
   6D9A  2315  coc  *R5,R12               
   6D9C  2129  coc  @>dad0(R9),R4         
         DAD0
   6DA0  D7E7  movb @>d2f3(R7),*R15       
         D2F3
   6DA4  D20D  movb R13,R8                
   6DA6  D719  movb *R9,*R12              
   6DA8  DA30  movb *R0+,@>26d0(R8)       
         26D0
   6DAC  29E7  xor  @>2ef3(R7),R7         
         2EF3
   6DB0  2E0D  xop  R13,8                 
   6DB2  2919  xor  *R9,R4                
   6DB4  2630  czc  *R0+,R8               
   6DB6  D4C9  movb R9,*R3                
   6DB8  D1E4  movb @>c6f1(R4),R7         
         C6F1
   6DBC  C60F  mov  R15,*R8               
   6DBE  D11C  movb *R12,R4               
   6DC0  D437  movb *R7+,*R0              
   6DC2  2CC9  xop  R9,3                  
   6DC4  2FE4  xop  @>35f1(R4),15         
         35F1
   6DC8  350F  stcr R15,4                 
   6DCA  2F1C  xop  *R12,12               
   6DCC  2C37  xop  *R7+,0                
   6DCE  CEC2  mov  R2,*R11+              
   6DD0  C6E1  mov  @>c4ef(R1),*R11       
         C4EF
   6DD4  C411  mov  *R1,*R0               
   6DD6  C61F  mov  *R15,*R8              
   6DD8  CE3E  mov  *R14+,*R8+            
   6DDA  32C2  ldcr R2,11                 
   6DDC  35E1  stcr @>3cef(R1),7          
         3CEF
   6DE0  3C11  div  *R1,R0                
   6DE2  351F  stcr *R15,4                
   6DE4  323E  ldcr *R14+,8               
   6DE6  0381  rtwp                       
   6DE8  0790  data >0790                 
   6DEA  0201  li   R1,>9f00              
         9F00
   6DEE  038C  rtwp                       
   6DF0  0190  data >0190                 
   6DF2  0201  li   R1,>9f00              
         9F00
   6DF6  0382  rtwp                       
   6DF8  0E93  data >0e93                 
   6DFA  0203  li   R3,>8d11              
         8D11
   6DFE  9202  cb   R2,R8                 
   6E00  038D  rtwp                       
   6E02  1791  jnc  >6d26                 
   6E04  0203  li   R3,>8b23              
         8B23
   6E08  9002  cb   R2,R0                 
   6E0A  019F  data >019f                 
   6E0C  0003  data >0003                 
   6E0E  8503  c    R3,*R4                
   6E10  9008  cb   R8,R0                 
   6E12  019F  data >019f                 
   6E14  0053  data >0053                 
   6E16  434F  szc  R15,R13               
   6E18  5245  szcb R5,R9                 
   6E1A  2020  coc  @>2020,R0             
         2020
   6E1E  2042  coc  R2,R1                 
   6E20  414C  szc  R12,R5                
   6E22  4C20  szc  @>2020,*R0+           
         2020
   6E26  2048  coc  R8,R1                 
   6E28  4947  szc  R7,@>4842(R5)         
         4842
   6E2C  5245  szcb R5,R9                 
   6E2E  414B  szc  R11,R5                
   6E30  2054  coc  *R4,R1                
   6E32  4852  szc  *R2,@>5521(R1)        
         5521
   6E36  2120  coc  @>4441,R4             
         4441
   6E3A  5441  szcb R1,*R1                
   6E3C  4249  szc  R9,R9                 
   6E3E  4F54  szc  *R4,*R13+             
   6E40  4943  szc  R3,@>5320(R5)         
         5320
   6E44  2053  coc  *R3,R1                
   6E46  454C  szc  R12,*R5               
   6E48  4543  szc  R3,*R5                
   6E4A  5420  szcb @>4741,*R0            
         4741
   6E4E  4D45  szc  R5,*R5+               
   6E50  3120  ldcr @>3d20,4              
         3D20
   6E54  4252  szc  *R2,R9                
   6E56  4541  szc  R1,*R5                
   6E58  4B41  szc  R1,@>5741(R13)        
         5741
   6E5C  5932  szcb *R2+,@>203d(R4)       
         203D
   6E60  2042  coc  R2,R1                 
   6E62  5245  szcb R5,R9                 
   6E64  414B  szc  R11,R5                
   6E66  5448  szcb R8,*R1                
   6E68  524F  szcb R15,R9                
   6E6A  5547  szcb R7,*R5                
   6E6C  4853  szc  *R3,@>454c(R1)        
         454C
   6E70  4543  szc  R3,*R5                
   6E72  5420  szcb @>4741,*R0            
         4741
   6E76  4D45  szc  R5,*R5+               
   6E78  2053  coc  *R3,R1                
   6E7A  5045  szcb R5,R1                 
   6E7C  4544  szc  R4,*R5                
   6E7E  3120  ldcr @>3d20,4              
         3D20
   6E82  534C  szcb R12,R13               
   6E84  4F57  szc  *R7,*R13+             
   6E86  3220  ldcr @>3d20,8              
         3D20
   6E8A  4D45  szc  R5,*R5+               
   6E8C  4449  szc  R9,*R1                
   6E8E  554D  szcb R13,*R5               
   6E90  3320  ldcr @>3d20,12             
         3D20
   6E94  4641  szc  R1,*R9                
   6E96  5354  szcb *R4,R13               
   6E98  5345  szcb R5,R13                
   6E9A  4C45  szc  R5,*R1+               
   6E9C  4354  szc  *R4,R13               
   6E9E  2054  coc  *R4,R1                
   6EA0  494C  szc  R12,@>4553(R5)        
         4553
   6EA4  3120  ldcr @>3d20,4              
         3D20
   6EA8  5649  szcb R9,*R9                
   6EAA  5349  szcb R9,R13                
   6EAC  424C  szc  R12,R9                
   6EAE  4532  szc  *R2+,*R4              
   6EB0  203D  coc  *R13+,R0              
   6EB2  2049  coc  R9,R1                 
   6EB4  4E56  szc  *R6,*R9+              
   6EB6  4953  szc  *R3,@>4942(R5)        
         4942
   6EBA  4C45  szc  R5,*R1+               
   6EBC  4741  szc  R1,*R13               
   6EBE  4D45  szc  R5,*R5+               
   6EC0  204F  coc  R15,R1                
   6EC2  5645  szcb R5,*R9                
   6EC4  5250  szcb *R0,R9                
   6EC6  5245  szcb R5,R9                 
   6EC8  5353  szcb *R3,R13               
   6ECA  3A31  mpy  *R1+,R8               
   6ECC  203D  coc  *R13+,R0              
   6ECE  2053  coc  *R3,R1                
   6ED0  414D  szc  R13,R5                
   6ED2  4520  szc  @>4741,*R4            
         4741
   6ED6  4D45  szc  R5,*R5+               
   6ED8  3220  ldcr @>3d20,8              
         3D20
   6EDC  4E45  szc  R5,*R9+               
   6EDE  5720  szcb @>4741,*R12           
         4741
   6EE2  4D45  szc  R5,*R5+               
   6EE4  3320  ldcr @>3d20,12             
         3D20
   6EE8  5155  szcb *R5,R5                
   6EEA  4954  szc  *R4,@>6279(R5)        
         6279
   6EEE  4465  szc  @>616e(R5),*R1        
         616E
   6EF2  2043  coc  R3,R1                 
   6EF4  6C65  s    @>7665(R5),*R1+       
         7665
   6EF8  6C61  s    @>6e64(R1),*R1+       
         6E64
   6EFC  7072  sb   *R2+,R1               
   6EFE  6F67  s    @>7261(R7),*R13+      
         7261
   6F02  6D6D  s    @>6564(R13),*R5+      
         6564
   6F06  7072  sb   *R2+,R1               
   6F08  6573  s    *R3+,*R5              
   6F0A  656E  s    @>7473(R14),*R5       
         7473
   6F0E  0100  data >0100                 
   6F10  0200  li   R0,>0400              
         0400
   6F14  0800  sra  R0,0                  
   6F16  0000  data >0000                 
   6F18  0000  data >0000                 
   6F1A  0000  data >0000                 
   6F1C  0000  data >0000                 
   6F1E  0000  data >0000                 
   6F20  0000  data >0000                 
   6F22  0000  data >0000                 
   6F24  0000  data >0000                 
   6F26  0000  data >0000                 
   6F28  0000  data >0000                 
   6F2A  0000  data >0000                 
   6F2C  0000  data >0000                 
   6F2E  0000  data >0000                 
   6F30  0000  data >0000                 
   6F32  0000  data >0000                 
   6F34  0008  data >0008                 
   6F36  0020  data >0020                 
   6F38  0003  data >0003                 
   6F3A  0005  data >0005                 
   6F3C  000A  data >000a                 
   6F3E  0000  data >0000                 
   6F40  0000  data >0000                 
   6F42  0000  data >0000                 
   6F44  0000  data >0000                 
   6F46  0000  data >0000                 
   6F48  0000  data >0000                 
   6F4A  0000  data >0000                 
   6F4C  0000  data >0000                 
   6F4E  0000  data >0000                 
   6F50  0000  data >0000                 
   6F52  0024  data >0024                 
   6F54  0000  data >0000                 
   6F56  0036  data >0036                 
   6F58  0000  data >0000                 
   6F5A  0005  data >0005                 
   6F5C  000A  data >000a                 
   6F5E  000F  data >000f                 
   6F60  002D  data >002d                 
   6F62  0000  data >0000                 
   6F64  0090  data >0090                 
   6F66  0000  data >0000                 
   6F68  5354  szcb *R4,R13               
   6F6A  4643  szc  R3,*R9                
   6F6C  5044  szcb R4,R1                 
   6F6E  4D52  szc  *R2,*R5+              
   6F70  71A2  sb   @>6f92(R2),R6         
         6F92
   6F74  6FA0  s    @>6f70,*R14+          
         6F70
   6F78  0345  idle                       
   6F7A  5350  szcb *R0,R13               
   6F7C  7064  sb   @>70aa(R4),R1         
         70AA
   6F80  6F7C  s    *R12+,*R13+           
   6F82  0220  ai   R0,>4600              
         4600
   6F86  71A6  sb   @>70f8(R6),R6         
         70F8
   6F8A  70F0  sb   *R0+,R3               
   6F8C  70E6  sb   @>701e(R6),R3         
         701E
   6F90  70B4  sb   *R4+,R2               
   6F92  6F86  s    R6,*R14+              
   6F94  0620  dec  @>464d                
         464D
   6F98  5848  szcb R8,@>4400(R1)         
         4400
   6F9C  7082  sb   R2,R2                 
   6F9E  710E  sb   R14,R4                
   6FA0  6F9C  s    *R12,*R14+            
   6FA2  0220  ai   R0,>4600              
         4600
   6FA6  70DA  sb   *R10,R3               
   6FA8  70BE  sb   *R14+,R2              
   6FAA  70C6  sb   R6,R3                 
   6FAC  70D0  sb   *R0,R3                
   6FAE  703B  sb   *R11+,R0              
   6FB0  6FA6  s    @>0546(R6),*R14+      
         0546
   6FB4  564D  szcb R13,*R9               
   6FB6  5820  szcb @>7162,@>6fca         
         7162
         6FCA
   6FBC  72A8  sb   @>6fb8(R8),R10        
         6FB8
   6FC0  0353  idle                       
   6FC2  2046  coc  R6,R1                 
   6FC4  7158  sb   *R8,R5                
   6FC6  6FC4  s    R4,*R15+              
   6FC8  0153  data >0153                 
   6FCA  5320  szcb @>4c6f,R12            
         4C6F
   6FCE  6164  s    @>4669(R4),R5         
         4669
   6FD2  6C65  s    @>204c(R5),*R1+       
         204C
   6FD6  6F61  s    @>644d(R1),*R13+      
         644D
   6FDA  656D  s    @>204c(R13),*R5       
         204C
   6FDE  6F61  s    @>6466(R1),*R13+      
         6466
   6FE2  6958  s    *R8,@>204c(R5)        
         204C
   6FE6  6F61  s    @>6456(R1),*R13+      
         6456
   6FEA  6172  s    *R2+,R5               
   6FEC  2053  coc  *R3,R1                
   6FEE  6176  s    *R6+,R5               
   6FF0  6546  s    R6,*R5                
   6FF2  696C  s    @>6520(R12),@>5361(R5)
         6520
         5361
   6FF8  7665  sb   @>4d65(R5),*R9        
         4D65
   6FFC  6D20  s    @>5361,*R4+           
         5361

 

 

Edited by HOME AUTOMATION
  • Like 1
Link to comment
Share on other sites

1 hour ago, HOME AUTOMATION said:

@Tursi, Is there a way to make a CALL, from your DEBUGGER, and than RETURN, like with EASYBUG?

Since the .BIN, is ROM only, I thought about mashing them together.:ponder:

 

No, unfortunately. You can change the program counter like a memory address or register (PC=xxxx), but you'll need to get back to where you started on your own, so take notes.

  • Like 2
Link to comment
Share on other sites

3 hours ago, Retrospect said:

BOUNCING BALL.txt < XB source , needs to be compiled for best results.

If anyone wants to convert my program to Assembly language so I can study it , that would be nice.  This post has nothing to do with AI, I've given up on it.  It's stupid.

 

Attached is an assembly version of your code, excluding the ACCEPT statement. I commented as much as I could.

 

Spoiler


* ###################
* #                 #
* #  BOUNCING BALL  #
* #                 #
* #  BY RETROSPECT  #
* #                 #
* ###################
* ------------------------------------------------------------------
* REGISTERS USED:
*
* r0    used for subroutines and temporary data
* r1    used for subroutines and temporary data
* r2    used for subroutines and temporary data
* r3    used for subroutines and temporary data
* r4    -- free --
* R5	BALL'S Y POSITION
* R6	BALL'S X POSITION
* R7	NUMBER TO ADD TO BALL'S Y POS
* R8	NUMBER TO ADD TO BALL'S X POS
* R9	USER DEFINED DELAY VALUE
* R10	"PING" NOISE ON OR OFF? 
* r11   branch and link return address (hardware defined this!)
* r12   -- free -- (but if we needed the keyboard or DSRs, this is the CRU register)
* R13	STORES THE VOLUME FOR THE "PING", DECREASES BY 4 EACH UPDATE
* r14   -- free --
* r15   -- free --
* TEMPR0	THE BALL'S OLD Y POSITION
* TEMPR1	THE BALL'S OLD X POSITION
* -------------------------------------------------------------------

* load with Editor/Assembler, loads at 32k
* this defines 'START' as a name you can use with LOAD AND RUN
    DEF START

* This pulls in some named addresses from E/A for us, you can also use EQUs
    REF VDPWA,VDPWD,SOUND
    
* this will store the data in scratchpad RAM. Remember this is very limited
* (only 256 bytes) and if you want to use VDP interrupts or any of the OS
* subroutines you have to preserve a lot of it. In this program we won't.
* You could also store these in the 32k RAM (low memory is good). If you ever
* want to move your code to ROM, I recommend you explicitly choose somewhere
* rather than just merging it with your main program.
* I am going to put the registers at >8300, that takes 32 bytes, so >8320 is next free
    aorg >8320

TEMPR5 bss 2        * bss "block starting with symbol" just reserves this many bytes of memory
TEMPR6 bss 2        * since we are storing 16-bit values, we want 2 bytes

* next information goes at >A000, you can use other addresses or let it automatically select
    aorg >a000

* Let's define some VDP access utilities. I'm not using the
* names here, but you could 'REF' the names in the E/A manual

* write the VDP address in R0 (as a 'write' address)
vadr
    ori r0,>4000    * make this a write address
    swpb r0         * we need to write the LSB first
    movb r0,@VDPWA  * this writes the LSB to the address register
    swpb r0         * get the MSB back
    movb r0,@VDPWA  * write the MSB to the address register (with the >40 bit set)
    andi r0,>3fff   * this turns the >4000 bit off again, restoring the original
    b *r11          * or "rt", this returns to caller
    
* copy a block of data from CPU memory to VDP memory (similar to VMBW)
* R0 = VDP address
* R1 = CPU address
* R2 = count of bytes
* R3 = temporary storage
vmbw
    mov r11,r3      * we have to save the return address from R11, the 9900 doesn't use a stack
    bl @vadr        * use the routine above to tell the VDP what address we want to write to
vmlp
    movb *r1+,@VDPWD    * move a byte from CPU memory to the VDP data address. R1 is automatically incremented
    dec r2              * count down the number of bytes
    jne vmlp            * keep looping until it's zero (jump if not equal (to zero))
    b *r3           * we saved the return address from r11 in r3, so use that to return
    
* CALL CLEAR - since we use it more than once, I am making it a function
* uses r0,r1,r2,r3
clear
* Under Editor/Assembler, the screen image table is at >0000
    mov r11,r3      * save the return from r11 to another register, as there's no stack
    clr r0          * going to be address 0
    bl @vadr        * set the VDP address
    li r1,>2000     * going to write spaces
    li r2,768       * we need 768 of them
lp150
    movb r1,@VDPWD  * write a single space to the VDP, the address automatically increments
    dec r2          * count down
    jne lp150       * loop around until the dec returns 0 (jump if not 'equal' (to zero))
    b *r3           * we saved the return address in r3, so use that to return
    
* char data for the ball
ballch
    data >3c7e,>ffff,>ffff,>7e3c
    
* color data - since we have an odd number of bytes, it's important to use
* the 'EVEN' directive to get the assembler address back to an even value
* Note that color codes are 1 less than in BASIC!!
coldat
    byte >40,>40,>40
    EVEN
    
* Start the program here
START

*100 * BOUNCING BALL PROGRAM
*110 *
*120 *
*130 *

*140 * CLEAR THE SCREEN
*150 CALL CLEAR
    bl @clear
    
*160 *
*170 *
*180 * DEFINE THE BALL & COLORS
*190 CALL CHAR(42,"3C7EFFFFFFFF7E3C")
* Under Editor/Assembler, the pattern descriptor table is at >0800.
* Each character takes 8 bytes, so character 42 is at 42*8+>0800 = >0950
* we need to store the bytes somewhere, so they are stored up above START
    li r0,>0950     * the VDP address for character 42
    li r1,ballch    * the CPU address for the pattern data
    li r2,8         * and there are 8 bytes
    bl @vmbw        * do the write

*200 CALL COLOR(2,5,1,3,5,1,4,5,1)
* Under Editor/Assembler, the color table is at >0380. Each color set is
* one byte consisting of foreground and background color. Since this
* sets sets 2-4, we can just use another vmbw with the data stored above.
* however, remember that BASIC color set 2 is NOT actually the first color
* set, we need to count all the way back to character 0. So character 42,
* which is color set 2 in BASIC, is 42/8=5 in assembly. So, we start this
* write at >0385
    li r0,>0385     * starting at >0385
    li r1,coldat    * pulling from coldat
    li r2,3         * write 3 bytes
    bl @vmbw        * and go do it

*210 *
*220 *
*230 *
*240 * VARIABLES TO START
*250 R5,R6=2
*260 R7,R8=1
*270 R10=0
* It gets a little tricky here. It's tradition (and only tradition) to
* reserve the lower registers for your function calls, thus the above used
* R0-R3. For that reason, I've renamed the variables in this program to
* use higher registers, starting at R5 to avoid confusion. You can also
* just store data directly in memory using labels, if you run out of registers,
* but we'll keep this one simple.
    li r5,2
    li r6,2
    li r7,1
    li r8,1
    clr r10

*280 *
*290 *
*300 *
*310 * ASK USER DELAY VAL
*320 DISPLAY AT(1,1):"DELAY VAL?"
*330 ACCEPT AT(3,1):R9
* this is actually a fairly complex request. There's no pre-made functions for input.
* the display is easy - you can use another vmbw. But the input, reading the keys,
* and converting each character to an ultimate number is more than I'm willing to
* do tonight. So with apologies, I am hard-coding the delay here. ;)
    li r9,>0800

*340 CALL CLEAR
    bl @clear

*350 *
*360 *
*370 *
*380 * DISPLAY THE BALL
*390 CALL HCHAR(R5,R6,42)
* this is the screen image table again, but now we need to do some math.
* since the base is 0, we don't need to add an offset, but we need to 
* multiply the rows by 32, then add the column. Interestingly, we can
* multiply by 32 more quickly and easily by shifting left by 5 (every
* shift is essentially multiplying by 2 thanks to binary math)
    mov r5,r0   * get the row into r0
    sla r0,5    * 2,4,8,16,32 -- 5 times
    a r6,r0     * add the column in - now we have the VDP address
    bl @vadr
    
* now we just have to write the asterisk
    li r1,>2A00     * character 42 in the MSB
    movb r1,@VDPWD  * write it to the VDP write data address
    
*400 *
*410 *
*420 *
*430 * KEEP THE OLD COORDS
*440 TEMPR5=R5
*450 TEMPR6=R6
* to handle non-register variables, we need to just dedicate some memory locations
* to them. I have done so up at the top, see the comments there.
* This is also where we loop around to at the bottom of the loop
l440
    mov r5,@TEMPR5      * copy r5 to the memory value
    mov r6,@TEMPR6      * and r6 too. note the '@' indicator to reference memory

*460 *
*470 *
*480 *
*490 * ADD R7 & R8
*500 R5=R5+R7
*510 R6=R6+R8
    a r7,r5         * add r7 to r5 and store in r5
    a r8,r6         * add r8 to r6 and store in r6

*520 *
*530 *
*540 *
*550 * IF AT BOUNDARIES, ADD R7 AND R8 
*560 IF R5>23 THEN R7=-R7 :: R10=1 :: R13=0
* here we can start using the compare instructions, as opposed to the previous
* assumed comparison against zero.
    ci r5,23        * compare against 23
    jle l570        * jump ahead to the label l570 if LESS or EQUAL (note: this is an unsigned test!)
    
    neg r7          * negert r7
    li r10,1        * set r10 to 1
    clr R13         * set R13 to 0
* and for any place we need to jump to, we need a label
l570

*570 IF R5<2 THEN R7=-R7 :: R10=1 :: R13=0
    ci r5,2         * compare against 2
    jhe l580        * jump if high or equal (again, note this is an unsigned test! It can't detect negative numbers)
    
    neg r7
    li r10,1
    clr r13
l580

*580 IF R6>30 THEN R8=-R8 :: R10=1 :: R13=0
    ci r6,30
    jle l590        * note how we are doing the opposite test to skip the code we don't want to execute
    
    neg r8
    li r10,1
    clr r13
l590    

*590 IF R6<2 THEN R8=-R8 :: R10=1 :: R13=0
    ci r6,2
    jhe l600
    
    neg r8
    li r10,1
    clr r13
l600   

*600 *
*610 *
*620 *
*630 * IS R10"ON"?
*640 IF R10=0 THEN 710
* To test against zero, it can be faster to use MOV than CI as it's a shorter instruction
    mov r10,r10     * test against zero
    jeq l710        * if equal, then jump ahead

*650 R13=R13+4 :: IF R13<30 THEN 670
    ai r13,4        * just add 4 to r13
    ci r13,30       * compare against 30
    jl l670         * jump if less than (unsigned test)

*660 R10=0 :: CALL SOUND(-1,110,30):: GOTO 710
* Sound is a tricky thing - more to say on the next one
* here, all we want to do is set the volume to muted, we
* don't actually care about the pitch and the duration is not important
* however, we have to manually mute both channels that we use. TI BASIC
* automatically mutes any channel you don't specify, but assembly won't!
* (Duration has to be handled manually)
    clr r10         * set r10 to 0
    li r0,>9FBF     * the volume register on the sound chip is at >9x, and volumes are 1/2 BASIC's value. F is 15. (And >Bx is channel 2)
    movb r0,@SOUND  * write the command to the sound chip
    swpb r0         * get the other command
    movb r0,@SOUND  * and send it to the sound chip too
    jmp l710        * unconditional jump

l670

*670 CALL SOUND(-150,900,R13,901,R13)
* This is a bigger deal. Because we do a nice ping and mute the sound explicitly, we can
* ignore the duration. Otherwise, you need to count it out yourself and then mute manually.
* The frequency is a tricky thing. While BASIC uses the frequency in hertz, the sound chip
* actually uses a 'sound code', or a countdown timer, which ranges from >0000 to >03FF. Higher
* numbers result in a lower tone (and >0000 wraps around and is the lowest, but might not work
* on some of the newer consoles as the newer variant of the sound chip changed that.)
* Because the pitches are fixed in this program, we COULD set them once at the start and
* never touch them again, only the volumes, but we'll go ahead and load them here for example.
* The formula to get a frequency code from Hz is 110860.8/Hz, which in this case works out to
* 123 for both channels (123.17 and 123.04). So you'll see that the sound doesn't interfere
* or make that synth noise you might have expected for that reason - the step isn't big enough.
* 908 should work though - that would give a code of 122. For now I'll match the BASIC code.
* To write a frequency directly to the sound chip takes two writes, and it's in a somewhat obtuse
* order. The first write contains the command nibble (ie: >8x for the first channel), and the
* /least/ significant nibble of the tone. The second write relies on the first to know where to
* go, and contains the two most significant nibbles (which, you'll note, is NOT a byte but
* straddles them both - see the range I listed above). This is a little confusing, yes, but it's
* just fact of life and never changes or gets more complicated, so eventually you just accept it.
* So, we have two frequencies, both are currently 123 (though you can change one to 122 if you want).
* converted to hex, that gives us >007B. The least significant nibble is >B, and the next two are >07.
* I'll load them separately here, so you can easily change the second one.
* So, the first byte we write has the command nibble, which for voice 1 tone is ">8x", plus that least
* significant nibble, so it will be >8B. Then we write the other two nibbles: >07.
* For voice 2, it's the same thing, but the tone command nibble is >Ax, so it will be >AB, >07.
    li r0,>8B07     * the two bytes to write for tone 1
    movb r0,@SOUND  * write the command and least significant nibble
    swpb r0         * get the other byte
    movb r0,@SOUND  * write the rest of it
    
    li r0,>AB07     * the two bytes for tone 2 - to change it to 122 as described above, change to >AA07
    movb r0,@SOUND  * write the command and least significant nibble
    swpb r0         * get the other byte
    movb r0,@SOUND  * write the rest of it

* now we still have to write the volumes. Normally in an assembly program you would manage the volumes
* in the range the hardware knows, which is 0-15, but since we are converting from BASIC we need to
* deal with 0-30. We can divide by 2 with a simple shift just like multiplying by 2.
* The command nibble for voice 1 volume is >9x, and voice 2 is >Bx
    mov r13,r0      * get the volume so we can work on it
    srl r0,1        * shift by 1. For right shift you select 'logical' for unsigned numbers, and 'arithmetic' for signed
    ai r0,>0090     * currently the value is in the least significant byte, so add in the command nibble
    swpb r0         * and get it up where we need it
    movb r0,@SOUND  * voice 1 volume loaded
    
    andi r0,>0F00   * since we are loading the same volume, just clear all the bits except the volume bits
    ai r0,>B000     * note we are in the MSB now because of the earlier swpb, add command for voice 2 volume
    movb r0,@SOUND  * and write it

*680 *
*690 *
*700 *

l710

*710 * KILL SOME TIME
*720 FOR DELAY=1 TO R9
*730 NEXT DELAY
* this is not so different in assembly. The main difference is it can be very, very fast. So usually,
* unless I need the fastest speeds, I put some dummy instructions inside the loop to slow it down a bit.
* I use shifts as they take 2 extra cycles for every count you shift by, up to 16, making it easy to
* adjust the speed of the delay loop by changing how much it shifts
    mov r9,r0       * get the delay value
l720
    srl r1,8        * do a dummy shift of r1 to waste time, we aren't using it right now
    dec r0          * count down the delay
    jne l720        * back up until it reaches zero

*740 *
*750 *
*760 *
*770 * DISPLAY NEW BALL
*780 CALL HCHAR(TEMPR5,TEMPR6,32,1,R5,R6,42,1)
* I don't think I knew you could do this in one call... ;)
* anyway, this should be clear by now - calculate the address, write the value
    mov @TEMPR5,r0   * get the row into r0
    sla r0,5         * 2,4,8,16,32 -- 5 times
    a @TEMPR6,r0     * add the column in - now we have the VDP address
    bl @vadr
    
* now we just have to write the space
    li r1,>2000     * character 32 in the MSB
    movb r1,@VDPWD  * write it to the VDP write data address
    
* now calculate the new address
    mov r5,r0   * get the row into r0
    sla r0,5    * 2,4,8,16,32 -- 5 times
    a r6,r0     * add the column in - now we have the VDP address
    bl @vadr
    
* and write the asterisk
    li r1,>2A00     * character 42 in the MSB
    movb r1,@VDPWD  * write it to the VDP write data address

*790 *
*800 *
*810 *
*820 * REPEAT THE LOOP
*830 GOTO 440
* If you have to go more than 127 instructions, you can't use jumps anymore, you have to branch.
* Branches can go anywhere in memory, but are slightly slower.
    b @l440

* Assemblers want you to include END - this is not the end of execution, it means end of the file!
    END


For testing, I assembled this using WinAsm994a, cause it's fast and easy. If you set the "object file" path to a Classic99 disk folder, you can directly LOAD AND RUN the executable after it builds. Just specify the filename to LOAD AND RUN, hit enter, and in this case use START as the program name. It should build in Editor/Assembler if you can get it in there but I didn't test it.

 

Note that because you don't use CALL SCREEN, the background from Editor/Assembler will be green instead of cyan. ;) Also note that it does not check the QUIT key, so you'll have to hard reset to end it. 

 

To get the interrupt, just put LIMI 2, LIMI 0 (on separate lines) in your main loop, maybe right before the final GOTO. To do a call screen, in this application you can cheat and use the vadr function I provided - just use LI R0,>870x, BL @vadr (on separate lines, where 'x' is the screen color minus 1, cause all assembly color codes are -1 from BASIC). Changing the screen color changes the internal address, so you'll need another call anyway to change it, so it's no big deal that my function will also set the address for write.

 

Going to attach a zip here with the source, the object file, AND the source for TI MOTIF. The reason for that is it was a large conversion from XB and contains most of the common utilities and examples already converted to an assembly language program, and might be useful for deeper learning/stealing functions. ;)

BOUNCING.zip

 

 

  • Like 4
  • Thanks 2
Link to comment
Share on other sites

Tursi, thankyou :)   For that code, and for your time.   I'm going to keep this code in a text file to study, and will attempt to use win994a assembler with it.

 

Yes line 780 is a bit dodgy , I actually shouldn't have done it like that as it's not very inclusive , it's a new feature on the latest XB256 / XB2.9 that allows us to use extra parenthesis on a call hchar.  Incidentally we can do the same with call gchar now.  But for those of us who aren't using the latest xb256 , say just plain vanilla xb, that's gonna throw up an error! 

 

:)

Edited by Retrospect
  • Like 3
Link to comment
Share on other sites

6 hours ago, HOME AUTOMATION said:

Using XB, I got...

 

* SYNTAX ERROR IN 780

 

:?

Sorry Automation, totally my fault!  I forgot to make this program plain vanilla XB to be more inclusive for users.  Line 780 has the new multiple parenthesis CALL HCHAR routine unique to the latest XB256 and XB 2.9 .... to use this in ordinary XB we need to break it up into two statements CALL HCHAR(TEMPR0,TEMPR1,32)::CALL HCHAR(R0,R1,42)

 

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

6 hours ago, Tursi said:

 

Attached is an assembly version of your code, excluding the ACCEPT statement. I commented as much as I could.

 

  Reveal hidden contents

 

 

* ###################
* #                 #
* #  BOUNCING BALL  #
* #                 #
* #  BY RETROSPECT  #
* #                 #
* ###################
* ------------------------------------------------------------------
* REGISTERS USED:
*
* r0    used for subroutines and temporary data
* r1    used for subroutines and temporary data
* r2    used for subroutines and temporary data
* r3    used for subroutines and temporary data
* r4    -- free --
* R5	BALL'S Y POSITION
* R6	BALL'S X POSITION
* R7	NUMBER TO ADD TO BALL'S Y POS
* R8	NUMBER TO ADD TO BALL'S X POS
* R9	USER DEFINED DELAY VALUE
* R10	"PING" NOISE ON OR OFF? 
* r11   branch and link return address (hardware defined this!)
* r12   -- free -- (but if we needed the keyboard or DSRs, this is the CRU register)
* R13	STORES THE VOLUME FOR THE "PING", DECREASES BY 4 EACH UPDATE
* r14   -- free --
* r15   -- free --
* TEMPR0	THE BALL'S OLD Y POSITION
* TEMPR1	THE BALL'S OLD X POSITION
* -------------------------------------------------------------------

* load with Editor/Assembler, loads at 32k
* this defines 'START' as a name you can use with LOAD AND RUN
    DEF START

* This pulls in some named addresses from E/A for us, you can also use EQUs
    REF VDPWA,VDPWD,SOUND
    
* this will store the data in scratchpad RAM. Remember this is very limited
* (only 256 bytes) and if you want to use VDP interrupts or any of the OS
* subroutines you have to preserve a lot of it. In this program we won't.
* You could also store these in the 32k RAM (low memory is good). If you ever
* want to move your code to ROM, I recommend you explicitly choose somewhere
* rather than just merging it with your main program.
* I am going to put the registers at >8300, that takes 32 bytes, so >8320 is next free
    aorg >8320

TEMPR5 bss 2        * bss "block starting with symbol" just reserves this many bytes of memory
TEMPR6 bss 2        * since we are storing 16-bit values, we want 2 bytes

* next information goes at >A000, you can use other addresses or let it automatically select
    aorg >a000

* Let's define some VDP access utilities. I'm not using the
* names here, but you could 'REF' the names in the E/A manual

* write the VDP address in R0 (as a 'write' address)
vadr
    ori r0,>4000    * make this a write address
    swpb r0         * we need to write the LSB first
    movb r0,@VDPWA  * this writes the LSB to the address register
    swpb r0         * get the MSB back
    movb r0,@VDPWA  * write the MSB to the address register (with the >40 bit set)
    andi r0,>3fff   * this turns the >4000 bit off again, restoring the original
    b *r11          * or "rt", this returns to caller
    
* copy a block of data from CPU memory to VDP memory (similar to VMBW)
* R0 = VDP address
* R1 = CPU address
* R2 = count of bytes
* R3 = temporary storage
vmbw
    mov r11,r3      * we have to save the return address from R11, the 9900 doesn't use a stack
    bl @vadr        * use the routine above to tell the VDP what address we want to write to
vmlp
    movb *r1+,@VDPWD    * move a byte from CPU memory to the VDP data address. R1 is automatically incremented
    dec r2              * count down the number of bytes
    jne vmlp            * keep looping until it's zero (jump if not equal (to zero))
    b *r3           * we saved the return address from r11 in r3, so use that to return
    
* CALL CLEAR - since we use it more than once, I am making it a function
* uses r0,r1,r2,r3
clear
* Under Editor/Assembler, the screen image table is at >0000
    mov r11,r3      * save the return from r11 to another register, as there's no stack
    clr r0          * going to be address 0
    bl @vadr        * set the VDP address
    li r1,>2000     * going to write spaces
    li r2,768       * we need 768 of them
lp150
    movb r1,@VDPWD  * write a single space to the VDP, the address automatically increments
    dec r2          * count down
    jne lp150       * loop around until the dec returns 0 (jump if not 'equal' (to zero))
    b *r3           * we saved the return address in r3, so use that to return
    
* char data for the ball
ballch
    data >3c7e,>ffff,>ffff,>7e3c
    
* color data - since we have an odd number of bytes, it's important to use
* the 'EVEN' directive to get the assembler address back to an even value
* Note that color codes are 1 less than in BASIC!!
coldat
    byte >40,>40,>40
    EVEN
    
* Start the program here
START

*100 * BOUNCING BALL PROGRAM
*110 *
*120 *
*130 *

*140 * CLEAR THE SCREEN
*150 CALL CLEAR
    bl @clear
    
*160 *
*170 *
*180 * DEFINE THE BALL & COLORS
*190 CALL CHAR(42,"3C7EFFFFFFFF7E3C")
* Under Editor/Assembler, the pattern descriptor table is at >0800.
* Each character takes 8 bytes, so character 42 is at 42*8+>0800 = >0950
* we need to store the bytes somewhere, so they are stored up above START
    li r0,>0950     * the VDP address for character 42
    li r1,ballch    * the CPU address for the pattern data
    li r2,8         * and there are 8 bytes
    bl @vmbw        * do the write

*200 CALL COLOR(2,5,1,3,5,1,4,5,1)
* Under Editor/Assembler, the color table is at >0380. Each color set is
* one byte consisting of foreground and background color. Since this
* sets sets 2-4, we can just use another vmbw with the data stored above.
* however, remember that BASIC color set 2 is NOT actually the first color
* set, we need to count all the way back to character 0. So character 42,
* which is color set 2 in BASIC, is 42/8=5 in assembly. So, we start this
* write at >0385
    li r0,>0385     * starting at >0385
    li r1,coldat    * pulling from coldat
    li r2,3         * write 3 bytes
    bl @vmbw        * and go do it

*210 *
*220 *
*230 *
*240 * VARIABLES TO START
*250 R5,R6=2
*260 R7,R8=1
*270 R10=0
* It gets a little tricky here. It's tradition (and only tradition) to
* reserve the lower registers for your function calls, thus the above used
* R0-R3. For that reason, I've renamed the variables in this program to
* use higher registers, starting at R5 to avoid confusion. You can also
* just store data directly in memory using labels, if you run out of registers,
* but we'll keep this one simple.
    li r5,2
    li r6,2
    li r7,1
    li r8,1
    clr r10

*280 *
*290 *
*300 *
*310 * ASK USER DELAY VAL
*320 DISPLAY AT(1,1):"DELAY VAL?"
*330 ACCEPT AT(3,1):R9
* this is actually a fairly complex request. There's no pre-made functions for input.
* the display is easy - you can use another vmbw. But the input, reading the keys,
* and converting each character to an ultimate number is more than I'm willing to
* do tonight. So with apologies, I am hard-coding the delay here. ;)
    li r9,>0800

*340 CALL CLEAR
    bl @clear

*350 *
*360 *
*370 *
*380 * DISPLAY THE BALL
*390 CALL HCHAR(R5,R6,42)
* this is the screen image table again, but now we need to do some math.
* since the base is 0, we don't need to add an offset, but we need to 
* multiply the rows by 32, then add the column. Interestingly, we can
* multiply by 32 more quickly and easily by shifting left by 5 (every
* shift is essentially multiplying by 2 thanks to binary math)
    mov r5,r0   * get the row into r0
    sla r0,5    * 2,4,8,16,32 -- 5 times
    a r6,r0     * add the column in - now we have the VDP address
    bl @vadr
    
* now we just have to write the asterisk
    li r1,>2A00     * character 42 in the MSB
    movb r1,@VDPWD  * write it to the VDP write data address
    
*400 *
*410 *
*420 *
*430 * KEEP THE OLD COORDS
*440 TEMPR5=R5
*450 TEMPR6=R6
* to handle non-register variables, we need to just dedicate some memory locations
* to them. I have done so up at the top, see the comments there.
* This is also where we loop around to at the bottom of the loop
l440
    mov r5,@TEMPR5      * copy r5 to the memory value
    mov r6,@TEMPR6      * and r6 too. note the '@' indicator to reference memory

*460 *
*470 *
*480 *
*490 * ADD R7 & R8
*500 R5=R5+R7
*510 R6=R6+R8
    a r7,r5         * add r7 to r5 and store in r5
    a r8,r6         * add r8 to r6 and store in r6

*520 *
*530 *
*540 *
*550 * IF AT BOUNDARIES, ADD R7 AND R8 
*560 IF R5>23 THEN R7=-R7 :: R10=1 :: R13=0
* here we can start using the compare instructions, as opposed to the previous
* assumed comparison against zero.
    ci r5,23        * compare against 23
    jle l570        * jump ahead to the label l570 if LESS or EQUAL (note: this is an unsigned test!)
    
    neg r7          * negert r7
    li r10,1        * set r10 to 1
    clr R13         * set R13 to 0
* and for any place we need to jump to, we need a label
l570

*570 IF R5<2 THEN R7=-R7 :: R10=1 :: R13=0
    ci r5,2         * compare against 2
    jhe l580        * jump if high or equal (again, note this is an unsigned test! It can't detect negative numbers)
    
    neg r7
    li r10,1
    clr r13
l580

*580 IF R6>30 THEN R8=-R8 :: R10=1 :: R13=0
    ci r6,30
    jle l590        * note how we are doing the opposite test to skip the code we don't want to execute
    
    neg r8
    li r10,1
    clr r13
l590    

*590 IF R6<2 THEN R8=-R8 :: R10=1 :: R13=0
    ci r6,2
    jhe l600
    
    neg r8
    li r10,1
    clr r13
l600   

*600 *
*610 *
*620 *
*630 * IS R10"ON"?
*640 IF R10=0 THEN 710
* To test against zero, it can be faster to use MOV than CI as it's a shorter instruction
    mov r10,r10     * test against zero
    jeq l710        * if equal, then jump ahead

*650 R13=R13+4 :: IF R13<30 THEN 670
    ai r13,4        * just add 4 to r13
    ci r13,30       * compare against 30
    jl l670         * jump if less than (unsigned test)

*660 R10=0 :: CALL SOUND(-1,110,30):: GOTO 710
* Sound is a tricky thing - more to say on the next one
* here, all we want to do is set the volume to muted, we
* don't actually care about the pitch and the duration is not important
* however, we have to manually mute both channels that we use. TI BASIC
* automatically mutes any channel you don't specify, but assembly won't!
* (Duration has to be handled manually)
    clr r10         * set r10 to 0
    li r0,>9FBF     * the volume register on the sound chip is at >9x, and volumes are 1/2 BASIC's value. F is 15. (And >Bx is channel 2)
    movb r0,@SOUND  * write the command to the sound chip
    swpb r0         * get the other command
    movb r0,@SOUND  * and send it to the sound chip too
    jmp l710        * unconditional jump

l670

*670 CALL SOUND(-150,900,R13,901,R13)
* This is a bigger deal. Because we do a nice ping and mute the sound explicitly, we can
* ignore the duration. Otherwise, you need to count it out yourself and then mute manually.
* The frequency is a tricky thing. While BASIC uses the frequency in hertz, the sound chip
* actually uses a 'sound code', or a countdown timer, which ranges from >0000 to >03FF. Higher
* numbers result in a lower tone (and >0000 wraps around and is the lowest, but might not work
* on some of the newer consoles as the newer variant of the sound chip changed that.)
* Because the pitches are fixed in this program, we COULD set them once at the start and
* never touch them again, only the volumes, but we'll go ahead and load them here for example.
* The formula to get a frequency code from Hz is 110860.8/Hz, which in this case works out to
* 123 for both channels (123.17 and 123.04). So you'll see that the sound doesn't interfere
* or make that synth noise you might have expected for that reason - the step isn't big enough.
* 908 should work though - that would give a code of 122. For now I'll match the BASIC code.
* To write a frequency directly to the sound chip takes two writes, and it's in a somewhat obtuse
* order. The first write contains the command nibble (ie: >8x for the first channel), and the
* /least/ significant nibble of the tone. The second write relies on the first to know where to
* go, and contains the two most significant nibbles (which, you'll note, is NOT a byte but
* straddles them both - see the range I listed above). This is a little confusing, yes, but it's
* just fact of life and never changes or gets more complicated, so eventually you just accept it.
* So, we have two frequencies, both are currently 123 (though you can change one to 122 if you want).
* converted to hex, that gives us >007B. The least significant nibble is >B, and the next two are >07.
* I'll load them separately here, so you can easily change the second one.
* So, the first byte we write has the command nibble, which for voice 1 tone is ">8x", plus that least
* significant nibble, so it will be >8B. Then we write the other two nibbles: >07.
* For voice 2, it's the same thing, but the tone command nibble is >Ax, so it will be >AB, >07.
    li r0,>8B07     * the two bytes to write for tone 1
    movb r0,@SOUND  * write the command and least significant nibble
    swpb r0         * get the other byte
    movb r0,@SOUND  * write the rest of it
    
    li r0,>AB07     * the two bytes for tone 2 - to change it to 122 as described above, change to >AA07
    movb r0,@SOUND  * write the command and least significant nibble
    swpb r0         * get the other byte
    movb r0,@SOUND  * write the rest of it

* now we still have to write the volumes. Normally in an assembly program you would manage the volumes
* in the range the hardware knows, which is 0-15, but since we are converting from BASIC we need to
* deal with 0-30. We can divide by 2 with a simple shift just like multiplying by 2.
* The command nibble for voice 1 volume is >9x, and voice 2 is >Bx
    mov r13,r0      * get the volume so we can work on it
    srl r0,1        * shift by 1. For right shift you select 'logical' for unsigned numbers, and 'arithmetic' for signed
    ai r0,>0090     * currently the value is in the least significant byte, so add in the command nibble
    swpb r0         * and get it up where we need it
    movb r0,@SOUND  * voice 1 volume loaded
    
    andi r0,>0F00   * since we are loading the same volume, just clear all the bits except the volume bits
    ai r0,>B000     * note we are in the MSB now because of the earlier swpb, add command for voice 2 volume
    movb r0,@SOUND  * and write it

*680 *
*690 *
*700 *

l710

*710 * KILL SOME TIME
*720 FOR DELAY=1 TO R9
*730 NEXT DELAY
* this is not so different in assembly. The main difference is it can be very, very fast. So usually,
* unless I need the fastest speeds, I put some dummy instructions inside the loop to slow it down a bit.
* I use shifts as they take 2 extra cycles for every count you shift by, up to 16, making it easy to
* adjust the speed of the delay loop by changing how much it shifts
    mov r9,r0       * get the delay value
l720
    srl r1,8        * do a dummy shift of r1 to waste time, we aren't using it right now
    dec r0          * count down the delay
    jne l720        * back up until it reaches zero

*740 *
*750 *
*760 *
*770 * DISPLAY NEW BALL
*780 CALL HCHAR(TEMPR5,TEMPR6,32,1,R5,R6,42,1)
* I don't think I knew you could do this in one call... ;)
* anyway, this should be clear by now - calculate the address, write the value
    mov @TEMPR5,r0   * get the row into r0
    sla r0,5         * 2,4,8,16,32 -- 5 times
    a @TEMPR6,r0     * add the column in - now we have the VDP address
    bl @vadr
    
* now we just have to write the space
    li r1,>2000     * character 32 in the MSB
    movb r1,@VDPWD  * write it to the VDP write data address
    
* now calculate the new address
    mov r5,r0   * get the row into r0
    sla r0,5    * 2,4,8,16,32 -- 5 times
    a r6,r0     * add the column in - now we have the VDP address
    bl @vadr
    
* and write the asterisk
    li r1,>2A00     * character 42 in the MSB
    movb r1,@VDPWD  * write it to the VDP write data address

*790 *
*800 *
*810 *
*820 * REPEAT THE LOOP
*830 GOTO 440
* If you have to go more than 127 instructions, you can't use jumps anymore, you have to branch.
* Branches can go anywhere in memory, but are slightly slower.
    b @l440

* Assemblers want you to include END - this is not the end of execution, it means end of the file!
    END

 


For testing, I assembled this using WinAsm994a, cause it's fast and easy. If you set the "object file" path to a Classic99 disk folder, you can directly LOAD AND RUN the executable after it builds. Just specify the filename to LOAD AND RUN, hit enter, and in this case use START as the program name. It should build in Editor/Assembler if you can get it in there but I didn't test it.

 

Note that because you don't use CALL SCREEN, the background from Editor/Assembler will be green instead of cyan. ;) Also note that it does not check the QUIT key, so you'll have to hard reset to end it. 

 

To get the interrupt, just put LIMI 2, LIMI 0 (on separate lines) in your main loop, maybe right before the final GOTO. To do a call screen, in this application you can cheat and use the vadr function I provided - just use LI R0,>870x, BL @vadr (on separate lines, where 'x' is the screen color minus 1, cause all assembly color codes are -1 from BASIC). Changing the screen color changes the internal address, so you'll need another call anyway to change it, so it's no big deal that my function will also set the address for write.

 

Going to attach a zip here with the source, the object file, AND the source for TI MOTIF. The reason for that is it was a large conversion from XB and contains most of the common utilities and examples already converted to an assembly language program, and might be useful for deeper learning/stealing functions. ;)

BOUNCING.zip 33.29 kB · 8 downloads

 

 

There are not enough superlatives to describe your generosity. 

Bravo.

  • Like 1
Link to comment
Share on other sites

11 hours ago, Tursi said:

For kicks, I took this challenge to ChatGPT. I teased it into generating a valid and reasonably efficient screen clear - and stopped there. It's rather long, so I threw the writeup over on Blogger:

 

https://tursilion.blogspot.com/2024/02/ai-code-gen.html

 

I kind of love that Skeletor config, makes reading otherwise mundane text entertaining. 

 

So far it seems like using Copilot and other LLMs for coding assistance falls into a couple of camps:

 

1. For more experienced developers, they use it to generate necessary boilerplate code and test code which saves them keystrokes/time.

2. More inexperienced or lazy developers will drop in entire blocks of generated code, causing a large amount of undesirable/unnecessary code churn, leading to violations of of  the DRY principle and a much higher occurrence of bugs.  Basically, doing it this way is a path to hell for long-term code quality and maintainability as you end up having to wholesale replace entire functions with newly generated code (as you noticed) from the AI.

 

Here is an interesting statistical study on the apparent impacts of copilot adoption in coding tooling over the last years:  https://www.gitclear.com/coding_on_copilot_data_shows_ais_downward_pressure_on_code_quality

 

Having said all that, I can see a future where the AI is fully training on your existing code-base and with specific "good behaviour" habits built it (like the DRY principle) and having it try to minimize code changes, etc. where it could become profoundly helpful, esp. on large code-bases.

 

 

  • Like 2
Link to comment
Share on other sites

6 hours ago, Tursi said:

 

Attached is an assembly version of your code, excluding the ACCEPT statement. I commented as much as I could.

 

  Reveal hidden contents

 

 

* ###################
* #                 #
* #  BOUNCING BALL  #
* #                 #
* #  BY RETROSPECT  #
* #                 #
* ###################
* ------------------------------------------------------------------
* REGISTERS USED:
*
* r0    used for subroutines and temporary data
* r1    used for subroutines and temporary data
* r2    used for subroutines and temporary data
* r3    used for subroutines and temporary data
* r4    -- free --
* R5	BALL'S Y POSITION
* R6	BALL'S X POSITION
* R7	NUMBER TO ADD TO BALL'S Y POS
* R8	NUMBER TO ADD TO BALL'S X POS
* R9	USER DEFINED DELAY VALUE
* R10	"PING" NOISE ON OR OFF? 
* r11   branch and link return address (hardware defined this!)
* r12   -- free -- (but if we needed the keyboard or DSRs, this is the CRU register)
* R13	STORES THE VOLUME FOR THE "PING", DECREASES BY 4 EACH UPDATE
* r14   -- free --
* r15   -- free --
* TEMPR0	THE BALL'S OLD Y POSITION
* TEMPR1	THE BALL'S OLD X POSITION
* -------------------------------------------------------------------

* load with Editor/Assembler, loads at 32k
* this defines 'START' as a name you can use with LOAD AND RUN
    DEF START

* This pulls in some named addresses from E/A for us, you can also use EQUs
    REF VDPWA,VDPWD,SOUND
    
* this will store the data in scratchpad RAM. Remember this is very limited
* (only 256 bytes) and if you want to use VDP interrupts or any of the OS
* subroutines you have to preserve a lot of it. In this program we won't.
* You could also store these in the 32k RAM (low memory is good). If you ever
* want to move your code to ROM, I recommend you explicitly choose somewhere
* rather than just merging it with your main program.
* I am going to put the registers at >8300, that takes 32 bytes, so >8320 is next free
    aorg >8320

TEMPR5 bss 2        * bss "block starting with symbol" just reserves this many bytes of memory
TEMPR6 bss 2        * since we are storing 16-bit values, we want 2 bytes

* next information goes at >A000, you can use other addresses or let it automatically select
    aorg >a000

* Let's define some VDP access utilities. I'm not using the
* names here, but you could 'REF' the names in the E/A manual

* write the VDP address in R0 (as a 'write' address)
vadr
    ori r0,>4000    * make this a write address
    swpb r0         * we need to write the LSB first
    movb r0,@VDPWA  * this writes the LSB to the address register
    swpb r0         * get the MSB back
    movb r0,@VDPWA  * write the MSB to the address register (with the >40 bit set)
    andi r0,>3fff   * this turns the >4000 bit off again, restoring the original
    b *r11          * or "rt", this returns to caller
    
* copy a block of data from CPU memory to VDP memory (similar to VMBW)
* R0 = VDP address
* R1 = CPU address
* R2 = count of bytes
* R3 = temporary storage
vmbw
    mov r11,r3      * we have to save the return address from R11, the 9900 doesn't use a stack
    bl @vadr        * use the routine above to tell the VDP what address we want to write to
vmlp
    movb *r1+,@VDPWD    * move a byte from CPU memory to the VDP data address. R1 is automatically incremented
    dec r2              * count down the number of bytes
    jne vmlp            * keep looping until it's zero (jump if not equal (to zero))
    b *r3           * we saved the return address from r11 in r3, so use that to return
    
* CALL CLEAR - since we use it more than once, I am making it a function
* uses r0,r1,r2,r3
clear
* Under Editor/Assembler, the screen image table is at >0000
    mov r11,r3      * save the return from r11 to another register, as there's no stack
    clr r0          * going to be address 0
    bl @vadr        * set the VDP address
    li r1,>2000     * going to write spaces
    li r2,768       * we need 768 of them
lp150
    movb r1,@VDPWD  * write a single space to the VDP, the address automatically increments
    dec r2          * count down
    jne lp150       * loop around until the dec returns 0 (jump if not 'equal' (to zero))
    b *r3           * we saved the return address in r3, so use that to return
    
* char data for the ball
ballch
    data >3c7e,>ffff,>ffff,>7e3c
    
* color data - since we have an odd number of bytes, it's important to use
* the 'EVEN' directive to get the assembler address back to an even value
* Note that color codes are 1 less than in BASIC!!
coldat
    byte >40,>40,>40
    EVEN
    
* Start the program here
START

*100 * BOUNCING BALL PROGRAM
*110 *
*120 *
*130 *

*140 * CLEAR THE SCREEN
*150 CALL CLEAR
    bl @clear
    
*160 *
*170 *
*180 * DEFINE THE BALL & COLORS
*190 CALL CHAR(42,"3C7EFFFFFFFF7E3C")
* Under Editor/Assembler, the pattern descriptor table is at >0800.
* Each character takes 8 bytes, so character 42 is at 42*8+>0800 = >0950
* we need to store the bytes somewhere, so they are stored up above START
    li r0,>0950     * the VDP address for character 42
    li r1,ballch    * the CPU address for the pattern data
    li r2,8         * and there are 8 bytes
    bl @vmbw        * do the write

*200 CALL COLOR(2,5,1,3,5,1,4,5,1)
* Under Editor/Assembler, the color table is at >0380. Each color set is
* one byte consisting of foreground and background color. Since this
* sets sets 2-4, we can just use another vmbw with the data stored above.
* however, remember that BASIC color set 2 is NOT actually the first color
* set, we need to count all the way back to character 0. So character 42,
* which is color set 2 in BASIC, is 42/8=5 in assembly. So, we start this
* write at >0385
    li r0,>0385     * starting at >0385
    li r1,coldat    * pulling from coldat
    li r2,3         * write 3 bytes
    bl @vmbw        * and go do it

*210 *
*220 *
*230 *
*240 * VARIABLES TO START
*250 R5,R6=2
*260 R7,R8=1
*270 R10=0
* It gets a little tricky here. It's tradition (and only tradition) to
* reserve the lower registers for your function calls, thus the above used
* R0-R3. For that reason, I've renamed the variables in this program to
* use higher registers, starting at R5 to avoid confusion. You can also
* just store data directly in memory using labels, if you run out of registers,
* but we'll keep this one simple.
    li r5,2
    li r6,2
    li r7,1
    li r8,1
    clr r10

*280 *
*290 *
*300 *
*310 * ASK USER DELAY VAL
*320 DISPLAY AT(1,1):"DELAY VAL?"
*330 ACCEPT AT(3,1):R9
* this is actually a fairly complex request. There's no pre-made functions for input.
* the display is easy - you can use another vmbw. But the input, reading the keys,
* and converting each character to an ultimate number is more than I'm willing to
* do tonight. So with apologies, I am hard-coding the delay here. ;)
    li r9,>0800

*340 CALL CLEAR
    bl @clear

*350 *
*360 *
*370 *
*380 * DISPLAY THE BALL
*390 CALL HCHAR(R5,R6,42)
* this is the screen image table again, but now we need to do some math.
* since the base is 0, we don't need to add an offset, but we need to 
* multiply the rows by 32, then add the column. Interestingly, we can
* multiply by 32 more quickly and easily by shifting left by 5 (every
* shift is essentially multiplying by 2 thanks to binary math)
    mov r5,r0   * get the row into r0
    sla r0,5    * 2,4,8,16,32 -- 5 times
    a r6,r0     * add the column in - now we have the VDP address
    bl @vadr
    
* now we just have to write the asterisk
    li r1,>2A00     * character 42 in the MSB
    movb r1,@VDPWD  * write it to the VDP write data address
    
*400 *
*410 *
*420 *
*430 * KEEP THE OLD COORDS
*440 TEMPR5=R5
*450 TEMPR6=R6
* to handle non-register variables, we need to just dedicate some memory locations
* to them. I have done so up at the top, see the comments there.
* This is also where we loop around to at the bottom of the loop
l440
    mov r5,@TEMPR5      * copy r5 to the memory value
    mov r6,@TEMPR6      * and r6 too. note the '@' indicator to reference memory

*460 *
*470 *
*480 *
*490 * ADD R7 & R8
*500 R5=R5+R7
*510 R6=R6+R8
    a r7,r5         * add r7 to r5 and store in r5
    a r8,r6         * add r8 to r6 and store in r6

*520 *
*530 *
*540 *
*550 * IF AT BOUNDARIES, ADD R7 AND R8 
*560 IF R5>23 THEN R7=-R7 :: R10=1 :: R13=0
* here we can start using the compare instructions, as opposed to the previous
* assumed comparison against zero.
    ci r5,23        * compare against 23
    jle l570        * jump ahead to the label l570 if LESS or EQUAL (note: this is an unsigned test!)
    
    neg r7          * negert r7
    li r10,1        * set r10 to 1
    clr R13         * set R13 to 0
* and for any place we need to jump to, we need a label
l570

*570 IF R5<2 THEN R7=-R7 :: R10=1 :: R13=0
    ci r5,2         * compare against 2
    jhe l580        * jump if high or equal (again, note this is an unsigned test! It can't detect negative numbers)
    
    neg r7
    li r10,1
    clr r13
l580

*580 IF R6>30 THEN R8=-R8 :: R10=1 :: R13=0
    ci r6,30
    jle l590        * note how we are doing the opposite test to skip the code we don't want to execute
    
    neg r8
    li r10,1
    clr r13
l590    

*590 IF R6<2 THEN R8=-R8 :: R10=1 :: R13=0
    ci r6,2
    jhe l600
    
    neg r8
    li r10,1
    clr r13
l600   

*600 *
*610 *
*620 *
*630 * IS R10"ON"?
*640 IF R10=0 THEN 710
* To test against zero, it can be faster to use MOV than CI as it's a shorter instruction
    mov r10,r10     * test against zero
    jeq l710        * if equal, then jump ahead

*650 R13=R13+4 :: IF R13<30 THEN 670
    ai r13,4        * just add 4 to r13
    ci r13,30       * compare against 30
    jl l670         * jump if less than (unsigned test)

*660 R10=0 :: CALL SOUND(-1,110,30):: GOTO 710
* Sound is a tricky thing - more to say on the next one
* here, all we want to do is set the volume to muted, we
* don't actually care about the pitch and the duration is not important
* however, we have to manually mute both channels that we use. TI BASIC
* automatically mutes any channel you don't specify, but assembly won't!
* (Duration has to be handled manually)
    clr r10         * set r10 to 0
    li r0,>9FBF     * the volume register on the sound chip is at >9x, and volumes are 1/2 BASIC's value. F is 15. (And >Bx is channel 2)
    movb r0,@SOUND  * write the command to the sound chip
    swpb r0         * get the other command
    movb r0,@SOUND  * and send it to the sound chip too
    jmp l710        * unconditional jump

l670

*670 CALL SOUND(-150,900,R13,901,R13)
* This is a bigger deal. Because we do a nice ping and mute the sound explicitly, we can
* ignore the duration. Otherwise, you need to count it out yourself and then mute manually.
* The frequency is a tricky thing. While BASIC uses the frequency in hertz, the sound chip
* actually uses a 'sound code', or a countdown timer, which ranges from >0000 to >03FF. Higher
* numbers result in a lower tone (and >0000 wraps around and is the lowest, but might not work
* on some of the newer consoles as the newer variant of the sound chip changed that.)
* Because the pitches are fixed in this program, we COULD set them once at the start and
* never touch them again, only the volumes, but we'll go ahead and load them here for example.
* The formula to get a frequency code from Hz is 110860.8/Hz, which in this case works out to
* 123 for both channels (123.17 and 123.04). So you'll see that the sound doesn't interfere
* or make that synth noise you might have expected for that reason - the step isn't big enough.
* 908 should work though - that would give a code of 122. For now I'll match the BASIC code.
* To write a frequency directly to the sound chip takes two writes, and it's in a somewhat obtuse
* order. The first write contains the command nibble (ie: >8x for the first channel), and the
* /least/ significant nibble of the tone. The second write relies on the first to know where to
* go, and contains the two most significant nibbles (which, you'll note, is NOT a byte but
* straddles them both - see the range I listed above). This is a little confusing, yes, but it's
* just fact of life and never changes or gets more complicated, so eventually you just accept it.
* So, we have two frequencies, both are currently 123 (though you can change one to 122 if you want).
* converted to hex, that gives us >007B. The least significant nibble is >B, and the next two are >07.
* I'll load them separately here, so you can easily change the second one.
* So, the first byte we write has the command nibble, which for voice 1 tone is ">8x", plus that least
* significant nibble, so it will be >8B. Then we write the other two nibbles: >07.
* For voice 2, it's the same thing, but the tone command nibble is >Ax, so it will be >AB, >07.
    li r0,>8B07     * the two bytes to write for tone 1
    movb r0,@SOUND  * write the command and least significant nibble
    swpb r0         * get the other byte
    movb r0,@SOUND  * write the rest of it
    
    li r0,>AB07     * the two bytes for tone 2 - to change it to 122 as described above, change to >AA07
    movb r0,@SOUND  * write the command and least significant nibble
    swpb r0         * get the other byte
    movb r0,@SOUND  * write the rest of it

* now we still have to write the volumes. Normally in an assembly program you would manage the volumes
* in the range the hardware knows, which is 0-15, but since we are converting from BASIC we need to
* deal with 0-30. We can divide by 2 with a simple shift just like multiplying by 2.
* The command nibble for voice 1 volume is >9x, and voice 2 is >Bx
    mov r13,r0      * get the volume so we can work on it
    srl r0,1        * shift by 1. For right shift you select 'logical' for unsigned numbers, and 'arithmetic' for signed
    ai r0,>0090     * currently the value is in the least significant byte, so add in the command nibble
    swpb r0         * and get it up where we need it
    movb r0,@SOUND  * voice 1 volume loaded
    
    andi r0,>0F00   * since we are loading the same volume, just clear all the bits except the volume bits
    ai r0,>B000     * note we are in the MSB now because of the earlier swpb, add command for voice 2 volume
    movb r0,@SOUND  * and write it

*680 *
*690 *
*700 *

l710

*710 * KILL SOME TIME
*720 FOR DELAY=1 TO R9
*730 NEXT DELAY
* this is not so different in assembly. The main difference is it can be very, very fast. So usually,
* unless I need the fastest speeds, I put some dummy instructions inside the loop to slow it down a bit.
* I use shifts as they take 2 extra cycles for every count you shift by, up to 16, making it easy to
* adjust the speed of the delay loop by changing how much it shifts
    mov r9,r0       * get the delay value
l720
    srl r1,8        * do a dummy shift of r1 to waste time, we aren't using it right now
    dec r0          * count down the delay
    jne l720        * back up until it reaches zero

*740 *
*750 *
*760 *
*770 * DISPLAY NEW BALL
*780 CALL HCHAR(TEMPR5,TEMPR6,32,1,R5,R6,42,1)
* I don't think I knew you could do this in one call... ;)
* anyway, this should be clear by now - calculate the address, write the value
    mov @TEMPR5,r0   * get the row into r0
    sla r0,5         * 2,4,8,16,32 -- 5 times
    a @TEMPR6,r0     * add the column in - now we have the VDP address
    bl @vadr
    
* now we just have to write the space
    li r1,>2000     * character 32 in the MSB
    movb r1,@VDPWD  * write it to the VDP write data address
    
* now calculate the new address
    mov r5,r0   * get the row into r0
    sla r0,5    * 2,4,8,16,32 -- 5 times
    a r6,r0     * add the column in - now we have the VDP address
    bl @vadr
    
* and write the asterisk
    li r1,>2A00     * character 42 in the MSB
    movb r1,@VDPWD  * write it to the VDP write data address

*790 *
*800 *
*810 *
*820 * REPEAT THE LOOP
*830 GOTO 440
* If you have to go more than 127 instructions, you can't use jumps anymore, you have to branch.
* Branches can go anywhere in memory, but are slightly slower.
    b @l440

* Assemblers want you to include END - this is not the end of execution, it means end of the file!
    END

 


For testing, I assembled this using WinAsm994a, cause it's fast and easy. If you set the "object file" path to a Classic99 disk folder, you can directly LOAD AND RUN the executable after it builds. Just specify the filename to LOAD AND RUN, hit enter, and in this case use START as the program name. It should build in Editor/Assembler if you can get it in there but I didn't test it.

 

Note that because you don't use CALL SCREEN, the background from Editor/Assembler will be green instead of cyan. ;) Also note that it does not check the QUIT key, so you'll have to hard reset to end it. 

 

To get the interrupt, just put LIMI 2, LIMI 0 (on separate lines) in your main loop, maybe right before the final GOTO. To do a call screen, in this application you can cheat and use the vadr function I provided - just use LI R0,>870x, BL @vadr (on separate lines, where 'x' is the screen color minus 1, cause all assembly color codes are -1 from BASIC). Changing the screen color changes the internal address, so you'll need another call anyway to change it, so it's no big deal that my function will also set the address for write.

 

Going to attach a zip here with the source, the object file, AND the source for TI MOTIF. The reason for that is it was a large conversion from XB and contains most of the common utilities and examples already converted to an assembly language program, and might be useful for deeper learning/stealing functions. ;)

BOUNCING.zip 33.29 kB · 8 downloads

 

 

Amazing!  Can we call this new forum code-generation feature "TursiGPT"? ;) 

  • Like 1
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...