new beep program on enter
@ -0,0 +1,61 @@
|
||||
[org 0x2000]
|
||||
|
||||
start:
|
||||
mov [bootdev], dl
|
||||
mov ah, 06h ; Scroll up function
|
||||
xor al, al ; Clear entire screen
|
||||
xor cx, cx ; Upper left corner CH=row, CL=column
|
||||
mov dx, 184FH ; lower right corner DH=row, DL=column
|
||||
mov bh, 4Fh ; YellowOnBlue
|
||||
int 10H ; execute interrupt
|
||||
|
||||
mov al, 182 ; meaning that we're about to load
|
||||
out 43h, al ; prepare speaker for output
|
||||
|
||||
mov ax, 2153 ; frequency countdown value is stored in ax. It is calculated by
|
||||
out 42h, al ; Output low byte.
|
||||
mov al, ah ; Output high byte.
|
||||
out 42h, al
|
||||
|
||||
in al, 61h
|
||||
or al, 00000011b
|
||||
out 61h, al ; Send the new value
|
||||
; mov bx, 200 ; Pause for duration of note.
|
||||
|
||||
mov al, 0
|
||||
mov ah, 86h
|
||||
mov cx, 1
|
||||
mov dx, 200
|
||||
int 15h
|
||||
|
||||
;.pause1:
|
||||
; mov cx, 65535
|
||||
;.pause2:
|
||||
; dec cx
|
||||
; jne .pause2
|
||||
; dec bx
|
||||
; jne .pause1
|
||||
; in al, 61h ; Turn off note (get value from
|
||||
; ; port 61h).
|
||||
; and al, 11111100b ; Reset bits 1 and 0.
|
||||
; out 61h, al ; Send new value.
|
||||
jmp exit
|
||||
|
||||
|
||||
waitforkey:
|
||||
mov ah, 0x00
|
||||
int 0x16
|
||||
cmp ah, 01h
|
||||
je exit
|
||||
jmp waitforkey
|
||||
|
||||
exit:
|
||||
in al, 61h ; Turn off note (get value from
|
||||
; port 61h).
|
||||
and al, 11111100b ; Reset bits 1 and 0.
|
||||
out 61h, al ; Send new value.
|
||||
mov dl, [bootdev]
|
||||
jmp 0x1000
|
||||
|
||||
bootdev db 0x80 ; Boot device number
|
||||
|
@ -0,0 +1,64 @@
|
||||
org 0x7C00
|
||||
%define SECTOR_AMOUNT 0x10 ;Precompiler defined value for easy changing
|
||||
jmp short start
|
||||
nop
|
||||
|
||||
; BPB
|
||||
OEMLabel db "Example " ; Disk label
|
||||
BytesPerSector dw 512 ; Bytes per sector
|
||||
SectorsPerCluster db 1 ; Sectors per cluster
|
||||
ReservedForBoot dw 1 ; Reserved sectors for boot record
|
||||
NumberOfFats db 2 ; Number of copies of the FAT
|
||||
RootDirEntries dw 224 ; Number of entries in root dir
|
||||
LogicalSectors dw 2880 ; Number of logical sectors
|
||||
MediumByte db 0F0h ; Medium descriptor byte
|
||||
SectorsPerFat dw 9 ; Sectors per FAT
|
||||
SectorsPerTrack dw 18 ; Sectors per track (36/cylinder)
|
||||
Sides dw 2 ; Number of sides/heads
|
||||
HiddenSectors dd 0 ; Number of hidden sectors
|
||||
LargeSectors dd 0 ; Number of LBA sectors
|
||||
DriveNo dw 0 ; Drive No: 0
|
||||
Signature db 41 ; Drive signature: 41 for floppy
|
||||
VolumeID dd 00000000h ; Volume ID: any number
|
||||
VolumeLabel db "Example "; Volume Label: any 11 chars
|
||||
FileSystem db "FAT12 " ; File system type: don't change!
|
||||
start:
|
||||
; ------------------------------------------------------------------
|
||||
|
||||
;Reset disk system
|
||||
mov ah, 0
|
||||
int 0x13 ; 0x13 ah=0 dl = drive number
|
||||
jc errorpart
|
||||
;Read from harddrive and write to RAM
|
||||
mov bx, 0x8000 ; bx = address to write the kernel to
|
||||
mov al, SECTOR_AMOUNT ; al = amount of sectors to read
|
||||
mov ch, 0 ; cylinder/track = 0
|
||||
mov dh, 0 ; head = 0
|
||||
mov cl, 2 ; sector = 2
|
||||
mov ah, 2 ; ah = 2: read from drive
|
||||
int 0x13 ; => ah = status, al = amount read
|
||||
jc errorpart
|
||||
jmp 0x8000
|
||||
|
||||
|
||||
errorpart: ;if stuff went wrong you end here so let's display a message
|
||||
mov si, errormsg
|
||||
mov bh, 0x00 ;page 0
|
||||
mov bl, 0x07 ;text attribute
|
||||
mov ah, 0x0E ;tells BIOS to print char
|
||||
.part:
|
||||
lodsb
|
||||
sub al, 0
|
||||
jz end
|
||||
int 0x10 ;interrupt
|
||||
jmp .part
|
||||
end:
|
||||
jmp $
|
||||
|
||||
errormsg db "Failed to load...",0
|
||||
times 510-($-$$) db 0
|
||||
;Begin MBR Signature
|
||||
db 0x55 ;byte 511 = 0x55
|
||||
db 0xAA ;byte 512 = 0xAA
|
||||
|
||||
|
@ -0,0 +1,101 @@
|
||||
%ifndef CODE_BUFFER
|
||||
%define CODE_BUFFER
|
||||
|
||||
;set's graphic mode
|
||||
initGraphics:
|
||||
mov ah, 0 ;set display mode
|
||||
mov al, 13h ;13h = 320x200
|
||||
int 0x10
|
||||
ret
|
||||
|
||||
;resets screen to full black
|
||||
resetBuffer:
|
||||
pusha
|
||||
mov cx, 80*60/2
|
||||
;xor ax, ax ;this will make the background black
|
||||
mov ax, 0xC3C3 ;this paints the background green
|
||||
mov di, [screenPos]
|
||||
rep stosw
|
||||
popa
|
||||
ret
|
||||
|
||||
;screen has size 320x200 but buffer only 80x60
|
||||
copyBufferOver:
|
||||
pusha
|
||||
push es
|
||||
mov es, word [graphicMemory]
|
||||
xor di, di
|
||||
mov cx, 200
|
||||
.loop:
|
||||
mov dx, cx
|
||||
mov cx, 320/4
|
||||
.innerloop:
|
||||
mov si, 320
|
||||
sub si, cx ;invert x-axis
|
||||
mov bx, 200
|
||||
sub bx, dx ;invert y-axis
|
||||
shr bx, 2
|
||||
imul bx, 80
|
||||
add si, bx
|
||||
add si, [screenPos]
|
||||
lodsb ;read from buffer (ds:si)
|
||||
mov ah, al
|
||||
stosw ;write 4 pixel row to graphic memory (es:di)
|
||||
stosw
|
||||
loop .innerloop
|
||||
mov cx, dx
|
||||
loop .loop
|
||||
pop es
|
||||
popa
|
||||
ret
|
||||
|
||||
;si = position of image, ax = xpos, bx = ypos
|
||||
;a bit messy because of all the error checks to not draw out of screen
|
||||
drawImage:
|
||||
pusha
|
||||
xor di, di
|
||||
imul di, bx, 80 ;add offset y-position
|
||||
add di, [screenPos] ;make it a pixel in buffer
|
||||
;add di, ax ;add offset x-position
|
||||
mov bp, ax ;backup x-position offset
|
||||
xor ax, ax
|
||||
lodsb
|
||||
mov cx, ax ;x-size
|
||||
lodsb
|
||||
mov dx, ax ;y-size
|
||||
.for_y:
|
||||
mov bx, di
|
||||
add bx, cx ;bx = offsetOnScreen + xsize
|
||||
sub bx, word [screenPos] ;skip if line is out of top border screen
|
||||
jl .skip_x
|
||||
sub bx, cx
|
||||
sub bx, 80*60
|
||||
jge .skip_x ;skip if line is out of bottom border screen
|
||||
xor bx, bx
|
||||
.for_x:
|
||||
mov al, byte [si+bx]
|
||||
add bx, bp
|
||||
test al, al ;skip 0bytes as transparent
|
||||
jz .skip
|
||||
cmp bx, 80 ;if pixel is right out of screen, skip it
|
||||
jge .skip
|
||||
cmp bx, 0 ;if pixel is left out of screen, skip it
|
||||
jl .skip
|
||||
mov byte [di+bx], al ;write byte to buffer
|
||||
.skip:
|
||||
sub bx, bp
|
||||
inc bx
|
||||
cmp bx, cx
|
||||
jl .for_x
|
||||
.skip_x:
|
||||
add di, 80 ;next row within buffer
|
||||
add si, cx ;next row within image
|
||||
dec dx
|
||||
jnz .for_y ;repeat for y-length
|
||||
popa
|
||||
ret
|
||||
|
||||
graphicMemory dw 0xA000
|
||||
screenPos dw 0x0500 ;double buffer will be at this address
|
||||
|
||||
%endif
|
After Width: | Height: | Size: 982 B |
After Width: | Height: | Size: 868 B |
After Width: | Height: | Size: 874 B |
After Width: | Height: | Size: 868 B |
After Width: | Height: | Size: 563 B |
@ -0,0 +1,47 @@
|
||||
from PIL import Image #Import Image from Pillow
|
||||
import sys
|
||||
|
||||
palleteFile = "colors.png" #pallete the BIOS uses
|
||||
if len(sys.argv) < 2:
|
||||
convertFile = "fox.png" #image to turn into a binary
|
||||
outputFile = "fox.bin" #name of output file
|
||||
elif len(sys.argv) < 3:
|
||||
convertFile = sys.argv[1]
|
||||
outputFile = sys.argv[1]+".bin"
|
||||
elif len(sys.argv) >= 3:
|
||||
convertFile = sys.argv[1]
|
||||
outputFile = sys.argv[2]
|
||||
|
||||
pal = Image.open(palleteFile).convert('RGB')
|
||||
pallete = pal.load() #load pixels of the pallete
|
||||
image = Image.open(convertFile).convert('RGB')
|
||||
pixels = image.load() #load pixels of the image
|
||||
|
||||
binary = open(outputFile, "wb") #open/create binary file
|
||||
|
||||
list = [] #create a list for the pallete
|
||||
for y in range(pal.height):
|
||||
for x in range(pal.width):
|
||||
list.append(pallete[x,y]) #save the pallete into an array
|
||||
|
||||
binary.write(bytearray([image.width&0xFF,image.height&0xFF])) #write width and height as the first two bytes
|
||||
data = []
|
||||
print(image.height)
|
||||
print(image.width)
|
||||
for y in range(image.height):
|
||||
for x in range(image.width):
|
||||
difference = 0xFFFFFFF #init difference with a high value
|
||||
choice = 0 #the index of the color nearest to the original pixel color
|
||||
index = 0 #current index within the pallete array
|
||||
#print sum([(pixels[x,y][i])**2 for i in range(3)])
|
||||
for c in list:
|
||||
dif = sum([(pixels[x,y][i] - c[i])**2 for i in range(3)]) #calculate difference for RGB values
|
||||
if dif < difference:
|
||||
difference = dif
|
||||
choice = index
|
||||
index += 1
|
||||
data = bytearray([choice&0xFF])
|
||||
print("[%d,%d] %d = %d (%d)" % (x,y,choice, difference, len(data)))
|
||||
binary.write(data) #write nearest pallete index into binary file
|
||||
binary.close() # close file handle
|
||||
print("Done.")
|
@ -0,0 +1 @@
|
||||
00000000000000000000000000000000000000000000000000000000000000000 00000000000 X 000000000000000000000 000000000000 0000000000000000 000000000000000000000 000000000000 0000000000000000 000000000000000000000 000000000000 0000000000000000 000000000000000000 00000000 0000000000000000 000000000000000000 00000000 0000000000000000 000000000 X 00000000 0000000000000000 000000000 00000000 00000 0000000000000000 00000000 00000 0000000000000000 0000000000000000000000 X 00000000000000 0000000000000000 0000000000000000000000 00000000000000 0000000000000000 0000000000000000000000 00000000000000 00000 00000 00000000000000 00000 P X 00000 00000 000000000 X 00000 0000000000000000 0000000000000000 0000000000000000000000 0000000000000000 0000000000000000 000000 0000000000000000 000000000 000000 X 0000000000000000 X 000000 00000 000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
After Width: | Height: | Size: 908 B |
After Width: | Height: | Size: 908 B |
After Width: | Height: | Size: 906 B |
After Width: | Height: | Size: 912 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 911 B |
After Width: | Height: | Size: 904 B |
After Width: | Height: | Size: 907 B |
After Width: | Height: | Size: 907 B |
After Width: | Height: | Size: 904 B |
After Width: | Height: | Size: 908 B |
After Width: | Height: | Size: 908 B |
After Width: | Height: | Size: 861 B |
@ -0,0 +1,531 @@
|
||||
org 0x8000
|
||||
bits 16
|
||||
|
||||
;precompiler constant
|
||||
%define entityArraySize 16
|
||||
;Let's begin by going into graphic mode
|
||||
call initGraphics
|
||||
|
||||
;Now let's register some custom interrupt handlers
|
||||
call registerInterruptHandlers
|
||||
|
||||
;init map
|
||||
call initMap
|
||||
|
||||
;Main game loop
|
||||
gameLoop:
|
||||
call resetBuffer ;reset screen to draw on empty canvas
|
||||
|
||||
;MODULAR DRAWING CODE
|
||||
mov di, entityArray
|
||||
add di, 2 ;skip drawing player
|
||||
.nextEntity:
|
||||
cmp [di], word 0
|
||||
je .skip
|
||||
pusha
|
||||
mov cx, [player+2] ;player x to draw relative
|
||||
mov dx, [player+4] ;player z to draw relative
|
||||
mov di, [di]
|
||||
call drawEntity
|
||||
popa
|
||||
.skip:
|
||||
add di, 2
|
||||
cmp di, entityArray+((entityArraySize-1)*2) ;confirm that di is still pointing into the entityArray
|
||||
jl .nextEntity
|
||||
|
||||
call drawMap
|
||||
|
||||
; PLAYER DRAWING CODE
|
||||
mov si, [player] ;get animation
|
||||
mov ax, [player+6] ;get index within animation
|
||||
xor dx,dx
|
||||
div word [si+2] ; animation time % time of full animation
|
||||
mov ax, dx
|
||||
xor dx, dx
|
||||
div word [si] ; (animation time % time of full animation) / time of one frame
|
||||
add ax, ax ; index*2 because image address is a word
|
||||
|
||||
add si, 4 ;skip first two words of structure
|
||||
add si, ax ;add the offset to the frame
|
||||
mov si, [si] ;set the image parameter to the image referenced in the frame
|
||||
|
||||
mov ax, 80/2 - 9/2 - 1 ;center player image
|
||||
mov bx, 50/2 - 12/2 - 1 ;center player image
|
||||
call drawImage
|
||||
; END OF PLAYER DRAWING CODE
|
||||
|
||||
call copyBufferOver ;draw frame to screen
|
||||
|
||||
call gameControls ;handle control logic
|
||||
|
||||
call synchronize ;synchronize emulator and real application through delaying
|
||||
|
||||
jmp gameLoop
|
||||
|
||||
|
||||
jmp $
|
||||
|
||||
;di = entity cx,dx = xpos,zpos
|
||||
drawEntity:
|
||||
push dx
|
||||
inc word [di+6]
|
||||
mov ax, [di+6] ;get index within animation
|
||||
mov si, [di]
|
||||
xor dx,dx
|
||||
div word [si+2] ; animation time % time of full animation
|
||||
mov ax, dx
|
||||
xor dx, dx
|
||||
div word [si] ; (animation time % time of full animation) / time of one frame
|
||||
add ax, ax ; index*2 because image address is a word
|
||||
|
||||
add si, 4 ;skip first two words of structure
|
||||
add si, ax ;add the offset to the frame
|
||||
mov si, [si] ;set the image parameter to the image referenced in the frame
|
||||
pop dx
|
||||
|
||||
;mov si, word [di] ;get animation
|
||||
;mov si, word [si+4] ;get first frame of animation
|
||||
|
||||
mov ax, word [di+2] ;get entity x
|
||||
sub ax, cx ;subtract the position of the player from the x position
|
||||
add ax, 80/2 - 9/2 - 1 ;relative to screen image drawing code for x position
|
||||
mov bx, word [di+4] ;get entity y
|
||||
sub bx, dx ;subtract the position of the player from the z position
|
||||
add bx, 50/2 - 12/2 - 1 ;relative to screen image drawing code for z position
|
||||
call drawImage ;draw image to buffer
|
||||
ret
|
||||
|
||||
;di = entity, cx = new_xpos, dx = new_zpos, bp = new animation
|
||||
;fixed for modular entity system
|
||||
checkForCollision:
|
||||
pusha ;save current state
|
||||
mov si, entityArray ;set si to entityArray
|
||||
.whileLoop:
|
||||
mov bx, word [si] ;read entityArray entry
|
||||
test bx, bx ;if entry is zero => end of array
|
||||
jz .whileSkip
|
||||
cmp bx, di ;if entity is equal to di => next entity to not collide with it self
|
||||
jz .whileSkip
|
||||
|
||||
mov ax, word [bx+2] ;ax = entity x
|
||||
sub ax, 8 ;subtract 8 because of hitbox
|
||||
cmp ax, cx ; (entityX-8 <= playerX)
|
||||
jg .whileSkip
|
||||
|
||||
mov ax, word [bx+2] ;ax = entity x
|
||||
add ax, 8 ;add 8 because of hitbox
|
||||
cmp ax, cx ; (entityX+8 > playerX)
|
||||
jle .whileSkip
|
||||
|
||||
mov ax, word [bx+4] ;ax = entity z
|
||||
sub ax, 10 ;subtract 10 because of hitbox
|
||||
cmp ax, dx ; (entityZ-10 <= playerZ)
|
||||
jg .whileSkip
|
||||
|
||||
mov ax, word [bx+4] ;ax = entity z
|
||||
add ax, 9 ;subtract 9 because of hitbox
|
||||
cmp ax, dx ; (entityZ+9 > playerZ)
|
||||
jle .whileSkip
|
||||
|
||||
;if we reach this point => actual collision
|
||||
;mov cx, [di+2] ;set new x pos to current x pos => no movement
|
||||
;mov dx, [di+4] ;set new z pos to current z pos => no movement
|
||||
|
||||
mov word [si], 0
|
||||
inc word [coinFound]
|
||||
|
||||
;ding ding count found
|
||||
|
||||
jmp .noMapCollision
|
||||
.whileSkip:
|
||||
add si, 2 ;set si to the next entry in the entityArray
|
||||
cmp si, entityArray+((entityArraySize-1)*2)
|
||||
jl .whileLoop
|
||||
.whileEnd
|
||||
|
||||
pusha
|
||||
mov si, cx
|
||||
mov bx, dx
|
||||
call collideMap
|
||||
popa
|
||||
jnc .noMapCollision
|
||||
;if we reach this point => actual collision
|
||||
mov cx, [di+2] ;set new x pos to current x pos => no movement
|
||||
mov dx, [di+4] ;set new z pos to current z pos => no movement
|
||||
.noMapCollision:
|
||||
mov byte [canWalk], 1
|
||||
mov word [di] ,bp ;update the animation in use
|
||||
mov word [di+2] ,cx ;update x pos
|
||||
mov word [di+4] ,dx ;update y pos
|
||||
popa ;reload old register state
|
||||
ret
|
||||
|
||||
canWalk db 0
|
||||
gameControls:
|
||||
mov byte [canWalk], 0
|
||||
mov di, player ;select the player as the main entity for "checkForCollision"
|
||||
mov al, byte [pressA]
|
||||
add al, byte [pressD]
|
||||
cmp al, 0
|
||||
jz .nokeyad
|
||||
mov cx, word [player_PosX] ;set cx to player x
|
||||
mov dx, word [player_PosZ] ;set dx to player z
|
||||
mov bp, [player] ;set bp to current animation
|
||||
cmp byte [pressD], 1 ;try to move x+1 if 'd' is pressed and set animation accordingly, test other cases otherwise
|
||||
jne .nd
|
||||
inc cx
|
||||
mov bp, playerImg_right
|
||||
.nd:
|
||||
cmp byte [pressA], 1 ;try to move x-1 if 'a' is pressed and set animation accordingly, test other cases otherwise
|
||||
jne .na
|
||||
dec cx
|
||||
mov bp, playerImg_left
|
||||
.na:
|
||||
call checkForCollision ;check if player would collide on new position, if not change position to new position
|
||||
.nokeyad:
|
||||
mov al, byte [pressW]
|
||||
add al, byte [pressS]
|
||||
cmp al, 0
|
||||
jz .nokeyws
|
||||
mov cx, word [player_PosX] ;set cx to player x
|
||||
mov dx, word [player_PosZ] ;set dx to player z
|
||||
mov bp, [player] ;set bp to current animation
|
||||
cmp byte [pressW], 1 ;try to move z-1 if 'w' is pressed and set animation accordingly, test other cases otherwise
|
||||
jne .nw
|
||||
dec dx
|
||||
mov bp, playerImg_back
|
||||
.nw:
|
||||
cmp byte [pressS], 1 ;try to move z+1 if 's' is pressed and set animation accordingly, test other cases otherwise
|
||||
jne .ns
|
||||
inc dx
|
||||
mov bp, playerImg_front
|
||||
.ns:
|
||||
call checkForCollision ;check if player would collide on new position, if not change position to new position
|
||||
.nokeyws:
|
||||
cmp byte [canWalk], 0
|
||||
jnz .noCollision
|
||||
mov word [player+6], 0 ;reset animation counter
|
||||
ret
|
||||
.noCollision:
|
||||
inc word [player+6] ;update animation if moving
|
||||
ret
|
||||
|
||||
;======================================== NEW STUFF ==========================================
|
||||
registerInterruptHandlers:
|
||||
mov [0x0024], dword keyboardINTListener ;implements keyboardListener
|
||||
ret
|
||||
|
||||
;; NEW KEYBOARD EVENT BASED CODE
|
||||
pressA db 0
|
||||
pressD db 0
|
||||
pressW db 0
|
||||
pressS db 0
|
||||
keyboardINTListener: ;interrupt handler for keyboard events
|
||||
pusha
|
||||
xor bx,bx ; bx = 0: signify key down event
|
||||
inc bx
|
||||
in al,0x60 ;get input to AX, 0x60 = ps/2 first port for keyboard
|
||||
btr ax, 7 ;al now contains the key code without key pressed flag, also carry flag set if key up event
|
||||
jnc .keyDown
|
||||
dec bx ; bx = 1: key up event
|
||||
.keyDown:
|
||||
cmp al,0x1e ;a
|
||||
jne .check1
|
||||
mov byte [cs:pressA], bl ;use cs overwrite because we don't know where the data segment might point to
|
||||
.check1:
|
||||
cmp al,0x20 ;d
|
||||
jne .check2
|
||||
mov byte [cs:pressD], bl
|
||||
.check2:
|
||||
cmp al,0x11 ;w
|
||||
jne .check3
|
||||
mov byte [cs:pressW], bl
|
||||
.check3:
|
||||
cmp al,0x1f ;s
|
||||
jne .check4
|
||||
mov byte [cs:pressS], bl
|
||||
.check4:
|
||||
mov al, 20h ;20h
|
||||
out 20h, al ;acknowledge the interrupt so further interrupts can be handled again
|
||||
popa ;resume state to not modify something by accident
|
||||
iret ;return from an interrupt routine
|
||||
|
||||
;using interrupts instread of the BIOS is SUUPER fast which is why we need to delay execution for at least a few ms per gametick to not be too fast
|
||||
synchronize:
|
||||
pusha
|
||||
mov si, 20 ; si = time in ms
|
||||
mov dx, si
|
||||
mov cx, si
|
||||
shr cx, 6
|
||||
shl dx, 10
|
||||
mov ah, 86h
|
||||
int 15h ;cx,dx sleep time in microseconds - cx = high word, dx = low word
|
||||
popa
|
||||
ret
|
||||
|
||||
;cx, dx = xpos, zpos, si = animation
|
||||
;eax == 0 => success, else failed
|
||||
addEntity:
|
||||
pusha
|
||||
mov bx, cx
|
||||
mov di, entityArray
|
||||
xor ax, ax
|
||||
mov cx, (entityArraySize-1)
|
||||
repne scasw ; iterate through entity array until empty stop is found
|
||||
sub di, 2
|
||||
test ecx, ecx ; abort here if at the end of the the entity array
|
||||
je .failed
|
||||
sub cx, (entityArraySize-1) ; calculate index within the array by using the amount of iterated entires
|
||||
neg cx
|
||||
shl cx, 3
|
||||
add cx, entityArrayMem
|
||||
mov [di], cx
|
||||
mov di, cx
|
||||
mov [di], si
|
||||
mov [di+2], bx ; set x position of the entity
|
||||
mov [di+4], dx ; set y position of the entity
|
||||
xor bx, dx ; "randomise" initial animation position
|
||||
mov [di+6], bx ; set animation state
|
||||
popa
|
||||
xor eax, eax ; return 0 if successfully added
|
||||
ret
|
||||
.failed:
|
||||
popa
|
||||
xor eax, eax
|
||||
inc eax ; return 1 if failed to find a place for the entity
|
||||
ret
|
||||
|
||||
;di = entity cx,dx = xpos,zpos
|
||||
drawBlock:
|
||||
mov ax, word [player+2]
|
||||
sub ax, cx
|
||||
imul ax, ax
|
||||
mov bx, word [player+4]
|
||||
sub bx, dx
|
||||
imul bx, bx
|
||||
add ax, bx
|
||||
cmp ax, 3000 ;calculate distance
|
||||
jge .skip
|
||||
|
||||
mov ax, cx
|
||||
mov bx, dx
|
||||
sub ax, word [player+2] ;subtract the position of the player from the x position
|
||||
add ax, 80/2 - 9/2 - 1 ;relative to screen image drawing code for x position
|
||||
sub bx, word [player+4] ;subtract the position of the player from the z position
|
||||
add bx, 50/2 - 12/2 - 1 ;relative to screen image drawing code for z position
|
||||
call drawImage ;draw image to buffer
|
||||
.skip:
|
||||
clc
|
||||
ret
|
||||
|
||||
;set the position of the player to x=cx, z=dx
|
||||
setSpawn:
|
||||
mov word [player+2], cx ; set player x
|
||||
mov word [player+4], dx ; set player z
|
||||
add word [player+4], 3 ; offset player z
|
||||
clc
|
||||
ret
|
||||
|
||||
;spawn the coins add set the spawn position of the player
|
||||
initMap:
|
||||
mov si, coinImg
|
||||
mov bp, addEntity
|
||||
mov ah, 'X'
|
||||
call iterateMap ; iterate the map and add a coin at every 'X' on the map
|
||||
call spawnPlayer ; set spawn for player
|
||||
ret
|
||||
|
||||
;draw the map
|
||||
drawMap:
|
||||
mov si, boxImg_0
|
||||
mov bp, drawBlock
|
||||
mov ah, '0'
|
||||
call iterateMap ; iterate the map and add a box at every '0' on the map
|
||||
;this second iteration is pretty unefficient but only optional for some ground texture
|
||||
mov si, tileImg_0
|
||||
mov bp, drawBlock
|
||||
mov ah, ' '
|
||||
call iterateMap ; iterate the map and add a tile at every ' ' on the map
|
||||
ret
|
||||
|
||||
; si = player X, bx = player Y
|
||||
collideMap:
|
||||
mov bp, blockCollison
|
||||
mov ah, '0'
|
||||
call iterateMap ; iterate the map and check for a collision with a '0'
|
||||
ret
|
||||
|
||||
;set the spawn of the player to the field 'P'
|
||||
spawnPlayer:
|
||||
mov bp, setSpawn
|
||||
mov ah, 'P'
|
||||
call iterateMap ; iterate the map and set the player position to the last 'P' found on the map
|
||||
ret
|
||||
|
||||
%define tileWidth 8
|
||||
%define ASCIImapWidth 64
|
||||
%define ASCIImapHeight 64
|
||||
;bp = function to call, ah = search for, si = parameter for bp function
|
||||
iterateMap:
|
||||
mov di, ASCIImap
|
||||
mov cx, 0x0 ; map start x
|
||||
mov dx, 0x0 ; map start y
|
||||
.next:
|
||||
mov al, [di]
|
||||
test al, al
|
||||
je .stop ; stop when null terminator found
|
||||
cmp al, ah
|
||||
jne .skip ; skip if the character is not the one this iteration is searching for
|
||||
push ax ; save the content of ax
|
||||
call bp ; call the specified function of this iteration
|
||||
pop ax
|
||||
jc .term ; the carry flag determines if the specified function has found what it was searching for (and thus exits)
|
||||
.skip:
|
||||
inc di ; point to the next character
|
||||
add cx, tileWidth ; increase x pixel position
|
||||
cmp cx, ASCIImapWidth*tileWidth ; check if x position is at the end of the line
|
||||
jl .next
|
||||
sub dx, tileWidth ; decrease y pixel position
|
||||
xor cx, cx ; reset x position
|
||||
jmp .next
|
||||
.stop:
|
||||
clc
|
||||
.term:
|
||||
ret
|
||||
|
||||
;si = player x, bx = player z, cx = block x, dx = block z
|
||||
blockCollison:
|
||||
push cx
|
||||
push dx
|
||||
sub cx, 8 ;subtract 8 because of hitbox
|
||||
cmp cx, si ; (blockX-8 <= playerX)
|
||||
jg .skip
|
||||
add cx, 8+8 ;add 8 because of hitbox
|
||||
cmp cx, si ; (blockX+8 > playerX)
|
||||
jle .skip
|
||||
sub dx, 10 ;subtract 10 because of hitbox
|
||||
cmp dx, bx ; (blockZ-10 <= playerZ)
|
||||
jg .skip
|
||||
add dx, 9+10 ;subtract 9 because of hitbox
|
||||
cmp dx, bx ; (blockZ+9 > playerZ)
|
||||
jle .skip
|
||||
stc
|
||||
jmp .end
|
||||
.skip:
|
||||
clc
|
||||
.end:
|
||||
pop dx
|
||||
pop cx
|
||||
ret
|
||||
|
||||
%include "buffer.asm"
|
||||
|
||||
|
||||
;game value
|
||||
|
||||
coinFound dw 0
|
||||
|
||||
;entity array
|
||||
|
||||
entityArray:
|
||||
dw player
|
||||
resw entityArraySize
|
||||
|
||||
;player structure
|
||||
player:
|
||||
player_Anim dw playerImg_front ;pointer to animation
|
||||
player_PosX dw 0x32 ;position of player (x)
|
||||
player_PosZ dw 0x32 ;position of player (z)
|
||||
player_AnimC dw 0 ;animation counter
|
||||
|
||||
;entity structure
|
||||
box:
|
||||
box_Anim dw boxImg ;pointer to animation
|
||||
box_PosX dw 0x10 ;position of box (x)
|
||||
box_PosZ dw 0x10 ;position of box (z)
|
||||
box_AnimC dw 0 ;animation counter
|
||||
|
||||
;other entity structures:
|
||||
entityArrayMem:
|
||||
resw entityArraySize*4
|
||||
|
||||
;animation structure
|
||||
playerImg_front:
|
||||
dw 5
|
||||
dw 20
|
||||
dw playerImg_front_0
|
||||
dw playerImg_front_1
|
||||
dw playerImg_front_0
|
||||
dw playerImg_front_2
|
||||
dw 0
|
||||
|
||||
playerImg_back:
|
||||
dw 5
|
||||
dw 20
|
||||
dw playerImg_back_0
|
||||
dw playerImg_back_1
|
||||
dw playerImg_back_0
|
||||
dw playerImg_back_2
|
||||
dw 0
|
||||
|
||||
playerImg_right:
|
||||
dw 5
|
||||
dw 20
|
||||
dw playerImg_right_0
|
||||
dw playerImg_right_1
|
||||
dw playerImg_right_0
|
||||
dw playerImg_right_2
|
||||
dw 0
|
||||
|
||||
playerImg_left:
|
||||
dw 5
|
||||
dw 20
|
||||
dw playerImg_left_0
|
||||
dw playerImg_left_1
|
||||
dw playerImg_left_0
|
||||
dw playerImg_left_2
|
||||
dw 0
|
||||
|
||||
boxImg:
|
||||
dw 1 ;time per frames
|
||||
dw 1 ;time of animation
|
||||
dw boxImg_0 ;frames
|
||||
dw 0 ;zero end frame
|
||||
|
||||
coinImg:
|
||||
dw 5 ;time per frames
|
||||
dw 20 ;time of animation
|
||||
dw coin_0 ;frames
|
||||
dw coin_1 ;frames
|
||||
dw coin_2 ;frames
|
||||
dw coin_1 ;frames
|
||||
dw 0 ;zero end frame
|
||||
|
||||
playerImg_front_0 incbin "img/player_front_0.bin"
|
||||
playerImg_front_1 incbin "img/player_front_1.bin"
|
||||
playerImg_front_2 incbin "img/player_front_2.bin"
|
||||
playerImg_back_0 incbin "img/player_back_0.bin"
|
||||
playerImg_back_1 incbin "img/player_back_1.bin"
|
||||
playerImg_back_2 incbin "img/player_back_2.bin"
|
||||
playerImg_right_0 incbin "img/player_right_0.bin"
|
||||
playerImg_right_1 incbin "img/player_right_1.bin"
|
||||
playerImg_right_2 incbin "img/player_right_2.bin"
|
||||
playerImg_left_0 incbin "img/player_left_0.bin"
|
||||
playerImg_left_1 incbin "img/player_left_1.bin"
|
||||
playerImg_left_2 incbin "img/player_left_2.bin"
|
||||
|
||||
coin_0 incbin "img/coin_0.bin"
|
||||
coin_1 incbin "img/coin_1.bin"
|
||||
coin_2 incbin "img/coin_2.bin"
|
||||
|
||||
boxImg_0 incbin "img/box.bin"
|
||||
tileImg_0 incbin "img/tile.bin"
|
||||
|
||||
ASCIImap incbin "img/map.bin"
|
||||
db 0
|
||||
|
||||
%assign usedMemory ($-$$)
|
||||
%assign usableMemory (512*16)
|
||||
%warning [usedMemory/usableMemory] Bytes used
|
||||
times (512*16)-($-$$) db 0 ;kernel must have size multiple of 512 so let's pad it to the correct size
|
||||
;times (512*1000)-($-$$) db 0 ;toggle this to use in bochs
|