				;'variables'
				;region
				;counters
				COUNT1 EQU 0x60
				COUNT2 EQU 0x61
				COUNT3 EQU 0x62
				;for subroutines
				INPUT EQU 0x63
				TEMP EQU 0x64
				RESULT EQU 0x65
				;store the information concerning a cell of the sudoku (2 bytes)
				VALUE1 EQU 0x66
				VALUE2 EQU 0x67
				;old value of FSR
				FSROLD EQU 0x68
				;current BANK
				BANK EQU 0x69
				;bit 0 indicates whether a value has been set in this iteration or not
				;bit 1 indicates whether we are on part 1 of the attack (remove possibilities) or part 2 of the attack (set sure values)
				FLAGS EQU 0x6A
				;endregion
				
				;EQU's
				;region				
				EMP1 EQU b'11111111'
				EMP2 EQU b'10000000'
				ONE1 EQU b'10000000'
				ONE2 EQU b'01010000'
				TWO1 EQU b'01000000'
				TWO2 EQU b'01010000'
				THR1 EQU b'00100000'
				THR2 EQU b'01010000'
				FOU1 EQU b'00010000'
				FOU2 EQU b'01010000'
				FIV1 EQU b'00001000'
				FIV2 EQU b'01010000'
				SIX1 EQU b'00000100'
				SIX2 EQU b'01010000'
				SEV1 EQU b'00000010'
				SEV2 EQU b'01010000'
				EIG1 EQU b'00000001'
				EIG2 EQU b'01010000'
				NIN1 EQU b'00000000'
				NIN2 EQU b'11010000'
				;endregion

				ORG 0x0000
		
				;sudoku input
				;region
				BCF STATUS,RP0
				BCF STATUS,RP1

				MOVLW SEV1 
				MOVWF 0x20 
				MOVLW SEV2 
				MOVWF 0x21 

				MOVLW EMP1 
				MOVWF 0x22 
				MOVLW EMP2 
				MOVWF 0x23 

				MOVLW EMP1 
				MOVWF 0x24 
				MOVLW EMP2 
				MOVWF 0x25 

				MOVLW ONE1 
				MOVWF 0x26 
				MOVLW ONE2 
				MOVWF 0x27 

				MOVLW EMP1 
				MOVWF 0x28 
				MOVLW EMP2 
				MOVWF 0x29 

				MOVLW EMP1 
				MOVWF 0x2A 
				MOVLW EMP2 
				MOVWF 0x2B 

				MOVLW EMP1 
				MOVWF 0x2C 
				MOVLW EMP2 
				MOVWF 0x2D 

				MOVLW EMP1 
				MOVWF 0x2E 
				MOVLW EMP2 
				MOVWF 0x2F 

				MOVLW SIX1 
				MOVWF 0x30 
				MOVLW SIX2 
				MOVWF 0x31 

				MOVLW EMP1 
				MOVWF 0x32 
				MOVLW EMP2 
				MOVWF 0x33 

				MOVLW THR1 
				MOVWF 0x34 
				MOVLW THR2 
				MOVWF 0x35 

				MOVLW EMP1 
				MOVWF 0x36 
				MOVLW EMP2 
				MOVWF 0x37 

				MOVLW NIN1 
				MOVWF 0x38 
				MOVLW NIN2 
				MOVWF 0x39 

				MOVLW EMP1 
				MOVWF 0x3A 
				MOVLW EMP2 
				MOVWF 0x3B 

				MOVLW EMP1 
				MOVWF 0x3C 
				MOVLW EMP2 
				MOVWF 0x3D 

				MOVLW EMP1 
				MOVWF 0x3E 
				MOVLW EMP2 
				MOVWF 0x3F 

				MOVLW TWO1 
				MOVWF 0x40 
				MOVLW TWO2 
				MOVWF 0x41 

				MOVLW EIG1 
				MOVWF 0x42 
				MOVLW EIG2 
				MOVWF 0x43 

				MOVLW EMP1 
				MOVWF 0x44 
				MOVLW EMP2 
				MOVWF 0x45 

				MOVLW FIV1 
				MOVWF 0x46 
				MOVLW FIV2 
				MOVWF 0x47 

				MOVLW EMP1 
				MOVWF 0x48 
				MOVLW EMP2 
				MOVWF 0x49 

				MOVLW EMP1 
				MOVWF 0x4A 
				MOVLW EMP2 
				MOVWF 0x4B 

				MOVLW EMP1 
				MOVWF 0x4C 
				MOVLW EMP2 
				MOVWF 0x4D 

				MOVLW EMP1 
				MOVWF 0x4E 
				MOVLW EMP2 
				MOVWF 0x4F 

				MOVLW EMP1 
				MOVWF 0x50 
				MOVLW EMP2 
				MOVWF 0x51 

				MOVLW EMP1 
				MOVWF 0x52 
				MOVLW EMP2 
				MOVWF 0x53 

				MOVLW EMP1 
				MOVWF 0x54 
				MOVLW EMP2 
				MOVWF 0x55 

				BSF STATUS,RP0
				BCF STATUS,RP1

				MOVLW EMP1 
				MOVWF 0x20 
				MOVLW EMP2 
				MOVWF 0x21 

				MOVLW EMP1 
				MOVWF 0x22 
				MOVLW EMP2 
				MOVWF 0x23 

				MOVLW THR1 
				MOVWF 0x24 
				MOVLW THR2 
				MOVWF 0x25 

				MOVLW EIG1 
				MOVWF 0x26 
				MOVLW EIG2 
				MOVWF 0x27 

				MOVLW EMP1 
				MOVWF 0x28 
				MOVLW EMP2 
				MOVWF 0x29 

				MOVLW SIX1 
				MOVWF 0x2A 
				MOVLW SIX2 
				MOVWF 0x2B 

				MOVLW NIN1 
				MOVWF 0x2C 
				MOVLW NIN2 
				MOVWF 0x2D 

				MOVLW ONE1 
				MOVWF 0x2E 
				MOVLW ONE2 
				MOVWF 0x2F 

				MOVLW EMP1 
				MOVWF 0x30 
				MOVLW EMP2 
				MOVWF 0x31 

				MOVLW EMP1 
				MOVWF 0x32 
				MOVLW EMP2 
				MOVWF 0x33 

				MOVLW FOU1 
				MOVWF 0x34 
				MOVLW FOU2 
				MOVWF 0x35 

				MOVLW ONE1 
				MOVWF 0x36 
				MOVLW ONE2 
				MOVWF 0x37 

				MOVLW EMP1 
				MOVWF 0x38 
				MOVLW EMP2 
				MOVWF 0x39 

				MOVLW EMP1 
				MOVWF 0x3A 
				MOVLW EMP2 
				MOVWF 0x3B 

				MOVLW EMP1 
				MOVWF 0x3C 
				MOVLW EMP2 
				MOVWF 0x3D 

				MOVLW EMP1 
				MOVWF 0x3E 
				MOVLW EMP2 
				MOVWF 0x3F 

				MOVLW SIX1 
				MOVWF 0x40 
				MOVLW SIX2 
				MOVWF 0x41 

				MOVLW EMP1 
				MOVWF 0x42 
				MOVLW EMP2 
				MOVWF 0x43 

				MOVLW EMP1 
				MOVWF 0x44 
				MOVLW EMP2 
				MOVWF 0x45 

				MOVLW EIG1 
				MOVWF 0x46 
				MOVLW EIG2 
				MOVWF 0x47 

				MOVLW EMP1 
				MOVWF 0x48 
				MOVLW EMP2 
				MOVWF 0x49 

				MOVLW EMP1 
				MOVWF 0x4A 
				MOVLW EMP2 
				MOVWF 0x4B 

				MOVLW EMP1 
				MOVWF 0x4C 
				MOVLW EMP2 
				MOVWF 0x4D 

				MOVLW SEV1 
				MOVWF 0x4E 
				MOVLW SEV2 
				MOVWF 0x4F 

				MOVLW EMP1 
				MOVWF 0x50 
				MOVLW EMP2 
				MOVWF 0x51 

				MOVLW EMP1 
				MOVWF 0x52 
				MOVLW EMP2 
				MOVWF 0x53 

				MOVLW EMP1 
				MOVWF 0x54 
				MOVLW EMP2 
				MOVWF 0x55 

				BSF STATUS,RP1
				BCF STATUS,RP0

				MOVLW NIN1 
				MOVWF 0x20 
				MOVLW NIN2 
				MOVWF 0x21 

				MOVLW EMP1 
				MOVWF 0x22 
				MOVLW EMP2 
				MOVWF 0x23 

				MOVLW EMP1 
				MOVWF 0x24 
				MOVLW EMP2 
				MOVWF 0x25 

				MOVLW SEV1 
				MOVWF 0x26 
				MOVLW SEV2 
				MOVWF 0x27 

				MOVLW TWO1 
				MOVWF 0x28 
				MOVLW TWO2 
				MOVWF 0x29 

				MOVLW EMP1 
				MOVWF 0x2A 
				MOVLW EMP2 
				MOVWF 0x2B 

				MOVLW EMP1 
				MOVWF 0x2C 
				MOVLW EMP2 
				MOVWF 0x2D 

				MOVLW EMP1 
				MOVWF 0x2E 
				MOVLW EMP2 
				MOVWF 0x2F 

				MOVLW EMP1 
				MOVWF 0x30 
				MOVLW EMP2 
				MOVWF 0x31 

				MOVLW EMP1 
				MOVWF 0x32 
				MOVLW EMP2 
				MOVWF 0x33 

				MOVLW EMP1 
				MOVWF 0x34 
				MOVLW EMP2 
				MOVWF 0x35 

				MOVLW EMP1 
				MOVWF 0x36 
				MOVLW EMP2 
				MOVWF 0x37 

				MOVLW EMP1 
				MOVWF 0x38 
				MOVLW EMP2 
				MOVWF 0x39 

				MOVLW EMP1 
				MOVWF 0x3A 
				MOVLW EMP2 
				MOVWF 0x3B 

				MOVLW ONE1 
				MOVWF 0x3C 
				MOVLW ONE2 
				MOVWF 0x3D 

				MOVLW TWO1 
				MOVWF 0x3E 
				MOVLW TWO2 
				MOVWF 0x3F 

				MOVLW EMP1 
				MOVWF 0x40 
				MOVLW EMP2 
				MOVWF 0x41 

				MOVLW EMP1 
				MOVWF 0x42 
				MOVLW EMP2 
				MOVWF 0x43 

				MOVLW EIG1 
				MOVWF 0x44 
				MOVLW EIG2 
				MOVWF 0x45 

				MOVLW EMP1 
				MOVWF 0x46 
				MOVLW EMP2 
				MOVWF 0x47 

				MOVLW EMP1 
				MOVWF 0x48 
				MOVLW EMP2 
				MOVWF 0x49 

				MOVLW EMP1 
				MOVWF 0x4A 
				MOVLW EMP2 
				MOVWF 0x4B 

				MOVLW FOU1 
				MOVWF 0x4C 
				MOVLW FOU2 
				MOVWF 0x4D 

				MOVLW EMP1 
				MOVWF 0x4E 
				MOVLW EMP2 
				MOVWF 0x4F 

				MOVLW EMP1 
				MOVWF 0x50 
				MOVLW EMP2 
				MOVWF 0x51 

				MOVLW EMP1 
				MOVWF 0x52 
				MOVLW EMP2 
				MOVWF 0x53 

				MOVLW EMP1 
				MOVWF 0x54 
				MOVLW EMP2 
				MOVWF 0x55 

				BCF STATUS,RP0
				BCF STATUS,RP1
				;endregion					

