Omnimaga

Omnimaga => Discontinued => Our Projects => Ash: Phoenix => Topic started by: squidgetx on October 07, 2012, 01:01:11 pm

Title: [A:P] Documentation
Post by: squidgetx on October 07, 2012, 01:01:11 pm
Spoiler For Battle Engine Specifications:
The battle engine will be turn based, similar to Pokemon and other common RPG battle engine styles.

Battle Stats: (I've modified this slightly from the original, which was essentially Pokemon, in favor of a slightly different mechanic)
HP: Um, HP. Yeah, self explanatory
MP: MP
Strength: Determines damage potential, similar to Runescape Strength. Sets a max of possible damage.
Skill: Higher skill means higher likelihood of hitting high within your range. (RS attack)
Defense: All around defense, for both physical and mystical attacks
Speed: Determines who moves first
Mystic Strength: Magic strength
Mystic Skill: same (Names may change later on)
Battle Types
Unchanged from the original, there will be 6 battle types: 3 physical, 3 magical, each with their own stat tendencies. Similar to Pokemon, attacks will be typed and bonuses applied accordingly. Each type also has a limited move-learning ability and can only wield certain items. Overall, the mystic types are more unbalanced/interesting than the physical types.
-Warrior: Standard sword and shield dudes. Kind of a bunch of thugs
-Archer: Invisible snipers.
-Assassin: Glass cannons, fast but weak.

-Holy/Spirit: Religious zealots, only their God grants them magic powers. Watch out....
-Undead: They're already dead! What can you do...They're tanks.
-Black/Shadow: Spawn of the night. Fast, poisonous, but even weaker than assassins.

Battle Calculations
Speed calculations: Unlike Pokemon, which uses a fairly black and white method for determining who is faster, my engine will use the following calculation: Speedplayer1/(Speedp1+Speedp2) is the chance that player 1 will go first. This will be realized by the condition rand^(speed1+speed2) > speed2

Damage calculation: Strength/Defense will basically be our indication of how hard we can hit so Strength*AttackPower/Defense is fine for setting the max of attack. Now, Skill will be used to determine the relationship between the actual damage and our base median figure. An unskilled fighter will have a large, low value set. A skilled fighter will be able to consistently hit in a high value, small set. So, we'll use an inverse relationship in which the range of damage is (256 - Skill)*dmg/256 This value will be subtracted from the maxdmg from the Strength/Defense section of the equ, making a level 1 skill fighter hitting anywhere from 0 to his max, while a level 256 skill fighter will always hit his max. This is then algebraically optimized to (Skill )*Max/256+Max. Attacks can have power levels generally capped at 256, while items will simply increase the stats of strength, attack, etc. Note that this means that if you can get your net skill over 256, say with a skill level of 200 and a sword of +100 skill, you can hit consistently over the "max damage" determined by the Strength/Defense calculation. If at any point overflow is detected, the damage calculation subroutine will exit and simply return 65535 as the amount of damage to be dealt.

There will be a type-advantage mechanic nearly identical to Pokemon's. Table below:
x Wr Ar As Ho Un Bl
Wr 1  2  1  2  .5 .5
Ar 2  1  2  2  .5 0
As 2  1  .5 1  1  1
Ho .5 1  .5 1  2  2
Un 1  1  1  1  1  1
Bl 1  1  2  .5 1  1


Stat Calculation
Stat calculations will follow the following formula:
Stat = (BaseStat*16 + TrainingExpValue) * Level / 100 + 5

Base stats for the player types here:
  HP MP Str Skl Spe Def MSt MSk Total
Wr 12 8  12  8   9  10  8   8   74
Ar 11  9   10  12  11  7   8   8   80
As 9  7   13  13  13  5   7   9   86
Ho 12 11 5   5   9   9   12   12  75
Un 14 10 15  7   6   12   12   6   82
Bl 5  10  12  12  15  4  13  14   87


TrainingExpValue is determined by what moves you use. Every time you use a certain type move, the corresponding stat for total "points" will be incremented. Points convert to TrainingExpValue by dividing by 8.

With this system, the highest a stat can be (not minding the TEV) is the Black/Shadow lvl 100 speed, which is 245.

Levels are grown with experience via the following formula:
To grow to level n, you need:
exp(n) = 2n^2+2n
samples exp(6) = 84XP
exp(30) = 1860XP
exp(60) = 7320XP
exp(100) = 20200XP

Instead of bothering to keep track of total XP, I'll only keep track of how much to the next level, avoiding annoying overflow problems, plus I'll save a few bytes in the calculations too :D.

Enemies will give experience simply by averaging all their stats together then multiplying by a constant. I'll figure out what that constant is, but as a rough rule of thumb lvl 100 enemies will give roughly 2k xp and lvl 3 enemies will give ~10 xp.


Spoiler For metadata:

___________________
|Player save files|
|_________________|

L4: Available space: $100

$00-$09:Player Name (9 chars, 1 null terminator)
$0A-$oB:Xpos
$0C-$0D:Ypos
$0E-$0F:MapID
$10-$11:OverworldX
$12-$13:OverworldY
$14-$15:Money
$16-$17:XP to next level   ;Battle stats
$18-$19:Level
$1A-$1B:Player Type
$1C-$1D:Strength
$1E-$1F:Skill
$20-$21:Speed
$22-$23:MStr
$24-$25:MSkl
$26-$27:Def
$28-$29:HP
$2A-$2B:MP
$2C-$2D:Weapon attacks (2)
$30-$33:Skills (4)
$34-$39:Type XP
$3A-$3F:Equipped items      ;weapon, shield, armor, hat, amulet, 6th item?
$40-$7F:Items         ;Items- Item ID, qty. $20 item slots (32d)
$80-$9F:Player flags      ;$20 player flags (32 bytes, 64 nibbles, 256 bits)
_______
|Flags|
________


Memory Allocations


$8000 section:metadata swap-in space
$8000-$801A: Map Metadata
$801C-$801D: Direction player is facing
$8020-$8036: Item Metadata
$8040-$8056: Move Metadata
$8058-$8096: Swap area for drawing bitmaps

L1: map spritebuffer (384) map char-store-area (64)
L1+500: list item freeram (battle moves, items, etc)
L2: NPC convos
L3: backbuf
L4: Player save data
L5: Enemy battle info
L6: frontbuf
tempvar: map
tempvar+1024: overworld map
tempvar+1152: sprite anim
tempvar+3200: map padding?


There will be a master-map...a tilemap of map pieces...each map 'piece' will be 32x32 tiles


____________
Map metadata
------------

$1B bytes per entry
$00-$15:name (21 characters, plus null terminator)   (MName)
$16:   tileset                (MapTS)
$17:   avg level of enemies             (AvgLv)
$18:   enemy type 1                (Ene1)
$19:   enemy type 2                (Ene2)
$1A:    enemy type 3                (Ene3)


_____________
Item metadata
_____________

$17 bytes per entry

$00-$0F:item name (15 chars, plus null terminator)    (IName)
$10-$11:itemID                   (ItID)r
$12:   equip or useable?             (IFlag)
$13:   stat to affect (0-7)            (IStat)
$14:   how many points to increase/decrease       (IStat+1)
$15:   stat to affect 2             (IStat+2)
$16:   points to inc/dec 2             (IStat+3)

_____________
move metadata
_____________

$17 bytes per entry

$00-$0F: move name (15 chars, plus null terminator)    (AName)
$10: move type                   (Atype)
$11: move animation               (AAnim)
$12: damage                  (Admg)
$13: stat to boost1               (AStat)
$14: amt to boost               (AStat+1)
$15: stat to boost2               (AStat+2)
$16: amt. to boost2               (AStat+3)


There will be a master-map...a tilemap of map pieces...each map 'piece' will be 32x32 tiles


____________
Map metadata
------------

$1B bytes per entry
$00-$15:name (21 characters, plus null terminator)
$16:   tileset (might not use this, since now maps have access to 192 tiles at once)
$17:   avg level of enemies
$18:   enemy type 1
$19:   enemy type 2
$1A:    enemy type 3


_____________
Item metadata
_____________

$17 bytes per entry

$00-$0F:item name (15 chars, plus null terminator)
$10-$11:itemID
$12:   equip or useable?
$13:   stat to affect (0-7)
$14:   how many points to increase/decrease
$15:   stat to affect 2
$16:   points to inc/dec 2

_____________
move metadata
_____________

$17 bytes per entry

$00-$0F: move name (15 chars, plus null terminator)
$10: move type
$11: move animation
$12: damage
$13: stat to boost1
$14: amt to boost
$15: stat to boost2
$16: amt. to boost2

Spoiler For Program spec:

*********
*Outline*
*********

Title Screen
   Draw title screen
   Menu*

if new game
   new game*
else
   load game*
end

setup*

loop
   if menu key
      main menu*
   end
   if arrow key
      move*
   end
   if interact ket
      interact*
   end
   counter++
   if counter = battlecounter
      battle*
      battlecounter = random
   end

   dispgraphrr
end

**********
*New game*
**********
intro cutscene*
   run cutscene* 0
ask name
   pokemon style input box
set new player values
   zero everythign
   set level to 5
   call stat calculation*

***********
*Load game*
***********
find save file
copy into L4

*******
*Setup*
*******

Load x,y to X,Y
MapLoad*
Draw Map()

***********
*Main Menu*
***********
Draw menu*
>Items
   loop items, display in list (L1+500)
   upon selecting item, use/equip, or drop
   use> look up behavior
   equip> equip that shit
>Save
   save game;
>Quit
press clear, return to game (redraw map)

********
*Moving*
********

if still centered movement:

for 8
shift screen in direction of movement
draw shifted in sprites
show screen
draw
end
for 4
shift screen
draw shifted in sprites
show screen
end
increment x, y accordingly

otherwise

draw tiles over character
move character

if character moving off of edge of map
check if other map available*
map load
scroll whole screen over
change coordinates accordingly to fit onto new map




**********
*Interact*
**********
Search npc database
   >if found, npc()*
otherwise, search trigger tile database
   >if found, npc()*

*****
*NPC*
*****

Copy from embers/old version of Ash
look up convo from argument in npc meta
load convo into L1+10 or somethingg
execute...


Slight change, all npc routine vars stay in L1
L1,L1+1 size of convo
L1+2,L1+3: position in convo

********
*battle*
********


calculate enemy, level, stats of enemy, etc...his battle stats will go into L5


DrawBattleScreen:
   draw character
   draw enemy
   draw hp boxes
   draw action box


playeraction:
   select action
   >attack
   >item (just run item routine)
   >run
      Attacking:   
         display list of moves
         select, execute
      AttacK:
         look up move in movemetadata
         damage formula, animate, apply stat changes, etc

enemyaction:
   random move select
   attack
animating:
erase player sprite
apply animation


Loop
   decide who goes first
      if bla
      playeraction()
      enemy action
      else
      enemyaction   
      playeraction()
   drawbattlescreen
end


End of battle recalculate stats...this will reset battle stat changes and also enable stats to change slightly due to EVs w/o leveling up

return
L1 not touched, npc data remains secure
























Title: Re: [A:P] Documentation
Post by: TIfanx1999 on October 07, 2012, 02:32:28 pm
Ah, I always love talk about battle engines. :D
Title: Re: [A:P] Documentation
Post by: Streetwalrus on October 09, 2012, 06:05:16 am
Yay for an awesome project that semms to sart up again ! (BTW, I should start exploring these forums a bit more :P)

Edit : Actually read this post. Battle mechanics seem very good. Also for the NPC handling, I have a good idea of what could be called "(tile)entities" (yay for stealing names from an other game). Basically an additional map storing IDs, then the engine refers to a unique list for each map to know what to do with it. It would work for NPCs, but also interactive tiles and warp tiles.
Title: Re: [A:P] Documentation
Post by: squidgetx on October 09, 2012, 01:39:01 pm
... for the NPC handling, I have a good idea of what could be called "(tile)entities" (yay for stealing names from an other game). Basically an additional map storing IDs, then the engine refers to a unique list for each map to know what to do with it. It would work for NPCs, but also interactive tiles and warp tiles.

Yeah, that's what I did with Embers and for the old version of Ash. So I kinda hacked together NPCs by putting them in as tiles in the tilemap and then marking them as interactive tiles haha. This time I won't cheat and I'll include sprite and movement data to have dynamic (moving) NPCs an such.
Title: Re: [A:P] Documentation
Post by: Streetwalrus on October 09, 2012, 04:33:49 pm
... for the NPC handling, I have a good idea of what could be called "(tile)entities" (yay for stealing names from an other game). Basically an additional map storing IDs, then the engine refers to a unique list for each map to know what to do with it. It would work for NPCs, but also interactive tiles and warp tiles.

Yeah, that's what I did with Embers and for the old version of Ash. So I kinda hacked together NPCs by putting them in as tiles in the tilemap and then marking them as interactive tiles haha. This time I won't cheat and I'll include sprite and movement data to have dynamic (moving) NPCs an such.

Ah. My idea works just fine w/ static NPCs and no AI, but if you want to get fancy as Pokémon, it'll require a bit more work. :P
Title: Re: [A:P] Documentation
Post by: Streetwalrus on October 13, 2012, 07:57:56 am
(Couple days since the previous one so I think it's permitted to double post.)

Anyway Squid, if you need some help, I'd like you to know I'll be more than happy to contribute.
Title: Re: [A:P] Documentation
Post by: squidgetx on October 13, 2012, 01:56:31 pm
I can't decide whether I want to use the same tile/map scheme as I did before, where the tiles were nibbles and each map had its own nibbleset. I remember feeling constricted by only having 16 tiles. I can't have every map able to access every tile, though (not enough RAM for practical use). Thoughts?

Just for reference, a set of 16 12x12 (same as 16x16) 4scale tiles is 1024 bytes. I think that having each map limited to 32 tiles is sufficient, but it seems like a massive waste when you realize that then that means every map doubles in size =/

Actually, I might just go for that, since I was going to RLE the maps anyway...

edit: Over the course of writing my post I ended up deciding what I was going to do, lol
Title: Re: [A:P] Documentation
Post by: leafy on October 13, 2012, 08:40:17 pm
Squidgetx, just wondering - do you have extra data that stores your enemies, NPCs, and whatnot? Or is it all built into tiles on the tilemap?
Title: Re: [A:P] Documentation
Post by: DJ Omnimaga on October 13, 2012, 09:30:22 pm
Nice that you post this. Sometimes battle formulas can be quite interesting for RPGs. Also glad this is still kinda alive.
Title: Re: [A:P] Documentation
Post by: chickendude on October 13, 2012, 11:35:10 pm
12x12 should only be the same as 12x16, though you could store them compacted then extract them to saferam before drawing the map. There aren't any tiles that are shared throughout maps? Why not have a basic tileset that is shared throughout all maps and then give each map a certain number of individual tiles. Or you want to keep each tile reduced to a nibble? RLE compression tends to work really well for tilemaps (there are so many repeated tiles) and it's pretty simple to write a "decompressor".
Title: Re: [A:P] Documentation
Post by: TIfanx1999 on October 14, 2012, 08:10:43 am
^This is what I was thinking. Also, don't you mean 12x12 would be the same as 16x12?
Title: Re: [A:P] Documentation
Post by: chickendude on October 14, 2012, 10:04:10 am
I have no idea which is supposed to come first, so maybe ;) Thanks.
Title: Re: [A:P] Documentation
Post by: squidgetx on October 14, 2012, 05:30:55 pm
Squidgetx, just wondering - do you have extra data that stores your enemies, NPCs, and whatnot? Or is it all built into tiles on the tilemap?
This will be stored outside the tilemap

12x12 should only be the same as 12x16, though you could store them compacted then extract them to saferam before drawing the map. There aren't any tiles that are shared throughout maps? Why not have a basic tileset that is shared throughout all maps and then give each map a certain number of individual tiles. Or you want to keep each tile reduced to a nibble? RLE compression tends to work really well for tilemaps (there are so many repeated tiles) and it's pretty simple to write a "decompressor".
Yeah, but once it's extracted it takes the same amount of RAM as 16x16 which is what I'm worried about (unless someone wants to write an axiom that supports 12x12 tiles or something). Also, I could also have tiles shared between maps, but from my mapdesigning experience it's not completely necessary (maybe a very basic subset could be done)
Title: Re: [A:P] Documentation
Post by: Streetwalrus on October 15, 2012, 02:20:36 pm
I have no idea which is supposed to come first, so maybe ;) Thanks.
Usually, it's Width*Height. ;)

