It is currently Sun Oct 21, 2018 11:12 pm

All times are UTC - 7 hours





Post new topic Reply to topic  [ 10 posts ] 
Author Message
 Post subject: My first attempt
PostPosted: Thu Mar 22, 2018 11:46 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20681
Location: NE Indiana, USA (NTSC)
So I finally got around to trying RGBDS, ending up with a port of my NES sprite demo after six hours. It runs in mGBA 0.7-5026-1a6b47a2 and on my GBC with an EverDrive GB X5. With my luck, there are probably a bunch of 6502 cargo cult practices that made their way in, much like the blatant lack of optimization that code written by 68000-to-6502 converts often shows.

Things I could do from here:

  1. Make the code less "Ho-ly-shit" in its (lack of) organization
  2. Test on NovaSquirrel's Super Game Boy to make sure I'm not hitting any mono bugs that were fixed in color
  3. Register on some other Game Boy dev forum and ask those more experienced with LR35902 for a code review. Is gbdev.gg8.se worthwhile, or is there better?
  4. Write a preprocessor to allow local non-label symbols, anonymous local symbols, and sane indentation


(Heh-heh, "lame boy".)


Attachments:
hello-1.png
hello-1.png [ 430 Bytes | Viewed 2333 times ]
hello-0.01.zip [12.27 KiB]
Downloaded 128 times
Top
 Profile  
 
 Post subject: Re: My first attempt
PostPosted: Thu Mar 22, 2018 3:09 pm 
Offline

Joined: Sun Mar 27, 2011 10:49 am
Posts: 266
Location: Seattle
I had a quick look. Nothing too egregious, but some thoughts:

  • Rather than hardcoding variable addresses, you may want to use BSS or HRAM SECTIONs
  • Using fixed SECTIONs to place code/data at addresses you care about is almost always cleaner than manually writing out garbage to fill space
  • You really ought to use the HALT instruction and wait for the vblank interrupt instead of busy looping in your main loop; this puts the CPU into low-power mode and saves battery
  • I don't know anything about needing to "release the controller", as you do on lines 344-346. That might be on me, though! Do you have a documentation source for that?


Top
 Profile  
 
 Post subject: Re: My first attempt
PostPosted: Thu Mar 22, 2018 3:30 pm 
Offline
User avatar

Joined: Sun Sep 19, 2004 9:28 pm
Posts: 3639
Location: Mountain View, CA
adam_smasher wrote:
You really ought to use the HALT instruction and wait for the vblank interrupt instead of busy looping in your main loop; this puts the CPU into low-power mode and saves battery

For tepples' benefit: this is conceptually like wai on 65816, which I believe you're familiar with. That said (and note: I do not know Z80), there do seem to be quirks you need to know of with HALT. The .txt file mentioned there does cover something that would terrify me had I not known about it in advance, if applicable:

Quote:
WARNING: The instruction immediately following the HALT instruction is "skipped" when interrupts are disabled (DI) on the GB,GBP, and SGB. As a result, always put a NOP after the HALT instruction. This instruction skipping doesn't occur when interrupts are enabled (EI). This "skipping" does not seem to occur on the GameBoy Color even in regular GB mode. ($143=$00)


Top
 Profile  
 
 Post subject: Re: My first attempt
PostPosted: Thu Mar 22, 2018 4:55 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20681
Location: NE Indiana, USA (NTSC)
Acknowledged about SECTIONs in RAM, SECTIONs in ROM, and interrupts. But the distinction in RGBDS between "labels" and "symbols", with only labels eligible to be .local, was kicking my behind at the time.

adam_smasher wrote:
You really ought to use the HALT instruction and wait for the vblank interrupt instead of busy looping in your main loop; this puts the CPU into low-power mode and saves battery

Agreed in principle. Are there examples?

adam_smasher wrote:
I don't know anything about needing to "release the controller", as you do on lines 344-346. That might be on me, though! Do you have a documentation source for that?

Search "GameBoy Programming Info" by Marat Fayzullin for "Set 1s at both P14 and P15 lines". Keeping the key matrix deselected while not reading could be a power saving method. Or it could just be cargo cult programming based on incomplete knowledge of hardware behavior, especially given the state the scene was in when Marat was most active.

koitsu is referring to WAI on 65816 and some 65C02 variants, and SWI 2 on GBA. These not only save battery on hardware but also improve emulation speed especially on a slow or mobile device. It's just a matter of sitting down and troubleshooting the IRQ edge cases, such as possibly not firing at all while rendering is disabled. And even though I use mGBA most of the time, beware in #gbdev on EFnet has convinced me to occasionally run it in (proprietary) bgb with "reality" and all "break on" enabled. (Sorry calima.)

As for the HALT "delay slot" quirk: RGBDS is encoding HALT as 76 00, a 2-byte instruction with the second being $00 (NOP). This reminded me of how the disassembler in the Apple II Monitor ROM since roughly IIGS ROM 01 began to treat BRK as the 2-byte instruction that it is.


Top
 Profile  
 
 Post subject: Re: My first attempt
PostPosted: Thu Mar 22, 2018 10:31 pm 
Offline

Joined: Sun Mar 27, 2011 10:49 am
Posts: 266
Location: Seattle
Here's some relevant snippets from my project:

Code:
SECTION "Boot", HOME[$0100]
      NOP
      JP Start

SECTION "Start", HOME[$0150]
Start:   DI            ; disable interrupts
         LD HL, $E000         ; init stack from $E000 down
         LD SP, HL
         CALL Init

;; Init calls InitInterrupts

