;######################################### ;# ;#THIS WHOLE SECTION SHOULD BE OPTIMIZED AND THE ALPHABET RESTRUCTURED ;# ;######################################### rotateLetter: .db %11110000,5 \ .dw rotateLeft ;even, 0-42 .db %11110000,5 \ .dw rotateRight ;odd, 0-43 .db %11111000,6 \ .dw rotateLeft ;even, 44- .db %11100000,4 \ .dw rotateRight+1 ;odd, 45- .db %11000000,3 \ .dw rotateLeft .db %11000000,3 \ .dw rotateLeft+2 .db %11000000,3 \ .dw rotateRight .db %11000000,3 \ .dw rotateRight+2 .db %11100000,4 \ .dw rotateLeft .db %11100000,4 \ .dw rotateLeft+3 .db %11000000,3 \ .dw rotateRight+2 drawLine: ld a,(letRow) add a,b call getTextRow inc hl ld a,%01111111 or (hl) ld (hl),a inc hl ld a,$FF ld b,8 lineLoop: ld (hl),a inc hl djnz lineLoop ld a,%11111110 or (hl) ld (hl),a ret drawTextTop: ld a,12 ld (letCol),a ld a,8 ld (letRow),a ;initialize row/column values push hl ;hl points to text string call clearRow ;draw the sides of the textbox ld hl,letRow inc (hl) ld a,9 call clearRow ;draw the sides of the textbox ld b,-2 ;where to draw the horizontal line in relation to letRow call drawLine ;draw the top part of the box pop hl ;recall string ret drawTextBottom: ld b,7 ;where to draw the horizontal line in relation to letRow call drawLine ;draw the top part of the box jp wait2nd ;############################# ;#DRAWTEXT ;#Display text to the screen ;# surrounded by a box ;#input: hl - address to text ;#special characters: ;# $FF - end of string ;# $FE - space ;# $FD - newline ;# $FC - insert string ;# $FB - menu (but sprite# $3E) ;############################# drawText: ld bc,$0000 push bc ;$0000=end of string call countLetters ;count the size of the word, if we need to wrap or not. call nc,newLine ;if the word doesn't fit, new line dT_loop: ld a,(hl) ;get the letter ID bit 7,a ;if < 128, skip these tests. if you add more than 127 characters to the alphabet, you'll have to change this. jr z,dT_notSpecial ex de,hl ;store hl ld bc,2 ;each entry takes up two bytes ld hl,dT_jumpTable-2 add hl,bc inc a jr nz,$-2 ;repeat add hl,bc / inc a until a=0 push hl ex de,hl ret ;jump to last address on stack (our jump table) dT_notSpecial: push hl push af call sacarLetra ;get information on the letter call prepareLetter pop af call dibLetra ;draw the letter to the gbuf pop hl ld a,(letCol) addSpace = $+1 add a,5 ;smc: letterwidth ld (letCol),a inc hl jr dT_loop dT_jumpTable: jr dT_eos jr dT_space jr dT_newLine jr dT_insert jr dT_menu dT_eos: inc hl pop bc ld a,b cp c ;=0? ret z ld l,c ld h,b jr dT_loop dT_space: inc hl exx ld hl,letCol inc (hl) exx call countLetters ;count the size of the word, if we need to wrap or not. call nc,newLine ;if the word doesn't fit, new line jr dT_loop dT_newLine: call newLine inc hl jr dT_loop dT_menu: exx ld hl,numOptions inc (hl) ld a,(hl) add a,a ;a*2, each entry has 2 bytes: y,x ld c,a ld b,0 ld hl,buttonCoords add hl,bc ld a,(letRow) ld (hl),a inc hl ld a,(letCol) inc a ;we need to shift over one column to draw INSIDE the box ld (hl),a exx ld a,$3E jr dT_notSpecial dT_insert: inc hl ld a,(hl) ;what to show? inc hl push hl ;we want to push the byte after the data, where to continue the string ld c,2 ;b should still = 0 ld hl,sL_jumpTable_insert-2 add hl,bc dec a jr nz,$-2 jp (hl) sL_jumpTable_insert jr insertPlayerMoney jr insertPlayerNumber jr insertCurrentProperty jr insertPropertyOwnedBy insertPlayerMoney: ld e,P_MONEY call getCurrentPlayer ld a,(hl) inc hl ld h,(hl) ld l,a call numberToString jp dT_loop insertPlayerNumber: ld a,(currentPlayer) inc a ld l,a ld h,0 call numberToString jp dT_loop insertCurrentProperty: call retrievePlayerBrush inc hl ;first byte is the sprite# byte inc hl ;skip the action byte ld a,(hl) inc hl ld h,(hl) ld l,a jp dT_loop insertPropertyOwnedBy: call retrievePlayerBrush ld de,6 ;player owner is 6th byte add hl,de ld l,(hl) ld h,d inc l call numberToString jp dT_loop ;################################ ;#PREPARELETTER ;#Takes the information from rotateLetter ;# and prepares the sprite routine to ;# extract the letter. ;################################ prepareLetter ex af,af' ld a,(hl) ;mask ld (mascLet),a inc hl ld a,(hl) ld (addSpace),a ;letter width (in pixels) ex af,af' inc hl ld e,(hl) ;rotate address pointer (1st byte) inc hl ld h,(hl) ;2nd byte ld l,e ld de,letRotate ldi ldi ldi ldi ld e,a ld d,0 ld hl,alfabeto add hl,de add hl,de add hl,de add hl,de add hl,de ;x5 ret ;read from table until reach FE/FF then check if passes for example 94 countLetters: push hl ld a,(letCol) ;current pen column scf cL_loop: ld b,a ;store total ld a,(hl) ;next letter bit 7,a ;if the letter is > $FE, it's a space or EOS jr nz,cL_exit ; so we can exit the routine exx call sacarLetra inc hl ;letter width ld a,(hl) exx inc hl add a,b cp 86 jr c,cL_loop cL_exit: pop hl ret newLine: push hl ld hl,letRow ld a,(hl) add a,6 ld (hl),a ld hl,letCol ld (hl),12 call clearRow ;a=row to clear pop hl ret ;############################## ;#CLEARROW ;#Clears a row and draws the text box ;#input: a = row number ;############################## clearRow: call getTextRow inc hl ld c,7 cB_outLoop ld b,8 ld (hl),%11000000 inc hl cB_inLoop: ld (hl),a inc hl djnz cB_inLoop ld (hl),%00000011 ld de,5 add hl,de dec c jr nz,cB_outLoop ret ;########################## ;#GETTEXTROW ;#Get the address of the row in the gbuf ;# pointed to by letRow ;########################## getTextRow: ld e,a ;a = row xor a ld d,a ld l,e ld h,d add hl,hl ;x2 add hl,de ;x3 add hl,hl ;x6 add hl,de ;x7 add hl,hl ;x14 ld de,saferam1 add hl,de ret ;########################### ;#SACARLETRA ;#Get correct address from rotateletter ;#input: a = letter ;#output hl=correct address ;########################### sacarLetra: or a ;reset carry flag rra ;a/2 ld hl,rotateLetter ld de,4 ;each row of data in rotateLetter is 4 bytes ; first row corresponds to the first sprite (the leftmost part) ; next row is the right byte jr nc,letPar ;is the letter even/odd? if dividing a/2 gave a carry, it's odd add hl,de ;point to the 2nd row, aka the right-hand byte letPar: ld e,8 ;skip two rows at a time (remember: most sprites have two characters ; either 4x4 or 5x3) cp FIVE_BY_THREE ;letters 0-43 (remember, it's divided by 2) use the first/second row ret c ; depending on whether or not it's an odd number add hl,de ;points to 5x3 sprites cp TWO_BY_TWO ;end of 5x3 ret c add hl,de ld b,THREE_BY_THREE + (THREE_BY_THREE-TWO_BY_TWO) cp b jr c,sL_2x2 ;3x3x2 add hl,de add hl,de sub b rra ;/2 jr nc,$+3 add hl,de ld a,THREE_BY_THREE ret sL_2x2: ;2x2x2x2 ld b,TWO_BY_TWO sub b rra ;/2 jr nc,$+3 add hl,de add a,b ret cp TWO_BY_TWO-1 ;64 - 71: 5th/6th row 2x2x2x2 ret c dec a add hl,de cp TWO_BY_TWO-1 ret c add hl,de cp TWO_BY_TWO ret c dec a add hl,de ret dropTable: .db 25,29,30,34,59 dibLetra: exx letRow = $+1 ;basically, penrow ld e,0 ld b,5 ld hl,dropTable ld d,(hl) cp (hl) jr nz,$+3 inc e inc hl djnz $-5 ld hl,0 ld d,l ;d=0 ld b,l ;b=0 add hl,de add hl,hl ;y*2 add hl,de ;y*3 add hl,hl ;y*6 add hl,de ;y*7 add hl,hl ;y*14 ld de,saferam1 add hl,de letCol = $+1 ;"pencol" ld a,0 ld c,a ;remember, b=0 and $7 ;offset srl c srl c srl c ;/8 add hl,bc ;hl = starting point in gbuf ld b,a exx ld c,5 letBucle: ld a,(hl) ;sprite letRotate: ;we need to rotate the sprite nop nop nop nop mascLet = $+1 ;a mask to ensure the bits underneath our sprite are empty and $F0 exx ld e,b ;guardar b ld d,0 dec b \ inc b ;offset = 0? jr z,skipClip rra \ rr d \ djnz $-3 ;rotate sprite ld b,e skipClip: xor (hl) ld (hl),a inc hl ld a,d xor (hl) ld (hl),a ld de,13 add hl,de exx inc hl dec c jp nz, letBucle ret ;########################## ;#WAIT2ND ;#Wait for the 2nd key to be pressed. ;# If 2nd is currently held, we first ;# wait for it to be released then ;# check if it has been pressed again. ;# Also, displays the gbuf ;########################## wait2nd: numOptions = $+1 ld a,$FF cp $FF jr z,w2_noMenu xor a ld (curOption),a ;start with the first menu choice call highlightButton w2_noMenu: call drawGbuf call waitKeyReleased ld a,$BE ;group 7 + arrow keys out (1),a w2_loop: in a,(1) cp 223 ;2nd jr z,waitKeyReleasedExit ;if 2nd isn't pressed, repeat loop cp $FF ;if no key is being pressed, loop jr z,w2_loop ld a,(numOptions) inc a ;if there are no options, there is no menu! call nz,menuKeys jr w2_loop ;################################ ;#HIGHLIGHTBUTTON ;#Highlight the currently selected ;# menu choice ;#no inputs ;################################ highlightButton: ld hl,buttonCoords ld a,(curOption) add a,a ;each option takes two bytes in memory: Y coord and X coord ld c,a ld b,0 add hl,bc ;point to correct coordinates ld a,(hl) ld (letRow),a inc hl ld a,(hl) ld (letCol),a ld a,$3F ;$3E=box, $3F filling call sacarLetra call prepareLetter call dibLetra call drawGbuf ret menuKeys: in a,(1) ld hl,numOptions ld de,curOption rra ;down rra ;left jr nc,mK_left rra ;right jr nc,mK_right rra ;up ret mK_left: ld a,(de) or a ret z call highlightButton ;erase the button ld hl,curOption dec (hl) call highlightButton jr waitKeyReleased ;instead of call XXX / ret mK_right: ld a,(de) cp (hl) ret nc call highlightButton ;erase the button ld hl,curOption inc (hl) call highlightButton jr waitKeyReleased ;instead of call XXX / ret waitKeyReleasedExit: ld hl,numOptions ld (hl),$FF waitKeyReleased: ld a,$BE ;group 7 and arrow key group out (1),a w2R_loop: in a,(1) cp $FF jr nz,w2R_loop ;if a key is being pressed ld a,(curOption) ;this is for the menu routine, put the currently selected option into a ret ;####################### ;#DISPNUMBER ;#Display the number stored in HL ;#input: hl = number to display ;####################### dispNumberAlign: ld a,20 ld (letRow),a ld (letCol),a dispNumber: call numberToString call drawText ;now the text is a string (ending in $FF, my EOS (end of string) marker) ret ;####################### ;#NUMBERTOSTRING ;#Convert number in HL to a string ;#input: hl = number to display ;#output: hl = pointer to string ;####################### numberToString: exx ld de,numberText2 exx ld de,-10000 ;check how many 10,000s there are in the number call dN_b2d ld de,-1000 ;check how many 1,000s units there are call dN_b2d ld de,-100 ;hundreds call dN_b2d ld de,-10 ;tens call dN_b2d ld de,-1 ;single digits call dN_b2d ld c,-1 ;this part here removes the leading 0s ld hl,numberText2 ld a,(hl) inc c inc hl cp 10 ;ten ($0A) is the value of 0 in my alphabet (i think ASCII uses $20?) jr z,$-5 ld de,numberText2 ld l,e ld h,d ld b,0 add hl,bc ld a,6 sub c ld c,a ldir ;essentially, for every 0, shift the number left one. ld hl,numberText2 ret dN_b2d: ld a,-1 dN_b2dloop: inc a add hl,de jr c,dN_b2dloop or a sbc hl,de exx ld hl,numberTable ld b,0 ld c,a add hl,bc ;hl=numberTable, bc = number of units ldi exx ret ;the "ASCII" numbers of my text characters ; it's different than normal ASCII because ; i used a custom character table numberTable: .db 10,57,36,37,38,39,40,41,42,43 numberText2: .db 0,0,0,0,0,$FF