Yeah, but once it's extracted it takes the same amount of RAM as 16x16 which is what I'm worried about (unless someone wants to write an axiom that supports 12x12 tiles or something).
In such low-level things that are the buffer and sprites, it's pretty hard to deal with a non-multiple of 8 width. However, a 16*12 routine is totally possible. i'm not an awesome ASM coder so I'm not the perfect candidate for this, but others can write one for you.
Title: Re: [A:P] Documentation
Post by: DJ Omnimaga on October 15, 2012, 03:33:46 pm
For tilemaps, aren't most 12x12 tilemappers much slower than 8x8/16x16 ones? Remember how slow Sam Heald's Zelda demo was, for example (8 frames per second, even with no grayscale/scrolling). I wonder how hard it would be to remake AP tiles to be actual 8x8 or 16x16 tiles, since most sprite routines supports multiples of 8?
Title: Re: [A:P] Documentation
Post by: squidgetx on October 15, 2012, 03:57:38 pm
Eh, I'm pretty set on using 12x12 tiles; I feel like 8x8 is too small graphics-wise, but 16x16 is too large =/

My 12x12 tilemapper is pretty much going to be a 16x16 mapper that draws extra tiles, so it'll be a bit slower. I don't think speed is really going to be a huge concern, though since it's an RPG, and the battles will be triggered and turn based as opposed to a game like Zelda (or Embers, for that matter)
Title: Re: [A:P] Documentation
Post by: DJ Omnimaga on October 15, 2012, 04:00:51 pm
I thought 16x16 was actually faster than 12x12? ??? (that's assuming of course you don't use 16x16 as some sort of cheat)

