It is currently Fri Aug 23, 2019 1:20 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sun Feb 17, 2019 6:24 am 
Offline

Joined: Wed Apr 04, 2018 7:29 pm
Posts: 65
Location: Montreal, Canada
Time for an update, trying a video format this time. Less work for me.

Image

-Mat


Top
 Profile  
 
PostPosted: Sun Feb 17, 2019 6:46 am 
Offline
Formerly WheelInventor
User avatar

Joined: Thu Apr 14, 2016 2:55 am
Posts: 2024
Location: Gothenburg, Sweden
Love the demo! Nice mechanics, it's evident you've spent lots of care. thanks for showcasing. :beer: Also interesting to see how you've implemented stuff and how you ease editing with a basic-like syntax where practical.

_________________
http://www.frankengraphics.com - personal NES blog


Top
 Profile  
 
PostPosted: Sun Feb 17, 2019 12:51 pm 
Offline
User avatar

Joined: Sun Apr 08, 2018 11:45 pm
Posts: 46
Location: Southern California
Wow, that looks absolutely fantastic. The asset too looks very versatile and easy to use, and its really neat how it allows you to visualize occluders, collision, etc. I'm impressed with how much gameplay you're able to create via scripting. :beer:
How did you add support for copy/paste from Aseprite?


Top
 Profile  
 
PostPosted: Sun Feb 17, 2019 1:28 pm 
Offline
User avatar

Joined: Sat Jul 25, 2015 1:22 pm
Posts: 520
Hey there!

I'm still watching the video now but I wanted to chime in, that if you did these graphics yourself, then they're definitely good enough.

I understand if you just don't have the time to do all of the graphics, or if these are place-holder graphics from another source. But people can tend to be harder on their own work than that of others, and I wouldn't exclude these graphics from use for reasons of quality.

The graphics in this work-in-progress are definitely better than average for commercially released NES games. If they're something that you just ripped from another source then I apologize for the misplaced compliment. :)


Top
 Profile  
 
PostPosted: Sun Feb 17, 2019 5:39 pm 
Offline

Joined: Wed Apr 04, 2018 7:29 pm
Posts: 65
Location: Montreal, Canada
samophlange wrote:
How did you add support for copy/paste from Aseprite?


Thanks for the kind words. Aseprite is open source, so it is quite easy to see how the "encode" their clipboard data. I can send you my C# code if you want. It is essentially a bunch of image data, compressed using a DEFLATE type algorithm. Super simple. My "convention" when working in aseprite is that color 0 is transparent, 1,2,3 is the first palette, 4,5,6 is the 2nd, and so on.

-Mat


Top
 Profile  
 
PostPosted: Sun Feb 17, 2019 5:41 pm 
Offline

Joined: Wed Apr 04, 2018 7:29 pm
Posts: 65
Location: Montreal, Canada
darryl.revok wrote:
The graphics in this work-in-progress are definitely better than average for commercially released NES games. If they're something that you just ripped from another source then I apologize for the misplaced compliment. :)


Thanks. They are, in fact, heavily inspired by a bunch of stuff I found on google images, pinterest, etc. But most of the stuff you find online uses way too many colors to fit on the NES. So even when you want to "steal" stuff, it takes a lot of work to make it look nice.

-Mat


Top
 Profile  
 
PostPosted: Sun Feb 17, 2019 6:04 pm 
Offline
User avatar

Joined: Tue Jun 24, 2008 8:38 pm
Posts: 2310
Location: Fukuoka, Japan
Looks good. Will be interesting to see how it progress :D


Top
 Profile  
 
PostPosted: Mon Feb 18, 2019 1:14 am 
Offline

Joined: Tue Oct 06, 2015 10:16 am
Posts: 965
The art reminds me of Pokemon.


Top
 Profile  
 
PostPosted: Mon Feb 18, 2019 8:51 am 
Offline
Formerly WheelInventor
User avatar

Joined: Thu Apr 14, 2016 2:55 am
Posts: 2024
Location: Gothenburg, Sweden
yeah i forgot to comment about the graphics, but those are nice - i especially liked the walking animation for the patrolling bug, it has lots of nice character to it. :)

_________________
http://www.frankengraphics.com - personal NES blog


Top
 Profile  
 
PostPosted: Mon Feb 18, 2019 11:18 am 
Offline

Joined: Mon Nov 11, 2013 2:23 pm
Posts: 29
Saw this over and Twitter and wanted to pop in to say WOW! Very nice graphics, and the rest looks solid as well!


Top
 Profile  
 
PostPosted: Mon Feb 18, 2019 5:52 pm 
Offline

Joined: Wed Apr 04, 2018 7:29 pm
Posts: 65
Location: Montreal, Canada
FrankenGraphics wrote:
yeah i forgot to comment about the graphics, but those are nice - i especially liked the walking animation for the patrolling bug, it has lots of nice character to it. :)


Ha thanks man.

SoleGooseProductions wrote:
Saw this over and Twitter and wanted to pop in to say WOW! Very nice graphics, and the rest looks solid as well!


Lol, one of my 3 followers. Hahah. Baby steps i guess. Thanks for the support man.

-Mat


Top
 Profile  
 