START:			CLRF BANK ;BANK equals zero at a start
				
				;setbank
				;region
SETBANK:		BTFSC BANK,0
				GOTO ODDBANK	
				BTFSC BANK,1
				GOTO BANK2
				GOTO BANK0

ODDBANK:		BTFSC BANK,1
				GOTO NEW ;means we finished
				GOTO BANK1 ;BANK1

BANK0:			MOVLW 0x20 ;that's where the GPRs start
				BCF STATUS,IRP
				GOTO INIT

BANK1:			MOVLW 0xA0
				BCF STATUS,IRP
				GOTO INIT

BANK2:			MOVLW 0x20
				BSF STATUS,IRP ;indirect addressing, we'll need that bit to be set
				GOTO INIT
				;endregion
		
INIT:			MOVWF FSR ;	
	
				;0x36 equals 54 in decimal, that's the amount of bytes we have to go through in a given bank (27 sudoku cells * 2 bytes per cell)
				MOVLW 0x36
				MOVWF COUNT1	

				;so, for each byte
LOOP:	
				;we check if it's an even byte or an odd byte
				BTFSC FSR,0 
				GOTO SECOND				

				;even byte, aka first byte of that cell, we simply store its value at VALUE1
FIRST:			MOVF INDF, W 
				MOVWF VALUE1
				GOTO NEXT

				;odd byte, aka second byte