As for speed I was more worried since in the demo the FPS was like 8 or something and grayscale suffered when scrolling. D: Was that improved?
Title: Re: [A:P] Documentation
Post by: leafy on October 15, 2012, 06:17:51 pm
16x16 is the same speed as 12x12, it's just that the bits on the edges are kind of wasted space and time. Axe can only draw sprites in multiples of 8, so 16 would be the natural choice when working with 12x12 tiles.
Title: Re: [A:P] Documentation
Post by: chickendude on October 15, 2012, 07:46:55 pm
Ah i didn't know Axe could only do multiples of 8. It's kinda silly since it's super easy to draw extra Y tiles, unless there's some weird trick he's using. One of my projects now has a 16x16 sprite drawing routine i've written for it. Changing one number turns it into a 16x12 sprite drawing routine ;) It could easily be a 16 x any number routine. I don't know how to write an Axiom and it's likely what i write ends up being less optimized than what Runer wrote. Ah and i am clueless when it comes to grayscale, are you using grayscale? And really, for a tilemap, it's usually more efficient to implement the sprite drawing into the mapper itself, not keeping the x and y coordinates on the screen but rather your position in the buffer, that way you don't have to recalculate your position in the buffer each time you go to draw a tile.

And squidgetx, unpacking the sprites would take the same space in RAM, but it would save space in your program. And it wouldn't even take up the user's RAM, just saferam. And you wouldn't have to have every map's set of sprites unpacked at the same time, just your current set. It might not be worth the trouble, but it'd save you 6 bytes (or 8, if you're using 16x16 sprites) per sprite.