PostPosted: Mon Feb 18, 2019 7:15 pm 
Offline

Joined: Tue Aug 28, 2018 8:54 am
Posts: 144
Location: Edmonton, Canada
I love it, I love the graphics too. Can you provide more details on the code generation of your script language?


Top
 Profile  
 
PostPosted: Mon Feb 18, 2019 8:37 pm 
Offline

Joined: Wed Apr 04, 2018 7:29 pm
Posts: 65
Location: Montreal, Canada
yaros wrote:
I love it, I love the graphics too. Can you provide more details on the code generation of your script language?

Sure. I was looking for simplest language to implement and i remembered BASIC, which is the 1st language i learned as a kid (im old).

I drew inspiration from ubasic (https://github.com/adamdunkels/ubasic), which is a very small BASIC interpreter. But I essentially re-wrote the whole thing in C#, which is what my tools are written it, and converted it into a compiler, instead of an interpreter. I made up the bytecode. I support stuff like math operation, test conditions, jumps, loops, etc. I also support calling "engine functions". The engine in ASM can expose functions that can be called from the script, using a well defined calling convention. Also, the script can implement a certain number of entry points (or events) which are all the "on_xxx" functions. These are called by the assemble code when stuff happens.

In assembly, bytecode is implemented as a simple jump table. each opcode will fetch the arguments it needs and do whatever it needs to do. I allocate a small "heap" of 32-byte for the script. This includes global variable, local variables, temporary variables. Temporary variables are needed for things like "4 + (2 + 3)". Behind the scene temporary variables will be allocated to hold temporary results of the addition. This is all done at compile time.

That's about it really, its <1000 lines of ASM, a bit more on the tool side. But it really opens up the possibilities for prototyping ideas.

-Mat


Top
 Profile  
 
PostPosted: Tue Feb 19, 2019 10:34 am 
Offline

Joined: Tue Aug 28, 2018 8:54 am
Posts: 144
Location: Edmonton, Canada
bleubleu wrote:
In assembly, bytecode is implemented as a simple jump table. each opcode will fetch the arguments it needs and do whatever it needs to do. I allocate a small "heap" of 32-byte for the script. This includes global variable, local variables, temporary variables. Temporary variables are needed for things like "4 + (2 + 3)". Behind the scene temporary variables will be allocated to hold temporary results of the addition. This is all done at compile time.


I am able to write simple parser, lexer or interpreter. When it comes to bytecode/machine code generation my brain shuts down. Could you advise some resources you used and learned from?


Top
 Profile  
 
PostPosted: Tue Feb 19, 2019 6:30 pm 
Offline

Joined: Wed Apr 04, 2018 7:29 pm
Posts: 65
Location: Montreal, Canada
yaros wrote:
I am able to write simple parser, lexer or interpreter. When it comes to bytecode/machine code generation my brain shuts down. Could you advise some resources you used and learned from?


Me too. I kind of made up the bytecode as I went along. Maybe the best way to go about it is with an example? This is an event that gets called when the player successfully hacks the keypad.

Code:
function on_game_event(event, param)
   if event = GAME_EVENT_KEYPAD_SUCCESS then
      set_timer(60)
   end if
end function


You can make your compiler simply generates the code as it parses (a real compiler would do multiple passes, use an intermediate representation to optimize more but we dont need that). You parse a statement (if, assignment, addition, etc.) and you output the bytes right away to an array. Sometimes, for jumps, you might need to patch some jump addresses and stuff, but for the most part, you can do it as you parse in one go.

This is the bytecode I use right now, and the disassembly next to it. There are generally two types of bytecode: stack based and register based, this is definitely register based.

The first byte is always the opcode.

Code:
   ; on_game_event
   .byte $0e, $01                 ;   0: get_arg0 event
   .byte $05, $01, $82            ;   2: compare_equal_byte event 0
   .byte $0a, $0a                 ;   5: jump_if_false 10
   .byte $13, $05, $8a            ;   7: invoke_r0 set_timer(60)
   .byte $1a                      ;  10: end


  • $0e = reads argument 0 passed from the engine, puts in variable slot $01 (i have 32 variable slots). Note that the compiler detected we never access the second argument, so it ignores it. Minor optimization.
  • $05 = equality comparison. Compares whatever is in variable $01 (what we just read) to constant $02 (when the minus bit, $80, is set, it means that its not a variable, but a constant stored in a table somewhere else. Whenever I encounter an hardcoded constant at compile-time, I look to see if I've seen it before and add it to that table if its new. Constants like "0" comes back quite often, so this is efficient).
  • $0a = jump to the location indicated (10, which is the end) if the last test condition was false. My conditional statements are optimized for "ORs of ANDs" (or "Disjunctive normal form" if you want to sound pretentious).
  • $13 = calls an engine function (engine function $05 is "set_timer") that takes a single argument and puts in in "r0" (a zero page variable in my engine), which is the constant table at location $0a.
  • $1a = end.

I hope this example can make it clear how easy it is to output this king of bytecode as you parse. Interpreting this is super easy, simple jump table, and a 32-byte array for your "RAM".

-Mat


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 19 posts ]  Go to page 1, 2  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group