InitInterrupts:   LD A, %00000001         ; enable VBlank
                  LDH [$FF], A
                  XOR A            ; clear pending IRQs
                  LDH [$0F], A
                  EI
                  RET

SECTION "VBlank", HOME[$40]
VBlank:      JP VBlank2

;; VBlank2 is my actual handler
SECTION "IRQHandlers", HOME
VBlank2:   PUSH AF
            PUSH BC
            PUSH DE
            PUSH HL
            CALL $FF80            ; sprite DMA
            CALL UpdateVRAM
            LD A, 1
            LD [VBlankFlag], A
            POP HL
            POP DE
            POP BC
            POP AF
            RETI

GameLoop:   CALL WaitForVBlank
;; followed by game logic...

WaitForVBlank:
  LD HL, VBlankFlag
  XOR A
  LD [HL], A
.loop
  HALT
  CP [HL]
  JR Z, .loop
  LD [HL], A
  RET


Hopefully that helps.


Top
 Profile  
 
 Post subject: Re: My first attempt
PostPosted: Fri Mar 23, 2018 2:01 pm 
Offline

Joined: Sat Jan 20, 2018 10:59 am
Posts: 2
tepples wrote:
Register on some other Game Boy dev forum and ask those more experienced with LR35902 for a code review. Is gbdev.gg8.se worthwhile, or is there better?

That's the place to go. It's not too active, but the regulars will notice and reply to your post. There's also a Discord if you want to chat, it's linked at https://avivace.github.io/awesome-gbdev


Top
 Profile  
 
 Post subject: Re: My first attempt
PostPosted: Sun Mar 25, 2018 9:58 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20681
Location: NE Indiana, USA (NTSC)
Right now, the main sticking point before I release my improvements so far is how to allocate local variables without using EQU. One solution suggested by someone in the parallel topic on gbdev.gg8.se involves putting all subroutines' sets of local variables into a UNION. But in a project larger than one file, that ends up separating the context where local variables are declared from the context where they are used, which in my opinion reduces maintainability.

After spending a while trying to work around the artificial distinction in RGBDS between labels and equates, I came up with a solution with one EQU for the locals area, a matching SECTION, and then RSSET/RB in each subroutine. In global.inc:
Code:
hLocals EQU $FF80
locals_size EQU 16


In init.s, where I keep hardware init code:
Code:
section "hram_locals", HRAM[hLocals]
  ds locals_size


In each subroutine that uses more local variables than will fit in BCDEHL:
Code:
draw_metasprite::
  RSSET hLocals
Lbasex rb 1
Lbasey rb 1
Lwidth rb 1
Lheight rb 1
  ; Code goes here
  ret

mul8::
  RSSET hLocals
Lfactor1 rb 1
Lfactor2 rb 1
Lproduct rw 1
  ; Code goes here
  ret

Is that acceptable? Or is there still too much EQU?


Top
 Profile  
 
 Post subject: Re: My first attempt
PostPosted: Mon Mar 26, 2018 10:33 pm 
Offline

Joined: Tue Feb 07, 2017 2:03 am
Posts: 617
I typically just make

ZPTemp1
ZPTemp2
ZPTemp3
....
Pointer1
Pointer2
...

then I use those labels in the code and comment their actual intended purpose on the function. This way when I modify code to call another function I can quickly see if they clash/trash each other variables.


Top
 Profile  
 
 Post subject: Re: My first attempt
PostPosted: Tue Mar 27, 2018 1:07 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20681
Location: NE Indiana, USA (NTSC)
Here's what I came up with so far.

Changes:
  • Split into separate files paralleling those of nrom-template
  • Use RLA SBC A sign extension idiom (suggested by ISSOtm)
  • Remove unnecessary and broken OAM clearing
  • Add optional zealous memory clearing to satisfy BGB exceptions
  • Add doc comments to most subroutines
  • lcd_*: Don't push HL so much
  • Put global variables and the DMA routine's run address under SECTION control
  • Try RSSET/RB to allocate local variables, nearly but not fully eliminating EQU allocation
  • Display frame count and initial A, B contents at top
  • Change frame count in vblank IRQ, and HALT until it changes
  • Explicitly mark MMIO port and local variable accesses as LDH because RGBDS lacks a counterpart to ca65 .importzp. What is this, NESASM? Ref
  • Add indentation correction to the build process
  • Change padding value to $FF
  • makefile: Add BGB as secondary emulator for "make debug"


Attachments:
demoopt.gif
demoopt.gif [ 11.98 KiB | Viewed 1824 times ]
hello-0.02.zip [20.62 KiB]
Downloaded 86 times
Top
 Profile  
 
 Post subject: Re: My first attempt
PostPosted: Fri May 11, 2018 10:03 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20681
Location: NE Indiana, USA (NTSC)
Slowly but surely, I'm coming to terms with this hardware.

0.03 (2018-05-12)
  • Switch to de facto standard hardware.inc (requested by gbdev Discord members)
  • makefile: Use target name for rgbfix instead of hardcoding hello.gb
  • Hide BG and sprites before game loop to avoid sprite garbage (reported by nitro2k01)
  • Use palette registers instead of LCDC to hide BG and sprites for GBC friendliness (requested by ISSOtm)
  • Fade out Nintendo logo while detecting Super Game Boy on DMG
  • Add GBC palette approximating that used by nrom-template on NES


Attachments:
hello-0.03opt.gif
hello-0.03opt.gif [ 38.34 KiB | Viewed 1429 times ]
hello-0.03.zip [29.47 KiB]
Downloaded 59 times
Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users and 2 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