SECOND:			
				;we store the second byte of our cell at VALUE2
				MOVF INDF, W
				MOVWF VALUE2
				
				;we'll behave differently whether that cell is already set or not
				BTFSC INDF,6 
				GOTO ISSET
				GOTO ISNOTSET
				
;is set
;region
ISSET:	
				;if we are on part 1 of the attack (that is, removing possibilities), a set cell is juicy
				;if not, we just move on to next byte
				BTFSC FLAGS,1
				GOTO NEXT
				BTFSS INDF,5 ;we check whether that value has already been removed from it's column/zone/row or not (don't want to do it more than once)
				GOTO DELETE
				GOTO NEXT

				;now that we are here, we are going to delete our value as possible from every cell in our column, zone and row
				;we'll only remove it from cells without a sure value, so we won't remove it from ours!
DELETE:				
				BSF INDF,5 ;we make sure that we won't do this more than once			
				
				;we save current FSR, since we are going to modify its value, and we'll want to have it back later
				MOVF FSR,W
				MOVWF FSROLD

				;delete our value as possible from our column
				;region																				
				CALL COLUMNSTARTS ;places in W the memory location where the first cell of our column is located
				MOVWF FSR ;and we move right there
				
				;for each cell of our column
				MOVLW 0x9
				MOVWF COUNT2		

