The Gigatron project

Discussion of chess software programming and technical issues.

Moderators: hgm, Harvey Williamson, bob

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
User avatar
hgm
Posts: 22311
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: The Gigatron project

Post by hgm » Sun Dec 10, 2017 11:32 am

stegemma wrote:For the screen output, why not use a char map instead of full graphics? It would avoid a lot of problems in the code, I think. maybe a double mode can be implemented, with a little circuit (the single pixel becomes an index in memory+an index for row/col).
I am not sure which problem you are trying to solve. What you propose would relieve you in no way from the obligation to generate sync pulses with cycle-accurate timing, and thus count all cycles consumed by the program. Of course if you would have an independently functioning video interface, you would not have that problem. But what you propose doesn't provide that, and such an interface would approximately have the same complexity as the entire CPU.

User avatar
hgm
Posts: 22311
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: The Gigatron project

Post by hgm » Sun Dec 10, 2017 11:51 am

I now use the coding strategy to store almost all tables vertically, and index them through the Y register. For 2-dimensional tables, such as leaperAttacks[stm][square] and neighbor[direction][square], each board-sized layer (player or direction) would be stored vertically, and the first index would go in the X register, to identify the layer in an [Y,X] addressing mode. (If the loop over layers is not unrolled, which would turn each layer index into a constant.)

