Compare commits
75 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8a27297c16 | |||
| 7439e26a69 | |||
| e5700ddc95 | |||
| ffd2d58ac4 | |||
| 04e8a91d8b | |||
| d22dd7ab59 | |||
| 82ab9b1de6 | |||
| 84ff13708e | |||
| 8ad238fa81 | |||
| 98c7d26b39 | |||
| aed23b410e | |||
| 66d3e03d3d | |||
| 32b961aeb7 | |||
| f7f0720b2e | |||
| 12d68e2231 | |||
| 9d1f276175 | |||
| 2c11b2ff26 | |||
| b7fb9a0551 | |||
| 5ad0df290e | |||
| 0c14b27b96 | |||
| f3fcc2a2fd | |||
| 5bf15967c3 | |||
| 6fe55f74ce | |||
| a3459dc549 | |||
| 716f665ebc | |||
| 8f6c3490d9 | |||
| 7b4902cc1d | |||
| 6f3a68d4a0 | |||
| 14b2adad93 | |||
| cc98ef24ab | |||
| fe23d86f22 | |||
| 4f98ceccb2 | |||
| 963e74b1e4 | |||
| ef8ddfb6a9 | |||
| 27a2a92be4 | |||
| b371e07c10 | |||
| dfd415476d | |||
| 40af13b49b | |||
| f517803b0f | |||
| fb52341375 | |||
| a4b20bb390 | |||
| 95f1a56fa2 | |||
| 9e6ce89a17 | |||
| 127493d2f2 | |||
| e6469bb1bc | |||
| 88f54e3381 | |||
| 1947389c23 | |||
| a9d084d88c | |||
| 8cd02e966a | |||
| ad6331a93d | |||
| d06a0cdf50 | |||
| 72579be239 | |||
| 9b3842f9ee | |||
| cf17b0b923 | |||
| 8a1bef44d5 | |||
| 56df53bfb6 | |||
| 1231eec31f | |||
| 3dfa8cc98c | |||
| 458e07b9ae | |||
| 2179b4e871 | |||
| 46b43bacf0 | |||
| e26dba93c0 | |||
| 1a623be950 | |||
| 7e5dea7247 | |||
| 140d6da9d9 | |||
| 9f97c094fb | |||
| 8d60c25751 | |||
| 75b5093574 | |||
| 6e80ed9728 | |||
| 6122aaf515 | |||
| 251cf22aad | |||
| e58b96cacf | |||
| bd17f8bb79 | |||
| d4363be3b4 | |||
| 67761eeaa4 |
8
.codebook.toml
Normal file
8
.codebook.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
words = [
|
||||
"jali",
|
||||
"listf",
|
||||
"luser",
|
||||
"mlftp",
|
||||
"pdp",
|
||||
"turist",
|
||||
]
|
||||
26
.git-monitor_after.sh
Executable file
26
.git-monitor_after.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/sh
|
||||
# Copies the source files to the ITS system
|
||||
|
||||
MLFTP="/opt/pidp10/bin/mlftp"
|
||||
|
||||
SOURCEFILE="./src/sudoku.s"
|
||||
TARGETFILE="SUDOKU 1 JALI;"
|
||||
PUZZLEFILE="./src/puzzle.1"
|
||||
PUZZLETARGET="PUZZLE 1 JALI;"
|
||||
|
||||
|
||||
# Functions
|
||||
log_message() {
|
||||
local level=$1
|
||||
local message=$2
|
||||
timestamp=$(date +'%Y-%m-%d %H:%M:%S')
|
||||
#echo "$timestamp [$level] $message" >> "$LOG_FILE"
|
||||
echo "$timestamp [$level] $message" # Also print to console (optional)
|
||||
}
|
||||
|
||||
# Main execution
|
||||
log_message "INFO" "Uploading $SOURCEFILE to $TARGETFILE on ITS"
|
||||
$MLFTP -w its "$TARGETFILE" $SOURCEFILE
|
||||
|
||||
log_message "INFO" "Uploading $PUZZLEFILE to $PUZZLETARGET on ITS"
|
||||
$MLFTP -w its "$PUZZLETARGET" $PUZZLEFILE
|
||||
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.git-monitor-last-commit
|
||||
14
.layout.tmux
Normal file
14
.layout.tmux
Normal file
@@ -0,0 +1,14 @@
|
||||
#!/usr/bin/zsh
|
||||
# Create a layout for development on the PDP-10
|
||||
RPDP=$(where rpdp)
|
||||
|
||||
# Split the window at the bottom and open the console of the PDP-10.
|
||||
$MUX split-window -v -l 8 -t ${SESSIONID}:0 telnet pidp10.local 1025
|
||||
|
||||
# Split again, and connect via ssh to the host machine
|
||||
$MUX split-window -h -t ${SESSIONID}:0 ssh pidp10.local
|
||||
|
||||
# Finally, start an instance of the Knight-TV console
|
||||
if [[ -v RPDP ]]; then
|
||||
$RPDP tvcon
|
||||
fi
|
||||
83
README.md
83
README.md
@@ -4,7 +4,7 @@
|
||||
|
||||
[Sudoku](https://en.wikipedia.org/wiki/Sudoku) is a logic based number-placement
|
||||
puzzle game originally from Japan. The word *sudoku* literally means
|
||||
*digit-single*. The objecttive is to fill a 9x9 grid with numbers between 1 and
|
||||
*digit-single*. The objective is to fill a 9x9 grid with numbers between 1 and
|
||||
9, without having a number repeat in a row, column or a 3x3 sub grid. Normally,
|
||||
there are a few numbers preset. In a regular sudoku, the pre-filled numbers make
|
||||
sure, that exactly one solution for the puzzle exists.
|
||||
@@ -48,17 +48,17 @@ The rules are the following:
|
||||
once.
|
||||
- Every 3x3 sub-grid must contain every number between 1 and 9 exactly once.
|
||||
|
||||
## Solving Sudokus programatically
|
||||
## Solving Sudokus algorithmically
|
||||
|
||||
### Backtracking (naïve approach)
|
||||
|
||||
Solving a Sudoku can be achieved in serveral ways. The most simple algorithm, is
|
||||
Solving a Sudoku can be achieved in several ways. The most simple algorithm, is
|
||||
a backtracking algorithm. With this a sudoku can be resolved basically by
|
||||
brute-forcing it. In this case, we walk through each cell of the grid
|
||||
recurseivly, and add a number. Then we check, if the grid is still valid. If it
|
||||
is, we recursivly move on to the next column. If we find a number that doesn't
|
||||
recursively, and add a number. Then we check, if the grid is still valid. If it
|
||||
is, we recursively move on to the next column. If we find a number that doesn't
|
||||
match, we return to the previous incarnation, and try another number. In order
|
||||
to check, if our grid is still valid, we can use simple function:
|
||||
to check if our grid is still valid, we can use simple function:
|
||||
|
||||
```C
|
||||
// Function to check, if it is save to place num at mat[row][col]
|
||||
@@ -141,6 +141,71 @@ And that's it.
|
||||
|
||||
## Using the PDP-10 to solve the Sudoku
|
||||
|
||||
The PDP-10 should be able to solve the sudoku using backtracking. The above
|
||||
algorithm will be implemented directly in PDP-10 assembly, using the MIDAS
|
||||
assembler, of the ITS operating system.
|
||||
In order to run this program, you need a working PDP-10 simulator (or, if you
|
||||
are a very lucky person,the real thing). You can either use the
|
||||
[PiDP-10 kit](https://obsolescence.wixsite.com/obsolescence/pidp10), or a
|
||||
Raspberry Pi 5 to run it on. The PiDP-10 can be run on any Raspberry 5 computer,
|
||||
even without the front panel, but having the front panel is fancier. You can
|
||||
also run [simh](https://opensimh.org/) on a PC, but that would only be half the
|
||||
fun.
|
||||
|
||||
The PiDP-10 should be booted into ITS, as this is the OS, this project is
|
||||
running against. Now the only thing you need to do, is copy the source code
|
||||
files into the file system of your PiDP-10. You can do this by using the `mlftp`
|
||||
tool, installed on the machine your simulator runs on. You clone the repository
|
||||
and run the following commands from the command line:
|
||||
|
||||
```bash
|
||||
/opt/pidp10/bin/mlftp -w ITS "SUDOKU 1 JALI;" ./src/sudoku.s
|
||||
/opt/pidp10/bin/mlftp -w ITS "PUZZLE 1 JALI;" ./src/puzzle_1.sudoku
|
||||
```
|
||||
|
||||
This will copy the source code file, and the example puzzle file onto the
|
||||
PiDP-10. Remember to change the directory name in the ITS path form `JALI` to
|
||||
the directory you want to copy to.
|
||||
|
||||
You can now edit both files in EMACS on the PiDP-10. However, if you prefer to
|
||||
edit your code in a somewhat more modern environment (your favourite IDE, for
|
||||
example), consider installing the
|
||||
[git-monitor](https://gitea.orca-central.de/jali/PiDP10Services) on your
|
||||
PiDP-10's host system. The monitor is a service written in
|
||||
[bash](https://www.gnu.org/software/bash/), that will clone your project
|
||||
repositories and then monitor a given branch for new commits. On new commits it
|
||||
pulls them, and runs the script `.git-monitor_after.sh`, which in turn, contains
|
||||
the upload commands for ITS. This way, you can automatically update your source
|
||||
code in ITS, even when you are working on a modern machine.
|
||||
|
||||
## Building and running
|
||||
|
||||
Log into ITS with your developers user name by typing `USERNAME$U` (where `$` is
|
||||
the ESC-Key), If you are a *luser*: Type `:LOGIN USERNAME` and swap `USERNAME`
|
||||
for your *actual* username. Confirm with `Enter`.
|
||||
|
||||
Now you can build the sudoku solver by invoking MIDAS in DDT:
|
||||
|
||||
```
|
||||
:MIDAS TS SUDOKU_SUDOKU
|
||||
```
|
||||
|
||||
This will instruct MIDAS to create a relocatable binary (TS) from the latest
|
||||
version of the `SUDOKU` file, and store it in a file named `TS SUDOKU` in the
|
||||
current directory. If this succeded, listing the files with `:LISTF` (or
|
||||
`CTRL+F`, if you're not a turist), should look something like this:
|
||||
|
||||
```
|
||||
KA JALI
|
||||
FREE BLOCKS #2=154 #3=169 #0=156 #1=171
|
||||
1 PUZZL1 SUDOKU 1 ! 9/21/2025 22:02:04
|
||||
3 SUDOKU 1 1 ! 9/21/2025 22:02:02
|
||||
1 TS SUDOKU 1 ! 9/21/2025 23:25:09
|
||||
```
|
||||
|
||||
To invoke the solver run it with:
|
||||
|
||||
```
|
||||
:SUDOKU PUZZLE 1
|
||||
```
|
||||
|
||||
This will pass the file `PUZZLE 1` to the program, and start solving it.
|
||||
|
||||
The result will be printed on the screen (once the project is finished).
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
;-*-MIDAS-*-
|
||||
TITLE SUDOKU SOLVER
|
||||
|
||||
A=1 ;Define ACs as universal registers
|
||||
B=2 ;from A to E
|
||||
C=3
|
||||
D=4
|
||||
E=5
|
||||
X=10 ;X and Y are used for indexing
|
||||
Y=11 ;loops etc.
|
||||
P=17 ;Define P as the stack pointer.
|
||||
|
||||
PDLLEN==30 ;Set the size of the stack to 30 words.
|
||||
PDL: BLOCK PDLLEN ;Reserve the stack memory
|
||||
BPTR==440700 ;Define a byte pointer.
|
||||
|
||||
CHTTYO==1 ;Define a channel for TTY output.
|
||||
|
||||
JCL: BLOCK 30 ;Reserve space for the command line.
|
||||
FNAME1: BLOCK 15 ;The first part of the file name.
|
||||
FNAME2: BLOCK 15 ;The second file name.
|
||||
|
||||
;Print flags
|
||||
;Allows to change the beavihour of the OUTSTR and PUTLN subroutines.
|
||||
;The different bits in the word have different meanings.
|
||||
;Flags:
|
||||
; 001 - SIXBIT: Prints the next character as a SIXBIT char, instead of ASCII, if set.
|
||||
PFLAGS: BLOCK 1
|
||||
|
||||
START: MOVE P,[-PDLLEN,,PDL-1] ;Initialize the stack.
|
||||
.OPEN CHTTYO,[.UAO,,'TTY] ;Open an output channel on the TTY.
|
||||
.LOSE %LSFIL ;Gobble up any errors.
|
||||
MOVEI A,001 ;Initialize the print flag
|
||||
MOVEM A,PFLAGS ;to print SIXBIT
|
||||
PUSHJ P,GETJCL ;Read the command line.
|
||||
MOVE A,[BPTR,,FNAME1] ;Read the parameter.
|
||||
PUSHJ P,PUTLN ;Print the file name
|
||||
MOVE A,[BPTR,,FNAME2] ;Print the second file name.
|
||||
PUSHJ P,PUTLN
|
||||
JRST DONE ;Jump to the end of the program.
|
||||
|
||||
;Subroutine to read the JCL from DDT and get the command line parameters.
|
||||
GETJCL: PUSH P,A ;Save the register A.
|
||||
PUSH P,B ;Save the register B.
|
||||
SETZM JCL ;Zero out the JCL
|
||||
MOVE A,[JCL,,JCL+30]
|
||||
BLT A,JCL+30
|
||||
.BREAK 12,[..RJCL,,JCL] ;Request the JCL.
|
||||
MOVE A,[BPTR,,JCL] ;Load the command parameters into A.
|
||||
MOVE B,[BPTR,,FNAME1] ;Pointer to the first file name.
|
||||
PUSHJ P,TOSIXB ;Transfer the first word into FNAME1
|
||||
MOVE B,[BPTR,,FNAME2] ;Pointer to the second file name.
|
||||
PUSHJ P,TOSIXB ;Transfer the second word into FNAME2
|
||||
POP P,B ;Restore the B register.
|
||||
POP P,A ;Restore the A register.
|
||||
POPJ P, ;Return from routine.
|
||||
|
||||
;Subroutine to convert an ASCII string into SIXBIT. Takes a byte
|
||||
;pointer in A and B, where A is the source and B is the destination.
|
||||
TOSIXB: PUSH P,D ;Store the contents of register D.
|
||||
TOSLP: ILDB D,A ;Load the next character from A.
|
||||
JUMPE D,TOSEN ;Exit the loop, if charachter is null.
|
||||
CAIN D,40 ;If the character is a whitespace,
|
||||
JUMPA TOSEN ;exit the loop.
|
||||
CAIL D,140 ;If the character is > 96,
|
||||
SUBI D,40 ;then cut it down, so it's in range.
|
||||
SUBI D,40 ;Convert 32..95 to 0..63
|
||||
IDPB D,B ;Deposit the character in the destination.
|
||||
JRST TOSLP ;Repeat with next character.
|
||||
TOSEN: POP P,D ;Restore the D register.
|
||||
POPJ P, ;Return from function.
|
||||
|
||||
;Subroutine to print a string of text on the output.
|
||||
;Clobbers A.
|
||||
OUTSTR: PUSH P,B ;Save register B.
|
||||
PUSH P,D ;Save register D.
|
||||
HRLI A,BPTR ;Ensure, A is a byte pointer.
|
||||
OUT: ILDB B,A ;Load the next byte from A.
|
||||
JUMPE B,OUTEX ;Exit the routine, if all bytes are done.
|
||||
MOVE D,PFLAGS ;Load the print flags.
|
||||
TRNE D,001 ;Test, if the SIXBIT flag is set.
|
||||
ADDI B,40 ;Convert SIXBIT to ASCII.
|
||||
.IOT CHTTYO,B ;Print a character.
|
||||
JRST OUT ;Jump back to print the next character.
|
||||
OUTEX: POP P,D ;Restore D to its original value.
|
||||
POP P,B ;Restore B to its original value.
|
||||
POPJ P, ;Return from the output routine.
|
||||
|
||||
;Subroutine to print an entire line of text, including a line break.
|
||||
;Clobbers A and B.
|
||||
PUTLN: PUSHJ P,OUTSTR ;Calls the OUTSTR subroutine
|
||||
.IOT CHTTYO,[^M] ;Print a carriage return
|
||||
.IOT CHTTYO,[^J] ;and a new line
|
||||
POPJ P, ;before returning.
|
||||
|
||||
DONE: .LOGOUT 2, ;Exit point for the program.
|
||||
END START
|
||||
57
src/chkmat.s
Normal file
57
src/chkmat.s
Normal file
@@ -0,0 +1,57 @@
|
||||
;-*-MIDAS-*-
|
||||
TITLE CHECK MATRIX
|
||||
A=1 ;Define the ACs as universal registers
|
||||
B=2 ;from A to E
|
||||
C=3
|
||||
D=4
|
||||
E=5
|
||||
X=10 ;X and Y are used for indexing
|
||||
Y=11 ;loops etc.
|
||||
P=17 ;Define P as the stack pointer
|
||||
|
||||
PDLLEN==30 ;Set the size of the stack to 30 words.
|
||||
PDL: BLOCK PDLLEN ;Reserve the stack memory
|
||||
|
||||
START: MOVE P,[-PDLLEN,,PDL-1] ;Initializes the stack
|
||||
DONE: .LOGOUT 2, ;Exit from the program
|
||||
|
||||
;Subroutine that checks a byte array, where one byte is a 4-bit value,
|
||||
;for duplicate values.
|
||||
;The algorithm works as follows:
|
||||
;The original word is walked through in 4-bit steps. Each 4-bit value
|
||||
;is read, and its value is used as a bit pointer to the 'hashing'-register.
|
||||
;If a number is found, the bit in the hashing register is set. If the bit
|
||||
;is already set, the number has already been found the in original data.
|
||||
;To make the walk through easy, we use a special feature of the PDP-10:
|
||||
;We access the data register, as if it was a memory address.
|
||||
;The following registers are used:
|
||||
;A: Accumulator used to store the values that are read from the data field.
|
||||
;B: Used to check if a bit is set, without destroying the contents of I.
|
||||
;C: Contains the data field itself: 36 bits, in 4-bit segments.
|
||||
;D: Contains the result, 0 if successfull, else >0.
|
||||
;E: Used as a table to store if a number was found in the field.
|
||||
;X: The byte pointer to the data field.
|
||||
CHKMAT: PUSH P,A ;Save the register A
|
||||
PUSH P,B ;Save the B-register
|
||||
PUSH P,C ;Save the data register
|
||||
PUSH P,E ;Save the E register
|
||||
PUSH P,X ;Save the index register
|
||||
MOVEI D,11 ;Load D with 16.
|
||||
SETZ E ;Set the hash register to 0.
|
||||
MOVE X,[440400,,C] ;Store a byte pointer to C
|
||||
CKLOOP: SOJE D,CHKEXT ;All bits set?
|
||||
ILDB A,X ;Store a byte in A
|
||||
MOVEI B,1 ;Set B to 1
|
||||
LSH B,A ;Set the Ath bit in the mask
|
||||
TRNE E,B ;Test, if a bit is already set
|
||||
JRST CHKEXT ;Double value found, exit.
|
||||
IORI E,B ;Set the Ath bit in the code
|
||||
JRST LOOP ;Back to the loop
|
||||
CHKEXT: POP P,X ;Restore X
|
||||
POP P,E ;Restore E
|
||||
POP P,C ;Restore C
|
||||
POP P,B ;Restore B
|
||||
POP P,A ;Restore A
|
||||
POPJ P, ;Return from function
|
||||
|
||||
|
||||
175
src/sudoku.s
Normal file
175
src/sudoku.s
Normal file
@@ -0,0 +1,175 @@
|
||||
;-*-MIDAS-*-
|
||||
TITLE SUDOKU SOLVER
|
||||
|
||||
A=1 ;Define ACs as universal registers
|
||||
B=2 ;from A to E
|
||||
C=3
|
||||
D=4
|
||||
E=5
|
||||
X=10 ;X and Y are used for indexing
|
||||
Y=11 ;loops etc.
|
||||
P=17 ;Define P as the stack pointer.
|
||||
|
||||
PDLLEN==30 ;Set the size of the stack to 30 words.
|
||||
PDL: BLOCK PDLLEN ;Reserve the stack memory
|
||||
|
||||
CHTTYO==1 ;Define a channel for TTY output.
|
||||
CHDSKI==2 ;Read channel for disk input.
|
||||
|
||||
JCL: BLOCK 30 ;Reserve space for the command line.
|
||||
FNAME1: BLOCK 1 ;The first part of the file name.
|
||||
FNAME2: BLOCK 1 ;The second file name.
|
||||
FIELD: BLOCK 9 ;Reserve 9 words to store the grid.
|
||||
|
||||
START: MOVE P,[-PDLLEN,,PDL-1] ;Initialize the stack.
|
||||
.OPEN CHTTYO,[.UAO,,'TTY] ;Open an output channel on the TTY.
|
||||
.LOSE %LSFIL ;Gobble up any errors.
|
||||
MOVE A,[440700,,WELCOME] ;Print the welcome message
|
||||
PUSHJ P,PUTLN
|
||||
PUSHJ P,GETJCL ;Read the command line.
|
||||
MOVE A,[440700,,LOADING] ;Print the loading message
|
||||
PUSHJ P,OUTSTR
|
||||
; Load the files into field
|
||||
MOVEI A,FIELD ;Store the address of field in C
|
||||
PUSHJ P,IMPRTF ;Load the file
|
||||
PUSHJ P,PFIELD ;Print the loaded field.
|
||||
|
||||
|
||||
JRST DONE ;Jump to the end of the program.
|
||||
|
||||
;Subroutine to read the JCL from DDT and get the command line parameters.
|
||||
GETJCL: PUSH P,A ;Save the register A.
|
||||
PUSH P,B ;Save the register B.
|
||||
SETZM JCL ;Zero out the JCL
|
||||
MOVE A,[JCL,,JCL+30]
|
||||
BLT A,JCL+30
|
||||
SETZM FNAME1 ;Zero out FNAME1
|
||||
SETZM FNAME2 ;Zero out FNAME2
|
||||
.BREAK 12,[..RJCL,,JCL] ;Request the JCL.
|
||||
MOVE A,[440700,,JCL] ;Load the command parameters into A.
|
||||
MOVE B,[440600,,FNAME1] ;Pointer to the first file name.
|
||||
PUSHJ P,TOSIXB ;Transfer the first word into FNAME1
|
||||
MOVE B,[440600,,FNAME2] ;Pointer to the second file name.
|
||||
PUSHJ P,TOSIXB ;Transfer the second word into FNAME2
|
||||
POP P,B ;Restore the B register.
|
||||
POP P,A ;Restore the A register.
|
||||
POPJ P, ;Return from routine.
|
||||
|
||||
;Subroutine to copy a string. Takes a bytepointer in A and B
|
||||
;where A is the source and B is the destination. It will stop copying, if
|
||||
;the end of the string is reached, or a whitespace is encounterd,
|
||||
CPSTR: PUSH P,D ;Store the contents of register D.
|
||||
CPSTLP: ILDB D,A ;Load the next character from A.
|
||||
JUMPE D,CPSTEN ;Exit the loop.
|
||||
CAIN D,40 ;If the character is whitespace
|
||||
JUMPA CPSTEN ;exit the loop.
|
||||
IDPB D,B ;Deposit the charcter at destination.
|
||||
JRST CPSTLP ;Repeat with the next character
|
||||
CPSTEN: POP P,D ;Restore the D register.
|
||||
POPJ P, ;Return from function.
|
||||
|
||||
;Subroutine to convert an ASCII string into SIXBIT. Takes a byte
|
||||
;pointer in A and B, where A is the source and B is the destination.
|
||||
TOSIXB: PUSH P,D ;Store the contents of register D.
|
||||
TOSLP: ILDB D,A ;Load the next character from A.
|
||||
JUMPE D,TOSEN ;Exit the loop, if charachter is null.
|
||||
CAIN D,40 ;If the character is a whitespace,
|
||||
JUMPA TOSEN ;exit the loop.
|
||||
CAIN D,15 ;If the character is a carriage return
|
||||
JUMPA TOSEN ;exit the loop.
|
||||
CAIL D,140 ;If the character is > 96,
|
||||
SUBI D,40 ;then cut it down, so it's in range.
|
||||
SUBI D,40 ;Convert 32..95 to 0..63
|
||||
IDPB D,B ;Deposit the character in the destination.
|
||||
JRST TOSLP ;Repeat with next character.
|
||||
TOSEN: POP P,D ;Restore the D register.
|
||||
POPJ P, ;Return from function.
|
||||
|
||||
;Subroutine to print a string of text on the output.
|
||||
;Clobbers A.
|
||||
OUTSTR: PUSH P,B ;Save register B.
|
||||
OUT: ILDB B,A ;Load the next byte from A.
|
||||
JUMPE B,OUTEX ;Exit the routine, if all bytes are done.
|
||||
TLNN A,000100 ;Test, if the SIXBIT flag is set.
|
||||
ADDI B,40 ;Convert SIXBIT to ASCII.
|
||||
.IOT CHTTYO,B ;Print a character.
|
||||
JRST OUT ;Jump back to print the next character.
|
||||
OUTEX: POP P,B ;Restore B to its original value.
|
||||
POPJ P, ;Return from the output routine.
|
||||
|
||||
;Subroutine to print an entire line of text, including a line break.
|
||||
;Clobbers A and B.
|
||||
PUTLN: PUSHJ P,OUTSTR ;Calls the OUTSTR subroutine
|
||||
.IOT CHTTYO,[^M] ;Print a carriage return
|
||||
.IOT CHTTYO,[^J] ;and a new line
|
||||
POPJ P, ;before returning.
|
||||
|
||||
;Subroutine to that prints the entire play field.
|
||||
;The contents of the field is expected in FIELD
|
||||
PFIELD: PUSH P,A ;Save the A register.
|
||||
PUSH P,B ;Save the contents of register B.
|
||||
PUSH P,C ;Save the contents of register C.
|
||||
PUSH P,X ;Save the contents of the index register.
|
||||
PUSH P,Y ;Save the contents of the Y register
|
||||
MOVEI C,121 ;Set a counter.
|
||||
MOVE X,[440400,,FIELD] ;Store a bytepointer in X.
|
||||
PFIELN: .IOT CHTTYO,[^M] ;Print a carriage return.
|
||||
.IOT CHTTYO,[^J] ;Print a new line.
|
||||
MOVE A,[440700,,HLINE] ;Print a horizontal line.
|
||||
PUSHJ P,PUTLN
|
||||
MOVEI Y,011 ;Load the index register with 9.
|
||||
MOVEI B,174 ;Print a '|' symbol.
|
||||
.IOT CHTTYO,B
|
||||
PFIENO: .IOT CHTTYO,[040] ;Print a space.
|
||||
ILDB B,X ;Load the next field.
|
||||
ADDI B,060 ;Convert number into char.
|
||||
CAIN B,060 ;If B is not '0', skip
|
||||
MOVEI B,040 ;Replace '0' with a space character.
|
||||
.IOT CHTTYO,B ;Print the number.
|
||||
.IOT CHTTYO,[040] ;Print a space
|
||||
.IOT CHTTYO,[174] ;Print a '|' symbol
|
||||
SOJE C,PFIEEX ;Exit, if no more elements are read.
|
||||
SOJE Y,PFIELN ;End the line and start a new one.
|
||||
JUMPA PFIENO ;Jump back to print the next number.
|
||||
|
||||
PFIEEX: .IOT CHTTYO,[^M] ;Print carriage return
|
||||
.IOT CHTTYO,[^J] ;Print line feed.
|
||||
MOVE A,[440700,,HLINE] ;Print a horizontal line
|
||||
PUSHJ P,PUTLN
|
||||
POP P,Y ;Restore the Y register.
|
||||
POP P,X ;Restore the index register.
|
||||
POP P,C ;Restore the C register.
|
||||
POP P,B ;Restore the B register.
|
||||
POP P,A ;Restore the A register.
|
||||
POPJ P, ;Return from the subroutine.
|
||||
|
||||
;Subroutine that reads the contents of the file into the buffer at FIELD
|
||||
IMPRTF: PUSH P,A ;Save the A register.
|
||||
PUSH P,B ;Save the B register.
|
||||
PUSH P,X ;Save the index register.
|
||||
MOVE X,[440400,,FIELD] ;Init a 4-bit byte pointer to FIELD.
|
||||
.CALL [SETZ ? SIXBIT/OPEN/ ;Open a file descriptor.
|
||||
[.UAI,,CHDSKI] ? [SIXBIT/DSK/] ;Mode, channel and device name
|
||||
%CLIN,,FNAME1 ? 400000,,FNAME2]
|
||||
.LOSE %LSFIL ;Handle errors after opening the file
|
||||
IMPRD: .IOT CHDSKI,A ;Read an ascii char into A.
|
||||
JUMPL A,IMPREX ;If there was nothing read, exit.
|
||||
CAIGE A,060 ;Is A >= '0' then skip,
|
||||
JUMPA IMPRD ;else read the next char.
|
||||
CAILE A,071 ;If A <= '9', then skip.
|
||||
JUMPA IMPRD ;else, read the next char.
|
||||
SUBI A,060 ;Convert A from the num char into int.
|
||||
IDPB A,X ;Store the byte and increment.
|
||||
JUMPA IMPRD ;Jump back to read the next byte.
|
||||
IMPREX: .CALL [SETZ ? SIXBIT/CLOSE/ ;Close the file, before returning.
|
||||
[,,CHDSKI] ((SETZ))]
|
||||
.LOSE %LSFIL
|
||||
POP P,X ;Restore the X register.
|
||||
POP P,B ;Restore the B register
|
||||
POP P,A ;Restore the A register.
|
||||
POPJ P, ;Return from the input subroutine,
|
||||
DONE: .LOGOUT 2, ;Exit point for the program.
|
||||
WELCOME:ASCIZ /SUDOKU SOLVER v0.1/ ;Text of the welcome banner.
|
||||
LOADING:ASCIZ /LOADING / ;Load message.
|
||||
HLINE: ASCIZ /|---|---|---|---|---|---|---|---|---|/ ;A horizontal line.
|
||||
END START
|
||||
Reference in New Issue
Block a user