LOOPCOLUMN:
				;we check if the cell has a sure value
				INCF FSR,F				
				BTFSS INDF,6
				GOTO DELFROMCOL ;it has not a sure value, so let's delete ours (in case it's there, anyways)
				GOTO NEXTINCOLUMN ;it has a sure value, so let's move on to next cell
								
DELFROMCOL:		CALL DELETEFROMINDF			
				
NEXTINCOLUMN:	;move on to next cell in the column
				INCF FSR,F
				DECFSZ COUNT2,F
				GOTO LOOPCOLUMN		
				;endregion								
								
				;delete our value as possible from our zone
				;region
				CALL ZONESTARTS ;places in W the memory location where the first cell of our zone is located
				MOVWF FSR ;and we move right there
				
				;going through every cell in a zone is a bit harder, remember it's 3x3
				MOVLW 0x3
				MOVWF COUNT2	
				MOVWF COUNT3

LOOPZONE:
				;we check if the cell has a sure value				
				INCF FSR,F				
				BTFSS INDF,6
				GOTO DELFROMZONE ;it has not a sure value, so let's delete ours (in case it's there, anyways)
				GOTO NEXTINZONE ;it has a sure value so let's move on to next cell
								
DELFROMZONE:	CALL DELETEFROMINDF						
				
NEXTINZONE:		;move on to next cell in the column
				INCF FSR,F
				DECFSZ COUNT2,F
				GOTO LOOPZONE
				DECFSZ COUNT3,F
				GOTO AUXZONE ;and COUNT3 is not
				GOTO FINISHZONE ;and COUNT3 is, too
				
AUXZONE:		;we'll go through 3 more cells
				MOVLW 0x3
				MOVWF COUNT2
				;that are in the next column (adding 0xC makes you move on to next column)
				MOVLW 0xC
				ADDWF FSR,F
				
				GOTO LOOPZONE
				
				;we are done with the zone
FINISHZONE:		
				
				;endregion
				
				;delete our value as possible from our row
				;region				
				CALL ROWSTARTS ;places in W the memory location where the first cell of our row is located
				MOVWF FSR ;and we move right there
				BCF STATUS,IRP ;all rows start in BANK 0 (keep in mind that not all cells in a row are in the same bank, as opposed to what happened with columns and zones)
				
				;3 cells in each one of the 3 banks
				MOVLW 0x3
				MOVWF COUNT2	
				MOVWF COUNT3	

LOOPROW:
				;we check if the cell has a sure value				
				INCF FSR,F				
				BTFSS INDF,6
				GOTO DELFROMROW ;it has not a sure value, so let's delete ours (in case it's there, anyways)
				GOTO NEXTINROW ;it has a sure value so let's move on to next cell
								
DELFROMROW:		CALL DELETEFROMINDF				
				
NEXTINROW:			
				;adding 0x11 takes you to the next cell
				MOVLW 0x11
				ADDWF FSR,F				
				DECFSZ COUNT2,F
				GOTO LOOPROW
				DECFSZ COUNT3,F
				GOTO AUXROW ;COUNT2 is zero, COUNT3 is not
				GOTO FINISHROW ;both COUNT2 and COUNT3 are zero
				
AUXROW:			;3 more cells, next bank
				MOVLW 0x3
				MOVWF COUNT2
				;check which bank we are currently at
				BTFSC FSR,7
				GOTO SETIRP ;we are in bank 1, so let's move on to bank 2 (by setting IRP)
				;we are in bank 0, so simply by increasing FSR we can move on to bank 1
				MOVLW 0x4A				
				ADDWF FSR,F
				GOTO LOOPROW
				
SETIRP:				
				BSF STATUS,IRP
				MOVLW 0xB6
				SUBWF FSR,F
				GOTO LOOPROW
				
				;we want our old FSR back
FINISHROW:		MOVF FSROLD,W
				MOVWF FSR
				;and our old bank back too, please
				BTFSC BANK,1
				GOTO ROWSETIRP
				
				BCF STATUS,IRP
				GOTO NEXT
ROWSETIRP:		BSF STATUS,IRP
				;endregion

				GOTO NEXT
				;endregion