@DJ: I think 16x16 is generally faster since you don't have to do as many calculations (it's faster to draw one 16x16 sprite than it is to draw 4 8x8 sprites)
Title: Re: [A:P] Documentation
Post by: squidgetx on October 15, 2012, 08:17:29 pm
Ah i didn't know Axe could only do multiples of 8. It's kinda silly since it's super easy to draw extra Y tiles, unless there's some weird trick he's using. One of my projects now has a 16x16 sprite drawing routine i've written for it. Changing one number turns it into a 16x12 sprite drawing routine ;) It could easily be a 16 x any number routine. I don't know how to write an Axiom and it's likely what i write ends up being less optimized than what Runer wrote. Ah and i am clueless when it comes to grayscale, are you using grayscale? And really, for a tilemap, it's usually more efficient to implement the sprite drawing into the mapper itself, not keeping the x and y coordinates on the screen but rather your position in the buffer, that way you don't have to recalculate your position in the buffer each time you go to draw a tile.

And squidgetx, unpacking the sprites would take the same space in RAM, but it would save space in your program. And it wouldn't even take up the user's RAM, just saferam. And you wouldn't have to have every map's set of sprites unpacked at the same time, just your current set. It might not be worth the trouble, but it'd save you 6 bytes (or 8, if you're using 16x16 sprites) per sprite.

