starting on hardware sprites
This commit is contained in:
parent
3e18d9cdb2
commit
23bc034f6f
18
arena.c
18
arena.c
|
@ -1,13 +1,14 @@
|
||||||
#include "bmpload.h"
|
#include "bmpload.h"
|
||||||
#include "const.h"
|
#include "const.h"
|
||||||
#include "arena.h"
|
#include "arena.h"
|
||||||
|
#include "system/vga.h"
|
||||||
|
|
||||||
char arenaLayout[10][10] = {
|
char arenaLayout[10][10] = {
|
||||||
{ 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 },
|
{ 1, 1, 1, 1, 0, 0, 1, 1, 1, 1 },
|
||||||
{ 1, 2, 2, 2, 0, 0, 2, 2, 2, 1 },
|
|
||||||
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||||
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||||
{ 2, 0, 0, 0, 0, 0, 0, 0, 0, 2 },
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||||
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||||
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
|
||||||
|
@ -37,9 +38,14 @@ void setupWallSprites(struct BMPImage *spritesheetImage) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern void renderFloorTile(byte *);
|
||||||
|
// push items onto stack
|
||||||
|
#pragma aux (__cdecl) renderFloorTile "renderFloorTile_"
|
||||||
|
|
||||||
void renderArenaTile(int x, int y) {
|
void renderArenaTile(int x, int y) {
|
||||||
char tile;
|
char tile;
|
||||||
struct SpriteRender *target;
|
struct SpriteRender *target;
|
||||||
|
byte *drawBuffer;
|
||||||
|
|
||||||
tile = arenaLayout[y][x];
|
tile = arenaLayout[y][x];
|
||||||
|
|
||||||
|
@ -58,8 +64,16 @@ void renderArenaTile(int x, int y) {
|
||||||
target->x = x * TILE_SIZE;
|
target->x = x * TILE_SIZE;
|
||||||
target->y = y * TILE_SIZE;
|
target->y = y * TILE_SIZE;
|
||||||
|
|
||||||
|
if (tile == 0) {
|
||||||
|
drawBuffer = getDrawBuffer();
|
||||||
|
|
||||||
|
renderFloorTile(
|
||||||
|
drawBuffer + target->x + target->y * VGA_DISPLAY_WIDTH
|
||||||
|
);
|
||||||
|
} else {
|
||||||
drawSprite(target);
|
drawSprite(target);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
char arenaRedrawRequests[ARENA_HEIGHT_TILES][ARENA_WIDTH_TILES];
|
char arenaRedrawRequests[ARENA_HEIGHT_TILES][ARENA_WIDTH_TILES];
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,174 @@
|
||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require 'rmagick'
|
||||||
|
require 'yaml'
|
||||||
|
require 'erb'
|
||||||
|
|
||||||
|
data = YAML.load(File.read('spritesheet.yml'))
|
||||||
|
|
||||||
|
class Sprite
|
||||||
|
def initialize(image:, sx:, sy:, width:, height:)
|
||||||
|
@image = image
|
||||||
|
@sx = sx
|
||||||
|
@sy = sy
|
||||||
|
@width = width
|
||||||
|
@height = height
|
||||||
|
end
|
||||||
|
|
||||||
|
def pixel_data
|
||||||
|
@height.times.each_with_object([]) do |y, obj|
|
||||||
|
obj << @width.times.map do |x|
|
||||||
|
color = @image.pixel_color(x + @sx, y + @sy)
|
||||||
|
|
||||||
|
colormap.find_index { |c| c == color }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def colormap
|
||||||
|
@colormap ||= @image.colors.times.map do |i|
|
||||||
|
Magick::Pixel.from_color(@image.colormap(i))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
MovBytePtr = Data.define(:offset, :data)
|
||||||
|
|
||||||
|
ASM_TEMPLATE = <<~ASM
|
||||||
|
<% sprites.each do |sprite| %>
|
||||||
|
PUBLIC <%= sprite.exported_name %><% end %>
|
||||||
|
|
||||||
|
.386
|
||||||
|
.model flat,c
|
||||||
|
|
||||||
|
.CODE
|
||||||
|
|
||||||
|
<% sprites.each do |sprite| %>
|
||||||
|
<%= sprite.exported_name %>:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
mov eax, [ebp + 8]
|
||||||
|
|
||||||
|
<% sprite.bytes.each do |byte| %>
|
||||||
|
mov BYTE PTR [eax + <%= byte.offset %>], <%= byte.data %><% end %>
|
||||||
|
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
<% end %>
|
||||||
|
end
|
||||||
|
ASM
|
||||||
|
|
||||||
|
C_TEMPLATE = <<~C
|
||||||
|
<% sprites.each do |sprite| %>
|
||||||
|
extern void <%= sprite.function_name %>(byte *);
|
||||||
|
#pragma aux (__cdecl) <%= sprite.function_name %> "<%= sprite.exported_name %>"
|
||||||
|
<% end %>
|
||||||
|
C
|
||||||
|
|
||||||
|
class AssemblerSprite
|
||||||
|
def initialize(
|
||||||
|
name:,
|
||||||
|
pixel_data:,
|
||||||
|
screen_width:,
|
||||||
|
transparent_color:,
|
||||||
|
offset_x:,
|
||||||
|
offset_y:,
|
||||||
|
prefix:
|
||||||
|
)
|
||||||
|
@name = name
|
||||||
|
@pixel_data = pixel_data
|
||||||
|
@screen_width = screen_width
|
||||||
|
@transparent_color = transparent_color
|
||||||
|
@offset_x = offset_x
|
||||||
|
@offset_y = offset_y
|
||||||
|
@prefix = prefix
|
||||||
|
end
|
||||||
|
|
||||||
|
def exported_name
|
||||||
|
"#{function_name}_"
|
||||||
|
end
|
||||||
|
|
||||||
|
def function_name
|
||||||
|
"#{@prefix}_#{@name}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def bytes
|
||||||
|
return @bytes if defined?(@bytes)
|
||||||
|
|
||||||
|
bytes = []
|
||||||
|
|
||||||
|
@pixel_data.each_with_index do |row, y|
|
||||||
|
row.each_with_index do |column, x|
|
||||||
|
next if @pixel_data[y][x] == @transparent_color
|
||||||
|
|
||||||
|
bytes << MovBytePtr.new(
|
||||||
|
data: @pixel_data[y][x],
|
||||||
|
offset: x - @offset_x + (y - @offset_y) * @screen_width
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
bytes
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Screen = Data.define(:width, :transparent_color)
|
||||||
|
SpriteData = Data.define(:image, :name, :position, :dimensions, :offset, :prefix)
|
||||||
|
|
||||||
|
screen = Screen.new(
|
||||||
|
width: data["screen"]["width"],
|
||||||
|
transparent_color: data["screen"]["transparentColor"]
|
||||||
|
)
|
||||||
|
|
||||||
|
sprite_data = []
|
||||||
|
|
||||||
|
data["files"].each do |spritesheet|
|
||||||
|
image = Magick::Image.read(spritesheet["file"]).first
|
||||||
|
|
||||||
|
spritesheet["sprites"].each do |name, details|
|
||||||
|
sprite_data << SpriteData.new(
|
||||||
|
image:,
|
||||||
|
name:,
|
||||||
|
prefix: spritesheet["prefix"],
|
||||||
|
position: details["position"],
|
||||||
|
dimensions: details["dimensions"],
|
||||||
|
offset: details["offset"]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
sprites = sprite_data.map do |sd|
|
||||||
|
sprite = Sprite.new(
|
||||||
|
image: sd.image,
|
||||||
|
sx: sd.position[0],
|
||||||
|
sy: sd.position[1],
|
||||||
|
width: sd.dimensions[0],
|
||||||
|
height: sd.dimensions[1],
|
||||||
|
)
|
||||||
|
|
||||||
|
AssemblerSprite.new(
|
||||||
|
name: sd.name,
|
||||||
|
prefix: sd.prefix,
|
||||||
|
pixel_data: sprite.pixel_data,
|
||||||
|
screen_width: screen.width,
|
||||||
|
transparent_color: screen.transparent_color,
|
||||||
|
offset_x: sd.offset[0],
|
||||||
|
offset_y: sd.offset[1],
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
File.open('sprites.asm', 'w') do |fh|
|
||||||
|
fh.puts ERB.new(ASM_TEMPLATE).result_with_hash(sprites:)
|
||||||
|
end
|
||||||
|
|
||||||
|
File.open('sprites.h', 'w') do |fh|
|
||||||
|
fh.puts ERB.new(C_TEMPLATE).result_with_hash(sprites:)
|
||||||
|
end
|
||||||
|
|
||||||
|
puts "sprites.{asm,h} written"
|
7
game.c
7
game.c
|
@ -331,16 +331,11 @@ int currentSpeedCalc = 0;
|
||||||
double averageSpeedCalc;
|
double averageSpeedCalc;
|
||||||
clock_t startTime;
|
clock_t startTime;
|
||||||
|
|
||||||
extern int doAThing(int);
|
// non cdecl is put params into eax, ebx, and ecx
|
||||||
#pragma aux (__cdecl) doAThing "doAThing_"
|
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
int keepRunning = 1;
|
int keepRunning = 1;
|
||||||
|
|
||||||
fprintf(stderr, "%d\n", doAThing(1000));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (setupGame()) return 1;
|
if (setupGame()) return 1;
|
||||||
|
|
||||||
maybeSpawnEnemy();
|
maybeSpawnEnemy();
|
||||||
|
|
3
makefile
3
makefile
|
@ -10,6 +10,9 @@ system/system.lib: .SYMBOLIC
|
||||||
.c.o:
|
.c.o:
|
||||||
wcc386 -q -bt=dos $<
|
wcc386 -q -bt=dos $<
|
||||||
|
|
||||||
|
.asm.o:
|
||||||
|
wasm $<
|
||||||
|
|
||||||
game.exe: $(obj) system/system.lib
|
game.exe: $(obj) system/system.lib
|
||||||
wcl386 -q -bt=dos -l=dos4g $(obj) system/system.lib
|
wcl386 -q -bt=dos -l=dos4g $(obj) system/system.lib
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
extern void sprite_arenaWallTop(byte *);
|
||||||
|
#pragma aux (__cdecl) sprite_arenaWallTop "sprite_arenaWallTop_"
|
||||||
|
|
||||||
|
extern void sprite_arenaWallSide(byte *);
|
||||||
|
#pragma aux (__cdecl) sprite_arenaWallSide "sprite_arenaWallSide_"
|
||||||
|
|
||||||
|
extern void sprite_arenaFloor(byte *);
|
||||||
|
#pragma aux (__cdecl) sprite_arenaFloor "sprite_arenaFloor_"
|
||||||
|
|
||||||
|
extern void sprite_rabbit(byte *);
|
||||||
|
#pragma aux (__cdecl) sprite_rabbit "sprite_rabbit_"
|
||||||
|
|
||||||
|
extern void sprite_mouse(byte *);
|
||||||
|
#pragma aux (__cdecl) sprite_mouse "sprite_mouse_"
|
||||||
|
|
||||||
|
extern void sprite_bullet(byte *);
|
||||||
|
#pragma aux (__cdecl) sprite_bullet "sprite_bullet_"
|
||||||
|
|
||||||
|
extern void sprite_enemy(byte *);
|
||||||
|
#pragma aux (__cdecl) sprite_enemy "sprite_enemy_"
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
screen:
|
||||||
|
width: 320
|
||||||
|
transparentColor: 0
|
||||||
|
files:
|
||||||
|
- file: sprtsht.bmp
|
||||||
|
prefix: "sprite"
|
||||||
|
sprites:
|
||||||
|
arenaWallTop:
|
||||||
|
position: [0, 0]
|
||||||
|
dimensions: [20, 20]
|
||||||
|
offset: [10, 10]
|
||||||
|
arenaWallSide:
|
||||||
|
position: [20, 0]
|
||||||
|
dimensions: [20, 20]
|
||||||
|
offset: [0, 0]
|
||||||
|
arenaFloor:
|
||||||
|
position: [40, 0]
|
||||||
|
dimensions: [20, 20]
|
||||||
|
offset: [0, 0]
|
||||||
|
rabbit:
|
||||||
|
position: [0, 20]
|
||||||
|
dimensions: [16, 16]
|
||||||
|
offset: [8, 8]
|
||||||
|
mouse:
|
||||||
|
position: [16, 20]
|
||||||
|
dimensions: [8, 8]
|
||||||
|
offset: [4, 4]
|
||||||
|
bullet:
|
||||||
|
position: [16, 28]
|
||||||
|
dimensions: [4, 4]
|
||||||
|
offset: [1, 1]
|
||||||
|
enemy:
|
||||||
|
position: [0, 20]
|
||||||
|
dimensions: [16, 16]
|
||||||
|
offset: [8, 8]
|
|
@ -22,7 +22,7 @@ byte *initializeDrawBuffer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void copyDrawBufferToDisplay() {
|
void copyDrawBufferToDisplay() {
|
||||||
memcpy(VGA, drawBuffer, 320 * 200);
|
memcpy(VGA, drawBuffer, VGA_DISPLAY_WIDTH * VGA_DISPLAY_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeDrawBuffer() {
|
void freeDrawBuffer() {
|
||||||
|
|
56
test.asm
56
test.asm
|
@ -1,10 +1,11 @@
|
||||||
PUBLIC doAThing_
|
#PUBLIC doAThing_
|
||||||
|
#PUBLIC renderTopTile_
|
||||||
|
PUBLIC renderFloorTile_
|
||||||
|
|
||||||
.386
|
.386
|
||||||
.model flat,c
|
.model flat,c
|
||||||
|
|
||||||
_TEXT segment byte public 'CODE'
|
.CODE
|
||||||
|
|
||||||
doAThing_:
|
doAThing_:
|
||||||
push ebp
|
push ebp
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
|
@ -14,6 +15,53 @@ doAThing_:
|
||||||
pop ebp
|
pop ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
_TEXT ends
|
renderTopTile_:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
mov eax, [ebp + 8]
|
||||||
|
mov ebx, 20
|
||||||
|
|
||||||
|
_renderNextLine:
|
||||||
|
mov DWORD PTR [eax], 02020202h
|
||||||
|
mov DWORD PTR [eax + 4], 02020202h
|
||||||
|
mov DWORD PTR [eax + 8], 02020202h
|
||||||
|
mov DWORD PTR [eax + 12], 02020202h
|
||||||
|
mov DWORD PTR [eax + 16], 02020202h
|
||||||
|
|
||||||
|
add eax, 320
|
||||||
|
dec ebx
|
||||||
|
cmp ebx, 0
|
||||||
|
jne _renderNextLine
|
||||||
|
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
renderFloorTile_:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push ebx
|
||||||
|
|
||||||
|
mov eax, [ebp + 8]
|
||||||
|
mov ebx, 20
|
||||||
|
|
||||||
|
_renderNextFloorLine:
|
||||||
|
mov DWORD PTR [eax], 04040404h
|
||||||
|
mov DWORD PTR [eax + 4], 04040404h
|
||||||
|
mov DWORD PTR [eax + 8], 04040404h
|
||||||
|
mov DWORD PTR [eax + 12], 04040404h
|
||||||
|
mov DWORD PTR [eax + 16], 04040404h
|
||||||
|
|
||||||
|
add eax, 320
|
||||||
|
dec ebx
|
||||||
|
cmp ebx, 0
|
||||||
|
jne _renderNextFloorLine
|
||||||
|
|
||||||
|
_done:
|
||||||
|
pop ebx
|
||||||
|
pop ebp
|
||||||
|
ret
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue