News:

NEW GAME: Jack and the Beanstalk ! Check this topic!

Main Menu

Is there an online sprite editor for O2?

Started by Caleb Garner, June 07, 2021, 03:58:56 PM

Previous topic - Next topic

Caleb Garner

Hi everyone,

I was thinking it would be fun to make a sprite editor for O2 games.  Basically something that could let you draw up a quick graphic and see the binary values and even other helpful stuff that might be something that could be copy / pasted into code..   

However I saw some people alluding to some other editors out there..  this thread talks about two of them https://videopac.nl/forum/index.php?topic=1631.0

So I wouldn't want to reinvent the wheel.  my hope would be it could help speed up the making of sprites for folks with a nice visual editor that gives exact chunks of code for O2 devs. 


TedFoolery

For O2, another quirk is that the sprites are drawn backwards, so if the sprite coded:
00000010
00000010
00000100
00000100
00001000
00001000
00010000
00010000

it is drawn:
01000000
01000000
00100000
00100000
00010000
00010000
00001000
00001000


About the tabbing:
Yes, all commands need to be preceded by a tab or some whitespace. It's required by the compiler. If there is no whitespace, then the compiler assumes that it is a "label". A label is just an easy-to-read marker in the code. It helps to mark a place where a jump will be made or if raw data is specified. These labels are only for the compiler and won't show in the compiled code. In the helloworld example:
start
        call    gfxoff              ; switch the graphics off

"start" is just a label. In those 6 jumps at the very beginning of the code, you'll see one of those will jump to this "start" position.  "Call" is a function and calls the address with the label gfxoff. If you look in the g7000.h file (should be somewhere in the compiler folder), you'll see what this is set to.

stop    jmp     stop                ; Thats all

hellostr db     1Dh, 12h, 0Eh, 0Eh, 17h, 0Ch

"stop" and "hellostr" are the labels. The "stop" line is an infinite loop. "hellostr" is just the spot where the raw data for the characters is read from.

For all of these, you can rename the labels to anything you like. Just make sure all instances are changed.
Soooooooo:
timer
    retr

"timer" is where the 8048 jumps to if the internal timer counts down to 0. Again, you can see "timer" in the 6 jmps at the beginning of the code. There's actually a BIOS subroutine that calls that "jmp timer" and you need to return back to that BIOS call using that "retr". 
----------------------
From the comments previously, I think there's some confusion about the 8048 and the VDC. The 8048 processor is just the CPU (like an 8-bit 6502 that's in the C64, Atari, Apple; to the 32-bit 486 in the 90's; to today's 64-bit Core i7). In all of these, all they do is manipulate numbers. They don't understand graphics or joysticks or sound, they just do math, move data around, manipulate bits, and perform logic/jumps (ex: if a byte is zero, then jump).
The VDC chip in the O2 is essentially the "graphics card". It generates the graphics, detects collisions of things on the screen, and makes sound.
You theoretically could plug the VDC chip into a 486. It could process a whole lot more data much faster, but it would look and sound just like an O2.
In any language, you have variables. In BASIC, you typically can create any variable - and lots of them:
10 LET A=10
20 LET B=30
30 LET C=44
40 LET D=A+B+C
50 PRINT D

In machine language, you can't do that. They have a set number of variables that you get to play with. They named these registers instead of variables. The 6502 only has three: X, Y, and A. The 8048 has eight: r0, r1, r2, r3, r4, r5, r6, r7, a. (A is called the accumulator). The accumulator is just a variable/register, but has some special abilities. These registers can only hold a value between 0 and 255 (#00 - #ff). The above BASIC program in 8048 would be something like:
    mov r0,#0ah    ; move 10 into r0
    mov r1,#1eh    ; move 30 into r1
    mov r2,#2ch    ; move 44 into r2
    mov a,r0          ; mov the value of r0 into the accumulator
    add a,r1           ; add the value r1 to the acc. and put the result in the acc.
    add a,r2           ; add the value r2 to the acc. and put the result in the acc.
    call some-subroutine-that-draws-the-value-of-the-acc
In the 8048, you can't add two registers together directly, so you use the accumulator as a 'work-space'

So, for reading the joysticks, you have to tell the 8048 to connect to the joystick port, read the pins that are set from the joystick port, put that value somewhere, then disconnect the joystick port. So, there's a pre-written function (subroutine) already in the BIOS that does all this for you. You set r1 to 0 or 1 (left or right joystick), then call the subroutine. It sets r2 for left/right and r3 for up/down and set F0 (which stands for Flag 0) is the button was pressed.
    mov r1,#00h        ; set to zero for left stick
    call getjoystick      ;call the subroutine. This routine expects the r1 register to be set
    mov a,r2              ;move the left/right value to the acc.
    jz notmoved         ;jump to the label 'notmoved' if no left/right movement (jump if a=0)

Graphics are similar. You have to tell the 8048 to connect to the VDC, write data to the VDC's memory, then disconnect from the VDC (if need be). By default, the 8048 is already connected to the VDC, so you don't see that mentioned in the helloworld example. I already gave a simple example of one character being written. That "printchar" routine expects those certain registers to be set. You could certainly write your own function that uses different registers.

So, since there's only 8 registers and all these subroutines use the same registers, you need some place to store data (You can't keep the score in r2, because it will get erased when you draw a character or read the joystick, etc.). This is where the internal and external ram comes in. There is 29 bytes of ram for you to use internally. This is where you'd typically keep the x/y coordinates of sprites and characters and keep the score. This ram area is from $20-$3c. You need the "indirect" move command for this (uses the @ symbol and only available for r0 and r1):
    mov r0, #20h    ;move 32 into r0
    mov a, @r0       ;move the value in memory location 32 into the accumulator
    add a,#01h       ;add 1 to the accumulator
    mov @r0, a       ;move the new value back to location 32
If the score was stored in memory location $20, you just added a point. Typically, you'd then have to call a subroutine to read this value and use to update the value displayed on the screen.

There's also 128 bytes of external ram you can use from $00 to $7f. You read/write the same way, but need the movx command. You also need to connect to the external ram first:
    call extramenable    ;connect to external ram
    mov r0, #7fh    ;move 127 into r0
    movx a, @r0       ;move the value in memory location 127 into the accumulator
    add a,#01h       ;add 1 to the accumulator
    movx @r0, a       ;move the new value back to location 127

Hopefully that cleared a few things up and didn't create more confusion.

TedFoolery


Caleb Garner

thanks for this!  That initial Nugget was super helpful too!  I'll invert it.

So no one has made an O2 specific sprite tool?   If not, challenge accepted! =D

I figure it will help me learn a little more about O2 and maybe make something someone out there might find a little helpful.  

It will support color selection and ideally something that can copy an entire chunk of code that could be pasted into your project with minimal effort.  


As for the additional info, the more the merrier!  I've not had time to get my inner neo focused over the last few days, but I'm anything but done with this!   I just bought a "Voice" module (untested, crossing fingers) so that's another thing i hope to be able to explore..  

Just wait till I start asking people about the Omidi MIDI Cart I want to make some day.  =D



Thanks!
Caleb

manopac

I just remembered that I actually implemented a sprite editor in the O2EM debugger  :D

I implemented a few nice features actually ... you can use the following commands:

findsprite #   - searches the loaded rom for the sprite-data currently used for sprite #  (1-4)
viewsprite addr  - shows the addr location as sprite data

and the best one:
editsprite addr  - it lets you edit a sprite in the cartridge data ;-)

you could for example load KC Munchkin, start a game, use "findsprite 1" to find where the sprites for the munchkin are stored, change them and save the cartridge and you basically made a very very quick hack of the game replacing the sprite for munchkin by something else ...

sex, lies, and videopac

Caleb Garner

how do you use it?  the only thing i know about is running a .bat file that runs the asw.exe which then spits out a .bin file. 

manopac

that's the debugger inside of the O2EM emulator (assuming that you use it to run your bin files ...) - just press F4 and ? to get a list of commands then
sex, lies, and videopac

Mux

Looks like this never got off the ground? I'll add it to my list of things to do :-)