new beep program on enter

master
Your Name 6 years ago
parent ad6565f7fd
commit 3a7fe80b7e

Binary file not shown.

Binary file not shown.

@ -3,24 +3,27 @@ all : image
compile : compile :
nasm -f bin -o boot.bin boot.asm nasm -f bin -o boot.bin boot.asm
nasm -f bin -o program.bin program.asm nasm -f bin -o program.bin program.asm
nasm -f bin -o program2.bin program2.asm nasm -f bin -o beep.bin beep.asm
# nasm -f bin -o program2.bin program2.asm
image : compile image : compile
sudo dd if=/dev/zero of=disk.img bs=1024 count=720 sudo dd if=/dev/zero of=disk.img bs=1024 count=720
#cat boot.bin program.bin > exe.bin
sudo dd if=boot.bin of=disk.img bs=512 count=1 conv=notrunc sudo dd if=boot.bin of=disk.img bs=512 count=1 conv=notrunc
sudo dd if=program.bin of=disk.img bs=512 seek=1 count=1 conv=notrunc sudo dd if=program.bin of=disk.img bs=512 seek=1 count=2 conv=notrunc
sudo dd if=program2.bin of=disk.img bs=512 seek=2 count=1 conv=notrunc sudo dd if=beep.bin of=disk.img bs=512 seek=3 count=1 conv=notrunc
flashusb : image flashusb : image
sudo dd if=boot.bin of=/dev/sdb bs=512 count=1 sudo dd if=boot.bin of=/dev/sdb bs=512 count=1
sudo dd if=program.bin of=/dev/sdb bs=512 seek=1 count=1 sudo dd if=program.bin of=/dev/sdb bs=512 seek=1 count=2
sudo dd if=program2.bin of=/dev/sdb bs=512 seek=2 count=1 sudo dd if=beep.bin of=/dev/sdb bs=512 seek=3 count=1
# sudo dd if=exe.bin of=/dev/sdb bs=512 count=4
run : image run : image
qemu-system-x86_64 disk.img qemu-system-x86_64 disk.img -soundhw pcspk
clean : clean :
rm *.img rm *.img

@ -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

Binary file not shown.

@ -1,5 +1,4 @@
[org 0x7c00] [org 0x7c00]
[bits 16] [bits 16]
pre: pre:
@ -12,13 +11,11 @@ welcome:
xor ax,ax ; We want a segment of 0 for DS for this question xor ax,ax ; We want a segment of 0 for DS for this question
mov ds,ax ; Set AX to appropriate segment value for your situation mov ds,ax ; Set AX to appropriate segment value for your situation
mov es,ax ; In this case we'll default to ES=DS mov es,ax ; In this case we'll default to ES=DS
mov bx,0x8000 ; Stack segment can be any usable memory mov bx,0x1000 ; Stack segment can be any usable memory
mov ss,bx ; This places it with the top of the stack @ 0x80000. mov ss,bx ; This places it with the top of the stack @ 0x80000.
mov sp,ax ; Set SP=0 so the bottom of stack will be @ 0x8FFFF mov sp,ax ; Set SP=0 so the bottom of stack will be @ 0x8FFFF
cld ; Set the direction flag to be positive direction cld ; Set the direction flag to be positive direction
mov ah, 01h ;make cursor invisible mov ah, 01h ;make cursor invisible
mov cx, 2607h mov cx, 2607h
int 10h int 10h
@ -82,16 +79,16 @@ load_it_all_1:
mov bx, 0x1000 ; BX = 0x1000. ES:BX=0x0:0x1000 mov bx, 0x1000 ; BX = 0x1000. ES:BX=0x0:0x1000
; ES:BX = starting address to read sector(s) into ; ES:BX = starting address to read sector(s) into
mov ah, 02 ; Int 13h/AH=2 = Read Sectors From Drive mov ah, 02 ; Int 13h/AH=2 = Read Sectors From Drive
mov al, 01 ; Sectors to read = 1 mov al, 0x10 ; Sectors to read = 1
mov ch, 00 ; CH=Cylinder. Second sector of disk mov ch, 00 ; CH=Cylinder. Second sector of disk
; is at Cylinder 0 not 1 ; is at Cylinder 0 not 1
mov cl, 02 ; Sector to read = 2 mov cl, 02 ; Sector to read = 2
mov dh, 00 ; Head to read = 0 mov dh, 00 ; Head to read = 0
; DL hasn't been destroyed by our bootloader code and still
; contains boot drive # passed to our bootloader by the BIOS
mov dl, [bootdev] mov dl, [bootdev]
int 13h int 13h
jc wolf_error jc wolf_error
popf popf
jmp 0x0:0x1000 jmp 0x0:0x1000

Binary file not shown.

@ -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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 874 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 906 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 861 B