@DJ: I think 16x16 is generally faster since you don't have to do as many calculations (it's faster to draw one 16x16 sprite than it is to draw 4 8x8 sprites)

Chickendude, if you can translate your 16x12 routine into asm opcodes I'd be happy to experiment with it. :)

Yes, unpacking the sprites takes the same space in RAM, but due to size (1024 at minimum, and more likely 2048) it has to be user ram (afaik there's no saferam that size...)
Title: Re: [A:P] Documentation
Post by: chickendude on October 16, 2012, 03:02:26 am
This is the basic code. First however, you'll need to calculate where to draw the sprite on screen and put that into hl, +2 bytes (since it draws from right to left, we start with the right side of the sprite and draw leftward). I'm not really sure how Axe handles inputs to routines, so if i got a little more information i could add that in for you too. The first line loads the x offset, that is, how many pixels away from 0 we are. If you are drawing at an aligned position (a multiple of 8) b will equal 0. If you are drawing at X=1, b = 1. If X=19, b=19%8=3. C should be how many rows you want to draw. Here it's 16 (10h). If you want 12, you would change 10h to 0Ch. And the address of the sprite should be in ix. I also wrote a quick small aligned 16x16 tilemapper, i'm not sure how you draw your tilemaps. None of this uses grayscale, however, so i don't know how useful it is to you. I'd be happy to help write something for you, though. So:
b = x offset (how many pixels away from being aligned the sprite is)
c = number of rows to draw, this could be changed easily to a variable height sprite routine.
ix = address of first byte in sprite
Code: [Select]
47 -  -  -   ld b,a
 0E 10 -  -   ld c,16
 -  -  -  -  
 -  -  -  -  drawPlayerLoop:
 C5 -  -  -   push bc
 DD 56 00 -   ld d,(ix)      ;sprite
 DD 5E 01 -   ld e,(ix+1)
 AF -  -  -   xor a
 B8 -  -  -   cp b
 CA 71 A0 -   jp z,skipSpriteClip
 CB 3A CB 1B F9 srl d \ rr e \ rra \ djnz $-5   ;rotate sprite
 -  -  -  -  skipSpriteClip:
 B6 -  -  -   or (hl)
 77 -  -  -   ld (hl),a
 2B -  -  -   dec hl
 7E -  -  -   ld a,(hl)
 B3 -  -  -   or e
 77 -  -  -   ld (hl),a
 2B -  -  -   dec hl
 7E -  -  -   ld a,(hl)
 B2 -  -  -   or d
 77 -  -  -   ld (hl),a
 DD 23 -  -   inc ix
 DD 23 -  -   inc ix
 11 0E 00 -   ld de,14
 19 -  -  -   add hl,de
 C1 -  -  -   pop bc
 0D -  -  -   dec c
 C2 5E A0 -   jp nz, drawPlayerLoop
 C9 -  -  -   ret

EDIT: This routine will also slow down a little the further away from being aligned you go. We could unroll the shifting loops which, although taking up more space, would be slightly faster and have a more even runtime, or something like a 12x12 version of what i posted over here:
http://ourl.ca/15050 :)
Title: Re: [A:P] Documentation
Post by: squidgetx on October 17, 2012, 09:57:11 pm
Thanks, this will hopefully help a lot. One question though, where do you input the Y position?
Title: Re: [A:P] Documentation
Post by: chickendude on October 18, 2012, 04:16:28 am
I'm not sure how parameters are handled in Axe. That routine there requires that the position in the gbuf be calculated beforehand.

I think this should work:
Code: [Select]
26 00 -  -  ld h,0
54 -  -  -  ld d,h
6B -  -  -  ld l,e ;hl=de
29 -  -  -  add hl, hl ; 2
19 -  -  -  add hl, de ; 3
29 -  -  -  add hl, hl ; 6
29 -  -  -  add hl, hl ; 12
 -  -  -  - 
 -  -  -  -  ; x / 8
78 -  -  -  ld a,b
CB 38 -  -  srl b
CB 38 -  -  srl b
CB 38 -  -  srl b
58 -  -  -  ld e,b
19 -  -  -  add hl,de ; A present on a le decalage dans hl
11 42 93 -  ld de,gbuf+2 ; Prendre le debut du graphbuffer
19 -  -  -  add hl,de ; Puis ajouter le decalage
E6 07 -  -  and $07
Though the best would be to have a specific 12x12 tilemap routine rather than recalculate the position in gbuf every time you draw a tile.

EDIT: Added opcodes.
Title: Re: [A:P] Documentation
Post by: squidgetx on October 18, 2012, 10:04:07 am
Wait, sorry, I just reread your first post. I think I get it (correct me if I'm wrong) - the (byte) position on the graph buffer is put into hl (+2 bytes), and the offset is put into b. So for example if I want to write a sprite to the coordinates 2,0 on a buffer starting at $8000, I would load the value $8002 into hl and 2 into b.

Thanks, chickendude. I don't need it to be blazing fast, but it sure is a huge step up from using 4 8x8 routines XP
Title: Re: [A:P] Documentation
Post by: chickendude on October 18, 2012, 11:33:27 am
Yeah, that's exactly it. If your buffer is 12 bytes wide and you want to draw on the 4th row, you'll need to add 4*12 to the buffer address. The other code i posted above will calculate that for you with e=y, b=x. However, if you can save your position in the gbuf each time you draw a tile, you can save quite a few clocks by not having to recalculate your location in the buffer again.
Title: Re: [A:P] Documentation
Post by: squidgetx on October 20, 2012, 09:19:24 pm
Just testing the sprite routine after trying to integrate it with Axe subroutines; but it doesn't seem to be working (instant crash)

Any insights? :(

Edit, realized that the absolute calls were probably messing stuff up.

Code: [Select]
//Subroutine takes arguments in sub args, at $83A5, in the form X,Y,Buffer,Spriteaddress

(Axe code):
r2*12+r1+r3+2->r3
r1^16->r2
r3->r1
r4
(Immediately proceeded by asm code):

E5DDE1        push hl / pop ix ;(move r4, the sprite pointer to ix)
2AA783        ld hl, ($83A7) ;(load r2, the offset, into hl)
45            ld b, l ;(load into b)

2AA583        ld hl, ($83A5) ;(load the draw location to hl)

 0E 0C -  -   ld c,12
 -  -  -  - 
 -  -  -  -  drawPlayerLoop:
 C5 -  -  -   push bc
 DD 56 00 -   ld d,(ix)      ;sprite
 DD 5E 01 -   ld e,(ix+1)
 AF -  -  -   xor a
 B8 -  -  -   cp b
 CA 71 A0 -   jp z,skipSpriteClip
 CB 3A CB 1B F9 srl d \ rr e \ rra \ djnz $-5   ;rotate sprite
 -  -  -  -  skipSpriteClip:
 B6 -  -  -   or (hl)
 77 -  -  -   ld (hl),a
 2B -  -  -   dec hl
 7E -  -  -   ld a,(hl)
 B3 -  -  -   or e
 77 -  -  -   ld (hl),a
 2B -  -  -   dec hl
 7E -  -  -   ld a,(hl)
 B2 -  -  -   or d
 77 -  -  -   ld (hl),a
 DD 23 -  -   inc ix
 DD 23 -  -   inc ix
 11 0E 00 -   ld de,14
 19 -  -  -   add hl,de
 C1 -  -  -   pop bc
 0D -  -  -   dec c
 C2 5E A0 -   jp nz, drawPlayerLoop
 C9 -  -  -   ret

Title: Re: [A:P] Documentation
Post by: DJ Omnimaga on October 21, 2012, 11:32:07 am
16x16 is the same speed as 12x12, it's just that the bits on the edges are kind of wasted space and time. Axe can only draw sprites in multiples of 8, so 16 would be the natural choice when working with 12x12 tiles.
Ah ok I thought that to draw in 12x12 that most older tricks just tried to cut the sprites at 12x12 rather than using 16x16 with unused/wasted space and that it was actually slower that way.
Title: Re: [A:P] Documentation
Post by: chickendude on October 22, 2012, 10:33:24 am
You're right, either way it'll still be slower. If you are using a 16x16 routine, you will be calling that routine more times than if you were drawing normal 16x16 sprites (essentially the last four rows will be time completely wasted, doing nothing), and calculating the offset every time means a lot more shifting bytes since at least every other tile will be unaligned. But another reason for the slowdown with Sam Heald's Zelda might just be that back then there weren't that many smooth-scrolling games in general.
Title: Re: [A:P] Documentation
Post by: squidgetx on October 25, 2012, 05:31:53 pm
*Documentation update*

(see first post)
The project is now (almost) officially moving out of spec-writing stage :), just going to tighten up the memory allocation meta
Title: Re: [A:P] Documentation
Post by: TIfanx1999 on October 29, 2012, 05:56:32 pm
Awesome! :D Also, the documentation is quite nice. ^^
Title: Re: [A:P] Documentation
Post by: chickendude on October 30, 2012, 07:04:42 am
I wrote a 12x12 tilemapper today in case you wanted to use it or base yours off of it, it got a bit messy since every other tile is unaligned, and i didn't bother drawing the last row (there are four empty pixels at the bottom), but i think you can get the basic idea behind a 12x12 mapper from it. Feel free to use it (or anyone else who wants it) for whatever you want, sharing is caring so use it without restrictions, it's in the PD. And of course if you've got any questions (about this or your own mapper) don't hesitate to ask :)
Title: Re: [A:P] Documentation
Post by: TIfanx1999 on October 30, 2012, 09:32:52 am
Looks nice! :)
Title: Re: [A:P] Documentation
Post by: squidgetx on November 03, 2012, 02:44:08 pm
Slight update to metadata, now that I've actually begun implementing some code.