;is not set
;region			
ISNOTSET:						
				;if we are on part 2 of the attack (that is, setting sure values), a free cell is juicy
				;if not, we just move on to next byte
				BTFSS FLAGS,1
				GOTO NEXT
				
				;we save current FSR, since we are going to modify its value, and we'll want to have it back later
				MOVF FSR,W
				MOVWF FSROLD
				
				;set the value as sure if it has only one possible value
				;region
				;get the number of 1s at VALUE1 (that is the number of possible values from 1 to 8)
				MOVF VALUE1,W
				MOVWF INPUT
				CALL NUMBEROF1S ;it'll store the result in W
				
				;if W equals 0, this cell must be a 9, so we set it's value
				ANDLW 0xFF ;this is just so the flags of STATUS are refreshed
				BTFSS STATUS,Z
				GOTO ISNOTZERO
				
				;so yes, W equals 0
				BSF INDF,6 ;the value is set
				BSF FLAGS,0 ;we have set a value
				GOTO NEXT
				
				;in case W doesn't equal 0
ISNOTZERO:				
				;if W was 1, and 9 wasn't a possible value, we can set its value too
				MOVWF TEMP
				DECFSZ TEMP,F
				GOTO UNIQUEINCOL ;W doesn't equal 1 either, it's more than that, we can't set it
				BTFSC INDF,7 ;W equals 1 and it can't be a 9
				GOTO UNIQUEINCOL ;W equals 1, but it could be a 9 too, so we know nothing
				
				BSF INDF,6 ;the value is set
				BSF FLAGS,0 ;we have set a value
				GOTO NEXT
				;endregion

				;set the value as sure if it's the only at its column with a certain value as possible
				;region
UNIQUEINCOL:									
				CALL COLUMNSTARTS ;places in W the memory location where the first cell of our column is located
				MOVWF FSR ;and we move right there			
				;for each cell of our column
				MOVLW 0x9
				MOVWF COUNT2		

LOOPCOLUMN2:
				;we check if the cell is not the one we are trying to find a value for (which is stored at FSROLD)
				INCF FSR,W
				SUBWF FSROLD,W
				BTFSS STATUS,Z
				GOTO DELPOSCOL ;it isn't the one we are trying to find a value for
				;could be the one we are trying to find a value for, or could be one with same FSR but different bank
				BTFSC BANK,1
				GOTO BANK2UC
				;if we are here it means that if STATUS,IRP equals 0 this is the one we are trying to find a value for
				BTFSC STATUS,IRP
				GOTO DELPOSCOL ;heh, it's not the one
				GOTO ITISTHEONEC
BANK2UC:		;if we are here it means that if STATUS,IRP equals 1 this is the one we are trying to find a value for
				BTFSS STATUS,IRP
				GOTO DELPOSCOL
				
ITISTHEONEC:	INCF FSR,F
				GOTO NEXTINCOL ;it is the one we are trying to find a value for								
				
								
DELPOSCOL:			
				CALL DELETEFROMVALUE12		
				