Only tables that are indexed by bit sets will be stored horizontally. (Because they sometimes need more than 128 entries, and because they start at index 0, and I want to leave some completely free pages at the low end of memory.

For local variables I will use the zero page, and copy / restore that to a save place (software stack) when recursing. With the unmodified Gigatron this sseems the fastest way to do it; accessing variables directly on a stack would require loading the frame pointer in Y for every access, and usually there are may accesses for a single recursive call. Y is very heavily used already, and usig it to address a local variable would probably destroy something useful in there that would have to be reloaded afterwards. As long as there is no mode [const,X], (one possible hardware extension), X is useless as frame pointer. The problem would be best solved by a zero-page relocatable through a Z register, but that requires an even more complex hardware extension. And the code using the zero page for local variables would work without modification after such an extesion, after replacing the code to save the zero page to a stack would be replaced by simply loading the Z register with a fresh page address.

This produces code (for the capture-generating C code I posted above) like:

Code: Select all

05A8      /* Capture generation */
05A8 00FC pawnStep = sliderAttacks  // uses 4 unused entries in sliderAttacks
05A8                PAGE
0600      moveLoop: 
0600 0011             LDA #KING+1    // piece list starts at King
0601 B555             SUB stm,Y
0602 09F2             LDA Y:next     // victim = next[KING+1-stm] // but we already checked for King capture, so skip
0603 D55F             TAY z_victim   // to Y and memory
0604 09EE             LDA Y:location // location[victim]
0605      
0605       xlp0:    
0605 D55A               TAY z_to           // Y = to = location[victim]
0606 00FE               LDA #leaperAttacks
0607 9155               ADD stm,X          // X = leapAttacks[stm]
0608 0D00               LDA [Y:X]          // leapSet = leapAttacks[stm][to]
0609 F01F               BEQ noleaps        // while(leapSet) {
060A D100               TAX leapSet
060B      
060B         xlp1:  
060B 1409                 LDA set2leaper:X   // piece = set2leaper[leapSet]
060C 0D00
060C F413                 BGE isPawn         // if&#40;piece < 0&#41;
060D 9555                 ADD stm,Y          // piece += stm
060E      
060E            isPiece&#58;
060E 207F                   AND #$7F         // piece &= 0x7F          // strip piece/pawn flag
060F D55E                   TAY z_piece      // writes to Y and RAM
0610 09EE                   LDA Y&#58;location   // from = location&#91;piece&#93;
0611 FC18                   BRA doleap
0612 C259                   STA z_from
0613      
0613            isPawn&#58;                      // else
0613 09FC                   LDA Y&#58;pawnStep   // step = pawnStep&#91;piece&#93;
0614 815A                   ADD z_to
0615 D559                   TAY z_from       // from = to + step
0616 09FF                   LDA Y&#58;board
0617 C25E                   STA z_piece      // piece = board&#91;from&#93;
0618      
0618            doleap&#58;
0618 FC49                 BRA SearchMove     // if&#40;SearchMove&#40;)) goto cutoff; /* does not return here on cutoff */
0619 011A                 LDA here+1
061A      
061A 0100                 LDA leapSet        // leapSet = leapSet & leapSet-1
061B A001                 SUB #1
061C 2100                 AND leapSet
061D EC0B                 BNE xlp1
061E D100                 TAX leapSet        // writes to X and RAM
                                             // &#125;
061F           
                      // now do sliders
061F        noleaps&#58;
061F 00FC               LDA #sliderAttacks
0620 9155               ADD stm,X           // X = slideAttacks&#91;stm&#93;
0621 155A               LDY z_to
0622 0D00               LDA &#91;Y&#58;X&#93;           // slideSet = slideAttacks&#91;stm&#93;&#91;to&#93;
0623 F043               BEQ noslides        // if&#40;slideSet&#41;
0624 D100               TAX slideSet        // to X and memory
0625      
0625 0000                 LDA #0
0626 C200                 STA attackers     // attackers = 0   // will collect slider attackers
0627      
0627            xlp2&#58;                       // do &#123;
0627 1408                   LDA set2dir&#58;X   // views = set2dir&#91;slideSet&#93;  // required layer of neighbor&#91;dir&#93;&#91;sqr&#93; table
0628 0D00
0628 1200                   LDX A
0629 155A                   LDY z_to
062A 0D00                   LDA &#91;Y&#58;X&#93;       // from = views&#91;to&#93;
062B 1600                   LDY A
062C 09FF                   LDA Y&#58;board     // piece = board&#91;from&#93;
062D 1600                   LDY A
062E 09EC                   LDA Y&#58;attBit    // attackers |= attBit&#91;piece&#93;
062F 4100                   ORA attackers
0630 C200                   STA attackers
0631 0100                   LDA slideSet    // slideSet = stripBit&#91;slideSet&#93;
0632 A001                   SUB #1
0633 2100                   AND slideSet
0634 EC27                   BNE xlp2        // &#125; while&#40;slideSet&#41;
0635 D100                   TAX slideSet
0636      
0636 1100                 LDX attackers
0637            xlp3&#58;                        // do &#123;
0637 140A                   LDA set2slider&#58;X // piece = set2slider&#91;attackers&#93;
0638 0D00
0638 8155                   ADD stm
0639 D55E                   TAY z_piece
063A 09EE                   LDA Y&#58;location   // from = location&#91;piece&#93;
063B C259                   STA z_from
063C FC49                   BRA SearchMove   // if&#40;SearchMove&#40;)) goto cutoff
063D 003E                   LDA #here+1
063E 0100                   LDA attackers    // attackers = stripBit&#91;attackers&#93;
063F A001                   SUB #1
0640 2100                   AND attackers
0641 EC37                   BNE xlp3         // &#125; while&#40;attackers&#41;
0642 D100                   TAX attackers
0643      
0643        noslides&#58;
0643 155F               LDY z_victim         // victim = next&#91;victim&#93;
0644 09F2               LDA Y&#58;next
0645 D55F               TAY z_victim         // to Y and memory
0646 A100               SUB threshold
0647 E405               BGT xlp0             // while&#40;victim > futilityThreshold&#41;
0648 09EE               LDA Y&#58;location
0649      futile&#58;   

User avatar
stegemma
Posts: 842
Joined: Mon Aug 10, 2009 8:05 pm
Location: Italy
Contact:

Re: The Gigatron project

Post by stegemma » Sun Dec 10, 2017 12:24 pm

hgm wrote:
stegemma wrote:For the screen output, why not use a char map instead of full graphics? It would avoid a lot of problems in the code, I think. maybe a double mode can be implemented, with a little circuit (the single pixel becomes an index in memory+an index for row/col).
I am not sure which problem you are trying to solve. What you propose would relieve you in no way from the obligation to generate sync pulses with cycle-accurate timing, and thus count all cycles consumed by the program. Of course if you would have an independently functioning video interface, you would not have that problem. But what you propose doesn't provide that, and such an interface would approximately have the same complexity as the entire CPU.
With a characters map you don't waste so much memory and you can put code almost everywhere, after the video memory. Maybe it is possible to have a separated video+characters map memory, that can be used for video displaying, leaving full access to program memory. This could avoid interleaving code with video displaying, almost while you're not accessing video memory. Of course I'm not an engeneer and I have no idea if this is possible or not, in this specific project.
Author of Drago, Raffaela, Freccia, Satana, Sabrina.
http://www.linformatica.com

User avatar
hgm
Posts: 22311
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: The Gigatron project

Post by hgm » Sun Dec 10, 2017 8:44 pm

The problem is not memory. The chess board I posted only takes 5KB out of 32KB to store it pixel-wise. The problem is that the CPU is fully tied up sending the video signal to the output port, as the video pixel frequency is exactly the same as the instruction execution rate. So every instruction must send a new pixel to the output. This could be reduced, as you suggest, by adding hardware behind the output port to translate an output to multiple pixes, one line from a lookup table of a character generator ROM. A simpler way to do this would be to abandon color, and make the output a shift register, so that every output operation can deliver 6 pixels. (Two output lines need to be reserved for the sync pulses.) Then you would only have to supply an output every 6 instructions.

But 6 instructions is not enough to do a task switch forth and back between video generation and something else. The video output uses both X and Y register, so that you would have to save and reload those if your other task wanted to use them, which already takes more than the 5 instructions you have in between. So you could still only do something else than video generation on a scan line that is entirely dark. There the only task is to generate the sync pulse at the end of the line, and you have about 160 instructions for useful work before you need to generate one. But you will have to generate it exactly in time, meaning yu u must be sure to execute exactly the right number of instructions befor you make it. Which is difficult if your code contains loops.

User avatar
hgm
Posts: 22311
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: The Gigatron project

Post by hgm » Sun Dec 10, 2017 10:10 pm

Some more sample code, this time for the routine that updates the attack map for the moves of the moved or captured piece. Basically it is just a switch on (colored) piece type, which then changes the attack flags at all capture targets.

Code: Select all

045F      /* Attack generation&#58; ultimately what can capture what is determined here.   */
045F      /* The attacks of a piece of a given type from a given square are recorded   */
045F      /* in the entries of the applicable attack map for the attacked square,      */
045F      /* as a bit flag. The update routine flips those flags, and can thus be      */
045F      /* used both to apply and to remove them. This will have to be done          */
045F      /* to remove the attacks of the moved piece from its old location; add those */
045F      /* from its new location, and remove the attacks of the captured piece.      */
045F      /* That is just for 3 pieces, but it has to be done again for UnMake&#40;)       */
045F      /* This does not sound much more efficient as generating the moves for all   */
045F      /* pieces from scratch. But the gain comes from the fact that it can be      */
045F      /* done one ply in advance, when the move was made from the grandparent,     */
045F      /* as the attacks only become relevant when we can move the piece again.     */
045F      /* So we will avoid doing this in nodes that have no grand children.         */
045F      /* Still, it is time-critical code, and for that reason loops are unrolled.  */
045F      
045F 0001 dbit0 = 1
045F 0002 dbit1 = 2
045F 0004 dbit2 = 4
045F 0008 dbit3 = 8
045F 0010 dbit4 = $10
045F 0020 dbit5 = $20
045F 0040 dbit6 = $40
045F 0080 dbit7 = $80
045F      
045F 000A step1 = WIDTH
045F 0001 step3 = 1
045F 0009 step5 = WIDTH - 1
045F 000B step7 = WIDTH + 1
045F FFF6 step2 = -step1
045F FFFF step4 = -step3
045F FFF7 step6 = -step5
045F FFF5 step8 = -step7
045F      
045F 000C hip1 = WIDTH + 2
045F 0015 hip2 = 2*WIDTH+1
045F 0013 hip3 = 2*WIDTH-1
045F 0008 hip4 = WIDTH - 2
045F FFF4 hip5 = -hip1
045F FFEB hip6 = -hip2
045F FFED hip7 = -hip3
045F FFF8 hip8 = -hip4
045F      
                    // parameters
045F 0042 g_sqr = tmp
045F 0043 g_bit = tmp+1
045F 0044 g_piece = tmp+2
045F      
045F                PAGE
0500      FlipAttacks&#58;
0500 C241           STA retad
0501 1544           LDY g_piece
0502 09E7           LDA Y&#58;attgen  // get its move-gen routine
0503 FE00           BRA &#91;A&#93;       // and execute it
0504      
0504      QueenWhite&#58;
0504 FC12           BRA OrthSlide
0505 10FC           LDX #sliderAttacks
0506      QueenBlack&#58;
0506 10FD           LDX #sliderAttacks+1
0507      QueenSlide&#58;
0507 0141           LDA retad
0508 C242           STA tmp        // set up DiagSlide to return here
0509 000C           LDA #here+3
050A C241           STA retad
050B FC2D           BRA DiagSlide
050C 0142           LDA tmp
050D FC12           BRA OrthSlide  // and then continue with OrthSlide
050E C241           STA retad
050F      
                    // Rook
050F      OrthWhite&#58;
050F FC12           BRA OrthSlide
0510 10FC           LDX #sliderAttacks
0511      OrthBlack&#58;
0511 10FD           LDX #sliderAttacks+1
0512      OrthSlide&#58;
0512 1542           LDY g_sqr
0513 0900           LDA Y&#58;views0u
0514 0D00           LDA &#91;Y&#58;X&#93;
0515 6001           XOR #dbit0
0516 CE00           STA &#91;Y&#58;X&#93;
0517 1542           LDY g_sqr
0518 0900           LDA Y&#58;views0d
0519 1600           LDY A
051A 0D00           LDA &#91;Y&#58;X&#93;
051B 6002           XOR #dbit1
051C CE00           STA &#91;Y&#58;X&#93;
051D 1542           LDY g_sqr
051E 0900           LDA Y&#58;views1u
051F 1600           LDY A
0520 0D00           LDA &#91;Y&#58;X&#93;
0521 6004           XOR #dbit2
0522 CE00           STA &#91;Y&#58;X&#93;
0523 1542           LDY g_sqr
0524 0900           LDA Y&#58;views1d
0525 1600           LDY A
0526 0D00           LDA &#91;Y&#58;X&#93;
0527 6008           XOR #dbit3
0528 FD41           BRA &#91;retad&#93;
0529 CE00           STA &#91;Y&#58;X&#93;
052A      
                    // Bishops
052A      DiagWhite&#58;
052A FC12           BRA OrthSlide
052B 10FC           LDX #sliderAttacks
052C      DiagBlack&#58;
052C 10FD           LDX #sliderAttacks+1
052D      DiagSlide&#58;
052D 1542           LDY g_sqr
052E 0900           LDA Y&#58;views2u
052F 1600           LDY A
0530 0D00           LDA &#91;Y&#58;X&#93;
0531 6010           XOR #dbit4
0532 CE00           STA &#91;Y&#58;X&#93;
0533 1542           LDY g_sqr
0534 0900           LDA Y&#58;views2d
0535 1600           LDY A
0536 0D00           LDA &#91;Y&#58;X&#93;
0537 6020           XOR #dbit5
0538 CE00           STA &#91;Y&#58;X&#93;
0539 1542           LDY g_sqr
053A 0900           LDA Y&#58;views3u
053B 1600           LDY A
053C 0D00           LDA &#91;Y&#58;X&#93;
053D 6040           XOR #dbit6
053E CE00           STA &#91;Y&#58;X&#93;
053F 1542           LDY g_sqr
0540 0900           LDA Y&#58;views3d
0541 1600           LDY A
0542 0D00           LDA &#91;Y&#58;X&#93;
0543 6080           XOR #dbit7
0544 FD41           BRA &#91;retad&#93;
0545 CE00           STA &#91;Y&#58;X&#93;
0546      
0546      
0546      /* Leaper attacks&#58; King and each Knight has its own bit in the leaper attack map. */
0546      /* Pawn attacks are just marked by whether they come from the left or right.      */
0546      /* The attacks are always recorded, even for empty squares. So we don't have to   */
0546      /* worry when a square gets occupied. Even off-board attacks are recorded         */
0546      /* &#40;the map includes a 2-wide guard band&#41;, so we don't have to test whether       */
0546      /* the leaper targets are off board.                                              */
0546      KnightWhite&#58;
0546 FC12           BRA OrthSlide
0547 10FE           LDX #leaperAttacks
0548      KnightBlack&#58;
0548 10FF           LDX #leaperAttacks+1
0549      KnightAttacks&#58;
0549 1544           LDY g_piece
054A 09EC           LDA Y&#58;attBit
054B C243           STA g_bit
054C 0142           LDA g_sqr
054D 940C           ADD #hip1,Y
054E 0D00           LDA &#91;Y&#58;X&#93;
054F 6143           XOR g_bit
0550 CE00           STA &#91;Y&#58;X&#93;
0551 0142           LDA g_sqr
0552 9415           ADD #hip2,Y
0553 0D00           LDA &#91;Y&#58;X&#93;
0554 6143           XOR g_bit
0555 CE00           STA &#91;Y&#58;X&#93;
0556 0142           LDA g_sqr
0557 9413           ADD #hip3,Y
0558 0D00           LDA &#91;Y&#58;X&#93;
0559 6143           XOR g_bit
055A CE00           STA &#91;Y&#58;X&#93;
055B 0142           LDA g_sqr
055C 9408           ADD #hip4,Y
055D 0D00           LDA &#91;Y&#58;X&#93;
055E 6143           XOR g_bit
055F CE00           STA &#91;Y&#58;X&#93;
0560 0142           LDA g_sqr
0561 94F4           ADD #hip5,Y
0562 0D00           LDA &#91;Y&#58;X&#93;
0563 6143           XOR g_bit
0564 CE00           STA &#91;Y&#58;X&#93;
0565 0142           LDA g_sqr
0566 94EB           ADD #hip6,Y
0567 0D00           LDA &#91;Y&#58;X&#93;
0568 6143           XOR g_bit
0569 CE00           STA &#91;Y&#58;X&#93;
056A 0142           LDA g_sqr
056B 94ED           ADD #hip7,Y
056C 0D00           LDA &#91;Y&#58;X&#93;
056D 6143           XOR g_bit
056E CE00           STA &#91;Y&#58;X&#93;
056F 0142           LDA g_sqr
0570 94F8           ADD #hip8,Y
0571 0D00           LDA &#91;Y&#58;X&#93;
0572 6143           XOR g_bit
0573 FD41           BRA &#91;retad&#93;
0574 CE00           STA &#91;Y&#58;X&#93;
0575      
0575      KingWhite&#58;
0575 FC12           BRA OrthSlide
0576 10FE           LDX #leaperAttacks
0577      KingBlack&#58;
0577 10FF           LDX #leaperAttacks+1
0578      KingAttacks&#58;
0578 0142           LDA g_sqr
0579 940A           ADD #step1,Y
057A 0D00           LDA &#91;Y&#58;X&#93;
057B 6040           XOR #$40
057C CE00           STA &#91;Y&#58;X&#93;
057D 0142           LDA g_sqr
057E 94F6           ADD #step2,Y
057F 0D00           LDA &#91;Y&#58;X&#93;
0580 6040           XOR #$40
0581 CE00           STA &#91;Y&#58;X&#93;
0582 0142           LDA g_sqr
0583 9401           ADD #step3,Y
0584 0D00           LDA &#91;Y&#58;X&#93;
0585 6040           XOR #$40
0586 CE00           STA &#91;Y&#58;X&#93;
0587 0142           LDA g_sqr
0588 94FF           ADD #step4,Y
0589 0D00           LDA &#91;Y&#58;X&#93;
058A 6040           XOR #$40
058B CE00           STA &#91;Y&#58;X&#93;
058C 0142           LDA g_sqr
058D 9409           ADD #step5,Y
058E 0D00           LDA &#91;Y&#58;X&#93;
058F 6040           XOR #$40
0590 CE00           STA &#91;Y&#58;X&#93;
0591 0142           LDA g_sqr
0592 94F7           ADD #step6,Y
0593 0D00           LDA &#91;Y&#58;X&#93;
0594 6040           XOR #$40
0595 CE00           STA &#91;Y&#58;X&#93;
0596 0142           LDA g_sqr
0597 940B           ADD #step7,Y
0598 0D00           LDA &#91;Y&#58;X&#93;
0599 6040           XOR #$40
059A CE00           STA &#91;Y&#58;X&#93;
059B 0142           LDA g_sqr
059C 94F5           ADD #step8,Y
059D 0D00           LDA &#91;Y&#58;X&#93;
059E 6040           XOR #$40
059F FD41           BRA &#91;retad&#93;
05A0 CE00           STA &#91;Y&#58;X&#93;
05A1      
05A1      WhitePawn&#58;
05A1 10FE           LDX #leaperAttacks
05A2 0142           LDA g_sqr
05A3 9409           ADD #step5,Y
05A4 0D00           LDA &#91;Y&#58;X&#93;
05A5 6001           XOR #1
05A6 CE00           STA &#91;Y&#58;X&#93;
05A7 0142           LDA g_sqr
05A8 940B           ADD #step7,Y
05A9 0D00           LDA &#91;Y&#58;X&#93;
05AA 6002           XOR #2
05AB FD41           BRA &#91;retad&#93;
05AC CE00           STA &#91;Y&#58;X&#93;
05AD      
05AD      BlackPawn&#58;
05AD 10FF           LDX #leaperAttacks+1
05AE 0142           LDA g_sqr
05AF 94F7           ADD #step6,Y
05B0 0D00           LDA &#91;Y&#58;X&#93;
05B1 6001           XOR #1
05B2 CE00           STA &#91;Y&#58;X&#93;
05B3 0142           LDA g_sqr
05B4 94F5           ADD #step8,Y
05B5 0D00           LDA &#91;Y&#58;X&#93;
05B6 6002           XOR #2
05B7 FD41           BRA &#91;retad&#93;
05B8 CE00           STA &#91;Y&#58;X&#93;
05B9      

Ras
Posts: 951
Joined: Tue Aug 30, 2016 6:19 pm
Contact:

Re: The Gigatron project

Post by Ras » Sun Dec 10, 2017 10:20 pm

In regard to the final playing level, what do you estimate where the device will land relative to the AVR-Max?

User avatar
hgm
Posts: 22311
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: The Gigatron project

Post by hgm » Sun Dec 10, 2017 10:30 pm

I truly have no idea.

User avatar
stegemma
Posts: 842
Joined: Mon Aug 10, 2009 8:05 pm
Location: Italy
Contact:

Re: The Gigatron project

Post by stegemma » Mon Dec 11, 2017 11:15 am

hgm wrote:Some more sample code, this time for the routine that updates the attack map for the moves of the moved or captured piece. Basically it is just a switch on (colored) piece type, which then changes the attack flags at all capture targets.

Code: Select all

045F      /* Attack generation&#58; ultimately what can capture what is determined here.   */
045F      /* The attacks of a piece of a given type from a given square are recorded   */
045F      /* in the entries of the applicable attack map for the attacked square,      */
045F      /* as a bit flag. The update routine flips those flags, and can thus be      */
045F      /* used both to apply and to remove them. This will have to be done          */
045F      /* to remove the attacks of the moved piece from its old location; add those */
045F      /* from its new location, and remove the attacks of the captured piece.      */
045F      /* That is just for 3 pieces, but it has to be done again for UnMake&#40;)       */
045F      /* This does not sound much more efficient as generating the moves for all   */
045F      /* pieces from scratch. But the gain comes from the fact that it can be      */
045F      /* done one ply in advance, when the move was made from the grandparent,     */
045F      /* as the attacks only become relevant when we can move the piece again.     */
045F      /* So we will avoid doing this in nodes that have no grand children.         */
045F      /* Still, it is time-critical code, and for that reason loops are unrolled.  */
045F      
045F 0001 dbit0 = 1
045F 0002 dbit1 = 2
045F 0004 dbit2 = 4
045F 0008 dbit3 = 8
045F 0010 dbit4 = $10
045F 0020 dbit5 = $20
045F 0040 dbit6 = $40
045F 0080 dbit7 = $80
045F      
045F 000A step1 = WIDTH
045F 0001 step3 = 1
045F 0009 step5 = WIDTH - 1
045F 000B step7 = WIDTH + 1
045F FFF6 step2 = -step1
045F FFFF step4 = -step3
045F FFF7 step6 = -step5
045F FFF5 step8 = -step7
045F      
045F 000C hip1 = WIDTH + 2
045F 0015 hip2 = 2*WIDTH+1
045F 0013 hip3 = 2*WIDTH-1
045F 0008 hip4 = WIDTH - 2
045F FFF4 hip5 = -hip1
045F FFEB hip6 = -hip2
045F FFED hip7 = -hip3
045F FFF8 hip8 = -hip4
045F      
                    // parameters
045F 0042 g_sqr = tmp
045F 0043 g_bit = tmp+1
045F 0044 g_piece = tmp+2
045F      
045F                PAGE
0500      FlipAttacks&#58;
0500 C241           STA retad
0501 1544           LDY g_piece
0502 09E7           LDA Y&#58;attgen  // get its move-gen routine
0503 FE00           BRA &#91;A&#93;       // and execute it
0504      
0504      QueenWhite&#58;
0504 FC12           BRA OrthSlide
0505 10FC           LDX #sliderAttacks
0506      QueenBlack&#58;
0506 10FD           LDX #sliderAttacks+1
0507      QueenSlide&#58;
0507 0141           LDA retad
0508 C242           STA tmp        // set up DiagSlide to return here
0509 000C           LDA #here+3
050A C241           STA retad
050B FC2D           BRA DiagSlide
050C 0142           LDA tmp
050D FC12           BRA OrthSlide  // and then continue with OrthSlide
050E C241           STA retad
050F      
                    // Rook
050F      OrthWhite&#58;
050F FC12           BRA OrthSlide
0510 10FC           LDX #sliderAttacks
0511      OrthBlack&#58;
0511 10FD           LDX #sliderAttacks+1
0512      OrthSlide&#58;
0512 1542           LDY g_sqr
0513 0900           LDA Y&#58;views0u
0514 0D00           LDA &#91;Y&#58;X&#93;
0515 6001           XOR #dbit0
0516 CE00           STA &#91;Y&#58;X&#93;
0517 1542           LDY g_sqr
0518 0900           LDA Y&#58;views0d
0519 1600           LDY A
051A 0D00           LDA &#91;Y&#58;X&#93;
051B 6002           XOR #dbit1
051C CE00           STA &#91;Y&#58;X&#93;
051D 1542           LDY g_sqr
051E 0900           LDA Y&#58;views1u
051F 1600           LDY A
0520 0D00           LDA &#91;Y&#58;X&#93;
0521 6004           XOR #dbit2
0522 CE00           STA &#91;Y&#58;X&#93;
0523 1542           LDY g_sqr
0524 0900           LDA Y&#58;views1d
0525 1600           LDY A
0526 0D00           LDA &#91;Y&#58;X&#93;
0527 6008           XOR #dbit3
0528 FD41           BRA &#91;retad&#93;
0529 CE00           STA &#91;Y&#58;X&#93;
052A      
                    // Bishops
052A      DiagWhite&#58;
052A FC12           BRA OrthSlide
052B 10FC           LDX #sliderAttacks
052C      DiagBlack&#58;
052C 10FD           LDX #sliderAttacks+1
052D      DiagSlide&#58;
052D 1542           LDY g_sqr
052E 0900           LDA Y&#58;views2u
052F 1600           LDY A
0530 0D00           LDA &#91;Y&#58;X&#93;
0531 6010           XOR #dbit4
0532 CE00           STA &#91;Y&#58;X&#93;
0533 1542           LDY g_sqr
0534 0900           LDA Y&#58;views2d
0535 1600           LDY A
0536 0D00           LDA &#91;Y&#58;X&#93;
0537 6020           XOR #dbit5
0538 CE00           STA &#91;Y&#58;X&#93;
0539 1542           LDY g_sqr
053A 0900           LDA Y&#58;views3u
053B 1600           LDY A
053C 0D00           LDA &#91;Y&#58;X&#93;
053D 6040           XOR #dbit6
053E CE00           STA &#91;Y&#58;X&#93;
053F 1542           LDY g_sqr
0540 0900           LDA Y&#58;views3d
0541 1600           LDY A
0542 0D00           LDA &#91;Y&#58;X&#93;
0543 6080           XOR #dbit7
0544 FD41           BRA &#91;retad&#93;
0545 CE00           STA &#91;Y&#58;X&#93;
0546      
0546      
0546      /* Leaper attacks&#58; King and each Knight has its own bit in the leaper attack map. */
0546      /* Pawn attacks are just marked by whether they come from the left or right.      */
0546      /* The attacks are always recorded, even for empty squares. So we don't have to   */
0546      /* worry when a square gets occupied. Even off-board attacks are recorded         */
0546      /* &#40;the map includes a 2-wide guard band&#41;, so we don't have to test whether       */
0546      /* the leaper targets are off board.                                              */
0546      KnightWhite&#58;
0546 FC12           BRA OrthSlide
0547 10FE           LDX #leaperAttacks
0548      KnightBlack&#58;
0548 10FF           LDX #leaperAttacks+1
0549      KnightAttacks&#58;
0549 1544           LDY g_piece
054A 09EC           LDA Y&#58;attBit
054B C243           STA g_bit
054C 0142           LDA g_sqr
054D 940C           ADD #hip1,Y
054E 0D00           LDA &#91;Y&#58;X&#93;
054F 6143           XOR g_bit
0550 CE00           STA &#91;Y&#58;X&#93;
0551 0142           LDA g_sqr
0552 9415           ADD #hip2,Y
0553 0D00           LDA &#91;Y&#58;X&#93;
0554 6143           XOR g_bit
0555 CE00           STA &#91;Y&#58;X&#93;
0556 0142           LDA g_sqr
0557 9413           ADD #hip3,Y
0558 0D00           LDA &#91;Y&#58;X&#93;
0559 6143           XOR g_bit
055A CE00           STA &#91;Y&#58;X&#93;
055B 0142           LDA g_sqr
055C 9408           ADD #hip4,Y
055D 0D00           LDA &#91;Y&#58;X&#93;
055E 6143           XOR g_bit
055F CE00           STA &#91;Y&#58;X&#93;
0560 0142           LDA g_sqr
0561 94F4           ADD #hip5,Y
0562 0D00           LDA &#91;Y&#58;X&#93;
0563 6143           XOR g_bit
0564 CE00           STA &#91;Y&#58;X&#93;
0565 0142           LDA g_sqr
0566 94EB           ADD #hip6,Y
0567 0D00           LDA &#91;Y&#58;X&#93;
0568 6143           XOR g_bit
0569 CE00           STA &#91;Y&#58;X&#93;
056A 0142           LDA g_sqr
056B 94ED           ADD #hip7,Y
056C 0D00           LDA &#91;Y&#58;X&#93;
056D 6143           XOR g_bit
056E CE00           STA &#91;Y&#58;X&#93;
056F 0142           LDA g_sqr
0570 94F8           ADD #hip8,Y
0571 0D00           LDA &#91;Y&#58;X&#93;
0572 6143           XOR g_bit
0573 FD41           BRA &#91;retad&#93;
0574 CE00           STA &#91;Y&#58;X&#93;
0575      
0575      KingWhite&#58;
0575 FC12           BRA OrthSlide
0576 10FE           LDX #leaperAttacks
0577      KingBlack&#58;
0577 10FF           LDX #leaperAttacks+1
0578      KingAttacks&#58;
0578 0142           LDA g_sqr
0579 940A           ADD #step1,Y
057A 0D00           LDA &#91;Y&#58;X&#93;
057B 6040           XOR #$40
057C CE00           STA &#91;Y&#58;X&#93;
057D 0142           LDA g_sqr
057E 94F6           ADD #step2,Y
057F 0D00           LDA &#91;Y&#58;X&#93;
0580 6040           XOR #$40
0581 CE00           STA &#91;Y&#58;X&#93;
0582 0142           LDA g_sqr
0583 9401           ADD #step3,Y
0584 0D00           LDA &#91;Y&#58;X&#93;
0585 6040           XOR #$40
0586 CE00           STA &#91;Y&#58;X&#93;
0587 0142           LDA g_sqr
0588 94FF           ADD #step4,Y
0589 0D00           LDA &#91;Y&#58;X&#93;
058A 6040           XOR #$40
058B CE00           STA &#91;Y&#58;X&#93;
058C 0142           LDA g_sqr
058D 9409           ADD #step5,Y
058E 0D00           LDA &#91;Y&#58;X&#93;
058F 6040           XOR #$40
0590 CE00           STA &#91;Y&#58;X&#93;
0591 0142           LDA g_sqr
0592 94F7           ADD #step6,Y
0593 0D00           LDA &#91;Y&#58;X&#93;
0594 6040           XOR #$40
0595 CE00           STA &#91;Y&#58;X&#93;
0596 0142           LDA g_sqr
0597 940B           ADD #step7,Y
0598 0D00           LDA &#91;Y&#58;X&#93;
0599 6040           XOR #$40
059A CE00           STA &#91;Y&#58;X&#93;
059B 0142           LDA g_sqr
059C 94F5           ADD #step8,Y
059D 0D00           LDA &#91;Y&#58;X&#93;
059E 6040           XOR #$40
059F FD41           BRA &#91;retad&#93;
05A0 CE00           STA &#91;Y&#58;X&#93;
05A1      
05A1      WhitePawn&#58;
05A1 10FE           LDX #leaperAttacks
05A2 0142           LDA g_sqr
05A3 9409           ADD #step5,Y
05A4 0D00           LDA &#91;Y&#58;X&#93;
05A5 6001           XOR #1
05A6 CE00           STA &#91;Y&#58;X&#93;
05A7 0142           LDA g_sqr
05A8 940B           ADD #step7,Y
05A9 0D00           LDA &#91;Y&#58;X&#93;
05AA 6002           XOR #2
05AB FD41           BRA &#91;retad&#93;
05AC CE00           STA &#91;Y&#58;X&#93;
05AD      
05AD      BlackPawn&#58;
05AD 10FF           LDX #leaperAttacks+1
05AE 0142           LDA g_sqr
05AF 94F7           ADD #step6,Y
05B0 0D00           LDA &#91;Y&#58;X&#93;
05B1 6001           XOR #1
05B2 CE00           STA &#91;Y&#58;X&#93;
05B3 0142           LDA g_sqr
05B4 94F5           ADD #step8,Y
05B5 0D00           LDA &#91;Y&#58;X&#93;
05B6 6002           XOR #2
05B7 FD41           BRA &#91;retad&#93;
05B8 CE00           STA &#91;Y&#58;X&#93;
05B9      
What do you use to assemble this code?
Author of Drago, Raffaela, Freccia, Satana, Sabrina.
http://www.linformatica.com

User avatar
hgm
Posts: 22311
Joined: Fri Mar 10, 2006 9:06 am
Location: Amsterdam
Full name: H G Muller
Contact:

Re: The Gigatron project

Post by hgm » Mon Dec 11, 2017 12:15 pm

I wrote an assembler.

I have not thouroughly tested it, however. I used it to assemble the program to display the Chess board in the emulator, and this seemed to work. But it was not nearly using all existing instructions. Just a fairly small subset.

This assembler has a few nice features that help me preparing for some hardware modifications I plan to make to the version of the Gigatron I will build, once Marcel is ready to deliver the kits. E.g. it understands the addressing mode [const,X], emitting it as [X] when you run with the option -mDX, but replaces it with the pair of instructions "LDY #const; ... [Y,X]" when this option is disabled. And it then keeps track of what is in the Y register during linear code sequences, for supporting an optional reload of Y with the value that had to be destroyed for emulating the [const,X] mode. So it is possible to write code that would work both with and without the -mDX option (but much more efficiently with the latter, if you have that hardware modification).

I also added a pseudo-instruction "SYNC label", which assembles to the sequence of instructions that is needed to test if there still is enough time to execute the code block upto the given label before you must output a video sync pulse. It would then deduct the required execution time from the cycle counter if there is, but would jump to the video handler (posting a return address in the accumulator) if there isn't. The video handler would then delay the remaining time before generating a sync pulse, reset the cycle budget to a full scan line, and return to execute the code block. Something like

Code: Select all

LDA #-timeRequired
ADD cycleBudget
STA cycleBudget
BLT VideoHandler
LDA l1                        // return address
l1&#58;
// code block

Post Reply