@ -1,6 +1,7 @@
[org 0x1000] [org 0x1000]
start: start:
mov [bootdev], dl
mov ah, 01h ;make cursor invisible mov ah, 01h ;make cursor invisible
mov cx, 2607h mov cx, 2607h
int 10h int 10h
@ -14,36 +15,45 @@ start:
mov ah, 06h ;draw rect on background mov ah, 06h ;draw rect on background
mov cx, 0101h mov cx, 0101h
mov dx, 164Dh mov dx, 124Dh
mov bh, 3Eh mov bh, 3Eh
int 10h int 10h
mov ah, 06h ;draw shadow mov ah, 06h ;draw shadow
mov cx, 1702h mov cx, 1302h
mov dx, 174Eh mov dx, 134Eh
mov bh, 0Eh mov bh, 0Eh
int 10h int 10h
mov ah, 06h ;draw shadow mov ah, 06h ;draw shadow
mov cx, 024Eh mov cx, 024Eh
mov dx, 174Eh mov dx, 134Eh
mov bh, 0Eh mov bh, 0Eh
int 10h int 10h
; menu bottom
mov ah, 06h ;draw rect on background
mov cx, 1700h
mov dx, 184Fh
mov bh, 3Fh
int 10h
mov ah, 02h ;sets cursor to top to write mov ah, 02h ;sets cursor to top to write
mov bh, 0h mov bh, 0h
mov dh, 1h mov dh, 17h
mov dl, 1h mov dl, 2h
int 10h int 10h
mov si, menuhelp
call print
mov al, 0xC9 ;draw border mov si, menuselect
mov bl, 0x03 call print
mov ah,0x0e
int 10h mov si, menuexit
mov al, 0xCD call print
mov bl, 0x03
mov ah,0x0e mov si, menuenter
int 10h call print
mov ah, 02h ;sets cursor to top to write mov ah, 02h ;sets cursor to top to write
mov bh, 0h mov bh, 0h
@ -111,6 +121,8 @@ waitforkey:
je .up je .up
cmp ah, 11h cmp ah, 11h
je .down je .down
cmp ah, 1Ch
je loadproject
jmp waitforkey jmp waitforkey
.up .up
@ -141,29 +153,90 @@ waitforkey:
jmp print_projects jmp print_projects
loadproject:
mov bx, [currentselection]
pushf
stc
mov ah,00
int 13h
.read_sector:
mov ax, 0x0
mov es, ax ; ES = 0
mov bx, 0x2000 ; BX = 0x1000. ES:BX=0x0:0x1000
; ES:BX = starting address to read sector(s) in$
mov ah, 02 ; Int 13h/AH=2 = Read Sectors From Drive;
mov al, 0x10 ; Sectors to read = 1
mov ch, 00 ; CH=Cylinder. Second sector of disk
; is at Cylinder 0 not 1
mov cl, 04 ; Sector to read = 2
mov dh, 00 ; Head to read = 0
mov dl, [bootdev]
int 13h
jc wolf_error
popf
jmp 0x0:0x2000
cli
hlt
wolf_error:
mov si, wolf_error_msg
call print
mov si, wolf_error_msg1
call print
mov ah,00
int 16h
xor ax,ax
int 19h
print: print:
lodsb lodsb
or al,al or al,al
jz exit jz exit
;mov bl, 0x03
mov ah,0x0e mov ah,0x0e
int 10h int 10h
jmp print jmp print
exit: exit:
ret ret
msg1 db "ARTIST / TITLE",0
msg1 db " X P U B",0x0A,0 project1 db "Name / Exampletitle of this",0
msg2 db " NOT MY DEFAULT",0x0D,0x0A,0 project2 db "Name2 / Silence and more",0
project3 db "Name3 / C00l, new title and more", 0
project1 db "Alex / Poetic Software", 0x0A,0 project4 db "Name4 / Everyon", 0
project2 db "Tash / Silence Making", 0x0A,0 project5 db "Name5 / Voices and more", 0
project3 db "Alice / F00d", 0x0A,0 project6 db "Name6 / Examples of titles", 0
project4 db "Joca / The ghost in the speaker", 0x0A,0
project5 db "Angeliki / Voices", 0x0A,0
project6 db "Zalan / Phantasmagoria", 0x0A,0
projects dq project1, project2, project3, project4, project5, project6 projects dq project1, project2, project3, project4, project5, project6
menuhelp db "F1 Help", 0
menuselect db " W/S Select Item",0
menuexit db 0x0D,0x0A," ESC Exit", 0
menuenter db " Enter publication",0
wolf_error_msg db 'Program not found!',0x0D,0x0A,0
wolf_error_msg1 db 'Press any key to restart..',0
currentselection dw 0 currentselection dw 0
storebx dw 0 storebx dw 0
bootdev db 0x80 ; Boot device number
%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

Binary file not shown.

@ -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
Loading…
Cancel
Save