NEXTINCOL:		;move on to next cell in the column
				INCF FSR,F
				DECFSZ COUNT2,F
				GOTO LOOPCOLUMN2
				
				;we are done with the column, let's get our old FSR back (it points to the second byte of the cell) and make it point to the 1st byte
				MOVF FSROLD,W
				MOVWF FSR					
				
				;if there's a bit at VALUE1 (or VALUE2, in case it's a nine) that equals 1, the cell can be set! and we move the contents from VALUE1 and VALUE2 to the cell's
				MOVF VALUE1,W
				MOVWF INPUT
				CALL NUMBEROF1S
				;if W equals 0, our only chance is that the cell is 9
				ANDLW 0xFF ;this is just so the flags of STATUS are refreshed
				BTFSS STATUS,Z
				GOTO CANSETVALUE
				
				;so yes, W equals 0, let's see if it's a nine
				BTFSS VALUE2,7												
				GOTO UNIQUEINZON ;it's not a 9, we can't set it :( (so we try another attack)
								
				;in case W doesn't equal 0, we can set it's value! we move the contents from VALUE1 and VALUE2 to the cell's				
CANSETVALUE:	CALL SETVALSUB				
				GOTO NEXT								
				;endregion
				
				;set the value as sure if it's the only at its zone with a certain value as possible
				;region
UNIQUEINZON:				

				;reset value1 and value2
				CALL RESETVAL12

				CALL ZONESTARTS ;places in W the memory location where the first cell of our zone is located
				MOVWF FSR ;and we move right there
				
				;going through every cell in a zone is a bit harder, remember it's 3x3
				MOVLW 0x3
				MOVWF COUNT2	
				MOVWF COUNT3

LOOPZONE2:
				;we check if the cell is not the one we are trying to find a value for (which is stored at FSROLD)
				INCF FSR,W
				SUBWF FSROLD,W
				BTFSS STATUS,Z
				GOTO DELPOSZON ;it isn't the one we are trying to find a value for
				;could be the one we are trying to find a value for, or could be one with same FSR but different bank
				BTFSC BANK,1
				GOTO BANK2UZ
				;if we are here it means that if STATUS,IRP equals 0 this is the one we are trying to find a value for
				BTFSC STATUS,IRP
				GOTO DELPOSZON ;heh, it's not the one
				GOTO ITISTHEONEZ
BANK2UZ:		;if we are here it means that if STATUS,IRP equals 1 this is the one we are trying to find a value for
				BTFSS STATUS,IRP
				GOTO DELPOSZON
				
ITISTHEONEZ:	INCF FSR,F
				GOTO NEXTINZON ;it is the one we are trying to find a value for				
								
DELPOSZON:			
				CALL DELETEFROMVALUE12			
				
NEXTINZON:		;move on to next cell in the column
				INCF FSR,F
				DECFSZ COUNT2,F
				GOTO LOOPZONE2
				DECFSZ COUNT3,F
				GOTO AUXZONE2 ;and COUNT3 is not
				GOTO FINISHZONE2 ;and COUNT3 is, too
				
AUXZONE2:		;we'll go through 3 more cells
				MOVLW 0x3
				MOVWF COUNT2
				;that are in the next column (adding 0xC makes you move on to next column)
				MOVLW 0xC
				ADDWF FSR,F
				
				GOTO LOOPZONE2
								
FINISHZONE2:																											
				;we are done with the zone, let's get our old FSR back
				MOVF FSROLD,W
				MOVWF FSR					
				
				;if there's a bit at VALUE1 (or VALUE2, in case it's a nine) that equals 1, the cell can be set! and we move the contents from VALUE1 and VALUE2 to the cell's
				MOVF VALUE1,W
				MOVWF INPUT
				CALL NUMBEROF1S
				;if W equals 0, our only chance is that the cell is 9
				ANDLW 0xFF ;this is just so the flags of STATUS are refreshed
				BTFSS STATUS,Z
				GOTO CANSETVALUE2
				
				;so yes, W equals 0, let's see if it's a nine
				BTFSS VALUE2,7												
				GOTO UNIQUEINROW ;it's not a 9, we can't set it :(
								
				;in case W doesn't equal 0, we can set it's value! we move the contents from VALUE1 and VALUE2 to the cell's
CANSETVALUE2:	CALL SETVALSUB				
				GOTO NEXT						
				;endregion
				
				;set the value as sure if it's the only at its row with a certain value as possible
				;region
UNIQUEINROW:				

				;reset value1 and value2
				CALL RESETVAL12

				CALL ROWSTARTS ;places in W the memory location where the first cell of our row is located
				MOVWF FSR ;and we move right there
				BCF STATUS,IRP ;all rows start in BANK 0 (keep in mind that not all cells in a row are in the same bank, as opposed to what happened with columns and zones)
				
				;3 cells in each one of the 3 banks
				MOVLW 0x3
				MOVWF COUNT2	
				MOVWF COUNT3	

LOOPROW2:
				;we check if the cell is not the one we are trying to find a value for (which is stored at FSROLD)
				INCF FSR,W
				SUBWF FSROLD,W
				BTFSS STATUS,Z
				GOTO DELPOSROW ;it isn't the one we are trying to find a value for
				;could be the one we are trying to find a value for, or could be one with same FSR but different bank
				BTFSC BANK,1
				GOTO BANK2UR
				;if we are here it means that if STATUS,IRP equals 0 this is the one we are trying to find a value for
				BTFSC STATUS,IRP
				GOTO DELPOSROW ;heh, it's not the one
				GOTO ITISTHEONER
BANK2UR:		;if we are here it means that if STATUS,IRP equals 1 this is the one we are trying to find a value for
				BTFSS STATUS,IRP
				GOTO DELPOSROW
				
ITISTHEONER:	INCF FSR,F
				GOTO NEXTINR ;it is the one we are trying to find a value for		
								
DELPOSROW:			
				CALL DELETEFROMVALUE12				

NEXTINR:			
				;adding 0x11 takes you to the next cell
				MOVLW 0x11
				ADDWF FSR,F				
				DECFSZ COUNT2,F
				GOTO LOOPROW2
				DECFSZ COUNT3,F
				GOTO AUXROW2 ;COUNT2 is zero, COUNT3 is not
				GOTO FINISHROW2 ;both COUNT2 and COUNT3 are zero
				
AUXROW2:		;3 more cells, next bank
				MOVLW 0x3
				MOVWF COUNT2
				;check which bank we are currently at
				BTFSC FSR,7
				GOTO SETIRP2 ;we are in bank 1, so let's move on to bank 2 (by setting IRP)
				;we are in bank 0, so simply by increasing FSR we can move on to bank 1
				MOVLW 0x4A				
				ADDWF FSR,F
				GOTO LOOPROW2
				
SETIRP2:				
				BSF STATUS,IRP
				MOVLW 0xB6
				SUBWF FSR,F
				GOTO LOOPROW2
				
				;we want our old FSR back
FINISHROW2:		MOVF FSROLD,W
				MOVWF FSR
				;and our old bank back too, please
				BTFSC BANK,1
				GOTO ROWSETIRP2				
				BCF STATUS,IRP
				GOTO KEEPONUNR
				
ROWSETIRP2:		BSF STATUS,IRP				
																																								

KEEPONUNR:

				;if there's a bit at VALUE1 (or VALUE2, in case it's a nine) that equals 1, the cell can be set! and we move the contents from VALUE1 and VALUE2 to the cell's
				MOVF VALUE1,W
				MOVWF INPUT
				CALL NUMBEROF1S
				;if W equals 0, our only chance is that the cell is 9
				ANDLW 0xFF ;this is just so the flags of STATUS are refreshed
				BTFSS STATUS,Z
				GOTO CANSETVALUE3
				
				;so yes, W equals 0, let's see if it's a nine
				BTFSS VALUE2,7												
				GOTO NEXT ;it's not a 9, we can't set it :(
								
				;in case W doesn't equal 0, we can set it's value! we move the contents from VALUE1 and VALUE2 to the cell's
CANSETVALUE3:	CALL SETVALSUB				
				GOTO NEXT										
				;endregion

								
;endregion

NEXT:			INCF FSR,F
				DECFSZ COUNT1,F
				GOTO LOOP

				;COUNT1 reached zero, move on to next bank
				INCF BANK,F
				GOTO SETBANK
												
NEW:			;we reach this point each time we have gone through every cell of the sudoku								
				
				;let's check if we are on attack 1 (remove possible values) or attack 2 (set values as sure)
				BTFSS FLAGS,1
				GOTO FIRSTATTACK
						
				;we are on attack 2
				BTFSS FLAGS,0						
				GOTO ENDING ;and we didn't set any new values, I'm afraid we are done with this sudoku
				;we did set at least one! restart the process				
				BCF FLAGS,1
				GOTO START																

FIRSTATTACK:	;let's move on to second attack
				BSF FLAGS,1 
				;and we haven't set any values yet
				BCF FLAGS,0 
				GOTO START				

				;subroutine that places in W the memory address where the first cell of our column is located (our cell's address is stored in FSROLD)
				;region
COLUMNSTARTS:
				;it basically checks which interval FSROLD is in (out of 6 possibilities)
				
				MOVF FSROLD,W
				SUBLW 0xC3
				BTFSS STATUS,C
				RETLW 0xC4
				
				MOVF FSROLD,W
				SUBLW 0xB1
				BTFSS STATUS,C
				RETLW 0xB2

				MOVF FSROLD,W
				SUBLW 0x9F
				BTFSS STATUS,C
				RETLW 0xA0								
				
				MOVF FSROLD,W
				SUBLW 0x43
				BTFSS STATUS,C
				RETLW 0x44

				MOVF FSROLD,W
				SUBLW 0x31
				BTFSS STATUS,C
				RETLW 0x32

				MOVF FSROLD,W
				SUBLW 0x1F
				BTFSS STATUS,C
				RETLW 0x20 				
				;endregion
				
				;subroutine that places in W the memory address where the first cell of our zone is located (our cell's address is stored in FSROLD)
				;region
ZONESTARTS:				
				MOVF FSROLD,W 
				ANDLW 0x7F ;we get rid of it's most significative bit				
				MOVWF TEMP		
				
				SUBLW 0x50-1
				BTFSS STATUS,C
				GOTO SUBZONEA				
	
				MOVF TEMP,W
				SUBLW 0x4A-1
				BTFSS STATUS,C
				GOTO SUBZONEB				

				MOVF TEMP,W
				SUBLW 0x44-1
				BTFSS STATUS,C
				GOTO SUBZONEC				
	
				MOVF TEMP,W
				SUBLW 0x3E-1
				BTFSS STATUS,C
				GOTO SUBZONEA				
	
				MOVF TEMP,W
				SUBLW 0x38-1
				BTFSS STATUS,C
				GOTO SUBZONEB				
	
				MOVF TEMP,W
				SUBLW 0x32-1
				BTFSS STATUS,C
				GOTO SUBZONEC				
					
				MOVF TEMP,W
				SUBLW 0x2C-1
				BTFSS STATUS,C
				GOTO SUBZONEA
					
				MOVF TEMP,W
				SUBLW 0x26-1
				BTFSS STATUS,C
				GOTO SUBZONEB				
				
				MOVF TEMP,W
				SUBLW 0x20-1
				BTFSS STATUS,C
				GOTO SUBZONEC				
		
				;and it's now that we take that most significative bit of FSROLD into account
		
SUBZONEA:
				RLF FSROLD,W
				BTFSS STATUS,C
				RETLW 0x2C
				RETLW 0xAC
			
SUBZONEB:
				RLF FSROLD,W
				BTFSS STATUS,C
				RETLW 0x26
				RETLW 0xA6
	
SUBZONEC:
				RLF FSROLD,W
				BTFSS STATUS,C
				RETLW 0x20
				RETLW 0xA0
				;endregion
				
				;subroutine that places in W the memory address where the first cell of our row is located (our cell's address is stored in FSROLD)
				;region
ROWSTARTS:				
				MOVF FSROLD,W
				ANDLW 0x7F ;we get rid of its most significative bit
				MOVWF TEMP
	
SUBROW:
			
				MOVF TEMP,W
				SUBLW 0x21
				BTFSC STATUS,Z
				RETLW 0x20

				MOVF TEMP,W
				SUBLW 0x23
				BTFSC STATUS,Z
				RETLW 0x22

				MOVF TEMP,W
				SUBLW 0x25
				BTFSC STATUS,Z
				RETLW 0x24

				MOVF TEMP,W
				SUBLW 0x27
				BTFSC STATUS,Z
				RETLW 0x26
				
				MOVF TEMP,W
				SUBLW 0x29
				BTFSC STATUS,Z
				RETLW 0x28
		
				MOVF TEMP,W
				SUBLW 0x2B
				BTFSC STATUS,Z
				RETLW 0x2A

				MOVF TEMP,W
				SUBLW 0x2D
				BTFSC STATUS,Z
				RETLW 0x2C

				MOVF TEMP,W
				SUBLW 0x2F
				BTFSC STATUS,Z
				RETLW 0x2E

				MOVF TEMP,W
				SUBLW 0x31
				BTFSC STATUS,Z
				RETLW 0x30				

				;if it reached this point, it means we aren't in a first-column cell, so we move on to previous column (same row)				
				MOVLW 0x12
				SUBWF TEMP,F				
				
				GOTO SUBROW
				;endregion
				
				;subroutine that finds out (and places in W) how many 1s there are at INPUT
				;region				
												
NUMBEROF1S:				
				CLRF RESULT
											
SUBNUMBERA:
				BCF STATUS,C
				ANDLW 0xFF
				BTFSS STATUS,Z ;if it's zero, there won't be any more bits with a value of 1, so we can stop counting
				GOTO SUBNUMBERB ;if not (there will be more 1s)
				MOVF RESULT,W
				RETURN

SUBNUMBERB:
				RLF INPUT,W
				BTFSC STATUS,C
				INCF RESULT,F ;we found a 1 (the carry was set after the rotation)
				MOVWF INPUT
				GOTO SUBNUMBERA
				;endregion
				
				;subroutine that deletes a value (which is sure at some cell) from the list of possible values of another cell
				;region
DELETEFROMINDF:
				;delete from its first byte
				DECF FSR,F
				COMF VALUE1,W				
				ANDWF INDF,F				

				;delete from its second byte
				INCF FSR,F
				COMF VALUE2,W
				ANDWF INDF,F	
				
				RETURN
				;endregion
			
				;subroutine that deletes possibilities (which are possible at some cell) from a copy of the list of possible values of another cell (the copy being at VALUE1, VALUE2)
				;region
DELETEFROMVALUE12:
				;delete from its first byte								
				COMF INDF,W				
				ANDWF VALUE1,F						

				;delete from its second byte
				INCF FSR,F
				COMF INDF,W
				ANDWF VALUE2,F			
				RETURN
				;endregion
				
				;subroutine that sets the content of VALUE1, VALUE2 into INDF
				;region
SETVALSUB:
				DECF FSR,F
				MOVF VALUE1,W				
				MOVWF INDF
				
				INCF FSR,F
				MOVF VALUE2,W
				MOVWF INDF				
				
				BSF INDF,6 ;the value is set
				BSF FLAGS,0 ;we have set a value
				
				RETURN
				;endregion
				
				;subroutine that reselts the content of VALUE1 and VALUE2
				;region
RESETVAL12:
				MOVF FSROLD,W
				MOVWF FSR
				MOVF INDF,W
				MOVWF VALUE2
				DECF FSR,F
				MOVF INDF,W
				MOVWF VALUE1				
				RETURN
				;endregion
				
ENDING:			END				