Isometric Chess display engine
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Graph Paper
Thank you!
Generally more recently I just arrange coloured blocks in Illustrator when designing graphical stuff.
When I did the sprites for my Isometric Chess display engine (Looks whats possible in 924 bytes thread on WOS*) I had to colour code it all to keep track of what BITs did what.
*Actually its currently 722 bytes!
Generally more recently I just arrange coloured blocks in Illustrator when designing graphical stuff.
When I did the sprites for my Isometric Chess display engine (Looks whats possible in 924 bytes thread on WOS*) I had to colour code it all to keep track of what BITs did what.
*Actually its currently 722 bytes!
Re: Graph Paper
Did you write about the development? I would be interested in finding out more how you did this Just curious. That is very impressive to get the display engine into such a state. Ok I admit it I am green with envy. Welcome to the forum fella.arkannoyed wrote: ↑Mon Feb 05, 2018 12:27 pm
When I did the sprites for my Isometric Chess display engine (Looks whats possible in 924 bytes thread on WOS*) I had to colour code it all to keep track of what BITs did what.
*Actually its currently 722 bytes!
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Graph Paper
Ta.
I sort of wrote about it on the WOS forums and posted the .ASM too. Its bloody complicated is what it is! I could do a thread trying to explain it all again maybe. I still have an ambition to re-write it (yet again!), and try to make it more straight forward to comprehend. Trouble is, the graphics format and actually decoding it is so finely balanced between beauty and utter disaster that I even struggle to remember its intricacies some days. Once I get a little free time I'll perhaps go for the push to get it under 700 bytes. Do you want me to post the .asm as it currently is?
I sort of wrote about it on the WOS forums and posted the .ASM too. Its bloody complicated is what it is! I could do a thread trying to explain it all again maybe. I still have an ambition to re-write it (yet again!), and try to make it more straight forward to comprehend. Trouble is, the graphics format and actually decoding it is so finely balanced between beauty and utter disaster that I even struggle to remember its intricacies some days. Once I get a little free time I'll perhaps go for the push to get it under 700 bytes. Do you want me to post the .asm as it currently is?
Re: Graph Paper
Yes that would be great, I am trying to make my own chess program and its been slow going seeing some super slick ideas I think will give me the motivation to plow on with my own project The literate programming is good for projects that are mind benders as you can just write about them actually in the code as your working. No messing with external documentation tools. I'll have a look at WOS see if I can track down your thread.arkannoyed wrote: ↑Mon Feb 05, 2018 3:32 pm Ta.
I sort of wrote about it on the WOS forums and posted the .ASM too. Its bloody complicated is what it is! I could do a thread trying to explain it all again maybe. I still have an ambition to re-write it (yet again!), and try to make it more straight forward to comprehend. Trouble is, the graphics format and actually decoding it is so finely balanced between beauty and utter disaster that I even struggle to remember its intricacies some days. Once I get a little free time I'll perhaps go for the push to get it under 700 bytes. Do you want me to post the .asm as it currently is?
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Graph Paper
Here you go. I did try and comment the source as far as I could, honest!
Just ask if anything doesn't make sense. Actually thats probably most of it!
Code: Select all
;Isometric Chess board display engine version 0.83c
;(c) 1992-2017 JES
;722 bytes
org 0fc00h
db %10010001,%00110011,%10000000,%11000100,%10000000,%10001000
initialise_board:
ld de,0ffc0h
ld hl,data_17
ld b,d
ld c,d
ib_loop1:
ld a,(hl)
inc a
ld (bc),a
ldi
jr nz,ib_loop1
dec e
ld b,20h
ib_loop2:
ld (de),a
inc e
djnz ib_loop2
ret ;24 bytes (+17 data)
nop
db %11111101,%10011001,%11111001,%11101110,%11111111,%10011001,%10111001,%10001011
db %10111011,%11001011,%11111011,%00100011,%00100010,%01100101,%01100100,%01100100
db %00100000,%00010011,%00110111,%10111101,%10011101,%10111011,%10001010,%10011011
db %01010111,%01010111,%01000101,%00011001,%01001101,%01101011,%00101001,%00001110
db %01101100,%00100000,%01001100,%01110011,%00110011,%01010101,%11111101,%10111111
db %11010011,%01101000,%01001000,%10111111,%11111101,%00001001,%01011101,%01001011
db %00111000,%01001111,%01001010,%00100000,%01101000,%01010011,%01010010,%01100001
db %01100001,%01011011,%11011011,%01110100,%11111001,%10000011,%11110001,%01010111
db %01000111,%00111100,%10100111,%00001100,%10100100,%10000011,%00010001,%11100010
db %01000010,%01111101,%11100000,%00000110,%10100110,%10010001,%10110001,%00000010
db %01011011,%01110101,%10101101,%10010010,%10000011,%10100100,%11100100,%11001110
db %10010001,%00110011,%11110011,%10100110,%10111111,%11001000,%10111011,%10101011
db %01001101,%01001101,%01100110,%01100010,%01010001,%00100110,%10110111,%11110011
db %11100011,%11001110,%11100001,%00100100,%01001000,%00111111,%10111111,%10011001
db %10111001,%00101100,%11111101,%01011111,%00100010,%00001001,%01100111,%01000101
db %01100101,%01100111,%01100110,%00001010,%11111011,%10101101,%00100010,%11101001
db %10101100,%00101010,%11111011,%00011001,%00111011,%00011101,%01011001,%00000110
db %00101000,%01010111,%00000011,%01100111,%10001001,%11001101,%10001101,%01000011
db %11111011,%10100011,%11100010,%00100111,%11100110,%00001010,%11101110,%00110011
db %11110101,%10110011,%10110101,%00101100,%11100000,%00011111,%10100011,%11000101
db %00100011,%11101101,%11000101,%01001101,%11000111,%10000011,%00100010,%11001101
db %10101110,%00111111,%11011011,%10110011,%10010011,%01010101,%11000110,%01001101
db %11001101,%01010100,%10111010,%10100011,%10100011,%00001001,%11101110,%01101111
db %11000010,%10100110,%01010111,%10011111,%11011010,%11001101,%11001010,%00000000
db %00010001,%01010100,%01100111,%00100110,%01100000,%10000011,%11111101,%10111101
db %11101000,%11000110,%11100111,%00000001,%01101111,%01101100,%00001100,%00111001
db %00011001,%01110111,%01110111,%01100110,%01000101,%10101010,%11101110,%01111011
db %10011011,%10110111,%11000110,%00010110,%11000010,%01011001,%11011011,%01011101
db %01001100,%11011101
index_data:
db %00000000;line 00
db 80h ;line 01
db 80h ;line 02
db %00000100;line 03
db %00000111;line 04
db %00001001;line 05
db %00011001;line 06
db %01110100;line 07
db %01110100;line 08
db 87h ;line 09
db 88h ;line 0A
db %01000111;line 0B
db %00101001;line 0C
db %00011001;line 0D
db %00001001;line 0E end of base
db %01000100;line 0F
db %01000011;line 10
db %01000011;line 11
db 90h ;line 12
db 91h ;line 13
db %00110011;line 14
db %00100100;line 15
db 94h ;line 16
db 95h ;line 17
db %00100011;line 18
db %00100011;line 19
db 98h ;line 1A
db 99h ;line 1B
db 98h ;line 1C
db %00000110;line 1D
db %00000111;line 1E
db %01000100;line 1F
db %00110101;line 20
db %00000111;line 21
db %00000110;line 22
db %00100011;line 23
db %00110011;line 24
db %00110011;line 25
db 0a4h ;line 26
db %01000011;line 27
db %00100101;line 28
db %00010111;line 29
db %00010110;line 2A
db %00000110;line 2B
db %00000100;line 2C
db %01000001;line 2D
db %00010011;line 2E
db %00000011;line 2F
db %00000001;line 30 end of king
db %00010110;line 31
db %00010111;line 32
db %00010111;line 33
db %00000111;line 34
db %00000100;line 35
db %00010001;line 36
db 0b0h ;line 37 end of queen
db 98h ;line 38
db 9dh ;line 39
db 9eh ;line 3A
db 9fh ;line 3B
db 0a0h ;line 3C
db 0a1h ;line 3D
db 0a2h ;line 3E
db 0a3h ;line 3F
db 0a4h ;line 40
db 0a5h ;line 41
db 0a4h ;line 42
db %00100100;line 43
db %00010100;line 44
db %00000101;line 45
db %00010011;line 46
db %00010011;line 47
db %00000011;line 48
db %00100010;line 49
db %00010010;line 4A
db 0b6h ;line 4B
db 0b0h ;line 4C end of bishop
db %00010101;line 4D
db 9dh ;line 4E
db 9eh ;line 4F
db 9fh ;line 50
db 0a0h ;line 51
db 0a1h ;line 52
db %00000110;line 53
db 91h ;line 54
db %01010011;line 55
db 9fh ;line 56
db 0d5h ;line 57
db 9fh ;line 58
db %00100110;line 59
db %00010111;line 5A
db %00010111;line 5B
db %00010111;line 5C
db %00000111;line 5D
db 83h ;line 5E end of castle
db 91h ;line 5F
db %00110011;line 60
db %00110011;line 61
db %00100011;line 62
db 99h ;line 63
db %00010100;line 64
db 9dh ;line 65
db 9eh ;line 66
db 9fh ;line 67
db 0a0h ;line 68
db 0a1h ;line 69
db 0a2h ;line 6A
db %00100011;line 6B
db 0a4h ;line 6C
db 0a5h ;line 6D
db 0a4h ;line 6E
db 0a5h ;line 6F
db 98h ;line 70
db %00010100;line 71
db 0b5h ;line 72
db %00000010;line 73 end of pawn
db 91h ;line 74
db 90h ;line 75
db 95h ;line 76
db %00010101;line 77
db 9dh ;line 78
db 9eh ;line 79
db 9fh ;line 7A
db 0a0h ;line 7B
db 0a1h ;line 7C
db %00100100;line 7D
db %00000111;line 7E
db %00001000;line 7F
db %01010011;line 80
db %01000100;line 81
db %00001001;line 82
db %00001001;line 83
db %00001001;line 84
db %00001001;line 85
db %00011000;line 86
db %00001010;line 87
db %00001011;line 88
db %00001011;line 89
db %00001010;line 8A
db %00001001;line 8B
db %00001000;line 8C
db %00010101;line 8D
db %00000101;line 8E
db %00000100;line 8F
db %00000011;line 90
db %00000010;line 91
;db %00000001;line 92 shared with first byte of routine.
;end of knight
;145 bytes
chess_builder:
ld bc,00c0h ;start address of board
ld ixh,0fch ;data Hi-byte
main_loop:
dec b ;B=FFh
ld a,(bc) ;get piece occupying square into A
ld (main_call+1),a ;store
get_piece_height:
ld hl,piece_sizes-2 ;piece sizes & positions table base address
rra ;find piece data
ld b,a ;/2 into L
add a,a ;X2
add a,b ;+L = X3 = Trigger line, jump line, piece height
add a,l ;
ld l,a ;
ld a,(hl) ;this byte determines which index line we make the jump at
ld (jump_line+1),a ;
inc l ;
jump_to:
ld a,(hl) ;
ex af,af' ;this is the index line to jump to.
inc l ;
set_height:
ld b,(hl) ;this is the piece height
push bc ;
calc_square_addr:
ld a,c
ld de,0022h ;DE constant
ld hl,09f0h ;HL=square 00 address - 47h (47F0h)*
csa_lp0:
ld bc,031eh ;B=counter, C=next offset to add for rows
csa_lp1:
rra ;get lsb into carry
jr nc,csa_ovr ;
add hl,de ;
csa_ovr:
rl e ;E x 2
djnz csa_lp1 ;loop
ld e,c ;ld E,1Eh
jr c,csa_lp0 ;if we arrived here from the 1st pass, the carry
;would be set, so we loop again with the new E value
ld a,h ;
add a,a ;x2
add a,a ;x4
add a,a ;x8
dec a ;
ld h,a ;HL=square address
pop bc ;B=height C=current square ;D=00 already for line counter
get_len:
push de ;save current line
push bc ;save height + current square no.
current_square:
ld a,c ;c=curent square
and 09h ;
jp pe,main_call ;if white square, jump to main call
;change to JP PO to effectively rotate the board
;90 degrees.
new_calc_line:
ld a,d ;D=current line
sub 11h ;are we above the height of the board square?
jr nc,main_call ;if so, skip drawing the line
adc a,d ;
jr nc,ovr_e ;
jr z,skp1 ;
dec a ;
skp1:
cpl ;
ovr_e:
and 0fh ;
;
inc a ;
ld b,a ;line length /2 in B
add_line_in:
ld d,l ;save HL position
ld e,80h
addl_lp1:
rlc e ;next bit left
jr nc,addl_ovr1 ;
dec l ;update HL if theres a carry
addl_ovr1:
djnz addl_lp1 ;loop
draw_line:
add a,a ;x2 to get line length
ld b,a ;into B again
addl_lp2:
ld a,(hl) ;
or e ;
ld (hl),a ;merge bit with screen content
rrc e ;next right bit
jr nc,addl_ovr2 ;
inc l ;update HL if carry occurs
addl_ovr2:
djnz addl_lp2 ;
ld l,d ;restore HL
main_call:
ld a,00h ;piece occupying the current square
or a ;is it empty?
call nz,builder_core ;call main build routine if a piece occupies the square
reset_centre:
res 0,l ;ensure we're at the centre again.
next_line_up:
ld a,h ;fairly standard stuff
dec h ;I'm sure we're all
and 07h ;familiar with!
jr nz,nlu_end ;
ld a,l ;
add a,0e0h ;
ld l,a ;
sbc a,a ;
and 08h ;
add a,h ;
ld h,a ;
nlu_end:
pop bc ;B=height C=current square
pop de ;D=line
inc d ;inc line
djnz get_len ;inner loop for pieces
xor a ;reset the index pointer
ld (hl_store+1),a ;
end_check_board:
inc c ;next square
jp nz,main_loop ;repeat if needed
ret ;ret
data_17:
db 04h,06h,08h,0ch,0ah,08h,06h,04h
db 02h,02h,02h,02h,02h,02h,02h,02h,0ffh ;17 bytes
builder_core:
push hl ;save screen position
ld de,081eh ;set the bit markers, 08h = White
rra ;is it a black or white piece?
jr c,hl_store
ld d,80h ;D=80h bit marker for Black
hl_store:
ld hl,0fd00h ;line no. current. in the index
ld a,l ;
inc a ;next index line
jump_line:
cp 00h ;test for line switch.
jr nz,update_line_point ;
switch:
ex af,af' ;restore A' holding index line to jump to
update_line_point:
ld (hl_store+1),a ;update the index pointer
calc_data_addr:
ld a,(hl) ;get the index data
add a,a ;test BIT 7
ld b,l ;
jr nc,calc_ovr ;if its a line, not a reference, then process
rrca ;
ld b,a ;corrected line reference
calc_ovr:
ld l,00h ;HL = base address FD00
ld c,e ;C holds data Lo byte
calc_lp0:
ld a,(hl) ;get index line data into A
add a,a ;test bit 7 and multiply data length x 2
jr c,calc_no_inc ;if no bit 7 then process addition of data len to the current position
and e ;mask data length value *1Eh
add a,c ;add current to total
jr nc,calc_lp1 ;
rrc d ;advance to next cycle bit
ld a,e ;reset data address to FD1Eh
calc_lp1:
ld c,a ;update data Lo byte
calc_no_inc:
inc l ;next index line
djnz calc_lp0 ;loop
ld ixl,c ;IX=data address
set_counters:
ld a,(hl) ;(HL) into A
add a,a ;X2
and e ;AND 1Eh
ld b,a ;into B
ld a,(hl) ;(HL) into A
rrca ;
rrca ;
rrca ;/8 (=C x 2)
and e ;mask again 1Eh
ld c,a ;into C
add a,b ;ADD B to get line length
restore_scradd:
pop hl ;restore buffer address
ret z ;if 00 then RET
rra ;line length /2 to give offset to left
ld e,80h ;set E screen bit mask
off_lp1:
rlc e ;calc offset left on screen
jr nc,off_lp2 ;
dec l ;
off_lp2:
dec a ;
jr nz,off_lp1
save_sp:
ld (sp_save+1),sp ;save SP to be restored at the end
set_white_ovr:
ld iy,4000h ;white overlay *depending upon the ititial value of IYL, this may not work reliably
push de ;save current bit position marker E
ld e,a ;set it to 00 invisible mode
b_w_check:
ld a,d ;current bit mask into A
add a,0f0h ;test for White
sbc a,a ;if white then there will be no carry
jr z,white ;result = 00 then jump to White
black: ;result = FF then Black
adc a,b
jr nz,get_bit ;
dec c ;the Black overlay is a 1 bit until C=00, then inverts to a 0 bit
sub c ;
jr alter_jr ;
white:
or c ;
jr z,get_bit ;go get data if C=00
dec c ;
add iy,iy ;propagate overlay bit into Carry
jr alter_jr ;
get_bit:
dec b ;DEC data counter
ld a,(ix+00) ;A=data byte
inc ixl ;next data byte for next pass
and d ;mask bit
sub d ;
alter_jr:
sbc a,a
jr nz,put_bit ;test if we've hit a zero bit to switch to placing data
pop de ;switch on E bit for screen printing
put_bit:
push hl ;backup screen address
xor (hl) ;
and e ;mask the bit
xor (hl) ;
ld (hl),a ;place the byte
push af ;backup byte result onto stack
next_right:
rrc e ;next bit right
jr nc,next_ovr
inc l
next_ovr:
push de
end_test:
ld a,b ;test if both counters = 00
or c ;
jr nz,b_w_check ;repeat if counters are not 00
restore_rhs:
pop de ;disregard this POP
pop af ;using the push'ed AFs
pop hl ;we can restore the background up to the point
ld (hl),a ;where we encounter a 0 bit
jr c,restore_rhs ;if 1 then we need to restore the bit from the background
sp_save:
ld sp,0000h ;restore base position of Stack Pointer
ret
piece_sizes:
db 11h ;square only - will use 2 previous bytes as blanks
db 0fh,5fh,24h ;pawn
db 17h,4dh,29h ;castle
db 0fh,74h,2eh ;knight
db 1ah,38h,2fh ;bishop
db 28h,31h,2fh ;queen
db 00h,00h,30h ;king
Re: Graph Paper
does it help printing real isometric graph papers?arkannoyed wrote: ↑Mon Feb 05, 2018 3:53 pm Apologies, I really should've perhaps created a new thread for it rather that ruin this one.
thats the one missing in this tread and the type off graph paper on which i learn some basics of 3d isometric drawing.
I was on school for 4 month to be a 'pipefitter' but my back is not strong enough (anymore).
- Ast A. Moore
- Rick Dangerous
- Posts: 2641
- Joined: Mon Nov 13, 2017 3:16 pm
Re: Isometric Chess display engine
Hey, [mention]arkannoyed[/mention] is here! Hello there, mate!
Every man should plant a tree, build a house, and write a ZX Spectrum game.
Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Re: Isometric Chess display engine
Robin Verhagen-Guest
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
SevenFFF / Threetwosevensixseven / colonel32
NXtel • NXTP • ESP Update • ESP Reset • CSpect Plugins
Re: Isometric Chess display engine
Know this is a bit cheeky arkannoyed but do you have a copy of the sprite reference sheet that you talk about, the dropbox link is 404.
https://www.worldofspectrum.org/forums/ ... 4-bytes/p3
https://dl.dropboxusercontent.com/u/280 ... g%20v4.pdf
That is quite an optimisation job, I didn't think you could get it that compact but each time you or Einar and the rest of the team take a look it seems bites are dropping off left and right
https://www.worldofspectrum.org/forums/ ... 4-bytes/p3
https://dl.dropboxusercontent.com/u/280 ... g%20v4.pdf
That is quite an optimisation job, I didn't think you could get it that compact but each time you or Einar and the rest of the team take a look it seems bites are dropping off left and right
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Isometric Chess display engine
Thanks everyone!
The sprite reference sheet would be a good place to begin, as its the case that the whole thing was built around the graphics data format initially.
I'll try and write some sort of easy to follow guide based upon a fragment of the data as an example.
https://dl.dropbox.com/s/2ncksrk1pgjv0 ... 4.pdf?dl=1
There have been a few minor changes to the actual sprites, but they were sort of done on the fly to save a few bits here and there, so I never got round to producing a 'final' graphics sheet.
The key on the top left hopefully gives an indication of what colour refers to what type of data the bit represents.
The sprite reference sheet would be a good place to begin, as its the case that the whole thing was built around the graphics data format initially.
I'll try and write some sort of easy to follow guide based upon a fragment of the data as an example.
https://dl.dropbox.com/s/2ncksrk1pgjv0 ... 4.pdf?dl=1
There have been a few minor changes to the actual sprites, but they were sort of done on the fly to save a few bits here and there, so I never got round to producing a 'final' graphics sheet.
The key on the top left hopefully gives an indication of what colour refers to what type of data the bit represents.
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Isometric Chess display engine
By the way, perhaps obvious to only me, but its upside-down because the sprites are drawn from the bottom up, so it was just easier to read it like that for me.
As you might be able to see, the White and Black pieces are the same width for each line, and symmetrical about the center line, except for when we get to the Knight.
As you can see, there are several leading (reading from the left) or trailing RED bits. These are balancing bits, which the sprite drawing routine ignores as actual sprite data, but interprets them as just an instruction to move the print position to the next pixel right. This allows the sprites to all be symmetrical without actually having to conform to that restriction in all cases.
The clever bit with this (well I thought so anyway!) is that these are no extra switch bits or whatever needed. The routine switches from mask to print mode. All of this is done in a rather memory hungry way by using the stack.
As you might be able to see, the White and Black pieces are the same width for each line, and symmetrical about the center line, except for when we get to the Knight.
As you can see, there are several leading (reading from the left) or trailing RED bits. These are balancing bits, which the sprite drawing routine ignores as actual sprite data, but interprets them as just an instruction to move the print position to the next pixel right. This allows the sprites to all be symmetrical without actually having to conform to that restriction in all cases.
The clever bit with this (well I thought so anyway!) is that these are no extra switch bits or whatever needed. The routine switches from mask to print mode. All of this is done in a rather memory hungry way by using the stack.
Re: Isometric Chess display engine
Ah I see so the red bits are position data for the drawing routine. That is very slick. Kind of like how the 32 byte demos use the UGL to encode commands.
So if you just use a colour you know you will not need, you can encode the bits with data and not have it display. That is very nice. I had a tile draw routine I was trying to figure out a way to encode attribute data to the tiles without extra data structures this would be a good method I think.
So if you just use a colour you know you will not need, you can encode the bits with data and not have it display. That is very nice. I had a tile draw routine I was trying to figure out a way to encode attribute data to the tiles without extra data structures this would be a good method I think.
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Isometric Chess display engine
The data is actually inverted due to the way the XOR/ AND/ XOR bit placing works.
So, for instance for the top line (the bottom line of the base, which is common to all the pieces), it is 8 x 0 bits for both the Black and White pieces.
its encoded as;
11111111
There is a separate index that gives the line lengths. Lines are either all data, or a mix of data and a standard infill (different whether Black or White)
The infill for Black is: 1111111110, where the leading '1's can be any length up to 16 bits and will always be on the Right, after the data has finished being placed.
The infill for White is:0100000000, where the trailing '0's can be any length up to 16 bits and will always be on the Left, and placed before the Data.
Sorry if I've lost anyone so far!!
The index of line data is constructed as follows;
Bit 7 indicates whether it is line data(0), or a reference to another line (1)
Bits 6-4 indicate the standard infill length
Bits 3-0 indicate the data length.
The line length is then made by adding the infill+data x 2
To find the print position to start from we take infill+data and move the position left from the center until we find it, which is a bit of a bottleneck in some on of the longer lines.
So, the index for the bottom line of the base is;
0 000 0100 (04h)
Before I move on, any questions?
So, for instance for the top line (the bottom line of the base, which is common to all the pieces), it is 8 x 0 bits for both the Black and White pieces.
its encoded as;
11111111
There is a separate index that gives the line lengths. Lines are either all data, or a mix of data and a standard infill (different whether Black or White)
The infill for Black is: 1111111110, where the leading '1's can be any length up to 16 bits and will always be on the Right, after the data has finished being placed.
The infill for White is:0100000000, where the trailing '0's can be any length up to 16 bits and will always be on the Left, and placed before the Data.
Sorry if I've lost anyone so far!!
The index of line data is constructed as follows;
Bit 7 indicates whether it is line data(0), or a reference to another line (1)
Bits 6-4 indicate the standard infill length
Bits 3-0 indicate the data length.
The line length is then made by adding the infill+data x 2
To find the print position to start from we take infill+data and move the position left from the center until we find it, which is a bit of a bottleneck in some on of the longer lines.
So, the index for the bottom line of the base is;
0 000 0100 (04h)
Before I move on, any questions?
Re: Isometric Chess display engine
Just one, how did you come to use this technique it was something you discovered from another program or it was a technique you cooked up? I like the way that the repeated graphics data gets copied across the chessmen.
I had seen isometric chess before on the spectrum but nothing like this. Haha its voodoo. so what gave you the insperation to try the project in the first place. Was it a way to showcase the technique or did the techniques grow out of the project requirements?
It seems the knight was the real headache If it were checkers no doubt you could have done it in a few hundred bytes.
I had seen isometric chess before on the spectrum but nothing like this. Haha its voodoo. so what gave you the insperation to try the project in the first place. Was it a way to showcase the technique or did the techniques grow out of the project requirements?
It seems the knight was the real headache If it were checkers no doubt you could have done it in a few hundred bytes.
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Isometric Chess display engine
Inspiration...well I can't actually remember that far back!
I designed the original sprites in about 1992 on a real Speccy. The board was just a huge 4096 bytes screen block and the sprites along with masks were 4000 bytes exactly.
Then there were data tables for the Print position for each square on the board, sprite address+size.
Many years later after rescuing it by using SAM disk on my old +D disks, I one day began looking at trying to make it a little less...huge?!
To begin with I made use of the fact that both Black and White used the same masks, that saved quite a chunk. Then the more I examined the sprite data, the more it became apparent that with very few alterations, there was the possibility to re-use many of the lines in other places within the sprite as a whole.
The standard infill data was then identified, which got the graphics data smaller again. Then I wondered if it was possible to make some sort of intelligent masking system. By actually just printing the pixels needed, there isn't any need to mask at all. as you retain the background anyway.
In the case of the Knight, it actually didn't take much to come up with the idea of 'balancing bits', and initially the stack was a quick and dirty way of doing it. However, the more I optimised everything else, the more I realised that no matter how hard I tried, I couldn't find a better way of doing it.
The DATA for the index and sprites continued to shrink along with the actual code to decode it. To the point that the Graphics now actually only occupy
145 bytes for the lines index, 19 bytes for the piece sizes and index positions, and 232 bytes for Sprite BMPs, giving a total of 396 bytes, which is less than 10% of the original 'circa 1992' size.
The board was examined and I decided that I liked the idea of building it procedurally, and in actual fact, why do we need to print the White squares? So there is a small routine to calculate the line length based upon the current overall line number (always beginning with 00), followed by a simple offset finder and line plotter together 39 bytes.
If the current line is above where the square would need to be drawn (if it were a Black square) then that routine is skipped.
Now, instead of the Print positions address table, we have a routine that calculates it by just being given the current square number (00-3fh, 0-63)
That routine is 27 bytes.
...and breathe!!.
I designed the original sprites in about 1992 on a real Speccy. The board was just a huge 4096 bytes screen block and the sprites along with masks were 4000 bytes exactly.
Then there were data tables for the Print position for each square on the board, sprite address+size.
Many years later after rescuing it by using SAM disk on my old +D disks, I one day began looking at trying to make it a little less...huge?!
To begin with I made use of the fact that both Black and White used the same masks, that saved quite a chunk. Then the more I examined the sprite data, the more it became apparent that with very few alterations, there was the possibility to re-use many of the lines in other places within the sprite as a whole.
The standard infill data was then identified, which got the graphics data smaller again. Then I wondered if it was possible to make some sort of intelligent masking system. By actually just printing the pixels needed, there isn't any need to mask at all. as you retain the background anyway.
In the case of the Knight, it actually didn't take much to come up with the idea of 'balancing bits', and initially the stack was a quick and dirty way of doing it. However, the more I optimised everything else, the more I realised that no matter how hard I tried, I couldn't find a better way of doing it.
The DATA for the index and sprites continued to shrink along with the actual code to decode it. To the point that the Graphics now actually only occupy
145 bytes for the lines index, 19 bytes for the piece sizes and index positions, and 232 bytes for Sprite BMPs, giving a total of 396 bytes, which is less than 10% of the original 'circa 1992' size.
The board was examined and I decided that I liked the idea of building it procedurally, and in actual fact, why do we need to print the White squares? So there is a small routine to calculate the line length based upon the current overall line number (always beginning with 00), followed by a simple offset finder and line plotter together 39 bytes.
If the current line is above where the square would need to be drawn (if it were a Black square) then that routine is skipped.
Now, instead of the Print positions address table, we have a routine that calculates it by just being given the current square number (00-3fh, 0-63)
That routine is 27 bytes.
...and breathe!!.
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Isometric Chess display engine
The other very important part is the board builder that sets the positions for the start of a new game.
Its actually a routine the Einar mainly contributed to, and has changed little since.
It consists of a 23 byte routine and 17 bytes of data to set the 64 positions of the board.
The routine currently resides in an empty space created amongst the Sprite data with 1 annoying spare byte at the end!
The data is plonked between the 2 main routines.
I've not given this routine much attention, but I'm fairly sure that with some clever processing I could make it all routine and no data, and probably smaller than 40 bytes.
The actual board map therefore isn't part of the overall size, as its built when needed, and can actually be located elsewhere if needed.
Its actually a routine the Einar mainly contributed to, and has changed little since.
It consists of a 23 byte routine and 17 bytes of data to set the 64 positions of the board.
The routine currently resides in an empty space created amongst the Sprite data with 1 annoying spare byte at the end!
The data is plonked between the 2 main routines.
I've not given this routine much attention, but I'm fairly sure that with some clever processing I could make it all routine and no data, and probably smaller than 40 bytes.
The actual board map therefore isn't part of the overall size, as its built when needed, and can actually be located elsewhere if needed.
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Isometric Chess display engine
So, once you've digested that, I'll try and clear up anything that I've not explained clearly enough, which is probably most of it, before I move on to some other aspects.
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Isometric Chess display engine
The Knight was a headache, and if I did without the whole masking thing, it would be faster and save 18 bytes too. But, I wanted from the outset to ensure that the sprites remained as true to the original design as was possible.Nomad wrote: ↑Tue Feb 06, 2018 11:58 am Just one, how did you come to use this technique it was something you discovered from another program or it was a technique you cooked up? I like the way that the repeated graphics data gets copied across the chessmen.
I had seen isometric chess before on the spectrum but nothing like this. Haha its voodoo. so what gave you the insperation to try the project in the first place. Was it a way to showcase the technique or did the techniques grow out of the project requirements?
It seems the knight was the real headache If it were checkers no doubt you could have done it in a few hundred bytes.
Re: Isometric Chess display engine
It's so fast that is some nice work. I can't pretend to understand what voodoo your working to get it to be that way lol. It will be fun figuring out exactly what its doing. Are you planning on adding the coordinates as isometric fonts?
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Isometric Chess display engine
One day, when I get as far as some control method and indication of state etc, I'll try to make it text free, and perhaps just graphically based. I did do some work towards that last year before moving on to other Speccy projects.
- arkannoyed
- Manic Miner
- Posts: 438
- Joined: Mon Feb 05, 2018 9:56 am
- Location: Northamptonshire
Re: Isometric Chess display engine
Theres definately on Voodoo involved. I'd really like to find a way to explain it clearly enough so that it de-mystifies it. Its not really so complex once you get to understand whats going on. I started to write a sprite designer in Basic on the Speccy that can encode the sprites as they need to be for the display routine. I could also write some sort of demonstration with annotations that could show step by step whats going on I suppose.
Re: Isometric Chess display engine
Lol its just me being a potato, I am sure once I sit down and work through it following the comments it will become clear. Don't let me put you out with extra work